Fixed problems with reserved words

This commit is contained in:
Matthias Koefferlein 2022-10-24 19:44:28 +02:00
parent 9011af54ac
commit a39d22c438
8 changed files with 44363 additions and 19932 deletions

View File

@ -249,6 +249,45 @@ MethodTable::is_property_getter (bool st, const std::string &name)
return (begin_getters (p.second) != end_getters (p.second));
}
/**
* @brief Returns true, if the name is a reserved keyword
*/
static bool is_reserved_word (const std::string &name)
{
return (name == "and" ||
name == "del" ||
name == "from" ||
name == "not" ||
name == "while" ||
name == "as" ||
name == "elif" ||
name == "global" ||
name == "or" ||
name == "with" ||
name == "assert" ||
name == "else" ||
name == "if" ||
name == "pass" ||
name == "yield" ||
name == "break" ||
name == "except" ||
name == "import" ||
name == "print" ||
name == "class" ||
name == "exec" ||
name == "in" ||
name == "raise" ||
name == "continue" ||
name == "finally" ||
name == "is" ||
name == "return" ||
name == "def" ||
name == "for" ||
name == "lambda" ||
name == "try" ||
name == "None");
}
/**
* @brief Extracts the Python name from a generic name
*
@ -374,7 +413,19 @@ static std::string extract_python_name (const std::string &name)
void
MethodTable::add_method (const std::string &name, const gsi::MethodBase *mb)
{
if (name == "new" && mb->ret_type ().type () == gsi::T_object && mb->ret_type ().pass_obj ()) {
if (is_reserved_word (name)) {
// drop non-standard names
if (tl::verbosity () >= 20) {
tl::warn << tl::to_string (tr ("Class ")) << mp_cls_decl->name () << ": " << tl::to_string (tr ("no Python mapping for method (reserved word) ")) << name;
}
std::string new_name = name + "_";
add_method_basic (new_name, mb);
mp_module->add_python_doc (mb, tl::sprintf (tl::to_string (tr ("This attribute is available as '%s' in Python")), new_name));
} else if (name == "new" && mb->ret_type ().type () == gsi::T_object && mb->ret_type ().pass_obj ()) {
add_method_basic (name, mb);
@ -482,6 +533,21 @@ MethodTable::add_method (const std::string &name, const gsi::MethodBase *mb)
void
MethodTable::add_setter (const std::string &name, const gsi::MethodBase *setter)
{
if (is_reserved_word (name)) {
std::string new_name = name + "_";
add_setter_basic (new_name, setter);
mp_module->add_python_doc (setter, tl::sprintf (tl::to_string (tr ("This attribute setter is available as '%s' in Python")), new_name));
} else {
add_setter_basic (name, setter);
}
}
void
MethodTable::add_setter_basic (const std::string &name, const gsi::MethodBase *setter)
{
bool st = setter->is_static ();
@ -501,6 +567,21 @@ MethodTable::add_setter (const std::string &name, const gsi::MethodBase *setter)
void
MethodTable::add_getter (const std::string &name, const gsi::MethodBase *getter)
{
if (is_reserved_word (name)) {
std::string new_name = name + "_";
add_getter_basic (new_name, getter);
mp_module->add_python_doc (getter, tl::sprintf (tl::to_string (tr ("This attribute getter is available as '%s' in Python")), new_name));
} else {
add_getter_basic (name, getter);
}
}
void
MethodTable::add_getter_basic (const std::string &name, const gsi::MethodBase *getter)
{
bool st = getter->is_static ();

View File

@ -278,6 +278,8 @@ private:
PythonModule *mp_module;
void add_method_basic (const std::string &name, const gsi::MethodBase *mb, bool enabled = true, bool init = false);
void add_setter_basic (const std::string &name, const gsi::MethodBase *setter);
void add_getter_basic (const std::string &name, const gsi::MethodBase *getter);
bool is_property_setter (bool st, const std::string &name);
bool is_property_getter (bool st, const std::string &name);
};

View File

@ -53,49 +53,6 @@ set_type_attr (PyTypeObject *type, const std::string &name, PythonRef &attr)
}
}
// --------------------------------------------------------------------------
// Name conversion helpers
/**
* @brief Returns true, if the name is a reserved keyword
*/
static bool is_reserved_word (const std::string &name)
{
return (name == "and" ||
name == "del" ||
name == "from" ||
name == "not" ||
name == "while" ||
name == "as" ||
name == "elif" ||
name == "global" ||
name == "or" ||
name == "with" ||
name == "assert" ||
name == "else" ||
name == "if" ||
name == "pass" ||
name == "yield" ||
name == "break" ||
name == "except" ||
name == "import" ||
name == "print" ||
name == "class" ||
name == "exec" ||
name == "in" ||
name == "raise" ||
name == "continue" ||
name == "finally" ||
name == "is" ||
name == "return" ||
name == "def" ||
name == "for" ||
name == "lambda" ||
name == "try" ||
name == "None");
}
// --------------------------------------------------------------------------
// The PythonModule implementation
@ -512,18 +469,6 @@ public:
mp_module->add_python_doc (*cls, mt, int (mid), tl::sprintf (tl::to_string (tr ("This attribute is available as '%s' in Python")), name));
} else if (is_reserved_word (name)) {
// drop non-standard names
if (tl::verbosity () >= 20) {
tl::warn << tl::to_string (tr ("Class ")) << cls->name () << ": " << tl::to_string (tr ("no Python mapping for method (reserved word) ")) << name;
}
name += "_";
mt->rename (mid, name);
mp_module->add_python_doc (*cls, mt, int (mid), tl::sprintf (tl::to_string (tr ("This attribute is available as '%s' in Python")), name));
}
// create documentation

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
from typing import Any, ClassVar, Dict, Sequence, List, Iterator, Optional
from typing import overload
import klayout.tl as tl
import klayout.db as db

