def register_component2(registry: ServiceRegistry,
                        target: Callable,
                        context: Type[Resource] = IResource):
    """ Imperative form of the component decorator """

    # This is one using a hypothetical fork of wired.dataclasses.injector
    # while Michael and I discuss props
    component_name = target.__name__

    def component_factory(container: ServiceContainer):
        def construct_component(**kwargs):
            """ A partial-partial, used to collect kwargs during calling """

            # Let's use copied version of Injector, one that supports props
            from wired_components.injector2 import Injector
            injector = Injector(target)
            component_instance = injector(container=container, props=kwargs)
            return component_instance

        return construct_component

    # Use the name of the class, e.g. Breadcrumb, as the name argument
    # during registration
    registry.register_factory(component_factory,
                              IComponent,
                              context=context,
                              name=component_name)
    # Next, add a zope.interface "subscription" to allow later reading of
    # all registered components
    adapter_registry: AdapterRegistry = registry._factories
    adapter_registry.subscribe([IResource], IComponent, target)
Beispiel #2
0
def register_dataclass(registry: ServiceRegistry,
                       target,
                       for_=None,
                       context=None):
    """ Generic injectory factory for dataclasses """

    # Note: This function could be a decorator which already knows
    # the registry, has all the targets, and can do them in one
    # container that it makes. For example:
    # from wired.decorators import factory
    # @factory(for_=Greeter, context=FrenchCustomer)
    # @datclass
    # class FrenchGreeter(Greeter):
    #   pass

    # The common case, for default registrations we can omit
    # the "for_" as it is the same as the class implementing it
    if for_ is None:
        for_ = target

    if getattr(target, 'factory', None):
        # This class wants to control its factory, use that one
        dataclass_factory = target.factory
    else:
        # Use a generic dataclass factory
        def dataclass_factory(c: ServiceContainer):
            instance = injector_construction(c, target)
            return instance

    registry.register_factory(dataclass_factory, for_, context=context)
Beispiel #3
0
def setup(settings: Settings) -> ServiceRegistry:
    # Make the registry
    registry = ServiceRegistry()

    # Make the greeter factories, using punctuation from settings
    punctuation = settings.punctuation

    # First the default greeter, no context
    def default_greeter_factory(container) -> Greeter:
        # Use the dataclass default for greeting
        return Greeter(punctuation=punctuation)

    # Register it as a factory using its class for the "key"
    registry.register_factory(default_greeter_factory, Greeter)

    # Now the French greeter, using context of FrenchCustomer
    def french_greeter_factory(container) -> Greeter:
        # Use the dataclass default for greeting
        return FrenchGreeter(punctuation=punctuation)

    # Register it as a factory using its class for the "key", but
    # this time register with a "context"
    registry.register_factory(
        french_greeter_factory, Greeter, context=FrenchCustomer
    )

    return registry
Beispiel #4
0
def setup(registry: ServiceRegistry, settings: Settings):
    # The French greeter, using context of FrenchCustomer
    punctuation = settings.punctuation

    def french_greeter_factory(container) -> Greeter:
        return FrenchGreeter(punctuation=punctuation)

    # Register it as a factory using its class for the "key", but
    # this time register with a "context"
    registry.register_factory(
        french_greeter_factory, Greeter, context=FrenchCustomer
    )

    # *** OVERRIDE !!! This add-on replaces the core, built-in Greeter
    # with a different implementation.
    def override_greeter_factory(container) -> Greeter:
        return OverrideGreeter(punctuation=punctuation)

    # Register it as a factory using its class for the "key", but
    # this time register with a "context"
    registry.register_factory(
        override_greeter_factory, Greeter, context=Customer
    )

    # Grab the Datastore and add a FrenchCustomer
    container: ServiceContainer = registry.create_container()
    datastore: Datastore = container.get(Datastore)
    customer1 = FrenchCustomer(name='Henri')
    datastore.customers.append(customer1)
Beispiel #5
0
def register_view(registry: ServiceRegistry,
                  target: Type,
                  context: Optional[Type[Resource]] = IResource):
    """ Imperative form of the decorator """
    def view_factory(container: ServiceContainer):
        injector = Injector(container)
        view_instance = injector(target)
        return view_instance

    registry.register_factory(view_factory, IView, context=context)
Beispiel #6
0
def app():
    # Do this once at startup
    registry = ServiceRegistry()
    registry.register_factory(greeter_factory, Greeter)
    registry.register_factory(Greeting, Greeting)

    # Do this for every "request" or operation
    container = registry.create_container()
    greeting: Greeting = container.get(Greeting)
    assert 'Hello from Marie' == greeting.greet()
