autoload-module


Nameautoload-module JSON
Version 2.0.0 PyPI version JSON
download
home_pagehttps://github.com/hiroki0525/autoload_module
SummaryPython Autoload Module
upload_time2023-06-16 07:17:13
maintainerHiroki Miyaji
docs_urlNone
authorHiroki Miyaji
requires_python>=3.8,<4.0
licenseMIT
keywords python import autoload autoload_module metaprogramming dynamic import
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # autoload_module
[![PyPI version](https://badge.fury.io/py/autoload-module.svg)](https://badge.fury.io/py/autoload-module)
[![Test](https://github.com/hiroki0525/autoload_module/actions/workflows/test.yml/badge.svg)](https://github.com/hiroki0525/autoload_module/actions/workflows/test.yml)
[![Downloads](https://pepy.tech/badge/autoload-module)](https://pepy.tech/project/autoload-module)
<img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat" alt="MIT License image">

This library will give you comfortable Python metaprogramming.  
The following is a plain example.

- Directory
```
project/
 ├ example.py
 └ validator/
   ├ validator_a.py
   ├ validator_b.py
   └ validator_c.py
```
- example.py
```python
from autoload import ModuleLoader

input = "foo bar baz"
loader = ModuleLoader()

# Automatically import modules and return class objects
validator_classes = loader.load_classes("validator")
try:
    # initialize and execute method
    [clazz().validate(input) for clazz in validator_classes]
except:
    print("input is invalid!!")
```
## Install
```
pip install autoload-module
```
## Usage
### Constructor
```
ModuleLoader(
  base_path: Optional[str] = None,
  strict: bool = False
)
```
The ModuleLoader can be generated with no parameters.
In that case, the instance has the absolute path where
it was initialized.  
- Directory
```
/usr/local/src/project/
  ├ example.py
  └ validator/
    ├ validator_a.py
    ├ validator_b.py
    └ validator_c.py
```
- example.py
```python
from autoload import ModuleLoader

# The instance has '/usr/local/src/project/'
loader = ModuleLoader()

# load modules in the directory; '/usr/local/src/project/validator/'
validator_classes = loader.load_classes("validator")
```
If you want to change the base path, you must generate the ModuleLoader with an absolute path parameter.
```python
loader = ModuleLoader('/user/local/src/custom')
```

About strict parameter, please see [here](#NOTE) .

You can also create global setting and initialize singleton object.
```python
from autoload import ModuleLoader
import os

# global setting
ModuleLoader.set_setting(base_path=os.getcwd(), strict=True)

loader_a = ModuleLoader()
loader_b = ModuleLoader()

print(loader_a.base_path)
# -> /Users/user1/abc
print(loader_b.base_path)
# -> /Users/user1/abc

# singleton setting
ModuleLoader.set_setting(singleton=True)

loader_c = ModuleLoader()
loader_d = ModuleLoader()
loader_e = ModuleLoader('/test')

assert loader_c is loader_d # OK
assert loader_c is loader_e # OK

# The base_path is '/Users/user1/abc'
assert loader_c.base_path is loader_e.base_path # OK
```

### Methods
#### load_classes
```
load_classes(
    src: str,
    excludes: Iterable[str] = (),
    recursive: bool = False,
) -> Tuple[Type, ...]:
```
This method read the Python package or module and return the tuple of class objects.

- Directory
```
pkg/
 ├ example.py
 ├ __init__.py
 ├ config.yaml
 └ main/
     ├ validator_a.py
     ├ validator_b.py
     ├ validator_c.py
     └ sub/
        ├ validator_d.py
        └ validator_e.py
```
- validator_a.py
```python
class ValidatorA:
    def validate(self):
        print("validateA!!")
```
- example.py
```python
loader = ModuleLoader()

# Automatically read modules without '__init__.py', not py file, and this file.
# return the tuple of ValidateA, ValidatorB, and ValidatorC class objects
validator_classes = loader.load_classes("main")

# initialize and execute method
[clazz().validate() for clazz in validator_classes]
# -> validateA!!
# -> validateB!!
# -> validateC!!
```
You can also load only specific modules using `excludes` variable or `load_config` decorator as below.
```python
# Pattern1: 'excludes'
# 'excludes' is a iterable object like tuple, list.
# You must specify module names in 'excludes'.
validator_classes = loader.load_classes("main", ["validator_a"])

[clazz().validate() for clazz in validator_classes]
# -> validateB!!
# -> validateC!!

# Pattern2: 'load_config'
from autoload import load_config

@load_config(load=False)
class ValidatorA:
  def validate(self):
    print("validateA!!")

validator_classes = loader.load_classes("main")

[clazz().validate() for clazz in validator_classes]
# -> validateB!!
# -> validateC!!
```
This function will check directory structure recursively if you specify `recursive=True`. 
```python
# 'recursive=False' is default.
# In this case, the loader will also check 'pkg/main/sub/'.
validator_classes = loader.load_classes("main", recursive=True)

[clazz().validate() for clazz in validator_classes]
# -> validateA!!
# -> validateB!!
# -> validateC!!
# -> validateD!!
# -> validateE!!
```
You can specify `src` as below.
```python
loader.load_classes("main/validator_a.py")
loader.load_classes("main.validator_a")
loader.load_classes("./main/validator_a")
loader.load_classes(".main.validator_a")
loader.load_classes("main.sub.validator_d")
loader.load_classes("./main/sub/validator_d")
loader.load_classes("../otherpkg")
loader.load_classes("..otherpkg")
```

#### load_functions
```
load_functions(
    src: str,
    excludes: Iterable[str] = (),
    recursive: bool = False,
) -> Tuple[Callable, ...]:
```
This method read the Python package or module and return the tuple of functions.
The usage is the same as `load_classes`.

##### NOTE
- To search class or function, **You must match the name of file, and the one of class or function.**
For example, if you named the file `test_module.py`, you must name the class `TestModule` or the function `test_module`.
When you want to customize their name, use `@load_config` decorator.
    - validator_a.py
    ```python
    from autoload import load_config
  
    @load_config()
    class CustomValidator:
        def validate(self):
            print("validateA!!")
    ```
- You can also control the order of loaded class objects using `@load_config` decorator.
    - validator_a.py
    ```python
    from autoload import load_config
  
    # sort in ascending order
    @load_config(order=1)
    class ValidatorA:
        def validate(self):
            print("validateA!!")
    ```
- If you decorate some classes or functions with `@load_config`, the loader will load them.
  However, initialized `strict=True`, the loader denies multiple loading as below.
  - pkg/validator_a.py
  ```python
  from autoload import load_config

  # This will be loaded because of name's rule.
  class ValidatorA:
    def validate(self):
        print("validateA!!")
  
  # Anything goes.
  @load_config(order=2)
  class Foo:
    pass
  ```
  
  - main.py
  ```python
  from autoload import ModuleLoader
  from autoload.exception import LoaderStrictModeError
  
  loader = ModuleLoader()
  # return ValidatorA and Foo class objects.
  classes = loader.load_classes("pkg")

  # ModuleLoader strictly try to load a class or function object
  # per a Python module on a basis of its name.
  strict_loader = ModuleLoader(strict=True)
  try:
    classes = strict_loader.load_classes("pkg")
  except LoaderStrictModeError as e:
    print(e)
  # -> Loader can only load a 'ValidatorA' class in validator_a module.
  # -> Please check 'Foo' in validator_a module.
  ```
#### load_class
```
load_class(file_name: str)
```
This method read the Python file and return the class object.
- Directory
```
project/
  ├ example.py
  └ validator.py
```
- validator.py
```python
class Validator:
    def validate(self):
        print("validate!!")
```
- example.py
```python
loader = ModuleLoader()
clazz = loader.load_class("validator")
clazz().validate()
# -> validate!!
```
How to specify `file_name` is the same as that of `load_classes`.

#### load_function
```
load_function(file_name: str)
```
This method read the Python file and return a function object.
The usage is the same as `load_class`.

## License
Released under the MIT license.
            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/hiroki0525/autoload_module",
    "name": "autoload-module",
    "maintainer": "Hiroki Miyaji",
    "docs_url": null,
    "requires_python": ">=3.8,<4.0",
    "maintainer_email": "nukoprogramming@gmail.com",
    "keywords": "python,import,autoload,autoload_module,metaprogramming,dynamic import",
    "author": "Hiroki Miyaji",
    "author_email": "nukoprogramming@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/d2/c7/e23a010c86b0072ee801d093fc7d72a87dac1be6f36834c0412f8bbb7009/autoload_module-2.0.0.tar.gz",
    "platform": null,
    "description": "# autoload_module\n[![PyPI version](https://badge.fury.io/py/autoload-module.svg)](https://badge.fury.io/py/autoload-module)\n[![Test](https://github.com/hiroki0525/autoload_module/actions/workflows/test.yml/badge.svg)](https://github.com/hiroki0525/autoload_module/actions/workflows/test.yml)\n[![Downloads](https://pepy.tech/badge/autoload-module)](https://pepy.tech/project/autoload-module)\n<img src=\"https://img.shields.io/badge/license-MIT-blue.svg?style=flat\" alt=\"MIT License image\">\n\nThis library will give you comfortable Python metaprogramming.  \nThe following is a plain example.\n\n- Directory\n```\nproject/\n \u251c example.py\n \u2514 validator/\n   \u251c validator_a.py\n   \u251c validator_b.py\n   \u2514 validator_c.py\n```\n- example.py\n```python\nfrom autoload import ModuleLoader\n\ninput = \"foo bar baz\"\nloader = ModuleLoader()\n\n# Automatically import modules and return class objects\nvalidator_classes = loader.load_classes(\"validator\")\ntry:\n    # initialize and execute method\n    [clazz().validate(input) for clazz in validator_classes]\nexcept:\n    print(\"input is invalid!!\")\n```\n## Install\n```\npip install autoload-module\n```\n## Usage\n### Constructor\n```\nModuleLoader(\n  base_path: Optional[str] = None,\n  strict: bool = False\n)\n```\nThe ModuleLoader can be generated with no parameters.\nIn that case, the instance has the absolute path where\nit was initialized.  \n- Directory\n```\n/usr/local/src/project/\n  \u251c example.py\n  \u2514 validator/\n    \u251c validator_a.py\n    \u251c validator_b.py\n    \u2514 validator_c.py\n```\n- example.py\n```python\nfrom autoload import ModuleLoader\n\n# The instance has '/usr/local/src/project/'\nloader = ModuleLoader()\n\n# load modules in the directory; '/usr/local/src/project/validator/'\nvalidator_classes = loader.load_classes(\"validator\")\n```\nIf you want to change the base path, you must generate the ModuleLoader with an absolute path parameter.\n```python\nloader = ModuleLoader('/user/local/src/custom')\n```\n\nAbout strict parameter, please see [here](#NOTE) .\n\nYou can also create global setting and initialize singleton object.\n```python\nfrom autoload import ModuleLoader\nimport os\n\n# global setting\nModuleLoader.set_setting(base_path=os.getcwd(), strict=True)\n\nloader_a = ModuleLoader()\nloader_b = ModuleLoader()\n\nprint(loader_a.base_path)\n# -> /Users/user1/abc\nprint(loader_b.base_path)\n# -> /Users/user1/abc\n\n# singleton setting\nModuleLoader.set_setting(singleton=True)\n\nloader_c = ModuleLoader()\nloader_d = ModuleLoader()\nloader_e = ModuleLoader('/test')\n\nassert loader_c is loader_d # OK\nassert loader_c is loader_e # OK\n\n# The base_path is '/Users/user1/abc'\nassert loader_c.base_path is loader_e.base_path # OK\n```\n\n### Methods\n#### load_classes\n```\nload_classes(\n    src: str,\n    excludes: Iterable[str] = (),\n    recursive: bool = False,\n) -> Tuple[Type, ...]:\n```\nThis method read the Python package or module and return the tuple of class objects.\n\n- Directory\n```\npkg/\n \u251c example.py\n \u251c __init__.py\n \u251c config.yaml\n \u2514 main/\n     \u251c validator_a.py\n     \u251c validator_b.py\n     \u251c validator_c.py\n     \u2514 sub/\n        \u251c validator_d.py\n        \u2514 validator_e.py\n```\n- validator_a.py\n```python\nclass ValidatorA:\n    def validate(self):\n        print(\"validateA!!\")\n```\n- example.py\n```python\nloader = ModuleLoader()\n\n# Automatically read modules without '__init__.py', not py file, and this file.\n# return the tuple of ValidateA, ValidatorB, and ValidatorC class objects\nvalidator_classes = loader.load_classes(\"main\")\n\n# initialize and execute method\n[clazz().validate() for clazz in validator_classes]\n# -> validateA!!\n# -> validateB!!\n# -> validateC!!\n```\nYou can also load only specific modules using `excludes` variable or `load_config` decorator as below.\n```python\n# Pattern1: 'excludes'\n# 'excludes' is a iterable object like tuple, list.\n# You must specify module names in 'excludes'.\nvalidator_classes = loader.load_classes(\"main\", [\"validator_a\"])\n\n[clazz().validate() for clazz in validator_classes]\n# -> validateB!!\n# -> validateC!!\n\n# Pattern2: 'load_config'\nfrom autoload import load_config\n\n@load_config(load=False)\nclass ValidatorA:\n  def validate(self):\n    print(\"validateA!!\")\n\nvalidator_classes = loader.load_classes(\"main\")\n\n[clazz().validate() for clazz in validator_classes]\n# -> validateB!!\n# -> validateC!!\n```\nThis function will check directory structure recursively if you specify `recursive=True`. \n```python\n# 'recursive=False' is default.\n# In this case, the loader will also check 'pkg/main/sub/'.\nvalidator_classes = loader.load_classes(\"main\", recursive=True)\n\n[clazz().validate() for clazz in validator_classes]\n# -> validateA!!\n# -> validateB!!\n# -> validateC!!\n# -> validateD!!\n# -> validateE!!\n```\nYou can specify `src` as below.\n```python\nloader.load_classes(\"main/validator_a.py\")\nloader.load_classes(\"main.validator_a\")\nloader.load_classes(\"./main/validator_a\")\nloader.load_classes(\".main.validator_a\")\nloader.load_classes(\"main.sub.validator_d\")\nloader.load_classes(\"./main/sub/validator_d\")\nloader.load_classes(\"../otherpkg\")\nloader.load_classes(\"..otherpkg\")\n```\n\n#### load_functions\n```\nload_functions(\n    src: str,\n    excludes: Iterable[str] = (),\n    recursive: bool = False,\n) -> Tuple[Callable, ...]:\n```\nThis method read the Python package or module and return the tuple of functions.\nThe usage is the same as `load_classes`.\n\n##### NOTE\n- To search class or function, **You must match the name of file, and the one of class or function.**\nFor example, if you named the file `test_module.py`, you must name the class `TestModule` or the function `test_module`.\nWhen you want to customize their name, use `@load_config` decorator.\n    - validator_a.py\n    ```python\n    from autoload import load_config\n  \n    @load_config()\n    class CustomValidator:\n        def validate(self):\n            print(\"validateA!!\")\n    ```\n- You can also control the order of loaded class objects using `@load_config` decorator.\n    - validator_a.py\n    ```python\n    from autoload import load_config\n  \n    # sort in ascending order\n    @load_config(order=1)\n    class ValidatorA:\n        def validate(self):\n            print(\"validateA!!\")\n    ```\n- If you decorate some classes or functions with `@load_config`, the loader will load them.\n  However, initialized `strict=True`, the loader denies multiple loading as below.\n  - pkg/validator_a.py\n  ```python\n  from autoload import load_config\n\n  # This will be loaded because of name's rule.\n  class ValidatorA:\n    def validate(self):\n        print(\"validateA!!\")\n  \n  # Anything goes.\n  @load_config(order=2)\n  class Foo:\n    pass\n  ```\n  \n  - main.py\n  ```python\n  from autoload import ModuleLoader\n  from autoload.exception import LoaderStrictModeError\n  \n  loader = ModuleLoader()\n  # return ValidatorA and Foo class objects.\n  classes = loader.load_classes(\"pkg\")\n\n  # ModuleLoader strictly try to load a class or function object\n  # per a Python module on a basis of its name.\n  strict_loader = ModuleLoader(strict=True)\n  try:\n    classes = strict_loader.load_classes(\"pkg\")\n  except LoaderStrictModeError as e:\n    print(e)\n  # -> Loader can only load a 'ValidatorA' class in validator_a module.\n  # -> Please check 'Foo' in validator_a module.\n  ```\n#### load_class\n```\nload_class(file_name: str)\n```\nThis method read the Python file and return the class object.\n- Directory\n```\nproject/\n  \u251c example.py\n  \u2514 validator.py\n```\n- validator.py\n```python\nclass Validator:\n    def validate(self):\n        print(\"validate!!\")\n```\n- example.py\n```python\nloader = ModuleLoader()\nclazz = loader.load_class(\"validator\")\nclazz().validate()\n# -> validate!!\n```\nHow to specify `file_name` is the same as that of `load_classes`.\n\n#### load_function\n```\nload_function(file_name: str)\n```\nThis method read the Python file and return a function object.\nThe usage is the same as `load_class`.\n\n## License\nReleased under the MIT license.",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python Autoload Module",
    "version": "2.0.0",
    "project_urls": {
        "Documentation": "https://github.com/hiroki0525/autoload_module",
        "Homepage": "https://github.com/hiroki0525/autoload_module",
        "Repository": "https://github.com/hiroki0525/autoload_module"
    },
    "split_keywords": [
        "python",
        "import",
        "autoload",
        "autoload_module",
        "metaprogramming",
        "dynamic import"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "aca2a83984002c05196eab9eb6be6228ad040427a3d098f3e0b0dd1880fb29b4",
                "md5": "879d969cc5316b6836f6081d27a4a3be",
                "sha256": "b26e25c2b4981926669909571bbb92aa64cb96cec90d5f41af7513647be63203"
            },
            "downloads": -1,
            "filename": "autoload_module-2.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "879d969cc5316b6836f6081d27a4a3be",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8,<4.0",
            "size": 10378,
            "upload_time": "2023-06-16T07:17:12",
            "upload_time_iso_8601": "2023-06-16T07:17:12.159365Z",
            "url": "https://files.pythonhosted.org/packages/ac/a2/a83984002c05196eab9eb6be6228ad040427a3d098f3e0b0dd1880fb29b4/autoload_module-2.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d2c7e23a010c86b0072ee801d093fc7d72a87dac1be6f36834c0412f8bbb7009",
                "md5": "1d72cb5f3a26467f59d54976f82503c2",
                "sha256": "d911d5a11aee02bb09ad7c0966458b8a215ebd657c788779097db7195e21d865"
            },
            "downloads": -1,
            "filename": "autoload_module-2.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "1d72cb5f3a26467f59d54976f82503c2",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<4.0",
            "size": 10141,
            "upload_time": "2023-06-16T07:17:13",
            "upload_time_iso_8601": "2023-06-16T07:17:13.561217Z",
            "url": "https://files.pythonhosted.org/packages/d2/c7/e23a010c86b0072ee801d093fc7d72a87dac1be6f36834c0412f8bbb7009/autoload_module-2.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-06-16 07:17:13",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "hiroki0525",
    "github_project": "autoload_module",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "autoload-module"
}
        
Elapsed time: 0.09418s