Skip to content

Commit

Permalink
Merge pull request #17 from hiroki0525/feature/singleton-strict
Browse files Browse the repository at this point in the history
Feature/singleton strict
  • Loading branch information
hiroki0525 committed Jun 12, 2021
2 parents 4f498ce + ce526a4 commit 8b45dc7
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 10 deletions.
26 changes: 26 additions & 0 deletions autoload/module_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

__all__ = ("ModuleLoader", "ModuleLoaderSetting")

from .exception import LoaderStrictModeError


class __Private:
"""Private namespace.
Expand Down Expand Up @@ -59,6 +61,7 @@ class ModuleLoaderSetting:
class ModuleLoader:
_setting: ClassVar[ModuleLoaderSetting] = ModuleLoaderSetting()
_instance: Optional["ModuleLoader"] = None
_INSTANCE_VAL_COUNT = 2

@classmethod
def get_setting(cls) -> ModuleLoaderSetting:
Expand All @@ -75,9 +78,32 @@ def set_setting(

def __new__(cls, *args, **kwargs):
if cls._setting.singleton is False:
cls._instance = None
return super(ModuleLoader, cls).__new__(cls)
if cls._instance is None:
cls._instance = super(ModuleLoader, cls).__new__(cls)
return cls._instance
if cls._setting.strict is False:
return cls._instance
base_path, strict = list(args) + [None] * (cls._INSTANCE_VAL_COUNT - len(args))
base_path = kwargs.get("base_path") if base_path is None else base_path
strict = kwargs.get("strict") if strict is None else strict
if base_path is None:
global_base_path = cls._setting.base_path
base_path = (
_access_private().init_base_url(base_path)
if global_base_path is None
else global_base_path
)
if strict is None:
strict = cls._setting.strict
ci = cls._instance
if ci.base_path != base_path or ci.strict != strict:
raise LoaderStrictModeError(
"Now singleton setting. "
"You have already initialized object that has some attributes. "
"Please check constructor variables."
)
return cls._instance

def __init__(self, base_path: Optional[str] = None, strict: Optional[bool] = None):
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "autoload-module"
version = "1.7.0"
version = "1.7.1"
description = "Python Autoload Module"
authors = ["Hiroki Miyaji <nukoprogramming@gmail.com>"]
license = "MIT"
Expand Down
38 changes: 29 additions & 9 deletions tests/clazz/base/test_autoload_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ def test_global_setting(self):
self.assertTupleEqual((test_loader.base_path, test_loader.strict), expected)
self.assertTupleEqual((test_loader2.base_path, test_loader2.strict), expected)

def test_switch_global_setting(self):
ModuleLoader.set_setting(singleton=True)
singleton_a = ModuleLoader()
singleton_b = ModuleLoader()
ModuleLoader.set_setting()
no_singleton_a = ModuleLoader()
no_singleton_b = ModuleLoader()
self.assertIs(singleton_a, singleton_b)
self.assertIsNot(singleton_a, no_singleton_a)
self.assertIsNot(no_singleton_a, no_singleton_b)

def test_singleton(self):
ModuleLoader.set_setting(singleton=True)
test_cases = (
Expand All @@ -61,6 +72,19 @@ def test_singleton(self):
self.assertEqual(instance.base_path, expected.base_path)
self.assertEqual(instance.strict, expected.strict)

def test_singleton_with_strict(self):
ModuleLoader.set_setting(singleton=True, strict=True)
singleton = ModuleLoader()
test_cases = (
('/test',),
('/test', {"strict": False},),
({"strict": True},),
)
for args in test_cases:
with self.subTest(args=args):
with self.assertRaises(LoaderStrictModeError, msg="Now singleton setting."):
ModuleLoader(*args)

def test_not_singleton(self):
test_cases = (
(ModuleLoader(), ModuleLoader(), False),
Expand Down Expand Up @@ -240,17 +264,13 @@ def test_strict_mode(self):
def test_strict_mode_raise_error(self):
self.loader = ModuleLoader(strict=True)
test_cases = (
"packageD",
"packageD.module_d1"
("packageD", "Loader can't load 'ModuleD6' in module_d3 module.",),
("packageD.module_d1", "Loader can only load a 'ModuleD1' class in module_d1 module.",)
)
for pkg_name in test_cases:
with self.assertRaises(LoaderStrictModeError):
try:
for pkg_name, msg in test_cases:
with self.subTest(pkg_name=pkg_name):
with self.assertRaises(LoaderStrictModeError):
self.loader.load_classes(pkg_name)
except LoaderStrictModeError as e:
# check message
print(e)
raise e


if __name__ == '__main__':
Expand Down

0 comments on commit 8b45dc7

Please sign in to comment.