معرفی شرکت ها


conject-0.4.0


Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر
Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر
Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر
Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر
Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر

توضیحات

Dependency Injection and configuration library.
ویژگی مقدار
سیستم عامل -
نام فایل conject-0.4.0
نام conject
نسخه کتابخانه 0.4.0
نگهدارنده []
ایمیل نگهدارنده []
نویسنده xppt
ایمیل نویسنده 21246102+xppt@users.noreply.github.com
آدرس صفحه اصلی https://github.com/xppt/py-conject
آدرس اینترنتی https://pypi.org/project/conject/
مجوز -
Conject === This library automates DI - allowing to create dependencies by its declarative description. Features: - Creates application components hierarchy automatically. - Eliminates the need to implemenent config files support - allows you to configure any application component out of the box, select implementations and link them together. - Makes it easy to finalize components. - Supports synchronous and asynchronous interfaces. - Doesn't require components code modification (assuming they are written in DI-compatible style). Example --- Let's assume we have a simple http service: ```python class HttpClient(abc.ABC): @abc.abstractmethod def request(self, method: str, url: str): raise NotImplementedError class MockHttpClient(HttpClient): def request(self, method: str, url: str): ... # return fake response class PooledHttpClient(HttpClient): def __init__(self, proxy: str, user_agent: str): ... def request(self, method: str, url: str): ... def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): ... # cleanup class FbApiClient: def __init__(self, http_client: HttpClient, access_token: str, api_ver: str): ... def get_user_info(self, user_id: str) -> dict: ... # use HttpClient to fetch user info class FetchFbUserHandler: def __init__(self, fb_api_client: FbApiClient): ... def __call__(self, req): ... # use FbApiClient.get_user_info and return def create_http_app(fetch_fb_user_handler: FetchFbUserHandler): http_app = HttpApp([ ('GET', '/fetch_fb_user/', fetch_fb_user_handler), ]) return http_app ``` In order to fully construct our HttpApp we need to: - Add config option to choose HttpClient implementation. - Use `ExitStack` since `PooledHttpClient` is a context manager (while `MockHttpClient` isn't). - Add config options for `proxy`, `user_agent`, `access_token`, `api_ver` parameters. **conject** lets you avoid doing it manually. ```python from conject import DepSpec, Impl def run(config: dict) -> None: spec = DepSpec([ Impl(Impl.Func, 'http_app', create_http_app), Impl(Impl.CtxMgr, 'pooled_http_client', PooledHttpClient), Impl(Impl.Class, 'mock_http_client', MockHttpClient), Impl(Impl.Class, 'fb_api_client', FbApiClient), Impl(Impl.Class, 'fetch_fb_user_handler', FetchFbUserHandler), ]) with spec.start_container(config) as container: # get or create component with name 'http_app' # expected type is optional, but allows type-checking http_app = container.get('http_app', HttpApp) ... # run_http_app(http_app) ``` Now we are able to control our components via configuration (formatted as toml for example): ```toml [http_client] # component name, can be anything -impl = 'pooled_http_client' # use implementation named 'pooled_http_client' user_agent = 'super-app/10' # implementation params [fb_api_client] access_token = 'abcdefgh' api_ver = '7.0' ``` Another possible config: ```toml [proxied_http_client] -impl = 'pooled_http_client' proxy = 'my-squid:3128' [proxied_fb_api_client] -impl = 'fb_api_client' http_client = {-ref = 'proxied_http_client'} # use component named 'proxied_http_client' access_token = 'fake_token' api_ver = '7.0' [http_app] fb_api_client = {-ref = 'proxied_fb_api_client'} ``` **conject** allows some configuration parts to be omitted: - If your component name matches implementation name component's `-impl` property can be omitted. - You can omit implementation parameter. It will receive: - default value, if there is one in the factory signature; - component with the same name; - If there is no need to set any of component's properties you can omit it completely. Registering implementations --- Factory types: - `FactoryType.Value` - just value. - `FactoryType.Func` - function returning implementation. - `FactoryType.Class` - implementation-class. - `FactoryType.GenFunc` - function generating implementation that can finalize it afterwards. - `FactoryType.CtxMgr` - implementation context manager. - `FactoryType.AFunc` - like `Func`, but async. - `FactoryType.AGenFunc` - like `GenFunc`, but async. - `FactoryType.ACtxMgr` - like `CtxMgr`, but async. Factory can receive any parameters except for variadic (`*args`, `**kwargs`) and _positional-only_. To register your implementations you need to create `DepSpec` (or `AsyncDepSpec`) object. Registration ways: ```python from conject import DepSpec, Impl spec = DepSpec() # you can pass impls to __init__ spec.add(Impl.CtxMgr, 'some_cls', SomeCls) spec.add_many([ Impl(Impl.GenFunc, 'some_gen_func', some_gen_func), ]) @spec.decorate(Impl.Func) def some_func(some_cls: SomeCls): return 1 ``` Creating a container --- To create a container you need to enter context `spec.start_container(config: Any)`, where `config` will be used to configure components. Example: ```python def run(spec: DepSpec) -> None: config = {'auth_provider': {'-impl': 'google_auth_provider'}} with spec.start_container(config) as container: auth_provider = container.get('auth_provider') assert isinstance(auth_provider, GoogleAuthProvider) ``` Using a container --- Dependency container lazily creates components and manages their lifetime. `def conject.Container.get(component_name: str) -> Any` `async def conject.AsyncContainer.get(component_name: str) -> Any` You can fetch any component by calling `get`. It will create every component dependency during this call. These created objects will be finalized after `spec.start_container()` context exit only. The order of finalization will be the reversed order of their creation. Usually you will need only one container that runs for a whole program lifetime. Components configuration --- Config should be a dict in which every key describes one component. Value is also a dict with options: - `-impl` is a special option, it allows you to select implementation name for this component. It could be omitted. - All other options represents factory parameters. Besides simple values, you can use special ones: - `{'-ref': '<component_name>'}` Pass another component by its name. - `{'-expr': '<expression>'}` Pass result of evaluation of python-expression. The expression may depend on other components from `refs` namespace, e.g. `refs.other_component`. Example: ```python import os spec.add(Impl.Value, 'environ', os.environ) spec.add(Impl.Class, 'fb_api_client', FbApiClient) ``` Config (formatted as toml): ```toml [fb_api_client] access_token = {-expr = 'refs.environ["FB_API_ACCESS_TOKEN"]'} ``` Special options `-ref`/`-expr` can also be used inside lists and dicts (including nested). Type checking --- In case your factories are type-annotated, **conject** will check its parameters in runtime. This is done via **pydantic** library. Also this allows you to pass e.g. `datetime` param from your toml configuration. To get the list of supported types see [pydantic docs](https://pydantic-docs.helpmanual.io/usage/types/). **Caveat**: your mutable parameter values (including dict/list/dataclass instances) will be rebuilt from scratch, so you may not receive the same instance you've expected. Utils --- `def conject.utils.load_package_recursively(package_name: str) -> None` Recursively import all package's modules. Doesn't handle namespace packages for now. `def conject.utils.skip_type_check(value: Any) -> SkipTypeCheck` Ask conject to assume this value is correct as any param type.


نیازمندی

مقدار نام
- async-exit-stack
- async-generator
- pydantic


زبان مورد نیاز

مقدار نام
>=3.6,<4.0 Python


نحوه نصب


نصب پکیج whl conject-0.4.0:

    pip install conject-0.4.0.whl


نصب پکیج tar.gz conject-0.4.0:

    pip install conject-0.4.0.tar.gz