Beispiel #7
0
def test():
    registry = ServiceRegistry()
    registry.register_factory(view_factory, View)

    # Per "request"
    container = registry.create_container()
    view: View = container.get(View)
    result = view.name
    expected = 'View'

    return expected, result
Beispiel #8
0
def setup() -> ServiceRegistry:
    # Make the registry
    registry = ServiceRegistry()

    # Make the greeter factory
    def greeter_factory(container) -> Greeter:
        return Greeter(greeting='Hello')

    # Register it as a factory using its class for the "key"
    registry.register_factory(greeter_factory, Greeter)

    return registry
Beispiel #9
0
def register_autowire(registry: ServiceRegistry,
                      cls: Type[Any],
                      iface: Type[Any] = Interface,
                      *,
                      context: Optional[Type[Any]] = None,
                      name: Text = "",
                      cls_args: Optional[Iterable[Any]] = None,
                      cls_kwargs: Optional[Mapping[Text, Any]] = None,
                      namespace: Optional[Mapping[Text, Any]] = None,
                      lazy: bool = False) -> None:
    factory = factory_factory(cls, cls_args, cls_kwargs, namespace, lazy)
    registry.register_factory(factory, iface, context=context, name=name)
Beispiel #10
0
def setup(registry: ServiceRegistry, settings: Settings):
    # The French greeter, using context of FrenchCustomer
    punctuation = settings.punctuation

    def french_greeter_factory(container) -> Greeter:
        # Use the dataclass default for greeting
        return FrenchGreeter(punctuation=punctuation)

    # Register it as a factory using its class for the "key", but
    # this time register with a "context"
    registry.register_factory(french_greeter_factory,
                              Greeter,
                              context=FrenchCustomer)
Beispiel #11
0
def setup(registry: ServiceRegistry, datastore: Datastore):
    """ Initialize the features in the core application  """

    # Register factories
    for target in (Resource, Request, View):
        registry.register_factory(target.factory, target)

    # Register dataclass factories (automated sniffing)
    register_dataclass(registry, Greeter, Greeter)

    # During bootstrap, make some Customers
    mary = Customer(name='mary', title='Mary')
    datastore.customers['mary'] = mary
Beispiel #12
0
class _RegistrarBase:
    """Represents the base class for classes able to register and manage
    services and function as an IoC object.

    This is an internal class and not meant for directy use in code. It
    was provided as a base class to aid unit testing.
    """
    def __init__(self):
        self._registry = ServiceRegistry()

    @property
    def services(self):
        key = '_container'
        if not hasattr(self, key):
            container = self._registry.create_container()
            setattr(self, key, container)
        return getattr(self, key)

    def register_service(self,
                         service,
                         iface=Interface,
                         context=None,
                         name=''):
        service_factory = SingletonServiceWrapper(service)
        self.register_service_factory(service_factory,
                                      iface,
                                      context=context,
                                      name=name)

    def register_service_factory(self,
                                 service_factory,
                                 iface=Interface,
                                 context=None,
                                 name=''):
        self._registry.register_factory(ProxyFactory(service_factory),
                                        iface,
                                        context=context,
                                        name=name)

    def find_service_factory(self, iface, context=None, name=''):
        factory = self._registry.find_factory(iface,
                                              context=context,
                                              name=name)
        if not factory:
            raise LookupError('could not find registered service')
        if isinstance(factory, ProxyFactory):
            return factory.factory
        return factory

    def find_service(self, iface, context=None, name=''):
        return self.services.get(iface, context=context, name=name)
Beispiel #13
0
def setup(settings: Settings) -> ServiceRegistry:
    # Make the registry
    registry = ServiceRegistry()

    # Make the greeter factory, using punctuation from settings
    punctuation = settings.punctuation

    def greeter_factory(container) -> Greeter:
        return Greeter(greeting='Hello', punctuation=punctuation)

    # Register it as a factory using its class for the "key"
    registry.register_factory(greeter_factory, Greeter)

    return registry
