# Singleton 및 TtlSingleton 메타클래스
이 프로젝트는 Python에서 싱글톤 클래스를 생성하기 위한 `Singleton` 및 `TtlSingleton` 메타클래스를 제공합니다. `TtlSingleton` 메타클래스는 `Singleton` 기능을 확장하여 지정된 시간이 지나면 인스턴스가 만료되는 TTL(Time-To-Live) 기능을 추가합니다.
## 기능
- **Singleton**: <b>클래스 이름과 초기화 매개변수가 동일한 경우</b> 하나의 인스턴스만 생성되도록 보장합니다.
- **TtlSingleton**: `Singleton`을 확장하여 TTL을 지원하며, <b>지정된 시간이 지나면 인스턴스가 만료</b>되고 새로 생성됩니다.
- 두 클래스 모두 `use_class_name_only` 매개변수를 true로 지정하면 초기화 매개변수와 관계없이 클래스 이름만으로 싱글톤을 생성할 수 있습니다. (전통적인 싱글톤과 동일)
## 설치
```bash
pip install advanced-python-singleton
```
`
이 프로젝트를 사용하려면 저장소를 클론하고 필요한 종속성을 설치하십시오:
```sh
git clone https://github.com/jogakdal/advanced-singleton.git
cd <repository-directory>
pip install -r requirements.txt
```
## 사용법
### Singleton
- 싱글톤 클래스를 생성하려면 `Singleton` 메타 클래스로 지정해 주면 됩니다.
- `use_class_name_only` 매개변수를 true로 지정하면 초기화 매개변수와 관계없이 클래스 이름만으로 싱글톤을 생성합니다. (전통적인 싱글톤과 동일, default는 false)
```python
from advanced_python_singleton.singleton import Singleton
class SomeClass(metaclass=Singleton):
def __init__(self, name):
self.name = name
```
### TtlSingleton
- TTL 기반 싱글톤 클래스를 생성하려면 `TtlSingleton` 메타클래스를 사용하고 `ttl` 매개변수를 지정해 주세요.
- ttl 매개변수는 인스턴스가 만료되기까지의 시간(초)을 나타냅니다. default는 60초입니다.
- `use_class_name_only` 매개변수를 true로 지정하면 초기화 매개변수와 관계없이 클래스 이름만으로 싱글톤을 생성합니다. (전통적인 싱글톤과 동일, default는 false)
```python
from advanced_python_singleton.ttlsingleton import TtlSingleton
class SomeClass(metaclass=TtlSingleton, ttl=10):
def __init__(self, name):
self.name = name
```
### 예제
다음은 `TtlSingleton` 사용법을 보여주는 예제입니다:
```python
import time
from advanced_python_singleton.singleton import Singleton
from advanced_python_singleton.ttlsingleton import TtlSingleton
# Singleton 테스트
class SingletonWithParamExample(metaclass=Singleton):
def __init__(self, name):
self.name = name
print(f'{self.name}({self}) is created')
class SingletonWithoutParamExample(metaclass=Singleton, use_class_name_only=True):
def __init__(self, name):
self.name = name
print(f'{self.name}({self}) is created')
a = SingletonWithParamExample('a')
b = SingletonWithParamExample('b')
c = SingletonWithParamExample('a')
assert a != b
assert a == c
assert b == SingletonWithParamExample('b')
a = SingletonWithoutParamExample('a')
b = SingletonWithoutParamExample('b')
assert a == b
assert a == SingletonWithoutParamExample('c')
# TtlSingleton 테스트
class TtlSingletonExample(metaclass=TtlSingleton, ttl=2):
def __init__(self, name):
self.name = name
print(f' {self.name} is created')
class SingletonTest():
def test(self, p):
return TtlSingletonExample(p)
print('a creating')
a = TtlSingletonExample('a')
assert a.name == 'a'
print('b creating')
b = TtlSingletonExample('b')
assert b.name == 'b'
print('sleep 1 sec')
time.sleep(1)
print('a creating')
c = TtlSingletonExample('a')
assert a == c
assert c.name == 'a'
print('sleep 2 sec')
time.sleep(2)
print('a creating')
d = TtlSingletonExample('a')
assert a != d # 시간이 2초 이상 지났음으로 새로운 객체 생성
print('a creating via SingletonTest()')
assert d == SingletonTest().test('a')
print('sleep 2 sec')
time.sleep(2)
print('a creating via SingletonTest()')
e = SingletonTest().test('a')
assert d != e
print('a creating')
assert e == TtlSingletonExample('a')
# TTL이 서로 다른 클래스 테스트
class TtlSingletonExample_5(metaclass=TtlSingleton, ttl=5):
def __init__(self, name):
self.name = name
class TtlSingletonExample_8(metaclass=TtlSingleton, ttl=8):
def __init__(self, name):
self.name = name
a = TtlSingletonExample_5('a')
b = TtlSingletonExample_8('a')
assert a != b
time.sleep(6)
c = TtlSingletonExample_5('a')
d = TtlSingletonExample_8('a')
assert a != c
assert b == d
time.sleep(3)
assert c == TtlSingletonExample_5('a')
assert d != TtlSingletonExample_8('a')
# use_class_name_only=True 테스트
class SingletonClassNameOnly(metaclass=TtlSingleton, ttl=60, use_class_name_only=True):
def __init__(self, name, value):
self.name = name
self.value = value
instance1 = SingletonClassNameOnly('test', 123)
instance2 = SingletonClassNameOnly('test', 456)
assert instance1 == instance2
assert instance1.value == 123
assert instance2.value == 123
# 인자 관련 테스트
class SomeClass(metaclass=Singleton):
def __init__(self, user_name, user_id=0):
self.user_name = user_name
self.user_id = user_id
class AnotherClass(metaclass=Singleton):
def __init__(self, user_name, user_id=0):
self.user_name = user_name
self.user_id = user_id
assert SomeClass('abc', 1) == SomeClass('abc', 1) # 클래스 명과 인자가 모두 같으면 같은 인스턴스가 되어야 한다.
assert SomeClass('abc', 1) != AnotherClass('abc', 1) # 클래스 명이 다르면 다른 인스턴스가 되어야 한다.
assert SomeClass('abc', user_id=1) == SomeClass('abc', 1) # 명시적 파라미터로 전달되어도 값이 같으면 같은 인스턴스가 되어야 한다.
assert SomeClass('abc', 1) != SomeClass('abc', 2) # 파라미터 값이 하나라도 다르면 다른 인스턴스가 되어야 한다.
assert SomeClass('abc', user_id=1) != SomeClass('abc', 2) # 파라미터 값이 하나라도 다르면 다른 인스턴스가 되어야 한다.
assert SomeClass('abc') == SomeClass('abc', 0) # 파라미터 디폴트 값과 동일한 값으로 전달되면 같은 인스턴스가 되어야 한다.
assert SomeClass('abc') != SomeClass('abc', 1) # 파라미터 디폴트 값과 다른 값으로 전달되면 다른 인스턴스가 되어야 한다.
assert SomeClass('abc') == SomeClass('abc', user_id=0) # 파라미터 디폴트 값과 동일한 값이 명시적으로 전달되어도 같은 인스턴스가 되어야 한다.
```
## 라이선스
이 라이브러리는 누구나 사용할 수 있는 프리 소프트웨어입니다. 다만 코드를 수정할 경우 변경된 내용을 원작성자에게 통보해 주시면 감사하겠습니다.
## 작성자
황용호(jogakdal@gmail.com)
Raw data
{
"_id": null,
"home_page": "https://github.com/jogakdal/advanced-singleton",
"name": "advanced-python-singleton",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": null,
"keywords": "jogakdal, Singleton, TTL, metaclass",
"author": "\ud669\uc6a9\ud638",
"author_email": "jogakdal@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/67/7e/f0df3f3ce136fff1e23989e5fda18fa2ac5a7dde3d5b7f385c79ee202237/advanced-python-singleton-1.3.2.tar.gz",
"platform": null,
"description": "# Singleton \ubc0f TtlSingleton \uba54\ud0c0\ud074\ub798\uc2a4\n\n\uc774 \ud504\ub85c\uc81d\ud2b8\ub294 Python\uc5d0\uc11c \uc2f1\uae00\ud1a4 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud55c `Singleton` \ubc0f `TtlSingleton` \uba54\ud0c0\ud074\ub798\uc2a4\ub97c \uc81c\uacf5\ud569\ub2c8\ub2e4. `TtlSingleton` \uba54\ud0c0\ud074\ub798\uc2a4\ub294 `Singleton` \uae30\ub2a5\uc744 \ud655\uc7a5\ud558\uc5ec \uc9c0\uc815\ub41c \uc2dc\uac04\uc774 \uc9c0\ub098\uba74 \uc778\uc2a4\ud134\uc2a4\uac00 \ub9cc\ub8cc\ub418\ub294 TTL(Time-To-Live) \uae30\ub2a5\uc744 \ucd94\uac00\ud569\ub2c8\ub2e4.\n\n## \uae30\ub2a5\n\n- **Singleton**: <b>\ud074\ub798\uc2a4 \uc774\ub984\uacfc \ucd08\uae30\ud654 \ub9e4\uac1c\ubcc0\uc218\uac00 \ub3d9\uc77c\ud55c \uacbd\uc6b0</b> \ud558\ub098\uc758 \uc778\uc2a4\ud134\uc2a4\ub9cc \uc0dd\uc131\ub418\ub3c4\ub85d \ubcf4\uc7a5\ud569\ub2c8\ub2e4.\n- **TtlSingleton**: `Singleton`\uc744 \ud655\uc7a5\ud558\uc5ec TTL\uc744 \uc9c0\uc6d0\ud558\uba70, <b>\uc9c0\uc815\ub41c \uc2dc\uac04\uc774 \uc9c0\ub098\uba74 \uc778\uc2a4\ud134\uc2a4\uac00 \ub9cc\ub8cc</b>\ub418\uace0 \uc0c8\ub85c \uc0dd\uc131\ub429\ub2c8\ub2e4.\n- \ub450 \ud074\ub798\uc2a4 \ubaa8\ub450 `use_class_name_only` \ub9e4\uac1c\ubcc0\uc218\ub97c true\ub85c \uc9c0\uc815\ud558\uba74 \ucd08\uae30\ud654 \ub9e4\uac1c\ubcc0\uc218\uc640 \uad00\uacc4\uc5c6\uc774 \ud074\ub798\uc2a4 \uc774\ub984\ub9cc\uc73c\ub85c \uc2f1\uae00\ud1a4\uc744 \uc0dd\uc131\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. (\uc804\ud1b5\uc801\uc778 \uc2f1\uae00\ud1a4\uacfc \ub3d9\uc77c)\n## \uc124\uce58\n```bash\npip install advanced-python-singleton\n```\n`\n\uc774 \ud504\ub85c\uc81d\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \uc800\uc7a5\uc18c\ub97c \ud074\ub860\ud558\uace0 \ud544\uc694\ud55c \uc885\uc18d\uc131\uc744 \uc124\uce58\ud558\uc2ed\uc2dc\uc624:\n\n```sh\ngit clone https://github.com/jogakdal/advanced-singleton.git\ncd <repository-directory>\npip install -r requirements.txt\n```\n\n## \uc0ac\uc6a9\ubc95\n\n### Singleton\n- \uc2f1\uae00\ud1a4 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud558\ub824\uba74 `Singleton` \uba54\ud0c0 \ud074\ub798\uc2a4\ub85c \uc9c0\uc815\ud574 \uc8fc\uba74 \ub429\ub2c8\ub2e4.\n- `use_class_name_only` \ub9e4\uac1c\ubcc0\uc218\ub97c true\ub85c \uc9c0\uc815\ud558\uba74 \ucd08\uae30\ud654 \ub9e4\uac1c\ubcc0\uc218\uc640 \uad00\uacc4\uc5c6\uc774 \ud074\ub798\uc2a4 \uc774\ub984\ub9cc\uc73c\ub85c \uc2f1\uae00\ud1a4\uc744 \uc0dd\uc131\ud569\ub2c8\ub2e4. (\uc804\ud1b5\uc801\uc778 \uc2f1\uae00\ud1a4\uacfc \ub3d9\uc77c, default\ub294 false)\n```python\nfrom advanced_python_singleton.singleton import Singleton\n\n\nclass SomeClass(metaclass=Singleton):\n def __init__(self, name):\n self.name = name\n```\n\n### TtlSingleton\n- TTL \uae30\ubc18 \uc2f1\uae00\ud1a4 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud558\ub824\uba74 `TtlSingleton` \uba54\ud0c0\ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uace0 `ttl` \ub9e4\uac1c\ubcc0\uc218\ub97c \uc9c0\uc815\ud574 \uc8fc\uc138\uc694.\n- ttl \ub9e4\uac1c\ubcc0\uc218\ub294 \uc778\uc2a4\ud134\uc2a4\uac00 \ub9cc\ub8cc\ub418\uae30\uae4c\uc9c0\uc758 \uc2dc\uac04(\ucd08)\uc744 \ub098\ud0c0\ub0c5\ub2c8\ub2e4. default\ub294 60\ucd08\uc785\ub2c8\ub2e4.\n- `use_class_name_only` \ub9e4\uac1c\ubcc0\uc218\ub97c true\ub85c \uc9c0\uc815\ud558\uba74 \ucd08\uae30\ud654 \ub9e4\uac1c\ubcc0\uc218\uc640 \uad00\uacc4\uc5c6\uc774 \ud074\ub798\uc2a4 \uc774\ub984\ub9cc\uc73c\ub85c \uc2f1\uae00\ud1a4\uc744 \uc0dd\uc131\ud569\ub2c8\ub2e4. (\uc804\ud1b5\uc801\uc778 \uc2f1\uae00\ud1a4\uacfc \ub3d9\uc77c, default\ub294 false)\n```python\nfrom advanced_python_singleton.ttlsingleton import TtlSingleton\n\n\nclass SomeClass(metaclass=TtlSingleton, ttl=10):\n def __init__(self, name):\n self.name = name\n```\n\n### \uc608\uc81c\n\n\ub2e4\uc74c\uc740 `TtlSingleton` \uc0ac\uc6a9\ubc95\uc744 \ubcf4\uc5ec\uc8fc\ub294 \uc608\uc81c\uc785\ub2c8\ub2e4:\n\n```python\nimport time\n\nfrom advanced_python_singleton.singleton import Singleton\nfrom advanced_python_singleton.ttlsingleton import TtlSingleton\n\n# Singleton \ud14c\uc2a4\ud2b8\nclass SingletonWithParamExample(metaclass=Singleton):\n def __init__(self, name):\n self.name = name\n print(f'{self.name}({self}) is created')\n\n\nclass SingletonWithoutParamExample(metaclass=Singleton, use_class_name_only=True):\n def __init__(self, name):\n self.name = name\n print(f'{self.name}({self}) is created')\n\n\na = SingletonWithParamExample('a')\nb = SingletonWithParamExample('b')\nc = SingletonWithParamExample('a')\nassert a != b\nassert a == c\nassert b == SingletonWithParamExample('b')\n\na = SingletonWithoutParamExample('a')\nb = SingletonWithoutParamExample('b')\nassert a == b\nassert a == SingletonWithoutParamExample('c')\n\n# TtlSingleton \ud14c\uc2a4\ud2b8\nclass TtlSingletonExample(metaclass=TtlSingleton, ttl=2):\n def __init__(self, name):\n self.name = name\n print(f' {self.name} is created')\n\n\nclass SingletonTest():\n def test(self, p):\n return TtlSingletonExample(p)\n\nprint('a creating')\na = TtlSingletonExample('a')\nassert a.name == 'a'\n\nprint('b creating')\nb = TtlSingletonExample('b')\nassert b.name == 'b'\n\nprint('sleep 1 sec')\ntime.sleep(1)\n\nprint('a creating')\nc = TtlSingletonExample('a')\nassert a == c\nassert c.name == 'a'\n\nprint('sleep 2 sec')\ntime.sleep(2)\n\nprint('a creating')\nd = TtlSingletonExample('a')\nassert a != d # \uc2dc\uac04\uc774 2\ucd08 \uc774\uc0c1 \uc9c0\ub0ac\uc74c\uc73c\ub85c \uc0c8\ub85c\uc6b4 \uac1d\uccb4 \uc0dd\uc131\n\nprint('a creating via SingletonTest()')\nassert d == SingletonTest().test('a')\n\nprint('sleep 2 sec')\ntime.sleep(2)\n\nprint('a creating via SingletonTest()')\ne = SingletonTest().test('a')\nassert d != e\n\nprint('a creating')\nassert e == TtlSingletonExample('a')\n\n# TTL\uc774 \uc11c\ub85c \ub2e4\ub978 \ud074\ub798\uc2a4 \ud14c\uc2a4\ud2b8\nclass TtlSingletonExample_5(metaclass=TtlSingleton, ttl=5):\n def __init__(self, name):\n self.name = name\n\nclass TtlSingletonExample_8(metaclass=TtlSingleton, ttl=8):\n def __init__(self, name):\n self.name = name\n\na = TtlSingletonExample_5('a')\nb = TtlSingletonExample_8('a')\nassert a != b\n\ntime.sleep(6)\n\nc = TtlSingletonExample_5('a')\nd = TtlSingletonExample_8('a')\nassert a != c\nassert b == d\n\ntime.sleep(3)\n\nassert c == TtlSingletonExample_5('a')\nassert d != TtlSingletonExample_8('a')\n\n\n# use_class_name_only=True \ud14c\uc2a4\ud2b8\nclass SingletonClassNameOnly(metaclass=TtlSingleton, ttl=60, use_class_name_only=True):\n def __init__(self, name, value):\n self.name = name\n self.value = value\n\ninstance1 = SingletonClassNameOnly('test', 123)\ninstance2 = SingletonClassNameOnly('test', 456)\n\nassert instance1 == instance2\nassert instance1.value == 123\nassert instance2.value == 123\n\n# \uc778\uc790 \uad00\ub828 \ud14c\uc2a4\ud2b8\nclass SomeClass(metaclass=Singleton):\n def __init__(self, user_name, user_id=0):\n self.user_name = user_name\n self.user_id = user_id\n\n\nclass AnotherClass(metaclass=Singleton):\n def __init__(self, user_name, user_id=0):\n self.user_name = user_name\n self.user_id = user_id\n\nassert SomeClass('abc', 1) == SomeClass('abc', 1) # \ud074\ub798\uc2a4 \uba85\uacfc \uc778\uc790\uac00 \ubaa8\ub450 \uac19\uc73c\uba74 \uac19\uc740 \uc778\uc2a4\ud134\uc2a4\uac00 \ub418\uc5b4\uc57c \ud55c\ub2e4.\nassert SomeClass('abc', 1) != AnotherClass('abc', 1) # \ud074\ub798\uc2a4 \uba85\uc774 \ub2e4\ub974\uba74 \ub2e4\ub978 \uc778\uc2a4\ud134\uc2a4\uac00 \ub418\uc5b4\uc57c \ud55c\ub2e4.\nassert SomeClass('abc', user_id=1) == SomeClass('abc', 1) # \uba85\uc2dc\uc801 \ud30c\ub77c\ubbf8\ud130\ub85c \uc804\ub2ec\ub418\uc5b4\ub3c4 \uac12\uc774 \uac19\uc73c\uba74 \uac19\uc740 \uc778\uc2a4\ud134\uc2a4\uac00 \ub418\uc5b4\uc57c \ud55c\ub2e4.\nassert SomeClass('abc', 1) != SomeClass('abc', 2) # \ud30c\ub77c\ubbf8\ud130 \uac12\uc774 \ud558\ub098\ub77c\ub3c4 \ub2e4\ub974\uba74 \ub2e4\ub978 \uc778\uc2a4\ud134\uc2a4\uac00 \ub418\uc5b4\uc57c \ud55c\ub2e4.\nassert SomeClass('abc', user_id=1) != SomeClass('abc', 2) # \ud30c\ub77c\ubbf8\ud130 \uac12\uc774 \ud558\ub098\ub77c\ub3c4 \ub2e4\ub974\uba74 \ub2e4\ub978 \uc778\uc2a4\ud134\uc2a4\uac00 \ub418\uc5b4\uc57c \ud55c\ub2e4.\nassert SomeClass('abc') == SomeClass('abc', 0) # \ud30c\ub77c\ubbf8\ud130 \ub514\ud3f4\ud2b8 \uac12\uacfc \ub3d9\uc77c\ud55c \uac12\uc73c\ub85c \uc804\ub2ec\ub418\uba74 \uac19\uc740 \uc778\uc2a4\ud134\uc2a4\uac00 \ub418\uc5b4\uc57c \ud55c\ub2e4.\nassert SomeClass('abc') != SomeClass('abc', 1) # \ud30c\ub77c\ubbf8\ud130 \ub514\ud3f4\ud2b8 \uac12\uacfc \ub2e4\ub978 \uac12\uc73c\ub85c \uc804\ub2ec\ub418\uba74 \ub2e4\ub978 \uc778\uc2a4\ud134\uc2a4\uac00 \ub418\uc5b4\uc57c \ud55c\ub2e4.\nassert SomeClass('abc') == SomeClass('abc', user_id=0) # \ud30c\ub77c\ubbf8\ud130 \ub514\ud3f4\ud2b8 \uac12\uacfc \ub3d9\uc77c\ud55c \uac12\uc774 \uba85\uc2dc\uc801\uc73c\ub85c \uc804\ub2ec\ub418\uc5b4\ub3c4 \uac19\uc740 \uc778\uc2a4\ud134\uc2a4\uac00 \ub418\uc5b4\uc57c \ud55c\ub2e4.\n```\n## \ub77c\uc774\uc120\uc2a4\n\uc774 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub294 \ub204\uad6c\ub098 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ud504\ub9ac \uc18c\ud504\ud2b8\uc6e8\uc5b4\uc785\ub2c8\ub2e4. \ub2e4\ub9cc \ucf54\ub4dc\ub97c \uc218\uc815\ud560 \uacbd\uc6b0 \ubcc0\uacbd\ub41c \ub0b4\uc6a9\uc744 \uc6d0\uc791\uc131\uc790\uc5d0\uac8c \ud1b5\ubcf4\ud574 \uc8fc\uc2dc\uba74 \uac10\uc0ac\ud558\uaca0\uc2b5\ub2c8\ub2e4.\n\n## \uc791\uc131\uc790\n\ud669\uc6a9\ud638(jogakdal@gmail.com)\n\n\n",
"bugtrack_url": null,
"license": null,
"summary": "Singleton & TtlSingleton meta-class",
"version": "1.3.2",
"project_urls": {
"Homepage": "https://github.com/jogakdal/advanced-singleton"
},
"split_keywords": [
"jogakdal",
" singleton",
" ttl",
" metaclass"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "6ab23776a89e1fa5c826b29515da8d9c81e37e4f50d7afbed4509b01189aec64",
"md5": "b6957431a620bfa9b0cae7d9936b6c7b",
"sha256": "d0ad406cc4be4f27e4244aa475a17ce0089e2b2ab91132294c48b8c0fe43c3bf"
},
"downloads": -1,
"filename": "advanced_python_singleton-1.3.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b6957431a620bfa9b0cae7d9936b6c7b",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 5731,
"upload_time": "2025-01-16T00:52:39",
"upload_time_iso_8601": "2025-01-16T00:52:39.878064Z",
"url": "https://files.pythonhosted.org/packages/6a/b2/3776a89e1fa5c826b29515da8d9c81e37e4f50d7afbed4509b01189aec64/advanced_python_singleton-1.3.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "677ef0df3f3ce136fff1e23989e5fda18fa2ac5a7dde3d5b7f385c79ee202237",
"md5": "2aecde1082a3f39fe2304e3d62c9e7dc",
"sha256": "03685fc0f79754285665bcfe7d1baa85ad158cd6f1c2721f12b2265b7841af45"
},
"downloads": -1,
"filename": "advanced-python-singleton-1.3.2.tar.gz",
"has_sig": false,
"md5_digest": "2aecde1082a3f39fe2304e3d62c9e7dc",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 4613,
"upload_time": "2025-01-16T00:52:42",
"upload_time_iso_8601": "2025-01-16T00:52:42.324365Z",
"url": "https://files.pythonhosted.org/packages/67/7e/f0df3f3ce136fff1e23989e5fda18fa2ac5a7dde3d5b7f385c79ee202237/advanced-python-singleton-1.3.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-16 00:52:42",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jogakdal",
"github_project": "advanced-singleton",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "expiringdict",
"specs": []
},
{
"name": "setuptools",
"specs": []
},
{
"name": "advanced-python-singleton",
"specs": []
}
],
"lcname": "advanced-python-singleton"
}