Skip to content

Internal Design

The intention was always to have a python class per OCICommand element from the Broadworks AS schema.

To make this easier the process_schema.py program was produced to break down the Broadworks schema into its component parts, which are represented as python classes.

The classes are broken down into types, requests (commands that are sent to the Broadworks system), and responses (the replies back from the Broadworks system). Unfortunately this means that each of those files is huge.

The classes themselves are described by a tuple of ElementInfo instances - one per property in the schema class, and a class property for each schema property. Naming of these is in the more pythonic snake case rather than the Java-esque CamelCase.

The ElementInfo class is used mainly to guide the XML serialisation and deserialisation of each object. They contain the python and XML names of each property and some flags about the propery - for example is this a required element is_required, an array like element is_array, a tabular set of data is_table or a complex element (ie containing sub-elements) is_complex.

All of the component classes of the system are intended to be immutable. There are currently no helpers to aid creating a modified instance from an existing instance because these operations do not appear to be part of a normal Broadworks workflow.

Implementation

The ElementInfo class was originally a named tuple, but this was changed later to an attrs based class for speed and to give some type checking.

The generated classes were all based on Michael DeHaan's[ClassForge] (https://classforge.io/) object system. However although this system fitted my reuirements very nicely and allowed the mkdocstrings auto documentation to work I was concerned that there were no other packages that used this system, there have been no updates or releases for well over a year and that the website had gone defunct. Therefore I moved to another class base.

Attrs mostly worked well as a base for the classes, but added an approximately 5 second startup cost on a fairly fast machine. The same occurred with using python's internal dataclass - and also forced a very recent version of python if support for immutable objects was required.

Therefore the current version is based on a class python objects using a customised __init__() method to set up the attributes from an array of ElementInfo objects. A hack is used to make these objects immutable. The objects have __slots__ defined to make them dict-less - although this might be overkill for the memory and speed benefits. Unfortunately this broke the mkdocstrings documentation (or at least made it take an absolutely vast amount of time to run), so the documentation for the types, requests and responses is generated statically.

Returned tables (only found in response objects), are defined as NamedTuples with a class name taken from the XML table name, with the elements within them using names taken from the table definition.

Due to the huge number of component classes, and that they need to have the session id associated with them on creation (since the objects themselves are immutable), the BroadworksAPI class has a set of helper methods to create and send the serialised commands to the server and then return the results.

In practice a user only interacts with the BroadworksAPI methods.

Problems

There is no easy way that I can find - especially when autogenerated - to replicate the XML schema choice elements - effectively a union between different possibilities. As such any element within a choice element has been expressed as a non-required element, and it is up to the library user to apply appropriate values to make the generated XML work.

As an example of this, look at the UnboundedPositiveInt elements within the usage example, which may have either a positive numeric quantity value or have unlimited set true.

Additionally in the example the surrounding ServicePackAuthorization element may have either unauthorized=True or authorized_quantity set to a UnboundedPositiveInt.

Additionally in version 2.0.1 onwards, schema sequence sets, within schema choice elements are similarly handled - all the contained attributes are made optional.

I can think of some ways to make the currently xfail flagged tests in test_faulty_command.py be handled correctly - at the cost of adding more complexity to the information stored about each command type and making the __init__ function more complex. However I am not fully convinced that this library should be performing that level of input checking - although the library will accept illegal combinations, the Broadworks server will quickly tell you that you are wrong!.

The tables returned in many command responses have no type information in the schema as to how to treat them - the column information is also passed within the response itself. This means that often there are boolean or numeric values that are represented as strings. In particular the booleans will have textual values of either true or false - all in lower case.