Beispiel #14
0
def register_dataclass(registry: ServiceRegistry,
                       target,
                       for_=None,
                       context=None,
                       name=''):
    """
    Register a factory for a dataclass that can sniff dependencies.

    .. code-block:: python

        from sqlalchemy.orm import Session

        @dataclass
        class LoginService:
            db: Session

        registry = ServiceRegistry()
        register_dataclass(registry, LoginService)

        # ... later
        container = registry.create_container()
        svc = container.get(LoginService)

    :param for_:
        By default, ``target`` is used as the service type. This can be used
        to override the ``iface_or_type`` argument in
        :meth:`wired.ServiceRegistry.register_factory` to some other type.

    :param context:
        The ``context`` argument in
        :meth:`wired.ServiceRegistry.register_factory`.

    :param str name:
        The ``name`` argument in
        :meth:`wired.ServiceRegistry.register_factory`.

    .. seealso::

        - :func:`wired.dataclasses.factory`

        - :func:`wired.dataclasses.injected`

    """
    # The common case, for default registrations we can omit
    # the "for_" as it is the same as the class implementing it
    if for_ is None:
        for_ = target

    injector = Injector(target)
    registry.register_factory(injector, for_, context=context, name=name)
Beispiel #15
0
def app():
    # Do this once at startup
    registry = ServiceRegistry()
    scanner = Scanner(registry=registry)
    # Point the scanner at a package/module and scan
    scanner.scan(decorators.basic_class)

    registry.register_factory(greeter_factory, Greeter)
    # No longer need this line
    # registry.register_factory(Greeting, Greeting)

    # Do this for every "request" or operation
    container = registry.create_container()
    greeting: Greeting = container.get(Greeting)
    assert 'Hello from Marie' == greeting.greet()
Beispiel #16
0
def make_registry(
    root: Optional[Root] = None,
    root_factory: Optional[Callable] = None,
    scannables: Union[Iterable[Scannable], Scannable] = tuple(),
    plugins: Union[Iterable[Plugin], Plugin] = tuple(),
    theme_config: Optional[ThemeConfig] = None,
) -> ServiceRegistry:
    """ Construct a Themester registry with some defaults """

    registry = ServiceRegistry()

    # Handle the venusian scanner
    scanner = Scanner(registry=registry)
    registry.register_singleton(scanner, Scanner)

    # Handle the root
    if root is not None:
        registry.register_singleton(root, Root)

    # Handle a root factory
    if root_factory is not None:
        registry.register_factory(root_factory, Root)

    # Handle the theme config
    if theme_config is not None:
        registry.register_singleton(theme_config, ThemeConfig)

    # Scan themester factories
    _scan_target(scanner, factories)

    # Handle anything that needs to be scanned
    if isinstance(scannables, Sequence):
        for scannable in scannables:
            _scan_target(scanner, scannable)
    else:
        _scan_target(scanner, scannables)

    # Handle any plugins
    if isinstance(plugins, Sequence):
        for plugin in plugins:
            _setup_target(registry, scanner, plugin)
    else:
        _setup_target(registry, scanner, plugins)

    return registry
Beispiel #17
0
def setup(registry: ServiceRegistry, settings: Settings):
    # The French greeter, using context of FrenchCustomer
    punctuation = settings.punctuation

    def french_greeter_factory(container) -> Greeter:
        return FrenchGreeter(punctuation=punctuation)

    # Register it as a factory using its class for the "key", but
    # this time register with a "context"
    registry.register_factory(french_greeter_factory,
                              Greeter,
                              context=FrenchCustomer)

    # Grab the Datastore and add a FrenchCustomer
    container: ServiceContainer = registry.create_container()
    datastore: Datastore = container.get(Datastore)
    henri = FrenchCustomer(name='henri', title='Henri')
    datastore.customers['henri'] = henri
Beispiel #18
0
def setup(settings: Settings) -> ServiceRegistry:
    # Make the registry
    registry = ServiceRegistry()

    # Make the greeter factory, using punctuation from settings
    punctuation = settings.punctuation

    # First the default greeter, no context
    def default_greeter_factory(container) -> Greeter:
        # Use the dataclass default for greeting
        return Greeter(punctuation=punctuation)

    # Register it as a factory using its class for the "key"
    registry.register_factory(default_greeter_factory, Greeter)

    # Import the add-on and initialize it
    from .custom import setup
    setup(registry, settings)

    return registry
Beispiel #19
0
def register_view(
        registry: ServiceRegistry,
        target: Callable = None,
        context: Optional[Type] = None,
        name: Optional[str] = None,
):
    """ Imperative form of the view decorator """

    def view_factory(container: ServiceContainer):
        injector = Injector(container)
        view_instance = injector(target)
        return view_instance

    if name is None:
        registry.register_factory(
            view_factory, View, context=context
        )
    else:
        registry.register_factory(
            view_factory, View, context=context, name=name
        )
