OpenAlchemy
OpenAlchemy copied to clipboard
Support enum
As a user I want to define a list of valid values for a variable so that only those values are accepted.
Reference to the OpenAPI documentation: https://swagger.io/docs/specification/data-models/enums/
Requested in #166
I am interested in working on this issue.
What is supported
- base types of
integer,numberandstring
What is not supported
- base types of
objectandarray
High Level Flow
OpenAlchemy follows the following high level steps to produce output:
- It validates the schema against any assumptions made (e.g. that a many-to-many relationship is well defined)
- It converts the schema to artefacts which are well defined classes in OpenAlchemy
- These artefacts are passed to SQLAlchemy in a facade to be converted to columns
- The artefacts are passed to a typing engine to generate the
models_autogenerated.pyfiles - The models are constructed by inheriting from
UtilityBasewhich adds some helper functions (such asfrom_dict)
For now, we will park step 4 and 5 for later
Validation
The functionality for validation is defined in the following folder:
open_alchemy/schemas/validation
The first step is break down the problem first to individual schemas and then to properties within those schemas. Then, there are a few different types of properties which is used to break down the problem a little further. The types are:
simplejsonbackrefrelationship
In this case we only need to worry about simple. For each property of this type the schema is passed to the check function in the following file:
open_alchemy/schemas/validation/property_/simple.py
This function needs to be modified to do the following checks if a property defines enum:
- [ ] Check that the value of
enumis alist - [ ] Check that each item within the array is a valid instance of the schema.
These checks should be performed after all other checks so that you can assume that the schema is otherwise valid.
I was looking for a function that could help with the item validation, the best I could find is that something similar is being done for the default function in open_alchemy/helpers/peek.py. I would recommend that a enum function be added to the same file that performs similar validation as default (it might be worth pulling that functionality out of the default function into a separate helper function) as well as the check for a list as above.
Other types
For relationship, a check should be implemented that enum is not defined. It should throw a FeatureNotImplementedError exception. The relevant file is: open_alchemy/schemas/validation/property_/relationship/property_.py
Artefacts
After validation passes, OpenAlchemy converts the schema into well-defined artefacts data classes. The relevant folder is: open_alchemy/schemas/artifacts
Again, the problem is broken down in a similar way as for validation. The relevant file to update is:
open_alchemy/schemas/artifacts/property_/simple.py
Additionally, the class that is returned has to be updated. The class is OpenApiSimplePropertyArtifacts which should have an enum property added (open to better ways of implementing this). This class is defined here:
SQLAlchemy model construction
To construct the SQLAlchemy model, the artefacts class needs to be converted to a SQLAlchemy Column which is done in the following file:
open_alchemy/facades/sqlalchemy/simple.py
The mapping should be done to the following SQLAlchemy type:
https://docs.sqlalchemy.org/en/13/core/type_basics.html#sqlalchemy.types.Enum
Example
To verify that everything works up to this point, create an example in the following folder:
And add a test to the following file:
tests/examples/test_example_specs.py
Next Steps
This is potentially enough to do an initial pull request. If you like, after completing each stage (e.g. validation), it would also be fine to do a pull request and have that stage merged into master, it won't break anything (assuming all tests pass) and it means you can more easily keep up with any changes on the master branch.
Let's reconnect after this, there are a few more things that we need to do:
- Update some integration tests
- Update the models file autogeneration
- Add a check for that
UtilityBasecorrectly rejects invalid values due toenum - Maybe some other things I can think of right now :wink:
Hi! Any news?