aglyph.binder
— The Aglyph component binder¶
Release: | 2.1.1 |
---|
The Aglyph binder provides a concise programmatic-configuration option for Aglyph.
New in version 1.1.0.
The Aglyph binder provides a much simpler and more compact alternative
to aglyph.assembler.Assembler
, aglyph.context.Context
,
and aglyph.component.Component
for programmatic configuration
of Aglyph.
“Binding” usually results in less configuration code. A Binder
also offers the same functionality as an
aglyph.assembler.Assembler
, so the same object used to
configure injection can be used to perform injection, further
reducing the amount of “bootstrap” code needed.
For example, the following two blocks exhibit identical behavior:
Using Context
, Component
, and Assembler
directly:
context = Context("context-id")
component = Component("my-class", dotted_name="my.package.MyClass")
component.init_args.append("value")
component.init_keywords["foo"] = "bar"
component.attributes["set_spam"] = "eggs"
context.add(component)
assembler = Assembler(context)
...
my_object = assembler.assemble("my-class")
Using Binder
:
binder = Binder()
(binder.bind("my-class", to="my.package.MyClass").
init("value", foo="bar").
attributes(set_spam="eggs"))
...
my_object = binder.lookup("my-class")
-
class
aglyph.binder.
Binder
(binder_id=None, after_inject=None, before_clear=None)[source]¶ Bases:
aglyph.assembler.Assembler
Configure and assemble application components.
Parameters: - binder_id (str) – a unique identifier for this binder
- after_inject (str) – specifies the name of the method that will be called on assembled objects after all of their dependencies have been injected
- before_clear (str) – specifies the name of the method that will be called on assembled objects immediately before they are cleared from cache
If binder_id is not provided, a random identifier is generated.
New in version 2.1.0: the after_inject and before_clear keyword arguments
-
binder_id
¶ The unique binder identifier (read-only).
-
bind
(component_spec, to=None, factory=None, member=None, strategy='prototype', parent=None, after_inject=None, before_clear=None)[source]¶ Define a component by associating the unique identifier for component_spec with the importable dotted-name for to.
Parameters: - component_spec – used to determine the value that will serve as the
lookup()
key for objects of the component - to – used to identify the class or function that will be called to initialize objects of the component
- factory (str) – names a callable member of the object identified by the component_spec argument or to keyword
- member (str) – names any member of the object identified by the component_spec argument or to keyword
- strategy (str) – specifies the component assembly strategy
- parent (str) – specifies the ID of a template or component that describes the default dependencies and/or lifecyle methods for this component
- after_inject (str) – specifies the name of the method that will be called on objects of this component after all of its dependencies have been injected
- before_clear (str) – specifies the name of the method that will be called on objects of this component immediately before they are cleared from cache
Returns: a proxy object that allows the component dependencies to be defined in chained-call fashion
Return type: If component_spec is a
str
, it is used as the unique identifier for the component. In this case, the to keyword is required.Otherwise, component_spec must be an importable class, unbound function, or module. Its dotted name will be used as the component identifier.
If to is not provided, the component identifier will be used as both the component’s identifier and dotted name. In such cases, component_spec must be either an importable class, unbound function, or module, or a dotted name.
New in version 2.0.0: the factory keyword argument
factory is the name of a callable member of the importable object (i.e. factory is a function, class, staticmethod, or classmethod). When provided, this member is called to assemble the component.
factory enables Aglyph to inject dependencies into objects that can only be initialized via nested classes,
staticmethod
, orclassmethod
. For example:# in module 'module.py' class Outer: class Nested: pass # elsewhere... binder.bind("nested-instance", to="module.Outer", factory="Nested")
When assembled, the “nested-instance” component will be an instance of the
module.Outer.Nested
class.New in version 2.0.0: the member keyword argument
member is the name of any member of the importable object (including a callable member, such as a nested class).
member differs from factory in two ways:
- member is not restricted to callable members; it may name an attribute or property, as well as a callable.
- When the binder looks up a component with a defined member, initialization is bypassed (i.e. no initialization dependencies are injected).
member enables Aglyph to reference classes, functions, staticmethods, classmethods, and attributes as dependencies. For example:
# in module 'module.py' class Outer: class Nested: pass # elsewhere... binder.bind("nested-class", to="module.Outer", member="Nested")
When assembled, the “nested-class” component will be the module.Outer.Nested
class
object itself.Note
Both factory and member can be dot-separated names to reference nested members.
Warning
The factory and member arguments are mutually exclusive. An exception is raised if both are provided.
strategy must be a recognized component assembly strategy, and defaults to
aglyph.component.Strategy.PROTOTYPE
(“prototype”) if not specified.Please see
aglyph.component.Strategy
for a description of the component assembly strategies supported by Aglyph.Warning
The
aglyph.component.Strategy.BORG
(“borg”) component assembly strategy is only supported for classes that do not define or inherit__slots__
!New in version 2.1.0: the parent keyword argument
If parent is a
str
, it is used as the unique identifier for the component’s parent template or component.If parent is not a string, then it must be an importable class, unbound function, or module. Its dotted name will be used as the
Component.parent_id
.New in version 2.1.0: the after_inject keyword argument
after_inject is the name of a method of objects of this component that will be called after all dependencies have been injected, but before the object is returned to the caller. This method will be called with no arguments (positional or keyword). Exceptions raised by this method are not caught.
Note
Component.after_inject
, if specified, replaces eitherTemplate.after_inject
(if this component also specifiesparent_id
) oraglyph.context.Context.after_inject
.New in version 2.1.0: the before_clear keyword argument
before_clear is the name of a method of objects of this component that will be called immediately before the object is cleared from cache via
aglyph.assembler.Assembler.clear_singletons()
,aglyph.assembler.Assembler.clear_borgs()
, oraglyph.assembler.Assembler.clear_weakrefs()
.Note
Component.before_clear
, if specified, replaces eitherTemplate.before_clear
(if this component also specifiesparent_id
) oraglyph.context.Context.before_clear
.Warning
The before_clear keyword argument has no meaning for and is ignored by “prototype” components. If before_clear is specified for a prototype, a
RuntimeWarning
will be issued.For “weakref” components, there is a possibility that the object no longer exists at the moment when the before_clear method would be called. In such cases, the before_clear method is not called. No warning is issued, but a
logging.WARNING
message is emitted.- component_spec – used to determine the value that will serve as the
-
describe
(template_spec, parent=None, after_inject=None, before_clear=None)[source]¶ Define a template using the unique identifier derived from template_spec.
Parameters: - template_spec – used to determine the value that will serve as the unique identifier for the template
- parent (str) – specifies the ID of a template or component that describes the default dependencies and/or lifecyle methods for this template
- after_inject (str) – specifies the name of the method that will be called on objects of components that refer to this template’s ID as the
Component.parent_id
immediately after all component dependencies have been injected - before_clear (str) – specifies the name of the method that will be called on objects of components that refer to this template’s ID as the
Component.parent_id
when the objects are removed from any internal cache
Returns: a proxy object that allows the template dependencies to be defined in chained-call fashion
Return type: If template_spec is a
str
, it is used as the unique identifier for the template. Otherwise, template_spec must be an importable class, unbound function, or module. Its dotted name will be used as the template identifier.If parent is a
str
, it is used as the unique identifier for the component’s parent template or component.If parent is not a string, then it must be an importable class, unbound function, or module. Its dotted name will be used as the
Component.parent_id
.after_inject is the name of a method (of objects of components that reference this template) that will be called after all dependencies have been injected, but before the object is returned to the caller.
The method named by after_inject will be called with no arguments (positional or keyword). Exceptions raised by this method are ignored (though a
RuntimeWarning
will be issued).Note
Template.after_inject
, if specified, replaces any after-inject method named by its parent or byaglyph.context.Context.after_inject
.before_clear is the name of a method (of objects of components that reference this template) that will be called when the object is cleared from cache via
Assembler.clear_singletons()
,Assembler.clear_borgs()
, orAssembler.clear_weakrefs()
.Note
Template.before_clear
, if specified, replaces any before-clear method named by its parent or byaglyph.context.Context.before_clear
.Warning
The before_clear keyword argument has no meaning for and is ignored by “prototype” components. If before_clear is specified for a prototype, a
RuntimeWarning
will be issued.For “weakref” components, there is a possibility that the object no longer exists at the moment when the before_clear method would be called. In such cases, the before_clear method is not called. No warning is issued, but a
logging.WARNING
message is emitted.
-
lookup
(component_spec)[source]¶ Return an instance of the component specified by component_spec with all of its dependencies provided.
component_spec must be an importable class or unbound function, or a user-defined unique identifier, that was previously bound by a call to
bind()
.Deprecated since version 2.1.0: use
assemble()
instead.
-
class
aglyph.binder.
_DependencySupportProxy
(depsupport)[source]¶ Bases:
object
Instances of
__DependencySupportProxy
are returned as proxy objects from theBinder.bind()
andBinder.describe()
methods.A
_DependencySupportProxy
allows component dependencies to be defined in chained-call fashion:binder = Binder() binder.bind(...).init(*args, **keywords).attributes(**keywords) # - or - (binder.describe(...). init(*args, **keywords). attributes(**keywords))
Note
This class should not be imported or otherwise directly referenced.
Parameters: depsupport – a Component
orTemplate
that was created byBinder.bind()
orBinder.describe()
, respectively-
init
(*args, **keywords)[source]¶ Define the initialization dependencies (i.e. positional and/or keyword arguments) for the component or template.
Parameters: Returns: a reference to
self
(enables chained calls)If any argument value is a class, unbound function, or module type, it is automatically turned into a
Reference
:# SomeClass becomes # ``Reference(format_dotted_name(SomeClass))`` binder.bind("thing", to="module.Thing").init(SomeClass)
Warning
In the above example, there must exist a component that has the ID “package.module.SomeClass”:
binder.bind(SomeClass).init(...).attributes(...) # - or - (binder.bind("package.module.SomeClass"). init(...).attributes(...))
If more flexibility is needed, simply create and pass in an explicit
Reference
:(binder.bind("something", to=SomeClass). init(...).attributes(...)) ... (binder.bind("thing", to="module.Thing"). init(Reference("something")))
Changed in version 2.0.0: Successive calls to this method on the same instance have a cumulative effect.
-
attributes
(*nvpairs, **keywords)[source]¶ Define the setter dependencies (i.e. attributes, setter methods, and/or properties) for the component.
Parameters: Returns: a reference to
self
(enables chained calls)New in version 2.1.0::: the nvpairs parameter.
If the order in which attribute/setter/property dependencies are injected is significant, use nvpairs to control the order; otherwise, if order of injection doesn’t matter, it is simpler to use keywords.
In each
(name, value)
2-tuple of nvpairs,name
corresponds to the name of a simple attribute, setter method, or property:(binder.bind("thing", to="module.Thing"). attributes(("id", 1), ("set_name", "First thing")))
Each key in keywords corresponds to the name of a simple attribute, setter method, or property:
(binder.bind("thing", to="module.Thing"). attributes(id=1, set_name="First thing"))
If any value in nvpairs or keywords is a class, unbound function, or module type, it is automatically turned into a
Reference
:# SomeClass becomes # ``Reference(format_dotted_name(SomeClass))`` (binder.bind("thing", to="module.Thing"). attributes(id=1, set_class=SomeClass))
Warning
In the above example, there must exist a component that has the ID “package.module.SomeClass”:
binder.bind(SomeClass).init(...).attributes(...) # - or - (binder.bind("package.module.SomeClass"). init(...).attributes(...))
If more flexibility is needed, simply create and pass in an explicit
Reference
:(binder.bind("something", to=SomeClass). init(...).attributes(...)) ... (binder.bind("thing", to="module.Thing"). attributes(id=1, set_class=Reference("something")))
Changed in version 2.0.0: Successive calls to this method on the same instance have a cumulative effect.
-