# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['autoload']

package_data = \
{'': ['*']}

setup_kwargs = {
    'name': 'autoload-module',
    'version': '1.7.0',
    'description': 'Python Autoload Module',
    'long_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<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 ├ example.py\n └ validator/\n   ├ validator_a.py\n   ├ validator_b.py\n   └ 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  ├ example.py\n  └ validator/\n    ├ validator_a.py\n    ├ validator_b.py\n    └ 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**NOTE**\n\nFrom version 1.5.0, `pkg_name` parameter is duplicated.\nIt will be deleted soon. \n`load_functions` is also same.\n\n- Directory\n```\npkg/\n ├ example.py\n ├ __init__.py\n ├ config.yaml\n └ main/\n     ├ validator_a.py\n     ├ validator_b.py\n     ├ validator_c.py\n     └ sub/\n        ├ validator_d.py\n        └ 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 `pkg_name` 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  ├ example.py\n  └ 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.',
    'author': 'Hiroki Miyaji',
    'author_email': 'nukoprogramming@gmail.com',
    'maintainer': 'Hiroki Miyaji',
    'maintainer_email': 'nukoprogramming@gmail.com',
    'url': 'https://github.com/hiroki0525/autoload_module',
    'packages': packages,
    'package_data': package_data,
    'python_requires': '>=3.7,<4.0',
}


setup(**setup_kwargs)
