Skip to content

Instantly share code, notes, and snippets.

@dankilman
Created December 6, 2016 12:07
Show Gist options
  • Save dankilman/e7b23691e4c31d8ac6dd04ec291573ed to your computer and use it in GitHub Desktop.
Save dankilman/e7b23691e4c31d8ac6dd04ec291573ed to your computer and use it in GitHub Desktop.
ARIA extension mechanism suggestion
# 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