|
@@ -916,10 +916,51 @@ Functions
|
|
|
|
|
|
.. function:: define_attribute(model_name, node, attr_name, attr_type)
|
|
|
|
|
|
+ Defines a new attribute on the element *node* in the metamodel identified by *model_name*.
|
|
|
+ The attribute is named *attr_name* and must conform to *attr_type*.
|
|
|
+ Note that, while there are other ways of creating attributes than this function, this function is by far the most user friendly.
|
|
|
+ The type being assigned needs to be specified in the metamodel as well, by instantiating the *SimpleAttribute* node.
|
|
|
+ As models are updated immediately, without any recompilation step inbetween, all instances can immediately make use of this new attribute.
|
|
|
+
|
|
|
+ Example:
|
|
|
+
|
|
|
+ To define a new attribute "tokens" on a PetriNet Place, which is of a Natural type:
|
|
|
+ .. code::
|
|
|
+ >> define_attribute("PetriNets", "Place", "tokens", Natural)
|
|
|
+
|
|
|
.. function:: all_instances(model_name, type_name)
|
|
|
|
|
|
+ Returns a list of all instances of type *type_name* in the model *model_name*.
|
|
|
+ This includes indirect instances, which are only typed by type_name through inheritance.
|
|
|
+
|
|
|
+ Example:
|
|
|
+
|
|
|
+ To get all places in a PetriNet model:
|
|
|
+ .. code::
|
|
|
+ >> all_instances("my_pn", "Place")
|
|
|
+ ["p1", "__12345"]
|
|
|
+
|
|
|
+ To get all nodes that can be instantiated directly for PetriNets:
|
|
|
+ .. code::
|
|
|
+ >> all_instances("PetriNets", "Class")
|
|
|
+ ["Place", "Transition", "P2T", "T2P"]
|
|
|
+
|
|
|
.. function:: service_poll(port)
|
|
|
|
|
|
+ Polls whether there is any input for the service we are hosting for communication handle *port*.
|
|
|
+ This returns either True or False, to get the actual data, a *service_get(port)* is required.
|
|
|
+ This function does not block when there is not data to be read.
|
|
|
+
|
|
|
+ Example:
|
|
|
+
|
|
|
+ To check whether there is any data for our port, when there is none:
|
|
|
+ >> service_poll(port)
|
|
|
+ False
|
|
|
+
|
|
|
+ To check whether there is any data for our port, when there is some:
|
|
|
+ >> service_poll(port)
|
|
|
+ True
|
|
|
+
|
|
|
Exceptions
|
|
|
^^^^^^^^^^
|
|
|
|
|
@@ -929,57 +970,163 @@ Below is a list of all exceptions that the wrappers can raise, together with a s
|
|
|
|
|
|
Generic Modelverse Exception, of which all others inherit.
|
|
|
This should be the only type of exception that the wrapper can raise.
|
|
|
+ General Python exceptions could theoretically still occur, though this likely is a bug in the wrapper.
|
|
|
|
|
|
.. exception:: UnknownError
|
|
|
|
|
|
Unknown exception has occured.
|
|
|
- This is likely something wrong with the connection, such as the Modelverse that suddenly disconnected.
|
|
|
+ This is likely something wrong with the connection, such as the Modelverse that suddenly disconnected, or the request timed out.
|
|
|
+ Note that this exception cannot be raised during *init*, as then the connection is nicely wrapped in a *ConnectionError*.
|
|
|
+
|
|
|
+ Example:
|
|
|
+
|
|
|
+ When the Modelverse is suddenly killed during execution:
|
|
|
+ .. code::
|
|
|
+ >> element_list("PetriNets") # <-- Modelverse killed during execution
|
|
|
+ UnknownError()
|
|
|
|
|
|
.. exception:: UnknownIdentifier
|
|
|
|
|
|
- The specified identifier could not be resolved in the Modelverse.
|
|
|
+ The specified element identifier could not be resolved in the specified model in the Modelverse.
|
|
|
+ The exception contains the identifier causing the problem, as there might be multiple identifiers used in a single request.
|
|
|
+
|
|
|
+ Example:
|
|
|
|
|
|
-.. exception:: UnknownType
|
|
|
+ When reading out a non-existing element in a PetriNets model:
|
|
|
+ .. code::
|
|
|
+ >> read("my_pn", "p0")
|
|
|
+ UnknownIdentifier("p0")
|
|
|
|
|
|
- The specified identifier could not be resolved as a type in the Modelverse.
|
|
|
+ When reading out the allowed connections between two elements, of which neither exists:
|
|
|
+ .. code::
|
|
|
+ >> connections_between("my_pn", "p0", "t0")
|
|
|
+ UnkownIdentifier("p0")
|
|
|
|
|
|
-.. exception:: NotAnAssociation
|
|
|
+ When reading out the allowed connections between two elements, of which the target doesn't exists:
|
|
|
+ .. code::
|
|
|
+ >> connections_between("my_pn", "p1", "t0")
|
|
|
+ UnkownIdentifier("t0")
|
|
|
|
|
|
- The specified identifier does not resolve to an association (or edge), even though this was intended.
|
|
|
+ When instantiating a non-existing element in the meta-model:
|
|
|
+ .. code::
|
|
|
+ >> instantiate("my_pn", "CapacityConstrainedPlace")
|
|
|
+ UnkownIdentifier("CapacityConstrainedPlace")
|
|
|
|
|
|
.. exception:: UnsupportedValue
|
|
|
|
|
|
The specified value is not a primitive that can be serialized.
|
|
|
- Supported types are: string, boolean, integer, float, and action.
|
|
|
+ Supported types are: string, boolean, integer, and float.
|
|
|
+
|
|
|
+ Example:
|
|
|
+
|
|
|
+ When assigning a list as attribute:
|
|
|
+ .. code::
|
|
|
+ >> attr_assign("my_pn", "p1", "tokens", [1, 2, 3])
|
|
|
+ UnsupporteValue("[1, 2, 3] : list")
|
|
|
+
|
|
|
+ When assigning a None value to an attribute:
|
|
|
+ .. code::
|
|
|
+ >> attr_assign("my_pn", "p1", "name", None)
|
|
|
+ UnsupportedValue("None : NoneType")
|
|
|
|
|
|
.. exception:: CompilationError
|
|
|
|
|
|
Error in the HUTN compiler during compilation.
|
|
|
+ This is mostly caused by a malformed expression in the specified code.
|
|
|
+ The compilation error is contained in the content of the exception.
|
|
|
+
|
|
|
+ Example:
|
|
|
+
|
|
|
+ When assigning a code block which cannot be parsed as action language:
|
|
|
+ .. code::
|
|
|
+ >> attr_assign_code("my_pn", "p1", "tokens", "1")
|
|
|
+ CompilationError("Parsing error at line 1: ...")
|
|
|
|
|
|
.. exception:: NoSuchAttribute
|
|
|
|
|
|
The specified attribute does not exist for this element.
|
|
|
+ While the attribute might exist as a type for the lower meta-level, this only looks at the current level.
|
|
|
+
|
|
|
+ Example:
|
|
|
+
|
|
|
+ When assigning a non-existing attribute:
|
|
|
+ .. code::
|
|
|
+ >> attr_assign("my_pn", "p1", "capacity", 2)
|
|
|
+ NoSuchAttribute("capacity")
|
|
|
|
|
|
.. exception:: UnknownModel
|
|
|
|
|
|
The specified model can not be resolved in the Modelverse.
|
|
|
+ While the model might technically exist, this exception merely indicates that it cannot be referred to with the specified identifier.
|
|
|
+
|
|
|
+ Example:
|
|
|
+
|
|
|
+ When trying to execute a non-existing transformation:
|
|
|
+ .. code::
|
|
|
+ >> transformation_execute_MT("pn_optimize", {"pn": "my_pn"}, {"pn": "my_optimized_pn"})
|
|
|
+ UnknownModel("pn_optimize")
|
|
|
|
|
|
.. exception:: ConnectionError
|
|
|
|
|
|
- Error with the connection to the Modelverse.
|
|
|
+ Error during initialization of the connection to the Modelverse.
|
|
|
+ The actual error is enclosed in the exception content.
|
|
|
+ Despite possibly multiple errors, the *init* call will try for at least the amount of time specified in the timeout.
|
|
|
+ This is done as the Modelverse might still be booting up and is not yet listening to incoming connections.
|
|
|
+
|
|
|
+ Example:
|
|
|
+
|
|
|
+ When trying to connect to a server which doesn't exist:
|
|
|
+ .. code::
|
|
|
+ >> init("http://www.modelverse.be")
|
|
|
+ ConnectionError("No such host")
|
|
|
|
|
|
.. exception:: ModelExists
|
|
|
|
|
|
The identifier to give to the newly created model already exists.
|
|
|
+ Note that some operations, such as model transformation, will default to overwriting a model if it already exists, but still is used as a target.
|
|
|
+ Of course, permissions of the overwritten model need to allow for this.
|
|
|
+
|
|
|
+ Example:
|
|
|
+
|
|
|
+ When the model "my_pn" already exists:
|
|
|
+ .. code::
|
|
|
+ >> model_add("my_pn", "PetriNets")
|
|
|
+ ModelExists("my_pn")
|
|
|
|
|
|
.. exception:: PermissionDenied
|
|
|
|
|
|
Permission denied to either write or read the specified resource.
|
|
|
+ This resource can be anything: a model, an element, a user, a group, ...
|
|
|
+
|
|
|
+ Example:
|
|
|
+
|
|
|
+ When changing the password of another user, while we are not an administrator:
|
|
|
+ .. code::
|
|
|
+ >> user_password("user2", "NewPassword")
|
|
|
+ PermissionDenied("user2")
|
|
|
+
|
|
|
+ When listing the elements of a model which we aren't allowed to read:
|
|
|
+ .. code::
|
|
|
+ >> element_list("secret_model")
|
|
|
+ PermissionDenied("secret_model")
|
|
|
+
|
|
|
+ When altering a model which we are only allowed to read:
|
|
|
+ .. code::
|
|
|
+ >> instantiate("SimpleClassDiagrams", "NewClass")
|
|
|
+ PermissionDenied("SimpleClassDiagrams")
|
|
|
|
|
|
.. exception:: InvalidMode
|
|
|
|
|
|
An operation was executed in the wrong context.
|
|
|
For example, all operations are only valid after a successful *init* and *login* call.
|
|
|
+ This error can also result from a previous exception, which wasn't handled correctly.
|
|
|
+ For example, when a *login* fails (thus raising a *PermissionDenied* exception), but the next operation assumes that the user is logged in.
|
|
|
+
|
|
|
+ .. code::
|
|
|
+ >> login("admmin", "wrong_password")
|
|
|
+ PermissionDenied("admin")
|
|
|
+ >> element_list("SimpleClassDiagrams")
|
|
|
+ InvalidMode()
|
|
|
|
|
|
.. exception:: InterfaceMismatch
|
|
|
|