Beispiel #20
0
def setup(registry: ServiceRegistry, settings: Settings):
    """ Initialize the features in the core application  """

    # Make and register the Datastore
    datastore = Datastore()
    registry.register_singleton(datastore, Datastore)

    # **** Default Greeter
    # Make the greeter factory, using punctuation from settings
    punctuation = settings.punctuation

    def default_greeter_factory(container) -> Greeter:
        # Use the dataclass default for greeting
        return Greeter(punctuation=punctuation)

    # Register it as a factory using its class for the "key"
    registry.register_factory(default_greeter_factory, Greeter)

    # During bootstrap, make some Customers
    customer1 = Customer(name='Mary')
    datastore.customers.append(customer1)
Beispiel #21
0
def register_dataclass(registry: ServiceRegistry,
                       target,
                       for_=None,
                       context=None):
    """ Generic injectory factory for dataclasses """

    # The common case, for default registrations we can omit
    # the "for_" as it is the same as the class implementing it
    if for_ is None:
        for_ = target

    if getattr(target, 'wired_factory', None):
        # This class wants to control its factory, use that one
        dataclass_factory = target.wired_factory
    else:
        # Use a generic dataclass factory
        def dataclass_factory(c: ServiceContainer):
            instance = injector_construction(c, target)
            return instance

    registry.register_factory(dataclass_factory, for_, context=context)
def register_component(registry: ServiceRegistry,
                       target: Callable,
                       context: Type[Resource] = IResource):
    """ Imperative form of the component decorator """
    component_name = target.__name__

    def component_factory(container: ServiceContainer):
        def construct_component(**props):
            """ A partial-partial, used to collect kwargs during calling """
            all_args = props.copy()

            # TODO Would be nice to replace this with DI once wired
            # supports props.
            # Only pass resource or view if the dataclass wants it
            fields = get_type_hints(target)
            if 'request' in fields:
                request: Request = container.get(Request)
                all_args['request'] = request
            if 'context' in fields:
                all_args['context'] = container.context
            if 'view' in fields:
                view: View = container.get(View)
                all_args['view'] = view
            component_instance = target(**all_args)
            return component_instance

        return construct_component

    # Use the name of the class, e.g. Breadcrumb, as the name argument
    # during registration
    registry.register_factory(component_factory,
                              IComponent,
                              context=context,
                              name=component_name)
    # Next, add a zope.interface "subscription" to allow later reading of
    # all registered components
    adapter_registry: AdapterRegistry = registry._factories
    adapter_registry.subscribe([IResource], IComponent, target)
Beispiel #23
0
def setup(registry: ServiceRegistry, settings: Settings):
    """ Initialize the features in the core application  """

    # Make and register the Datastore singleton
    datastore = Datastore()
    registry.register_singleton(datastore, Datastore)

    # Context factory
    def context_factory(container) -> Resource:
        # Presumes that "url" is in the container
        ds: Datastore = container.get(Datastore)
        url: str = container.get(Url)
        context: Resource = ds.customers.get(url)
        return context

    registry.register_factory(context_factory, Resource)

    # Request factory
    def request_factory(container) -> Request:
        url: str = container.get(Url)
        request = Request(url=url, container=container)
        return request

    registry.register_factory(request_factory, Request)

    # **** Default View
    def view_factory(container) -> View:
        request: Request = container.get(Request)
        context: Resource = container.get(Resource)
        greeter: Greeter = container.get(Greeter, context=context)
        view = View(request=request, context=context, greeter=greeter)
        return view

    registry.register_factory(view_factory, View)

    # **** Default Greeter
    def default_greeter_factory(container) -> Greeter:
        # Use the dataclass default for greeting
        return Greeter(punctuation=settings.punctuation)

    # Register it as a factory using its class for the "key"
    registry.register_factory(default_greeter_factory, Greeter)

    # During bootstrap, make some Customers
    mary = Customer(name='mary', title='Mary')
    datastore.customers['mary'] = mary
Beispiel #24
0
def wired_setup(
    registry: ServiceRegistry,
    scanner: Scanner,
):
    registry.register_factory(resource_factory, Resource)
    scanner.scan(themester.sphinx)
Beispiel #25
0
def wired_setup(registry: ServiceRegistry):
    registry.register_factory(context_parents, IParents)
def wired_setup(registry: ServiceRegistry) -> None:
    registry.register_factory(all_components, IAllComponents)
    registry.register_factory(wrap_components, IWrapComponents)