Skip to content

Commit

Permalink
Merge pull request #16 from hiroki0525/feature/singleton
Browse files Browse the repository at this point in the history
Feature/singleton
  • Loading branch information
hiroki0525 committed Jun 10, 2021
2 parents aa8c563 + 5ce93a8 commit 4f498ce
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 4 deletions.
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ loader = ModuleLoader('/user/local/src/custom')

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

You can also create global setting.
You can also create global setting and initialize singleton object.
```python
from autoload import ModuleLoader
import os
Expand All @@ -86,6 +86,19 @@ 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
Expand Down
20 changes: 18 additions & 2 deletions autoload/module_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,32 @@ def _access_private():
class ModuleLoaderSetting:
base_path: Optional[str] = None
strict: bool = False
singleton: bool = False


class ModuleLoader:
_setting: ClassVar[ModuleLoaderSetting] = ModuleLoaderSetting()
_instance: Optional["ModuleLoader"] = None

@classmethod
def get_setting(cls) -> ModuleLoaderSetting:
return cls._setting

@classmethod
def set_setting(cls, base_path: Optional[str] = None, strict: bool = False) -> None:
cls._setting = ModuleLoaderSetting(base_path, strict)
def set_setting(
cls,
base_path: Optional[str] = None,
strict: bool = False,
singleton: bool = False,
) -> None:
cls._setting = ModuleLoaderSetting(base_path, strict, singleton)

def __new__(cls, *args, **kwargs):
if cls._setting.singleton is False:
return super(ModuleLoader, cls).__new__(cls)
if cls._instance is None:
cls._instance = super(ModuleLoader, cls).__new__(cls)
return cls._instance

def __init__(self, base_path: Optional[str] = None, strict: Optional[bool] = None):
"""initialize
Expand All @@ -75,6 +89,8 @@ def __init__(self, base_path: Optional[str] = None, strict: Optional[bool] = Non
per a Python module on a basis of its name.
"""
setting = ModuleLoader._setting
if setting.singleton is True and hasattr(self, "_ModuleLoader__base_path"):
return
global_base_path, global_strict = setting.base_path, setting.strict
self.__base_path: str = (
_access_private().init_base_url(base_path)
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.6.0"
version = "1.7.0"
description = "Python Autoload Module"
authors = ["Hiroki Miyaji <nukoprogramming@gmail.com>"]
license = "MIT"
Expand Down
26 changes: 26 additions & 0 deletions tests/clazz/base/test_autoload_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,33 @@ def test_global_setting(self):
with self.subTest(setting=setting):
ModuleLoader.set_setting(*setting)
test_loader = ModuleLoader()
test_loader2 = ModuleLoader()
self.assertTupleEqual((test_loader.base_path, test_loader.strict), expected)
self.assertTupleEqual((test_loader2.base_path, test_loader2.strict), expected)

def test_singleton(self):
ModuleLoader.set_setting(singleton=True)
test_cases = (
(ModuleLoader(), ModuleLoader()),
(ModuleLoader('/test', strict=True), ModuleLoader()),
)
for instance, expected in test_cases:
with self.subTest(instance=instance):
self.assertIs(instance, expected)
self.assertEqual(instance.base_path, expected.base_path)
self.assertEqual(instance.strict, expected.strict)

def test_not_singleton(self):
test_cases = (
(ModuleLoader(), ModuleLoader(), False),
(ModuleLoader('/test', strict=True), ModuleLoader(), True),
)
for instance, expected, optional in test_cases:
with self.subTest(instance=instance):
self.assertIsNot(instance, expected)
if optional:
self.assertNotEqual(instance.base_path, expected.base_path)
self.assertNotEqual(instance.strict, expected.strict)

def test_initialize(self):
test_cases = (
Expand Down

0 comments on commit 4f498ce

Please sign in to comment.