Changelog

For any given version N, all releases N.X.X guarantee:

  • API stability: Python code that used to work will continue work.

  • Namespace stability for antidote, antidote.core and antidote.exceptions. All other namespaces have no guarantees.

  • best effort for typing stability. Meaning that code relying on Antidote that used to pass MyPy or any other static type checker should continue working, but it’s not guaranteed.

Most, if not all, the API is annotated with decorators such as @API.public specifying whether the given functionality can be relied upon.

1.1.0 (2022-03-19)

Breaking static typing change

  • A function decorated with factory() will not have the @ operator anymore from a static typing perspective. It’s unfortunately not possible with the addition of the class support for the decorator.

Deprecation

  • Service and ABCService are deprecated in favor of service(). instead which has the same behavior as service().

  • Passing a function to the argument dependencies of inject() is deprecated. If you want to customize how Antidote injects dependencies, just wrap inject() instead.

  • inject()’s auto_provide argument is deprecated. If you rely on this behavior, wrap inject().

  • world.lazy is deprecated. It never brought a lot of value, one can easily write it oneself.

  • dependency @ factory and dependency @ implementation are replaced by the more explicit notation:

    world.get(dependency, source=factory)
    
    @inject(dependencies={'db': Get(dependency, source=factory)})
    def (db):
        ...
    
  • Annotation Provide has been renamed Inject.

  • world.get will not support extracting annotated dependencies anymore.

  • world.get will require the dependency in the future when a type is specified. It supported was added using the type as the dependency itself to have a shorter syntax for @service/@service. However, as world.get provides now better type information it shouldn’t be needed anymore.

    from antidote import world, service
    
    @service
    class Dummy:
        pass
    
    # this will expose the correct type:
    world.get(Dummy)
    
    # so this is deprecated
    world.get[Dummy]()
    
    # you can still specify the type explicitly
    world.get[Dummy](Dummy)
    

Change

  • Both world.get and const have better type checking behavior, doing it only when the specified type is an actual instance of type. For protocols, type check will only be done with those decorated with @typing.runtime_checkable.

  • Dropped Python 3.6 support.

Features

  • Add ignore_type_hints to inject() to support cases when type hints cannot be evaluated, typically in circular imports.

  • Adding Markers for inject() which replace default arguments:

    from antidote import const, Constants, factory, inject, service
    
    
    class Config(Constants):
        HOST = const[str]("host")
    
    
    @service
    class Dummy:
        value: str
    
    
    @factory
    def dummy_factory() -> Dummy:
        return Dummy()
    
    
    # inject type hint
    @inject
    def f(dummy: Dummy = inject.me()) -> Dummy:
        return dummy
    
    
    # inject type hint with factory
    @inject
    def f2(dummy: Dummy = inject.me(source=dummy_factory)) -> Dummy:
        return dummy
    
    
    # inject constants
    @inject
    def f3(host: str = Config.HOST) -> str:
        return host
    
    
    # inject a dependency explicitly
    @inject
    def f4(x=inject.get(Dummy)) -> Dummy:
        return x
    
    
    # inject a dependency with a factory explicitly
    @inject
    def f5(x=inject.get(Dummy, source=dummy_factory)) -> Dummy:
        return x
    

1.0.1 (2021-11-06)

Change

  • Update fastrlock dependency to >=0.7,<0.9 to support Python 3.10 for the compiled version.

1.0.0 (2021-04-29)

No changes. From now on breaking changes will be avoided as much as possible.

0.14.2 (2021-04-28)

Features

0.14.1 (2021-04-25)

Features

  • Added ABCService for services to be easier to work with ABC abstract classes.

  • Added support for a function in auto_provide

0.14.0 (2021-03-30)

Breaking Change

  • LazyDependency and WithWiringMixin are not part of the public API anymore. For the first just use world.lazy instead, and the later was experimental.

  • world.scopes.new() argument name is keyword-only now.

0.13.0 (2021-03-24)

Breaking Change

  • _with_kwargs() class method has been replaced by Service.parameterized() and Factory.parameterized() with a cleaner design. Now parameters must be explicitly defined in their respective configuration. Those will be verified to ensure they don’t have any injections or default values, as sanity checks. Otherwise passing the default value as a parameter or relying on the actual default would not point to the same dependency value.

0.12.1 (2021-03-07)

Change

  • Improved world.test.clone() performance to be as fast as possible to avoid any overhead in tests in the compiled version.

0.12.0 (2021-02-06)

Feature / Breaking Change

0.11.0 (2021-02-05)

Features

  • Add scope support.

  • Add annotated type hints support (PEP-593).

  • Add async injection support.

  • Multiple factories can be defined for the same class.

  • Cleaner testing support, by separating explicitly the case where test existing dependencies or want to create new ones.

  • All methods of Service, Factory and Constants are automatically wired to support annotated type hints anywhere.

Breaking changes

  • Remove public configuration for Factory and Constants. They didn’t really bring any value, you hardly hide anything in Python.

  • Removed tags. They didn’t bring enough value.

  • Reworked inject(): it will only inject annotated type, nothing else anymore. use_type_hint has been replaced by auto_provide and use_names has been removed.

  • Reworked Constants to be more flexible.

  • Removed world.singletons. There was no way to track back where a singleton was defined.

  • Reworked Wiring to be simpler, not super class wiring

0.10.0 (2020-12-24)

Breaking change

  • In Wiring, ignore_missing_methods has been replaced by attempt_methods.

Bug fix

  • Using inject() on __init__() of a Service, or any methods injected by default by Antidote, will not raise a double injection error anymore.

0.9.0 (2020-12-23)

Features

  • Antidote exposes its type information (PEP 561) and passes strict Mypy (with implicit optionals).

Breaking changes

  • Antidote exceptions have no public attributes anymore.

  • Injecting twice the same function/method will raise an error.

  • Constants has been simplified, const() is now simply always required to define a constant.

Changes

  • Better, simpler DependencyInstantiationError when a deeply nested dependency fails.

  • Cleaner packaging: Antidote will only try to compile Cython when the environment variable ANTIDOTE_COMPILED is set to true and doesn’t require Cython to be pre-installed to do so. Antidote’s version is also hardcoded at publish time.

  • Added a Scope example in the documentation. It is a bit more complicated than I would like, but scopes are hard

0.8.0 (2020-12-09)

Features

  • Reworked entirely world:
    • Cleaner singletons declarations in world.singletons

    • Test utilities in world.test. Those allow you to change locally, withing a context manager, dependencies declarations. Hence you can replace an existing dependency by a mock for example.

    • Override utilities in world.test.override to be used in tests.

    • Debug utility world.debug() which returns a tree of all the dependencies that will/may be retrieved by Antidote.

    • Add type hints to world.get which can now be used like world.get[<class>]("x")

    • Add world.lazy for dependencies to retrieve dependencies lazily.

  • implementation() is more flexible than @implements and supports changing the implementation at runtime for example.

  • Service and Factory expose a handy class method with_kwargs() which allows you to specify some key word argument to customize the service you’re retrieving. Typically you would have only one database service class but use this feature to have two different dependencies which each point to different database.

  • Constants, formerly LazyConstantsMeta, supports a new of defining constants: const(). It has two purposes, explicitly define constants and optionally specify the actual type.

  • Added world.freeze() which will prevent any new dependencies to be added.

Breaking changes

  • Drop support of Python 3.5.

  • Singletons do check for duplicates now. Hence one cannot redefine an existing singleton through world.

  • world.update_singletons does not exists anymore, use world.test.singleton_all() or world.test.singleton() instead.

  • @register is now replaced by the class Service and provides mostly the same features. The only corner cases are service that used factories, those should now really use a factory, namely Factory or factory. If you cannot inherit the super class for some reason, you may fallback to the class decorator service().

  • @factory for functions behaves the same way, however for factory classes the super class Factory must be used. The dependency identifier has also been to changed, the factory must now be specified like dependency @ factory instead of dependency.

  • LazyConstantsMeta has been replaced by the class Constants. One cannot choose the lazy method anymore, but it is more flexible regarding definition of constants.

  • @implements has been entirely reworked and split into implementation() and Implementation. The latter can be used for straightforward cases where only one implementation exists. The first lets you handle all other cases with multiple implementations which can vary during runtime or not.

  • @provider has been replaced by the class decorator world.provider().

  • Everything related to the container management has been removed for the public interface.

Changes

  • Add Python 3.9 support.

  • public APIs are clearly defined as such, marked by @API.public. Overall public API is also better defined.

  • Improved Cython performance

0.7.2 (2020-04-21)

Bug fixes

  • The wrapper of the injection function didn’t behave exactly like a proxy for the all of the wrapped functions attributes. Furthermore the Cython version didn’t support setting dynamically attributes at all.

0.7.0 (2020-01-15)

Breaking changes

  • @register does not wire __init__() anymore if a function is provided as a factory. This didn’t make a lot of sense, __init__() is wrapped automatically if and only if it is treated as the “factory” that creates the object.

  • Now when using dependencies argument with a sequence (matching dependencies with arguments through their position), the first argument will be ignored for methods (self) and classmethod (cls). So now you can write:

    from antidote import inject, service
    
    class Service:
        @inject(dependencies=('dependency',))
        def method(self, arg1):
            ...
    
        @inject(dependencies=('dependency',))
        @classmethod
        def method(cls, arg1):
            ...
    
    @service(dependencies=('dependency',))
    class Service2:
        def __init__(self, arg1):
            ...
    

    Hence all other decorators profit from this. No need anymore to explicitly ignore self.

Bug fixes

  • Prevent double LazyMethodCall wrapping in LazyConstantsMeta (Thanks @keelerm84)

  • @inject cannot be applied on classes. This was never intended as it would not return a class. Use @wire instead if you relied on this.

  • @inject returned ValueError instead of TypeError in with erroneous types.

  • @register now raises an error when using a method as a factory that is neither a classmethod nor a staticmethod. It was never intended to use methods, as it would not make sense.

Changes

  • When wrapping multiple methods, @wire used to raise an error if a sequence was provided for dependencies. This limitation has been removed.

0.6.1 (2019-12-01)

  • Add support for Python 3.8

0.6.0 (2019-05-06)

Features

  • Add @implements to define service implementing an interface.

  • Add IndirectProvider() which supports @implements.

  • Add Container.safe_provide() which does the same as Container.provide() except that it raises an error if the dependency cannot be found instead of returning None.

Breaking changes

  • Container.provide() returns a DependencyInstance not the instance itself anymore.

  • Rename LazyConfigurationMeta to LazyConstantsMeta.

  • LazyConfigurationMeta default method is get().

  • ServiceProvider renamed to FactoryProvider and reworked ServiceProvider.register() with is split into register_factory(), register_class, register_providable_factory.

Changes

  • Moved is_compiled to antidote.utils.

  • Add better type hints.

0.5.1 (2019-04-27)

Features

  • Add is_compiled() to check whether the current version is compiled or pure python.

0.5.0 (2019-04-27)

Breaking changes

  • @resource has been removed an replaced by LazyConfigurationMeta to handle configuration.

Features

  • Add LazyMethodCall and LazyCall to support output of functions as dependencies.

Changes

  • Add better type hints for helper decorators.

0.4.0 (2019-02-03)

A lot of internals have changed, but it can roughly be resumed as the following:

Breaking changes

  • The DependencyManager does not exist anymore and has been replaced by multiple helpers which accepts a container argument. By default the global container of Antidote is used. Thus one can easily replace from antidote import antidote to import antidote to adapt existing code.

  • The global container of Antidote, previously named container, has been renamed world.

  • Dependency does not take additional arguments anymore, for custom dependencies Build, Tagged must be used instead.

  • Custom providers must inherit Provider.

  • register_parameters() has been replaced by a more general function, resource(). See the documentation to imitate its functionality.

  • factory() is more strict. Subclasses are not handled anymore, one should use register() with its factory argument instead.

Features

  • Dependencies can be tagged at registration. Those can then be retrieved as a dependency. This allows one to extend an app by registering a service in special way just by adding a tag.

  • Type hints usage can now be finely controlled or disabled with use_type_hints.

  • Add resource() to support custom resources, such as configuration.

  • Dependency providers are more strict for more maintainable code.

  • Use of Cython for better injection performance.

0.3.0 (2018-04-29)

Initial release