View File

@ -1,5 +1,6 @@
from typing import Any, ClassVar, Dict, Sequence, List, Iterator, Optional
from typing import overload
import klayout.tl as tl
import klayout.db as db
class RdbReference:
r"""
@ -8,17 +9,28 @@ class RdbReference:
"""
parent_cell_id: int
r"""
Getter:
@brief Gets parent cell ID for this reference
@return The parent cell ID
Setter:
@brief Sets the parent cell ID for this reference
"""
trans: db.DCplxTrans
r"""
Getter:
@brief Gets the transformation for this reference
The transformation describes the transformation of the child cell into the parent cell. In that sense that is the usual transformation of a cell reference.
@return The transformation
Setter:
@brief Sets the transformation for this reference
"""
@classmethod
def new(cls, trans: db.DCplxTrans, parent_cell_id: int) -> RdbReference:
r"""
@brief Creates a reference with a given transformation and parent cell ID
"""
def __copy__(self) -> RdbReference:
r"""
@brief Creates a copy of self
@ -68,22 +80,50 @@ class RdbReference:
r"""
@brief Assigns another object to self
"""
def create(self) -> None:
r"""
@brief Ensures the C++ object is created
Use this method to ensure the C++ object is created, for example to ensure that resources are allocated. Usually C++ objects are created on demand and not necessarily when the script object is created.
"""
def database(self) -> ReportDatabase:
r"""
@brief Gets the database object that category is associated with
This method has been introduced in version 0.23.
"""
def destroy(self) -> None:
r"""
@brief Explicitly destroys the object
Explicitly destroys the object on C++ side if it was owned by the script interpreter. Subsequent access to this object will throw an exception.
If the object is not owned by the script, this method will do nothing.
"""
def destroyed(self) -> bool:
r"""
@brief Returns a value indicating whether the object was already destroyed
This method returns true, if the object was destroyed, either explicitly or by the C++ side.
The latter may happen, if the object is owned by a C++ object which got destroyed itself.
"""
def dup(self) -> RdbReference:
r"""
@brief Creates a copy of self
"""
def is_const_object(self) -> bool:
r"""
@brief Returns a value indicating whether the reference is a const reference
This method returns true, if self is a const reference.
In that case, only const methods may be called on self.
"""
class RdbCell:
r"""
@brief A cell inside the report database
This class represents a cell in the report database. There is not necessarily a 1:1 correspondence of RDB cells and layout database cells. Cells have an ID, a name, optionally a variant name and a set of references which describe at least one example instantiation in some parent cell. The references do not necessarily map to references or cover all references in the layout database.
"""
@classmethod
def new(cls) -> RdbCell:
r"""
@brief Creates a new object of this class
"""
def __init__(self) -> None:
r"""
@brief Creates a new object of this class
@ -134,12 +174,29 @@ class RdbCell:
r"""
@brief Removes all references from this cell
"""
def create(self) -> None:
r"""
@brief Ensures the C++ object is created
Use this method to ensure the C++ object is created, for example to ensure that resources are allocated. Usually C++ objects are created on demand and not necessarily when the script object is created.
"""
def database(self) -> ReportDatabase:
r"""
@brief Gets the database object that category is associated with
This method has been introduced in version 0.23.
"""
def destroy(self) -> None:
r"""
@brief Explicitly destroys the object
Explicitly destroys the object on C++ side if it was owned by the script interpreter. Subsequent access to this object will throw an exception.
If the object is not owned by the script, this method will do nothing.
"""
def destroyed(self) -> bool:
r"""
@brief Returns a value indicating whether the object was already destroyed
This method returns true, if the object was destroyed, either explicitly or by the C++ side.
The latter may happen, if the object is owned by a C++ object which got destroyed itself.
"""
def each_item(self) -> Iterator[RdbItem]:
r"""
@brief Iterates over all items inside the database which are associated with this cell
@ -150,6 +207,12 @@ class RdbCell:
r"""
@brief Iterates over all references
"""
def is_const_object(self) -> bool:
r"""
@brief Returns a value indicating whether the reference is a const reference
This method returns true, if self is a const reference.
In that case, only const methods may be called on self.
"""
def name(self) -> str:
r"""
@brief Gets the cell name
@ -188,11 +251,19 @@ class RdbCategory:
"""
description: str
r"""
Getter:
@brief Gets the category description
@return The description string
Setter:
@brief Sets the category description
@param description The description string
"""
@classmethod
def new(cls) -> RdbCategory:
r"""
@brief Creates a new object of this class
"""
def __init__(self) -> None:
r"""
@brief Creates a new object of this class
@ -234,12 +305,29 @@ class RdbCategory:
Usually it's not required to call this method. It has been introduced in version 0.24.
"""
def create(self) -> None:
r"""
@brief Ensures the C++ object is created
Use this method to ensure the C++ object is created, for example to ensure that resources are allocated. Usually C++ objects are created on demand and not necessarily when the script object is created.
"""
def database(self) -> ReportDatabase:
r"""
@brief Gets the database object that category is associated with
This method has been introduced in version 0.23.
"""
def destroy(self) -> None:
r"""
@brief Explicitly destroys the object
Explicitly destroys the object on C++ side if it was owned by the script interpreter. Subsequent access to this object will throw an exception.
If the object is not owned by the script, this method will do nothing.
"""
def destroyed(self) -> bool:
r"""
@brief Returns a value indicating whether the object was already destroyed
This method returns true, if the object was destroyed, either explicitly or by the C++ side.
The latter may happen, if the object is owned by a C++ object which got destroyed itself.
"""
def each_item(self) -> Iterator[RdbItem]:
r"""
@brief Iterates over all items inside the database which are associated with this category
@ -250,6 +338,12 @@ class RdbCategory:
r"""
@brief Iterates over all sub-categories
"""
def is_const_object(self) -> bool:
r"""
@brief Returns a value indicating whether the reference is a const reference
This method returns true, if self is a const reference.
In that case, only const methods may be called on self.
"""
def name(self) -> str:
r"""
@brief Gets the category name
@ -360,11 +454,14 @@ class RdbItemValue:
"""
tag_id: int
r"""
Getter:
@brief Gets the tag ID if the value is a tagged value or 0 if not
@return The tag ID
See \tag_id= for details about tagged values.
Tagged values have been added in version 0.24.
Setter:
@brief Sets the tag ID to make the value a tagged value or 0 to reset it
@param id The tag ID
To get a tag ID, use \RdbDatabase#user_tag_id (preferred) or \RdbDatabase#tag_id (for internal use).
@ -372,6 +469,66 @@ class RdbItemValue:
This variant has been introduced in version 0.24
"""
@classmethod
def from_s(cls, s: str) -> RdbItemValue:
r"""
@brief Creates a value object from a string
The string format is the same than obtained by the to_s method.
"""
@overload
@classmethod
def new(cls, b: db.DBox) -> RdbItemValue:
r"""
@brief Creates a value representing a DBox object
"""
@overload
@classmethod
def new(cls, e: db.DEdge) -> RdbItemValue:
r"""
@brief Creates a value representing a DEdge object
"""
@overload
@classmethod
def new(cls, ee: db.DEdgePair) -> RdbItemValue:
r"""
@brief Creates a value representing a DEdgePair object
"""
@overload
@classmethod
def new(cls, f: float) -> RdbItemValue:
r"""
@brief Creates a value representing a numeric value
This variant has been introduced in version 0.24
"""
@overload
@classmethod
def new(cls, p: db.DPath) -> RdbItemValue:
r"""
@brief Creates a value representing a DPath object
This method has been introduced in version 0.22.
"""
@overload
@classmethod
def new(cls, p: db.DPolygon) -> RdbItemValue:
r"""
@brief Creates a value representing a DPolygon object
"""
@overload
@classmethod
def new(cls, s: str) -> RdbItemValue:
r"""
@brief Creates a value representing a string
"""
@overload
@classmethod
def new(cls, t: db.DText) -> RdbItemValue:
r"""
@brief Creates a value representing a DText object
This method has been introduced in version 0.22.
"""
def __copy__(self) -> RdbItemValue:
r"""
@brief Creates a copy of self
@ -422,12 +579,6 @@ class RdbItemValue:
This method has been introduced in version 0.22.
"""
def __repr__(self) -> str:
r"""
@brief Converts a value to a string
The string can be used by the string constructor to create another object from it.
@return The string
"""
def __str__(self) -> str:
r"""
@brief Converts a value to a string
@ -480,6 +631,23 @@ class RdbItemValue:
@brief Gets the box if the value represents one.
@return The \DBox object or nil
"""
def create(self) -> None:
r"""
@brief Ensures the C++ object is created
Use this method to ensure the C++ object is created, for example to ensure that resources are allocated. Usually C++ objects are created on demand and not necessarily when the script object is created.
"""
def destroy(self) -> None:
r"""
@brief Explicitly destroys the object
Explicitly destroys the object on C++ side if it was owned by the script interpreter. Subsequent access to this object will throw an exception.
If the object is not owned by the script, this method will do nothing.
"""
def destroyed(self) -> bool:
r"""
@brief Returns a value indicating whether the object was already destroyed
This method returns true, if the object was destroyed, either explicitly or by the C++ side.
The latter may happen, if the object is owned by a C++ object which got destroyed itself.
"""
def dup(self) -> RdbItemValue:
r"""
@brief Creates a copy of self
@ -500,15 +668,16 @@ class RdbItemValue:
@return The numeric value or 0
This method has been introduced in version 0.24.
"""
def from_s(self, s: str) -> RdbItemValue:
r"""
@brief Creates a value object from a string
The string format is the same than obtained by the to_s method.
"""
def is_box(self) -> bool:
r"""
@brief Returns true if the value object represents a box
"""
def is_const_object(self) -> bool:
r"""
@brief Returns a value indicating whether the reference is a const reference
This method returns true, if self is a const reference.
In that case, only const methods may be called on self.
"""
def is_edge(self) -> bool:
r"""
@brief Returns true if the value object represents an edge
@ -576,13 +745,43 @@ class RdbItem:
@brief An item inside the report database
An item is the basic information entity in the RDB. It is associated with a cell and a category. It can be assigned values which encapsulate other objects such as strings and geometrical objects. In addition, items can be assigned an image (i.e. a screenshot image) and tags which are basically boolean flags that can be defined freely.
"""
@property
def image(self) -> None:
r"""
WARNING: This variable can only be set, not retrieved.
@brief Sets the attached image from a PixelBuffer object
This method has been added in version 0.28.
"""
image_str: str
r"""
Getter:
@brief Gets the image associated with this item as a string
@return A base64-encoded image file (in PNG format)
Setter:
@brief Sets the image from a string
@param image A base64-encoded image file (preferably in PNG format)
"""
tags_str: str
r"""
Getter:
@brief Returns a string listing all tags of this item
@return A comma-separated list of tags
Setter:
@brief Sets the tags from a string
@param tags A comma-separated list of tags
"""
@classmethod
def new(cls) -> RdbItem:
r"""
@brief Creates a new object of this class
"""
def __copy__(self) -> RdbItem:
r"""
@brief Creates a copy of self
"""
def __init__(self) -> None:
r"""
@brief Creates a new object of this class
@ -688,6 +887,10 @@ class RdbItem:
This method has been introduced in version 0.25.3.
"""
def assign(self, other: RdbItem) -> None:
r"""
@brief Assigns another object to self
"""
def category_id(self) -> int:
r"""
@brief Gets the category ID
@ -704,21 +907,61 @@ class RdbItem:
r"""
@brief Removes all values from this item
"""
def create(self) -> None:
r"""
@brief Ensures the C++ object is created
Use this method to ensure the C++ object is created, for example to ensure that resources are allocated. Usually C++ objects are created on demand and not necessarily when the script object is created.
"""
def database(self) -> ReportDatabase:
r"""
@brief Gets the database object that item is associated with
This method has been introduced in version 0.23.
"""
def destroy(self) -> None:
r"""
@brief Explicitly destroys the object
Explicitly destroys the object on C++ side if it was owned by the script interpreter. Subsequent access to this object will throw an exception.
If the object is not owned by the script, this method will do nothing.
"""
def destroyed(self) -> bool:
r"""
@brief Returns a value indicating whether the object was already destroyed
This method returns true, if the object was destroyed, either explicitly or by the C++ side.
The latter may happen, if the object is owned by a C++ object which got destroyed itself.
"""
def dup(self) -> RdbItem:
r"""
@brief Creates a copy of self
"""
def each_value(self) -> Iterator[RdbItemValue]:
r"""
@brief Iterates over all values
"""
def has_image(self) -> bool:
r"""
@brief Gets a value indicating that the item has an image attached
See \image_str how to obtain the image.
This method has been introduced in version 0.28.
"""
def has_tag(self, tag_id: int) -> bool:
r"""
@brief Returns a value indicating whether the item has a tag with the given ID
@return True, if the item has a tag with the given ID
"""
def image_pixels(self) -> lay.PixelBuffer:
r"""
@brief Gets the attached image as a PixelBuffer object
This method has been added in version 0.28.
"""
def is_const_object(self) -> bool:
r"""
@brief Returns a value indicating whether the reference is a const reference
This method returns true, if self is a const reference.
In that case, only const methods may be called on self.
"""
def is_visited(self) -> bool:
r"""
@brief Gets a value indicating whether the item was already visited
@ -739,35 +982,54 @@ class ReportDatabase:
"""
description: str
r"""
Getter:
@brief Gets the databases description
The description is a general purpose string that is supposed to further describe the database and it's content in a human-readable form.
@return The description string
Setter:
@brief Sets the databases description
@param desc The description string
"""
generator: str
r"""
Getter:
@brief Gets the databases generator
The generator string describes how the database was created, i.e. DRC tool name and tool options.
In a later version this will allow re-running the tool that created the report.
@return The generator string
Setter:
@brief Sets the generator string
@param generator The generator string
"""
original_file: str
r"""
Getter:
@brief Gets the original file name and path
The original file name is supposed to describe the file from which this report database was generated. @return The original file name and path
Setter:
@brief Sets the original file name and path
@param path The path
"""
top_cell_name: str
r"""
Getter:
@brief Gets the top cell name
The top cell name identifies the top cell of the design for which the report was generated. This property must be set to establish a proper hierarchical context for a hierarchical report database. @return The top cell name
Setter:
@brief Sets the top cell name string
@param cell_name The top cell name
"""
@classmethod
def new(cls, name: str) -> ReportDatabase:
r"""
@brief Creates a report database
@param name The name of the database
The name of the database will be used in the user interface to refer to a certain database.
"""
def __init__(self, name: str) -> None:
r"""
@brief Creates a report database
@ -834,6 +1096,11 @@ class ReportDatabase:
@param qname The qualified name of the cell (name plus variant name optionally)
@return The cell object or nil if no such cell exists
"""
def create(self) -> None:
r"""
@brief Ensures the C++ object is created
Use this method to ensure the C++ object is created, for example to ensure that resources are allocated. Usually C++ objects are created on demand and not necessarily when the script object is created.
"""
@overload
def create_category(self, name: str) -> RdbCategory:
r"""
@ -1009,6 +1276,18 @@ class ReportDatabase:
@param shapes The shape container from which to take the items
@param trans The transformation to apply
"""
def destroy(self) -> None:
r"""
@brief Explicitly destroys the object
Explicitly destroys the object on C++ side if it was owned by the script interpreter. Subsequent access to this object will throw an exception.
If the object is not owned by the script, this method will do nothing.
"""
def destroyed(self) -> bool:
r"""
@brief Returns a value indicating whether the object was already destroyed
This method returns true, if the object was destroyed, either explicitly or by the C++ side.
The latter may happen, if the object is owned by a C++ object which got destroyed itself.
"""
def each_category(self) -> Iterator[RdbCategory]:
r"""
@brief Iterates over all top-level categories
@ -1043,6 +1322,12 @@ class ReportDatabase:
This property is set when a database is saved or loaded. It cannot be set manually.
@return The file name and path
"""
def is_const_object(self) -> bool:
r"""
@brief Returns a value indicating whether the reference is a const reference
This method returns true, if self is a const reference.
In that case, only const methods may be called on self.
"""
def is_modified(self) -> bool:
r"""
@brief Returns a value indicating whether the database has been modified

File diff suppressed because it is too large Load Diff