The Python code generator is a plug-out directly written in C++.
The generated sources follows the definition made in BOUML at the artifact / class / operation / relation / attribute / extra member levels.
When the code generation is applied on a artifact associated to several classes, the code generation is made for all these classes. Nevertheless the Python code generator produce first the code in memory and update the appropriate files only when it is necessary, to not change the last write date of the files for nothing. Depending on the toggle verbose code generation of the global menu Languages the code generator is verbose or not.
The Python code generator plug-out may be called on :
a class : in this case the code generation is in fact applied on the class's artifact, then on all the classes associated to this artifact
a artifact : in this case the code generation is in fact applied on all the classes associated to the artifact
a class view : the code generation will be applied on all the sub classes, then on all the artifacts associated to these classes
a deployment view : the code generation is applied on all the sub artifacts
a package (may be the project itself) : the code generation will be applied on all the sub class views and deployment views, then on all their sub classes and artifacts.
When the Python code generator is ask through the Tools menu, it is applied on the project, then on all the artifacts.
The name of the generated files depend on the artifact name, the extension depend on the language and is fixed for each by the generations settings (see below), the directory where the files are generated may be set in each package containing directly or indirectly the artifact (see generation directory).
The generator change automatically the indentation, adding/removing when necessary the indentation step specified through the generations settings (see dialog screen below) At least the first line of an operation's body must not be indented when you enter it through the operation dialog (except if you ask for non contextual indent), but of course you have to manage yourself the indentation change due to control statement for instance.
The Python definition of a artifact is set through the Python source tabs of the artifact dialog.
The code generation depend on the stereotype of the artifact :
text : the Python definition of the artifact is produced without changes, the name of the generated file is the name of the artifact, including the extension.
source : see below.
else nothing is generated for the artifact.
The generated file name is the artifact's name with the extension specified in the first Python tab of the generations settings :
In BOUML the generated code is obtained by the substitution of macros in a text, the macros known by the Python code generator are :
${NAME} produce the artifact name capitalized, ${Name} produce the artifact name with the first letter capitalized, ${nAME} produce the artifact name forced in lowercase, at least ${name} produce the artifact name without modification.
${comment} is replaced by the artifact description adding ## at the beginning of each line and a newline at end, or nothing if the description is empty
${description} is replaced by the artifact description without adding ##
${imports} is replaced by import and from .. import forms from the dependencies between classes and between artifacts stereotyped import or from. A dependency stereotyped import between artifact produces an import, stereotyped from this produces a from ... import *. A dependency stereotyped import between classes produces an import, stereotyped from this produces a form from ... import. Or course the packages are taken into account. You can also directly add import forms by hand in the artifact definition, they will be taken into account to not produce useless package path when classe names will be generated.
${definition} is replaced by the definition of the classes and extra artifact definitions associated to the artifact.
@{xyz} is replaced by the user property value in case xyz is the key of this property. The property if searched first for the artifact, if not found for the deployment view containing the artifact, if not found in the package containing the deployment view etc ...
Bouml allows to define class for any releases of Python, to help for Python 2.2 classes generation a toggle Python 2.2 is defined in each class, its default value is set through the generation settings. When Python 2.2 is set and a class doesn't inherit in the model, the inheritance or object is automatically added.
The Python definition of a class is set through the Uml and Python tabs of the class dialog.
A Python type definition may be a class, or an enum defined through a class, depending on the stereotype and its translation in Python (see generation settings).
In BOUML the generated code is obtained by the substitution of macros in a text, the macros known by the Python code generator are :
${docstring} is replaced by the description of the class placed between ””” and followed by a newline. If the description is empty nothing is produced. By default (set through the generation settings ${docstring} is used rather than ${comment} or ${description}.
${comment} is replaced by the description of the class adding #
${description} is replaced by the class description without adding #
${name} is replaced by the class's name. If needed the package path is produced, the code generator tale into account the imports associated to the depdencies and the ones writtent by hand directly in the artifact definition.
${inherit} is replaced by the class inheritance
${members} is replaced by the code generated for all the class's members (relations, attributes, operations, extra members and nested classes) following the browser order.
@{xyz} is replaced by the user property value in case xyz is the key of this property. The property if searched first for the class, if not found for the container of the class (an other class of a class view) etc ...
In the special case where the class is declared external, its Python type declaration must contains a line indicating how the name of the class is generated, and followed by an optional line giving the needed import forms. By default the specification of the name is ${name} meaning that the name is produced unchanged, the only allowed keywords are ${name}, ${Name} and ${NAME}.
The Python definition of an operation is set through the Uml and Python tabs of the operation dialog.
In BOUML the generated code is obtained by the substitution of macros in a text, the macros known by the Python code generator are :
${@} is replaced by the decorators, don't use decorator to produce @staticmethod and @abstractmethod, see ${static} and ${abstract} bellow
${comment} is replaced by the description of the operation adding # at the beginning of each line and forcing a newline at the end. Produce nothing when the description is empty.
${description} is replaced by the operation description without adding #. Produce nothing when the description is empty.
${static} is replaced by @staticmethod followed by a newline if the method is declared static in the UML tab, else an empty string
${abstract} is replaced by @abstractmethod followed by a newline if the method is declared abstract in the UML tab, else an empty string
${name} is replaced by the name of the operation.
${class} is replaced by the name of the class containing the operation.
${(} and ${)} produce ( and ), but there are also a mark for BOUML to find the parameters list
${t<n>}, ${p<n>} and ${v<n>} produce the type, name and default value of each parameter (count from 0), this allows you to remove a parameter, etc ...
${m<n>} produce the multiplicity of each parameter (count from 0), a priori used in a comment
${type} produces the operation return type, if it is not empty the type generation is preceded by -> (ref. pep3107)
${multiplicity} is replaced by the multiplicity of the return type (see the UML tab), a priori used in a comment
${body} is replaced by the body of the operation, this macro may also be replaced by the body itself (BOUML use this way for the get and set operations associated to a relation/attribute). The usage of ${body} has a great advantage : when you hit Default definition the body is not cleared ! At least BOUML share the definition forms of the operations (and other objects) to minimize the needed memory size, ${body} help for this ! The indentation of the keyword ${body} is added at the beginning of each line. In the special case of the __init__ operation the initialization of the instance attributes and relations is added just before the body, they are not produced if ${body} is not part of the operation definition.
${association} in case the operation is a getter/setter on a relation produce the association (may be the class forming a class-association with the relation) set on the relation
${type} is replaced by the class pointed by the return type, a priori used in a comment, may be for a form @return
@{xyz} is replaced by the user property value in case xyz is the key of this property. The property if searched first for the operation, if not found for the class containing the operation etc ...If the toggle preserve operations's body is set through the Languages menu, the generators do not modify the body of the operations protected by dedicated delimiters. This means that for them the body definition set through BOUML is not used. The first time you generate the code with the toggle set, because the delimiters are not yet present in the generated code, the operation's body will be updated depending on their definition under BOUML. After, while the toggle is set and the delimiters present, the bodies will not change, allowing you to modify them out of BOUML.
Notes :
In case the file containing a body definition is not consistent with the artifact under BOUML, the body will be regenerated by the code generation, using its definition under the model.
When you import a project, the body of the imported operations must be the right one in the imported model. The preserved bodies of the imported operations will not be find because the identifier of an operation used to mark its body changes during the import.
The bodies under the model are not updated by the code generation, use roundtrip body for that
Only the operations using the keyword ${body} may have a preserved body.
The only modification you can do in the lines containing the delimiters is the indent.
The toggle is saved in the file associated to the project, be sure the save is done when you change this toggle !
The Python definition of an attribute is set through the Uml and Python tabs of the attribute dialog.
An attribute may be a standard attribute or the item of an enumeration defined through a class.
The static attributes are produced in order directly in the class definition. The instance attributes are produced at the beginning of the operation __init__ when its definition contains ${body}. The operation __init__ is automatically added by the code generation, even if they are no instance attribute or relation.
In BOUML the generated code is obtained by the substitution of macros in a text, the macros known by the Python code generator are :
${comment} is replaced by the description of the attribute adding # at the beginning of each line and forcing a newline at the end. Produce nothing when the description is empty.
${description} is replaced by the attribute description without adding #. Produce nothing when the description is empty.
${self} inside the operation __init__ this produces the name of the first parameter followed by a dot, else nothing.
${name} is replaced by the attribute's name (see the UML tab)
${multiplicity} is replaced by the multiplicity of the attribute, probably used inside a comment
${stereotype} is replaced by the translation in Python of the attribute's stereotype (see the UML tab), probably something like list
${type} produces the type of the attribute, probably used inside a comment, may be for a form @var
${value} is replaced by the initial value of the attribute (see the UML tab)
@{xyz} is replaced by the user property value in case xyz is the key of this property. The property if searched first for the attribute, if not found for the class containing the attribute etc ...
The Python definition of a relation is set through the Uml and Python tabs of the relation dialog.
The static relations corresponding to variables are produced in order directly in the class definition. The instance relations corresponding to variables are produced at the beginning of the operation __init__ when its definition contains ${body}. The operation __init__ is automatically added by the code generation, even if they are no instance attribute or relation.
In BOUML the generated code is obtained by the substitution of macros in a text, the macros known by the Python code generator are :
${comment} is replaced by the description of the relation adding # at the beginning of each line and forcing a newline at the end. Produce nothing when the description is empty.
${description} is replaced by the relation description without adding #. Produce nothing when the description is empty.
${self} inside the operation __init__ this produces the name of the first parameter followed by a dot, else nothing.
${name} is replaced by the role's name (see the UML tab)
${inverse_name} is replaced by the name of the inverse role (see the UML tab)
${multiplicity} is replaced by the multiplicity of the relation, probably used inside a comment
${stereotype} is replaced by the translation in Python of the relation's stereotype (see the UML tab), probably something like list
${type} is replaced by the type of the relation, it is used by default when the relation is a composition to create an instance of this type, can also be used in a comment for a form @var
${value} is replaced by the initial value of the attribute (see the UML tab)
${association} produce the association (may be the class forming a class-association with the relation)
@{xyz} is replaced by the user property value in case xyz is the key of this property. The property if searched first for the attribute, if not found for the class containing the attribute etc ...
The class inheritance are managed at the class level.
${type} is replaced by the name of the inherited class.
An inheritance implicitly produces an import form in the artifact if needed.
The dependencies allows to add import forms in the artifact, refer to ${import} description
The Python definition of an extra member is set through the Python tabs of the extra member dialog.
The definition of the extra members are produced without any modification, this means you are also responsible to the indent
No macros.
Previous : Php roundtrip
Next : Python reverse