thinking-injection


Namethinking-injection JSON
Version 0.0.1 PyPI version JSON
download
home_pageNone
SummaryDI framework
upload_time2024-09-08 22:15:01
maintainerNone
docs_urlNone
authorNone
requires_python>=3.12
licenseMIT License Copyright (c) 2024 Filip Malczak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords thinking dependency injection di
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # thinking-injection

[![CI](https://github.com/FilipMalczak/thinking-injection/actions/workflows/ci.yml/badge.svg)](https://github.com/FilipMalczak/thinking-injection/actions/workflows/ci.yml)
[![PyPI version](https://badge.fury.io/py/thinking-injection.svg)](https://badge.fury.io/py/thinking-injection)
[![codecov](https://codecov.io/github/FilipMalczak/thinking-injection/graph/badge.svg?token=X5HGHMQXAP)](https://codecov.io/github/FilipMalczak/thinking-injection)

> Part of [thinking](https://github.com/search?q=owner%3AFilipMalczak+thinking&type=repositories) family.

Pythonic DI for AI, as funny as it sounds.

> Requires python 3.12. Is properly typed.

> Better docs pending. For now, see "long story short" and an example

## Long story short

 - put your code in a root package (let's call it `root`) with any number and depth of subpackages
 - mark the types that should be picked up by framework with `@discover`
   - `from thinking_injection.discovery import discover`
 - mark your protocols and ABCs with `@interface`
   - `from thinking_injection.interfaces import interface`
 - make the classes that should be managed extend `Injectable`
   - in Java you'd call these "beans", but I wanted to avoid that kind of copycating
   - `from thinking_injection.injectable import Injectable`
 - implement `inject_requirements(self, ...)` and make sure to annotate the arguments
   - `class X(Injectable): def inject_requirements(self, a: A, b: list[B], c: C | None: ...`
   - in that case, instance of `X` will be created for you, and that method will be called with auto-created instances
     of `A`, list of all known instances of `B` and instance of `C` if there is one
   - `A` is a `SIMPLE` dependency, `B` - a `COLLECTIVE` one, `C` - an optional one
   - there is a notion of `primary` implementation, which works as you'd expect it (the type itself for non-interface
     types, the subclass if there is only one subclass, but you can also force one, e.g. with decorator)
     - see ['Implementations.build(...)'](./thinking_injection/implementations.py)
     - `from thinking_injection.discovery import PrimaryImplementation` - use `@PrimaryImplementation(Supertype)` on the subtype
   - simple dependencies will use the primary implementation
   - optional dependencies can be phrased any way you like: `C | None`, `Optional[C]` or `Union[C, None]`, etc
     - if there is no primary implementation, `None` will be injected, even if there are multiple implementations
   - collective dependencies can only be phrased as lists of supertype (interface or not) 
   - framework will only call that method for you with proper args, you should store them in `self` on your own - or
     act on them in any way you'd like
 - make a `ContextScope` using `of` factory method:
   - `from thinking_injection.scope import ContextScope`
   - `ContextScope.of(*from_package("root"))`
   - more readable factory methods pending
   - generally, it's `ContextScope.of(Type1, Type2, ...)`
   - you can also define which implementations should be primary with `defaults` and `forced` kw-only args
     - > todo document this
   - there is also `from_module("root.some.submodule")` function, as well as `types(Type1, Type2, ...)`
   - see [`thinking_injection.typeset`](./thinking_injection/typeset.py)

The entrypoint to your program should boil down to:

```python
if __name__=="__main__":
    scope = ContextScope.of(...)
    ctx = BasicContext.build(scope)
    with ctx.lifecycle():
        instance = ctx.instance(SomeType)
        instance.foo(...)
```

## An example

There is an example app in this repo. It's short, but showcases most of the basic features.

See the [./calculator](./calculator/README.md) directory.

## Local development

There are 2 useful scripts in this repo. They both work based on [`./thinking-dependencies.txt`](./thinking-dependencies.txt)
file, which lists other `thinking` projects used by this one.

 - [`install_develop.sh`](./install_develop.sh)
   - will install all the `thinking` dependencies from their `develop` branches
 - [`./install_local_thinking.sh`](./install_local_thinking.sh)
   - aligned to my personal layout of home directory
   - assumes you clone repositories to `~/repos`
   - expects all the `thinking` dependencies to be cloned there
   - will create venv for you if missing or use an existing one
   - will remove currently installed `thinking` dependencies
   - and will install them again from the cloned repos
   - useful when you're making complimentary changes across repos

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "thinking-injection",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": null,
    "keywords": "thinking, dependency, injection, di",
    "author": null,
    "author_email": "Filip Malczak <filip.malczak@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/e2/4a/245bb1a49d96afcde5f10ffdb45df7558e9b19d25cb0da7bc40f2f40533a/thinking_injection-0.0.1.tar.gz",
    "platform": null,
    "description": "# thinking-injection\n\n[![CI](https://github.com/FilipMalczak/thinking-injection/actions/workflows/ci.yml/badge.svg)](https://github.com/FilipMalczak/thinking-injection/actions/workflows/ci.yml)\n[![PyPI version](https://badge.fury.io/py/thinking-injection.svg)](https://badge.fury.io/py/thinking-injection)\n[![codecov](https://codecov.io/github/FilipMalczak/thinking-injection/graph/badge.svg?token=X5HGHMQXAP)](https://codecov.io/github/FilipMalczak/thinking-injection)\n\n> Part of [thinking](https://github.com/search?q=owner%3AFilipMalczak+thinking&type=repositories) family.\n\nPythonic DI for AI, as funny as it sounds.\n\n> Requires python 3.12. Is properly typed.\n\n> Better docs pending. For now, see \"long story short\" and an example\n\n## Long story short\n\n - put your code in a root package (let's call it `root`) with any number and depth of subpackages\n - mark the types that should be picked up by framework with `@discover`\n   - `from thinking_injection.discovery import discover`\n - mark your protocols and ABCs with `@interface`\n   - `from thinking_injection.interfaces import interface`\n - make the classes that should be managed extend `Injectable`\n   - in Java you'd call these \"beans\", but I wanted to avoid that kind of copycating\n   - `from thinking_injection.injectable import Injectable`\n - implement `inject_requirements(self, ...)` and make sure to annotate the arguments\n   - `class X(Injectable): def inject_requirements(self, a: A, b: list[B], c: C | None: ...`\n   - in that case, instance of `X` will be created for you, and that method will be called with auto-created instances\n     of `A`, list of all known instances of `B` and instance of `C` if there is one\n   - `A` is a `SIMPLE` dependency, `B` - a `COLLECTIVE` one, `C` - an optional one\n   - there is a notion of `primary` implementation, which works as you'd expect it (the type itself for non-interface\n     types, the subclass if there is only one subclass, but you can also force one, e.g. with decorator)\n     - see ['Implementations.build(...)'](./thinking_injection/implementations.py)\n     - `from thinking_injection.discovery import PrimaryImplementation` - use `@PrimaryImplementation(Supertype)` on the subtype\n   - simple dependencies will use the primary implementation\n   - optional dependencies can be phrased any way you like: `C | None`, `Optional[C]` or `Union[C, None]`, etc\n     - if there is no primary implementation, `None` will be injected, even if there are multiple implementations\n   - collective dependencies can only be phrased as lists of supertype (interface or not) \n   - framework will only call that method for you with proper args, you should store them in `self` on your own - or\n     act on them in any way you'd like\n - make a `ContextScope` using `of` factory method:\n   - `from thinking_injection.scope import ContextScope`\n   - `ContextScope.of(*from_package(\"root\"))`\n   - more readable factory methods pending\n   - generally, it's `ContextScope.of(Type1, Type2, ...)`\n   - you can also define which implementations should be primary with `defaults` and `forced` kw-only args\n     - > todo document this\n   - there is also `from_module(\"root.some.submodule\")` function, as well as `types(Type1, Type2, ...)`\n   - see [`thinking_injection.typeset`](./thinking_injection/typeset.py)\n\nThe entrypoint to your program should boil down to:\n\n```python\nif __name__==\"__main__\":\n    scope = ContextScope.of(...)\n    ctx = BasicContext.build(scope)\n    with ctx.lifecycle():\n        instance = ctx.instance(SomeType)\n        instance.foo(...)\n```\n\n## An example\n\nThere is an example app in this repo. It's short, but showcases most of the basic features.\n\nSee the [./calculator](./calculator/README.md) directory.\n\n## Local development\n\nThere are 2 useful scripts in this repo. They both work based on [`./thinking-dependencies.txt`](./thinking-dependencies.txt)\nfile, which lists other `thinking` projects used by this one.\n\n - [`install_develop.sh`](./install_develop.sh)\n   - will install all the `thinking` dependencies from their `develop` branches\n - [`./install_local_thinking.sh`](./install_local_thinking.sh)\n   - aligned to my personal layout of home directory\n   - assumes you clone repositories to `~/repos`\n   - expects all the `thinking` dependencies to be cloned there\n   - will create venv for you if missing or use an existing one\n   - will remove currently installed `thinking` dependencies\n   - and will install them again from the cloned repos\n   - useful when you're making complimentary changes across repos\n",
    "bugtrack_url": null,
    "license": "MIT License  Copyright (c) 2024 Filip Malczak  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ",
    "summary": "DI framework",
    "version": "0.0.1",
    "project_urls": {
        "Homepage": "https://github.com/FilipMalczak/thinking-injection"
    },
    "split_keywords": [
        "thinking",
        " dependency",
        " injection",
        " di"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "68fef82fef969e7d7ab3cacc6ae0ca7a43f2ad0bec77fdcf5b7f4fdc352029d1",
                "md5": "5b970817079329500fa9001b52f11d6d",
                "sha256": "0de444a031ec1d399b766da9f863244275633394397c0df299c57cb3aeb23cc2"
            },
            "downloads": -1,
            "filename": "thinking_injection-0.0.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "5b970817079329500fa9001b52f11d6d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 19602,
            "upload_time": "2024-09-08T22:15:00",
            "upload_time_iso_8601": "2024-09-08T22:15:00.387512Z",
            "url": "https://files.pythonhosted.org/packages/68/fe/f82fef969e7d7ab3cacc6ae0ca7a43f2ad0bec77fdcf5b7f4fdc352029d1/thinking_injection-0.0.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e24a245bb1a49d96afcde5f10ffdb45df7558e9b19d25cb0da7bc40f2f40533a",
                "md5": "8493f38d21fc665caf3f3eb5ecffbf4f",
                "sha256": "b54864f6e155c9541c8ca3085dfa4ab9587dd0880fc6e685896c11b1e58519de"
            },
            "downloads": -1,
            "filename": "thinking_injection-0.0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "8493f38d21fc665caf3f3eb5ecffbf4f",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 16661,
            "upload_time": "2024-09-08T22:15:01",
            "upload_time_iso_8601": "2024-09-08T22:15:01.563218Z",
            "url": "https://files.pythonhosted.org/packages/e2/4a/245bb1a49d96afcde5f10ffdb45df7558e9b19d25cb0da7bc40f2f40533a/thinking_injection-0.0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-09-08 22:15:01",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "FilipMalczak",
    "github_project": "thinking-injection",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "thinking-injection"
}
        
Elapsed time: 3.73123s