Created
December 6, 2016 12:07
-
-
Save dankilman/e7b23691e4c31d8ac6dd04ec291573ed to your computer and use it in GitHub Desktop.
ARIA extension mechanism suggestion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# The current extension mechanism in ARIA is not consistent in different locations of the code base. This is not healty. What follows is | |
# suggested solution of consolidating the API's to define how different extensions may "register" themselves. Extensions may be parser | |
# related, CLI commands, etc... The mechanism is general. | |
# The mechanism is build out of two different phases | |
# 1. Extension authors should somehow specify which modules in their code contains extensions | |
# 2. After a module is loaded, extensions then need to register with specific hooks | |
# | |
# (1) is addressed by extending the current implementation that was implemented as part of the parser effort. The logic suggested is: | |
# * Start by iterating all top level packages, for each package if its name starts with `aria_extension_`, simply load it. | |
# * In addition, iterate all entry_point that are registered under the name `aria_extension` and load them. | |
# This mechanism is added in case consumers do not wish to add a top level package named with an `aria_extension_` prefix. | |
# entry points is a mechanism exposed by setuptools, to make use of this mode, the extension author should add something like this to his | |
# setup.py | |
setup( | |
entry_points={ | |
'aria_extension': [ | |
'some_name': 'my_package.my_module_with_extension_registration' | |
] | |
} | |
) | |
# (1) is activated by running "aria.install_aria_extensions" functions. Which should be executed once, most likely somewhere in the | |
# beggining of the program making use of ARIA. | |
# (2) is addressed by adding a registy module, in that registry module different hooks are defined in the form of decorators (from the | |
# user perspective). Currently this module contains 4 entry points for different parser related aspects. These are copy pasted below | |
# they are actually located withing a parser namespace, which is removed here for simplification | |
@_registerer | |
def presenter_class(*_): | |
""" | |
Decorator for parser presentation class registration. | |
Decorated functions can return a single class or a list/tuple of classes | |
""" | |
return [] | |
@_registerer | |
def specification_package(*_): | |
""" | |
Decorator for specification package registration. | |
Decorated functions can return a single class or a list/tuple of classes | |
""" | |
return [] | |
@_registerer | |
def specification_url(*_): | |
""" | |
Decorator for parser specification URL registration. | |
Decorated functions should return a dictionary from names to URLs | |
a list/tuple of classes | |
""" | |
return {} | |
@_registerer | |
def uri_loader_prefix(*_): | |
""" | |
Decorator for parser uri loader prefix registration. | |
Decorated functions can return a single class or a list/tuple of classes | |
""" | |
return collections.StrictList(value_class=basestring) | |
# Each of these functions define an registry. Each registry function returns a list instance or a dict instance to specify whether | |
# which will then be used to store results from consumers. | |
# What follows is an example of how aria_extension_tosca consumes these registries | |
from aria import registry | |
@registry.parser.presenter_class | |
def presenter_classes(): | |
return ToscaSimplePresenter1_0, ToscaSimpleNfvPresenter1_0 | |
@registry.parser.specification_package | |
def specification_package(): | |
return 'aria_extension_tosca' | |
@registry.parser.specification_url | |
def specification_urls(): | |
return { | |
'yaml-1.1': 'http://yaml.org', | |
'tosca-simple-1.0': 'http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01' | |
'/TOSCA-Simple-Profile-YAML-v1.0-cos01.html', | |
'tosca-simple-nfv-1.0': 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/' | |
'tosca-nfv-v1.0.html' | |
} | |
# Note how list based registries are given single element or sequence of elements, while dict based registries expect a dictionary | |
# The last part is how ARIA's core actually reads these. | |
from registry import parser | |
# registered_presentation_classes is a concatanation of results from all | |
# functions that registered to the presentation_class registry | |
registered_presentation_classes = parser.presentation_class.registry | |
# ... do something with registered_presentation_classes | |
# An additional registry is added named `on_init` that should address the needs of running arbitrary code during initialization that | |
# isn't address by existing registries. Functions registered to `on_init` are called at the end of `aria.install_aria_extensions()` | |
# invocation | |
# The above suggestion is implemented in a branch named `ARIA-31-extensions` | |
# (https://github.com/apache/incubator-ariatosca/tree/ARIA-31-extensions) | |
# if anyone wishes to have a deeper look |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment