summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--python-inject.spec902
-rw-r--r--sources1
3 files changed, 904 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..6f7a713 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/Inject-4.3.1.tar.gz
diff --git a/python-inject.spec b/python-inject.spec
new file mode 100644
index 0000000..70e6d84
--- /dev/null
+++ b/python-inject.spec
@@ -0,0 +1,902 @@
+%global _empty_manifest_terminate_build 0
+Name: python-Inject
+Version: 4.3.1
+Release: 1
+Summary: Python dependency injection framework
+License: Apache License 2.0
+URL: https://github.com/ivankorobkov/python-inject
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/23/e2/04673185baadf9f4e175de51212fd2966eed2fca3236fdcfb7e732e4d09e/Inject-4.3.1.tar.gz
+BuildArch: noarch
+
+
+%description
+# python-inject [![Build Status](https://travis-ci.org/ivankorobkov/python-inject.svg?branch=master)](https://travis-ci.org/ivankorobkov/python-inject)
+Dependency injection the python way, the good way. Not a port of Guice or Spring.
+
+## Key features
+* Fast.
+* Thread-safe.
+* Simple to use.
+* Does not steal class constructors.
+* Does not try to manage your application object graph.
+* Transparently integrates into tests.
+* Supports Python 3.5+ (`v4.*`) and Python 2.7–3.5 (`v3.*`).
+* Supports type hinting in Python 3.5+.
+* Autoparams leveraging type annotations.
+
+## Python Support
+
+| Python | Inject Version |
+|--------|----------------|
+| 3.6+ | 4.1+ |
+| 3.5 | 4.0 |
+| < 3.5 | 3.* |
+
+
+## Installation
+Use pip to install the lastest version:
+
+```bash
+pip install inject
+```
+
+## Autoparams example
+`@inject.autoparams` returns a decorator which automatically injects arguments into a function
+that uses type annotations. This is supported only in Python >= 3.5.
+
+```python
+@inject.autoparams()
+def refresh_cache(cache: RedisCache, db: DbInterface):
+ pass
+```
+
+There is an option to specify which arguments we want to inject without attempts of
+injecting everything:
+
+```python
+@inject.autoparams('cache', 'db')
+def sign_up(name, email, cache: RedisCache, db: DbInterface):
+ pass
+```
+
+## Step-by-step example
+```python
+# Import the inject module.
+import inject
+
+
+# `inject.instance` requests dependencies from the injector.
+def foo(bar):
+ cache = inject.instance(Cache)
+ cache.save('bar', bar)
+
+
+# `inject.params` injects dependencies as keyword arguments or positional argument.
+# Also you can use @inject.autoparams in Python 3.5, see the example above.
+@inject.params(cache=Cache, user=CurrentUser)
+def baz(foo, cache=None, user=None):
+ cache.save('foo', foo, user)
+
+# this can be called in different ways:
+# with injected arguments
+baz('foo')
+
+# with positional arguments
+baz('foo', my_cache)
+
+# with keyword arguments
+baz('foo', my_cache, user=current_user)
+
+
+# `inject.param` is deprecated, use `inject.params` instead.
+@inject.param('cache', Cache)
+def bar(foo, cache=None):
+ cache.save('foo', foo)
+
+
+# `inject.attr` creates properties (descriptors) which request dependencies on access.
+class User(object):
+ cache = inject.attr(Cache)
+
+ def __init__(self, id):
+ self.id = id
+
+ def save(self):
+ self.cache.save('users', self)
+
+ @classmethod
+ def load(cls, id):
+ return cls.cache.load('users', id)
+
+
+# Create an optional configuration.
+def my_config(binder):
+ binder.install(my_config2) # Add bindings from another config.
+ binder.bind(Cache, RedisCache('localhost:1234'))
+
+# Configure a shared injector.
+inject.configure(my_config)
+
+
+# Instantiate User as a normal class. Its `cache` dependency is injected when accessed.
+user = User(10)
+user.save()
+
+# Call the functions, the dependencies are automatically injected.
+foo('Hello')
+bar('world')
+```
+
+
+## Usage with Django
+Django can load some modules multiple times which can lead to
+`InjectorException: Injector is already configured`. You can use `configure_once` which
+is guaranteed to run only once when the injector is absent:
+```python
+import inject
+inject.configure_once(my_config)
+```
+
+## Testing
+In tests use `inject.clear_and_configure(callable)` to create a new injector on setup,
+and optionally `inject.clear()` to clean up on tear down:
+```python
+class MyTest(unittest.TestCase):
+ def setUp(self):
+ inject.clear_and_configure(lambda binder: binder
+ .bind(Cache, Mock()) \
+ .bind(Validator, TestValidator()))
+
+ def tearDown(self):
+ inject.clear()
+```
+
+## Thread-safety
+After configuration the injector is thread-safe and can be safely reused by multiple threads.
+
+## Binding types
+**Instance** bindings always return the same instance:
+
+```python
+redis = RedisCache(address='localhost:1234')
+def config(binder):
+ binder.bind(Cache, redis)
+```
+
+**Constructor** bindings create a singleton on injection:
+
+```python
+def config(binder):
+ # Creates a redis cache singleton on first injection.
+ binder.bind_to_constructor(Cache, lambda: RedisCache(address='localhost:1234'))
+```
+
+**Provider** bindings call the provider on injection:
+
+```python
+def get_my_thread_local_cache():
+ pass
+
+def config(binder):
+ # Executes the provider on each injection.
+ binder.bind_to_provider(Cache, get_my_thread_local_cache)
+```
+
+**Runtime** bindings automatically create singletons on injection, require no configuration.
+For example, only the `Config` class binding is present, other bindings are runtime:
+
+```python
+class Config(object):
+ pass
+
+class Cache(object):
+ config = inject.attr(Config)
+
+class Db(object):
+ config = inject.attr(Config)
+
+class User(object):
+ cache = inject.attr(Cache)
+ db = inject.attr(Db)
+
+ @classmethod
+ def load(cls, user_id):
+ return cls.cache.load('users', user_id) or cls.db.load('users', user_id)
+
+inject.configure(lambda binder: binder.bind(Config, load_config_file()))
+user = User.load(10)
+```
+## Disabling runtime binding
+Sometimes runtime binding leads to unexpected behaviour. Say if you forget
+to bind an instance to a class, `inject` will try to implicitly instantiate it.
+
+If an instance is unintentionally created with default arguments it may lead to
+hard-to-debug bugs. To disable runtime binding and make sure that only
+explicitly bound instances are injected, pass `bind_in_runtime=False`
+to `inject.configure`, `inject.configure_once` or `inject.clear_and_configure`.
+
+In this case `inject` immediately raises `InjectorException` when the code
+tries to get an unbound instance.
+
+## Keys
+It is possible to use any hashable object as a binding key. For example:
+
+```python
+import inject
+
+inject.configure(lambda binder: \
+ binder.bind('host', 'localhost') \
+ binder.bind('port', 1234))
+```
+
+## Why no scopes?
+I've used Guice and Spring in Java for a lot of years, and I don't like their scopes.
+`python-inject` by default creates objects as singletons. It does not need a prototype scope
+as in Spring or NO_SCOPE as in Guice because `python-inject` does not steal your class
+constructors. Create instances the way you like and then inject dependencies into them.
+
+Other scopes such as a request scope or a session scope are fragile, introduce high coupling,
+and are difficult to test. In `python-inject` write custom providers which can be thread-local,
+request-local, etc.
+
+For example, a thread-local current user provider:
+
+```python
+import inject
+import threading
+
+# Given a user class.
+class User(object):
+ pass
+
+# Create a thread-local current user storage.
+_LOCAL = threading.local()
+
+def get_current_user():
+ return getattr(_LOCAL, 'user', None)
+
+def set_current_user(user):
+ _LOCAL.user = user
+
+# Bind User to a custom provider.
+inject.configure(lambda binder: binder.bind_to_provider(User, get_current_user))
+
+# Inject the current user.
+@inject.params(user=User)
+def foo(user):
+ pass
+```
+
+## Links
+* Project: https://github.com/ivankorobkov/python-inject
+
+## License
+Apache License 2.0
+
+## Contributors
+* Ivan Korobkov [@ivankorobkov](https://github.com/ivankorobkov)
+* Jaime Wyant [@jaimewyant](https://github.com/jaimewyant)
+* Sebastian Buczyński [@Enforcer](https://github.com/Enforcer)
+* Oleksandr Fedorov [@Fedorof](https://github.com/Fedorof)
+* cselvaraj [@cselvaraj](https://github.com/cselvaraj)
+* 陆雨晴 [@SixExtreme](https://github.com/SixExtreme)
+* Andrew William Borba [@andrewborba10](https://github.com/andrewborba10)
+* jdmeyer3 [@jdmeyer3](https://github.com/jdmeyer3)
+* Alex Grover [@ajgrover](https://github.com/ajgrover)
+* Harro van der Kroft [@wisepotato](https://github.com/wisepotato)
+* Samiur Rahman [@samiur](https://github.com/samiur)
+* 45deg [@45deg](https://github.com/45deg)
+* Alexander Nicholas Costas [@ancostas](https://github.com/ancostas)
+* Dmitry Balabka [@dbalabka](https://github.com/dbalabka)
+
+%package -n python3-Inject
+Summary: Python dependency injection framework
+Provides: python-Inject
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+%description -n python3-Inject
+# python-inject [![Build Status](https://travis-ci.org/ivankorobkov/python-inject.svg?branch=master)](https://travis-ci.org/ivankorobkov/python-inject)
+Dependency injection the python way, the good way. Not a port of Guice or Spring.
+
+## Key features
+* Fast.
+* Thread-safe.
+* Simple to use.
+* Does not steal class constructors.
+* Does not try to manage your application object graph.
+* Transparently integrates into tests.
+* Supports Python 3.5+ (`v4.*`) and Python 2.7–3.5 (`v3.*`).
+* Supports type hinting in Python 3.5+.
+* Autoparams leveraging type annotations.
+
+## Python Support
+
+| Python | Inject Version |
+|--------|----------------|
+| 3.6+ | 4.1+ |
+| 3.5 | 4.0 |
+| < 3.5 | 3.* |
+
+
+## Installation
+Use pip to install the lastest version:
+
+```bash
+pip install inject
+```
+
+## Autoparams example
+`@inject.autoparams` returns a decorator which automatically injects arguments into a function
+that uses type annotations. This is supported only in Python >= 3.5.
+
+```python
+@inject.autoparams()
+def refresh_cache(cache: RedisCache, db: DbInterface):
+ pass
+```
+
+There is an option to specify which arguments we want to inject without attempts of
+injecting everything:
+
+```python
+@inject.autoparams('cache', 'db')
+def sign_up(name, email, cache: RedisCache, db: DbInterface):
+ pass
+```
+
+## Step-by-step example
+```python
+# Import the inject module.
+import inject
+
+
+# `inject.instance` requests dependencies from the injector.
+def foo(bar):
+ cache = inject.instance(Cache)
+ cache.save('bar', bar)
+
+
+# `inject.params` injects dependencies as keyword arguments or positional argument.
+# Also you can use @inject.autoparams in Python 3.5, see the example above.
+@inject.params(cache=Cache, user=CurrentUser)
+def baz(foo, cache=None, user=None):
+ cache.save('foo', foo, user)
+
+# this can be called in different ways:
+# with injected arguments
+baz('foo')
+
+# with positional arguments
+baz('foo', my_cache)
+
+# with keyword arguments
+baz('foo', my_cache, user=current_user)
+
+
+# `inject.param` is deprecated, use `inject.params` instead.
+@inject.param('cache', Cache)
+def bar(foo, cache=None):
+ cache.save('foo', foo)
+
+
+# `inject.attr` creates properties (descriptors) which request dependencies on access.
+class User(object):
+ cache = inject.attr(Cache)
+
+ def __init__(self, id):
+ self.id = id
+
+ def save(self):
+ self.cache.save('users', self)
+
+ @classmethod
+ def load(cls, id):
+ return cls.cache.load('users', id)
+
+
+# Create an optional configuration.
+def my_config(binder):
+ binder.install(my_config2) # Add bindings from another config.
+ binder.bind(Cache, RedisCache('localhost:1234'))
+
+# Configure a shared injector.
+inject.configure(my_config)
+
+
+# Instantiate User as a normal class. Its `cache` dependency is injected when accessed.
+user = User(10)
+user.save()
+
+# Call the functions, the dependencies are automatically injected.
+foo('Hello')
+bar('world')
+```
+
+
+## Usage with Django
+Django can load some modules multiple times which can lead to
+`InjectorException: Injector is already configured`. You can use `configure_once` which
+is guaranteed to run only once when the injector is absent:
+```python
+import inject
+inject.configure_once(my_config)
+```
+
+## Testing
+In tests use `inject.clear_and_configure(callable)` to create a new injector on setup,
+and optionally `inject.clear()` to clean up on tear down:
+```python
+class MyTest(unittest.TestCase):
+ def setUp(self):
+ inject.clear_and_configure(lambda binder: binder
+ .bind(Cache, Mock()) \
+ .bind(Validator, TestValidator()))
+
+ def tearDown(self):
+ inject.clear()
+```
+
+## Thread-safety
+After configuration the injector is thread-safe and can be safely reused by multiple threads.
+
+## Binding types
+**Instance** bindings always return the same instance:
+
+```python
+redis = RedisCache(address='localhost:1234')
+def config(binder):
+ binder.bind(Cache, redis)
+```
+
+**Constructor** bindings create a singleton on injection:
+
+```python
+def config(binder):
+ # Creates a redis cache singleton on first injection.
+ binder.bind_to_constructor(Cache, lambda: RedisCache(address='localhost:1234'))
+```
+
+**Provider** bindings call the provider on injection:
+
+```python
+def get_my_thread_local_cache():
+ pass
+
+def config(binder):
+ # Executes the provider on each injection.
+ binder.bind_to_provider(Cache, get_my_thread_local_cache)
+```
+
+**Runtime** bindings automatically create singletons on injection, require no configuration.
+For example, only the `Config` class binding is present, other bindings are runtime:
+
+```python
+class Config(object):
+ pass
+
+class Cache(object):
+ config = inject.attr(Config)
+
+class Db(object):
+ config = inject.attr(Config)
+
+class User(object):
+ cache = inject.attr(Cache)
+ db = inject.attr(Db)
+
+ @classmethod
+ def load(cls, user_id):
+ return cls.cache.load('users', user_id) or cls.db.load('users', user_id)
+
+inject.configure(lambda binder: binder.bind(Config, load_config_file()))
+user = User.load(10)
+```
+## Disabling runtime binding
+Sometimes runtime binding leads to unexpected behaviour. Say if you forget
+to bind an instance to a class, `inject` will try to implicitly instantiate it.
+
+If an instance is unintentionally created with default arguments it may lead to
+hard-to-debug bugs. To disable runtime binding and make sure that only
+explicitly bound instances are injected, pass `bind_in_runtime=False`
+to `inject.configure`, `inject.configure_once` or `inject.clear_and_configure`.
+
+In this case `inject` immediately raises `InjectorException` when the code
+tries to get an unbound instance.
+
+## Keys
+It is possible to use any hashable object as a binding key. For example:
+
+```python
+import inject
+
+inject.configure(lambda binder: \
+ binder.bind('host', 'localhost') \
+ binder.bind('port', 1234))
+```
+
+## Why no scopes?
+I've used Guice and Spring in Java for a lot of years, and I don't like their scopes.
+`python-inject` by default creates objects as singletons. It does not need a prototype scope
+as in Spring or NO_SCOPE as in Guice because `python-inject` does not steal your class
+constructors. Create instances the way you like and then inject dependencies into them.
+
+Other scopes such as a request scope or a session scope are fragile, introduce high coupling,
+and are difficult to test. In `python-inject` write custom providers which can be thread-local,
+request-local, etc.
+
+For example, a thread-local current user provider:
+
+```python
+import inject
+import threading
+
+# Given a user class.
+class User(object):
+ pass
+
+# Create a thread-local current user storage.
+_LOCAL = threading.local()
+
+def get_current_user():
+ return getattr(_LOCAL, 'user', None)
+
+def set_current_user(user):
+ _LOCAL.user = user
+
+# Bind User to a custom provider.
+inject.configure(lambda binder: binder.bind_to_provider(User, get_current_user))
+
+# Inject the current user.
+@inject.params(user=User)
+def foo(user):
+ pass
+```
+
+## Links
+* Project: https://github.com/ivankorobkov/python-inject
+
+## License
+Apache License 2.0
+
+## Contributors
+* Ivan Korobkov [@ivankorobkov](https://github.com/ivankorobkov)
+* Jaime Wyant [@jaimewyant](https://github.com/jaimewyant)
+* Sebastian Buczyński [@Enforcer](https://github.com/Enforcer)
+* Oleksandr Fedorov [@Fedorof](https://github.com/Fedorof)
+* cselvaraj [@cselvaraj](https://github.com/cselvaraj)
+* 陆雨晴 [@SixExtreme](https://github.com/SixExtreme)
+* Andrew William Borba [@andrewborba10](https://github.com/andrewborba10)
+* jdmeyer3 [@jdmeyer3](https://github.com/jdmeyer3)
+* Alex Grover [@ajgrover](https://github.com/ajgrover)
+* Harro van der Kroft [@wisepotato](https://github.com/wisepotato)
+* Samiur Rahman [@samiur](https://github.com/samiur)
+* 45deg [@45deg](https://github.com/45deg)
+* Alexander Nicholas Costas [@ancostas](https://github.com/ancostas)
+* Dmitry Balabka [@dbalabka](https://github.com/dbalabka)
+
+%package help
+Summary: Development documents and examples for Inject
+Provides: python3-Inject-doc
+%description help
+# python-inject [![Build Status](https://travis-ci.org/ivankorobkov/python-inject.svg?branch=master)](https://travis-ci.org/ivankorobkov/python-inject)
+Dependency injection the python way, the good way. Not a port of Guice or Spring.
+
+## Key features
+* Fast.
+* Thread-safe.
+* Simple to use.
+* Does not steal class constructors.
+* Does not try to manage your application object graph.
+* Transparently integrates into tests.
+* Supports Python 3.5+ (`v4.*`) and Python 2.7–3.5 (`v3.*`).
+* Supports type hinting in Python 3.5+.
+* Autoparams leveraging type annotations.
+
+## Python Support
+
+| Python | Inject Version |
+|--------|----------------|
+| 3.6+ | 4.1+ |
+| 3.5 | 4.0 |
+| < 3.5 | 3.* |
+
+
+## Installation
+Use pip to install the lastest version:
+
+```bash
+pip install inject
+```
+
+## Autoparams example
+`@inject.autoparams` returns a decorator which automatically injects arguments into a function
+that uses type annotations. This is supported only in Python >= 3.5.
+
+```python
+@inject.autoparams()
+def refresh_cache(cache: RedisCache, db: DbInterface):
+ pass
+```
+
+There is an option to specify which arguments we want to inject without attempts of
+injecting everything:
+
+```python
+@inject.autoparams('cache', 'db')
+def sign_up(name, email, cache: RedisCache, db: DbInterface):
+ pass
+```
+
+## Step-by-step example
+```python
+# Import the inject module.
+import inject
+
+
+# `inject.instance` requests dependencies from the injector.
+def foo(bar):
+ cache = inject.instance(Cache)
+ cache.save('bar', bar)
+
+
+# `inject.params` injects dependencies as keyword arguments or positional argument.
+# Also you can use @inject.autoparams in Python 3.5, see the example above.
+@inject.params(cache=Cache, user=CurrentUser)
+def baz(foo, cache=None, user=None):
+ cache.save('foo', foo, user)
+
+# this can be called in different ways:
+# with injected arguments
+baz('foo')
+
+# with positional arguments
+baz('foo', my_cache)
+
+# with keyword arguments
+baz('foo', my_cache, user=current_user)
+
+
+# `inject.param` is deprecated, use `inject.params` instead.
+@inject.param('cache', Cache)
+def bar(foo, cache=None):
+ cache.save('foo', foo)
+
+
+# `inject.attr` creates properties (descriptors) which request dependencies on access.
+class User(object):
+ cache = inject.attr(Cache)
+
+ def __init__(self, id):
+ self.id = id
+
+ def save(self):
+ self.cache.save('users', self)
+
+ @classmethod
+ def load(cls, id):
+ return cls.cache.load('users', id)
+
+
+# Create an optional configuration.
+def my_config(binder):
+ binder.install(my_config2) # Add bindings from another config.
+ binder.bind(Cache, RedisCache('localhost:1234'))
+
+# Configure a shared injector.
+inject.configure(my_config)
+
+
+# Instantiate User as a normal class. Its `cache` dependency is injected when accessed.
+user = User(10)
+user.save()
+
+# Call the functions, the dependencies are automatically injected.
+foo('Hello')
+bar('world')
+```
+
+
+## Usage with Django
+Django can load some modules multiple times which can lead to
+`InjectorException: Injector is already configured`. You can use `configure_once` which
+is guaranteed to run only once when the injector is absent:
+```python
+import inject
+inject.configure_once(my_config)
+```
+
+## Testing
+In tests use `inject.clear_and_configure(callable)` to create a new injector on setup,
+and optionally `inject.clear()` to clean up on tear down:
+```python
+class MyTest(unittest.TestCase):
+ def setUp(self):
+ inject.clear_and_configure(lambda binder: binder
+ .bind(Cache, Mock()) \
+ .bind(Validator, TestValidator()))
+
+ def tearDown(self):
+ inject.clear()
+```
+
+## Thread-safety
+After configuration the injector is thread-safe and can be safely reused by multiple threads.
+
+## Binding types
+**Instance** bindings always return the same instance:
+
+```python
+redis = RedisCache(address='localhost:1234')
+def config(binder):
+ binder.bind(Cache, redis)
+```
+
+**Constructor** bindings create a singleton on injection:
+
+```python
+def config(binder):
+ # Creates a redis cache singleton on first injection.
+ binder.bind_to_constructor(Cache, lambda: RedisCache(address='localhost:1234'))
+```
+
+**Provider** bindings call the provider on injection:
+
+```python
+def get_my_thread_local_cache():
+ pass
+
+def config(binder):
+ # Executes the provider on each injection.
+ binder.bind_to_provider(Cache, get_my_thread_local_cache)
+```
+
+**Runtime** bindings automatically create singletons on injection, require no configuration.
+For example, only the `Config` class binding is present, other bindings are runtime:
+
+```python
+class Config(object):
+ pass
+
+class Cache(object):
+ config = inject.attr(Config)
+
+class Db(object):
+ config = inject.attr(Config)
+
+class User(object):
+ cache = inject.attr(Cache)
+ db = inject.attr(Db)
+
+ @classmethod
+ def load(cls, user_id):
+ return cls.cache.load('users', user_id) or cls.db.load('users', user_id)
+
+inject.configure(lambda binder: binder.bind(Config, load_config_file()))
+user = User.load(10)
+```
+## Disabling runtime binding
+Sometimes runtime binding leads to unexpected behaviour. Say if you forget
+to bind an instance to a class, `inject` will try to implicitly instantiate it.
+
+If an instance is unintentionally created with default arguments it may lead to
+hard-to-debug bugs. To disable runtime binding and make sure that only
+explicitly bound instances are injected, pass `bind_in_runtime=False`
+to `inject.configure`, `inject.configure_once` or `inject.clear_and_configure`.
+
+In this case `inject` immediately raises `InjectorException` when the code
+tries to get an unbound instance.
+
+## Keys
+It is possible to use any hashable object as a binding key. For example:
+
+```python
+import inject
+
+inject.configure(lambda binder: \
+ binder.bind('host', 'localhost') \
+ binder.bind('port', 1234))
+```
+
+## Why no scopes?
+I've used Guice and Spring in Java for a lot of years, and I don't like their scopes.
+`python-inject` by default creates objects as singletons. It does not need a prototype scope
+as in Spring or NO_SCOPE as in Guice because `python-inject` does not steal your class
+constructors. Create instances the way you like and then inject dependencies into them.
+
+Other scopes such as a request scope or a session scope are fragile, introduce high coupling,
+and are difficult to test. In `python-inject` write custom providers which can be thread-local,
+request-local, etc.
+
+For example, a thread-local current user provider:
+
+```python
+import inject
+import threading
+
+# Given a user class.
+class User(object):
+ pass
+
+# Create a thread-local current user storage.
+_LOCAL = threading.local()
+
+def get_current_user():
+ return getattr(_LOCAL, 'user', None)
+
+def set_current_user(user):
+ _LOCAL.user = user
+
+# Bind User to a custom provider.
+inject.configure(lambda binder: binder.bind_to_provider(User, get_current_user))
+
+# Inject the current user.
+@inject.params(user=User)
+def foo(user):
+ pass
+```
+
+## Links
+* Project: https://github.com/ivankorobkov/python-inject
+
+## License
+Apache License 2.0
+
+## Contributors
+* Ivan Korobkov [@ivankorobkov](https://github.com/ivankorobkov)
+* Jaime Wyant [@jaimewyant](https://github.com/jaimewyant)
+* Sebastian Buczyński [@Enforcer](https://github.com/Enforcer)
+* Oleksandr Fedorov [@Fedorof](https://github.com/Fedorof)
+* cselvaraj [@cselvaraj](https://github.com/cselvaraj)
+* 陆雨晴 [@SixExtreme](https://github.com/SixExtreme)
+* Andrew William Borba [@andrewborba10](https://github.com/andrewborba10)
+* jdmeyer3 [@jdmeyer3](https://github.com/jdmeyer3)
+* Alex Grover [@ajgrover](https://github.com/ajgrover)
+* Harro van der Kroft [@wisepotato](https://github.com/wisepotato)
+* Samiur Rahman [@samiur](https://github.com/samiur)
+* 45deg [@45deg](https://github.com/45deg)
+* Alexander Nicholas Costas [@ancostas](https://github.com/ancostas)
+* Dmitry Balabka [@dbalabka](https://github.com/dbalabka)
+
+%prep
+%autosetup -n Inject-4.3.1
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-Inject -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Sat Feb 25 2023 Python_Bot <Python_Bot@openeuler.org> - 4.3.1-1
+- Package Spec generated
diff --git a/sources b/sources
new file mode 100644
index 0000000..06279b7
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+a674cbdb5df1e1020a5ea30c692e4b5f Inject-4.3.1.tar.gz