onecache 0.5.1__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,23 +1,24 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: onecache
3
- Version: 0.5.1
3
+ Version: 0.7.0
4
4
  Summary: Python cache for sync and async code
5
- Home-page: UNKNOWN
5
+ License: MIT
6
6
  Author: Johanderson Mogollon
7
7
  Author-email: johander1822@gmail.com
8
- License: MIT
9
- Platform: UNKNOWN
8
+ Requires-Python: >=3.8,<3.13
10
9
  Classifier: Development Status :: 5 - Production/Stable
11
10
  Classifier: Intended Audience :: Developers
12
- Classifier: Operating System :: OS Independent
13
11
  Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Programming Language :: Python :: 3.6
15
- Classifier: Programming Language :: Python :: 3.7
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
16
14
  Classifier: Programming Language :: Python :: 3.8
17
15
  Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
18
19
  Classifier: Programming Language :: Python :: Implementation :: PyPy
19
20
  Description-Content-Type: text/markdown
20
- Provides-Extra: test
21
+
21
22
 
22
23
  [![Coverage Status](https://coveralls.io/repos/github/sonic182/onecache/badge.svg?branch=master)](https://coveralls.io/github/sonic182/onecache?branch=master)
23
24
  ![github status](https://github.com/sonic182/onecache/actions/workflows/python.yml/badge.svg)
@@ -27,7 +28,7 @@ Python cache for sync and async code.
27
28
 
28
29
  Cache uses LRU algoritm. Cache can optionally have TTL.
29
30
 
30
- Tested in python 3.7, 3.9, and pypy3.9 for windows, mac and linux (see github status badge), it should work in versions between them. It may work for python3.6
31
+ Tested in python 3.7, 3.9, 3.11 and pypy3.9 for windows, mac and linux (see github status badge), it should work in versions between them. It may work for python3.6
31
32
 
32
33
  # Usage
33
34
 
@@ -7,7 +7,7 @@ Python cache for sync and async code.
7
7
 
8
8
  Cache uses LRU algoritm. Cache can optionally have TTL.
9
9
 
10
- Tested in python 3.7, 3.9, and pypy3.9 for windows, mac and linux (see github status badge), it should work in versions between them. It may work for python3.6
10
+ Tested in python 3.7, 3.9, 3.11 and pypy3.9 for windows, mac and linux (see github status badge), it should work in versions between them. It may work for python3.6
11
11
 
12
12
  # Usage
13
13
 
@@ -2,13 +2,13 @@
2
2
 
3
3
  from collections import OrderedDict
4
4
  from contextlib import contextmanager
5
- from datetime import datetime, timedelta
5
+ from datetime import timedelta
6
6
  from sys import getsizeof
7
7
  from threading import Lock
8
8
  from typing import Any, Dict, Optional
9
9
 
10
10
  from onecache.cache_value import CacheValue
11
- from onecache.utils import IS_PYPY
11
+ from onecache.utils import IS_PYPY, utcnow
12
12
 
13
13
 
14
14
  class ExpirableCache(object):
@@ -26,10 +26,10 @@ class ExpirableCache(object):
26
26
  def __init__(
27
27
  self,
28
28
  size: int = 512,
29
- timeout: int = None,
29
+ timeout: Optional[int] = None,
30
30
  refresh_ttl=False,
31
31
  thread_safe=False,
32
- max_mem_size: int = None,
32
+ max_mem_size: Optional[int] = None,
33
33
  ):
34
34
  self.cache: Dict[str, CacheValue] = OrderedDict()
35
35
  self.timeout = timeout
@@ -49,7 +49,7 @@ class ExpirableCache(object):
49
49
  self._pop_one()
50
50
 
51
51
  if self.timeout:
52
- expire_at = datetime.utcnow() + timedelta(milliseconds=self.timeout)
52
+ expire_at = utcnow() + timedelta(milliseconds=self.timeout)
53
53
  value = CacheValue(data, expire_at)
54
54
  else:
55
55
  value = CacheValue(data)
@@ -108,7 +108,7 @@ class ExpirableCache(object):
108
108
  cache_value = self.cache.get(key)
109
109
  if cache_value and (milliseconds or self.timeout):
110
110
  ms = milliseconds if milliseconds else self.timeout
111
- expire_at = datetime.utcnow() + timedelta(milliseconds=ms)
111
+ expire_at = utcnow() + timedelta(milliseconds=ms)
112
112
  cache_value.refresh_ttl(expire_at)
113
113
 
114
114
  @classmethod
@@ -154,7 +154,7 @@ class LRUCache(ExpirableCache):
154
154
  with self._scoped():
155
155
  self._increment(cache_value)
156
156
  return cache_value.value
157
-
157
+
158
158
  return None
159
159
 
160
160
  def _increment(self, val: CacheValue):
@@ -1,14 +1,14 @@
1
1
  from datetime import datetime
2
2
  from sys import getsizeof
3
- from typing import Any
3
+ from typing import Any, Optional
4
4
 
5
- from onecache.utils import IS_PYPY
5
+ from onecache.utils import IS_PYPY, utcnow
6
6
 
7
7
 
8
8
  class CacheValue:
9
9
  """Dummy class for handling cache values."""
10
10
 
11
- def __init__(self, value: Any, expire_at: datetime = None):
11
+ def __init__(self, value: Any, expire_at: Optional[datetime] = None):
12
12
  self.size = None if IS_PYPY else getsizeof(value)
13
13
  self.access = 0
14
14
 
@@ -21,7 +21,7 @@ class CacheValue:
21
21
  def expired(self):
22
22
  """Check if value is expired."""
23
23
  if self.expire_at:
24
- return datetime.utcnow() > self.expire_at
24
+ return utcnow() > self.expire_at
25
25
  return False # pragma: no cover
26
26
 
27
27
  def refresh_ttl(self, expire_at: datetime):
@@ -0,0 +1,11 @@
1
+ import datetime
2
+ import platform
3
+ import sys
4
+
5
+ IS_PYPY = platform.python_implementation().lower().startswith("pypy")
6
+
7
+ def utcnow():
8
+ if sys.version_info >= (3, 11):
9
+ return datetime.datetime.now(datetime.UTC)
10
+ else:
11
+ return datetime.datetime.utcnow()
@@ -0,0 +1,40 @@
1
+ [tool.poetry]
2
+ name = "onecache"
3
+ version = "0.7.0"
4
+ description = "Python cache for sync and async code"
5
+ authors = ["Johanderson Mogollon <johander1822@gmail.com>"]
6
+ license = "MIT"
7
+ readme = "README.md"
8
+ classifiers = [
9
+ "Development Status :: 5 - Production/Stable",
10
+ "Intended Audience :: Developers",
11
+ "Operating System :: OS Independent",
12
+ "License :: OSI Approved :: MIT License",
13
+ "Programming Language :: Python :: 3.8",
14
+ "Programming Language :: Python :: 3.9",
15
+ "Programming Language :: Python :: 3.10",
16
+ "Programming Language :: Python :: 3.11",
17
+ "Programming Language :: Python :: Implementation :: PyPy",
18
+ ]
19
+ # packages = [{include = "onecache"}]
20
+
21
+ [tool.poetry.dependencies]
22
+ python = ">=3.8,<3.13"
23
+
24
+ [tool.poetry.group.test.dependencies]
25
+ flake8 = {version= "^7.1.0", python = ">=3.8.1"}
26
+ flake8-docstrings = "^1.7.0"
27
+ pytest = "^8.3.2"
28
+ pytest-asyncio = "^0.23.8"
29
+ pytest-sugar = "^1.0.0"
30
+ pytest-cov = "^5.0.0"
31
+
32
+
33
+ [tool.poetry.group.dev.dependencies]
34
+ autopep8 = {version="^2.3.1", python=">=3.8"}
35
+ sphinx = {version= "^8.0.2", python = ">=3.10"}
36
+ pylint = {version="^3.2.6", python=">=3.8"}
37
+
38
+ [build-system]
39
+ requires = ["poetry-core>=1.0.0"]
40
+ build-backend = "poetry.core.masonry.api"
@@ -1,2 +0,0 @@
1
- include README.md
2
- include *.txt
@@ -1,3 +0,0 @@
1
- import platform
2
-
3
- IS_PYPY = platform.python_implementation().lower().startswith("pypy")
@@ -1,101 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: onecache
3
- Version: 0.5.1
4
- Summary: Python cache for sync and async code
5
- Home-page: UNKNOWN
6
- Author: Johanderson Mogollon
7
- Author-email: johander1822@gmail.com
8
- License: MIT
9
- Platform: UNKNOWN
10
- Classifier: Development Status :: 5 - Production/Stable
11
- Classifier: Intended Audience :: Developers
12
- Classifier: Operating System :: OS Independent
13
- Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Programming Language :: Python :: 3.6
15
- Classifier: Programming Language :: Python :: 3.7
16
- Classifier: Programming Language :: Python :: 3.8
17
- Classifier: Programming Language :: Python :: 3.9
18
- Classifier: Programming Language :: Python :: Implementation :: PyPy
19
- Description-Content-Type: text/markdown
20
- Provides-Extra: test
21
-
22
- [![Coverage Status](https://coveralls.io/repos/github/sonic182/onecache/badge.svg?branch=master)](https://coveralls.io/github/sonic182/onecache?branch=master)
23
- ![github status](https://github.com/sonic182/onecache/actions/workflows/python.yml/badge.svg)
24
- # OneCache
25
-
26
- Python cache for sync and async code.
27
-
28
- Cache uses LRU algoritm. Cache can optionally have TTL.
29
-
30
- Tested in python 3.7, 3.9, and pypy3.9 for windows, mac and linux (see github status badge), it should work in versions between them. It may work for python3.6
31
-
32
- # Usage
33
-
34
- ```python
35
- from onecache import CacheDecorator
36
- from onecache import AsyncCacheDecorator
37
-
38
-
39
- class Counter:
40
- def __init__(self, count=0):
41
- self.count = count
42
-
43
-
44
- @pytest.mark.asyncio
45
- async def test_async_cache_counter():
46
- """Test async cache, counter case."""
47
- counter = Counter()
48
-
49
- @AsyncCacheDecorator()
50
- async def mycoro(counter: Counter):
51
- counter.count += 1
52
- return counter.count
53
-
54
- assert 1 == (await mycoro(counter))
55
- assert 1 == (await mycoro(counter))
56
-
57
-
58
- def test_cache_counter():
59
- """Test async cache, counter case."""
60
- counter = Counter()
61
-
62
- @CacheDecorator()
63
- def sample(counter: Counter):
64
- counter.count += 1
65
- return counter.count
66
-
67
- assert 1 == (sample(counter))
68
- assert 1 == (sample(counter))
69
- ```
70
-
71
- Decorator classes supports the following arguments
72
-
73
- * **maxsize (int)**: Maximun number of items to be cached. default: 512
74
- * **ttl (int)**: time to expire in milliseconds, if None, it does not expire. default: None
75
- * **skip_args (bool)**: apply cache as the function doesn't have any arguments, default: False
76
- * **cache_class (class)**: Class to use for cache instance. default: LRUCache
77
- * **refresh_ttl (bool)**: if cache with ttl, This flag makes key expiration timestamp to be refresh per access. default: False
78
- * **thread_safe (bool)**: tell decorator to use thread safe lock. default=False
79
- * **max_mem_size (int)**: max mem size in bytes. Ceil for sum of cache values sizes. default=None which means no limit. For pypy this value is ignored as the objects can change by the JIT compilation.
80
-
81
- If num of records exceds maxsize, it drops the oldest.
82
-
83
-
84
- # Development
85
-
86
- Install packages with pip-tools:
87
- ```bash
88
- pip install pip-tools
89
- pip-compile
90
- pip-compile test-requirements.in
91
- pip-sync requirements.txt test-requirements.txt
92
- ```
93
-
94
- # Contribute
95
-
96
- 1. Fork
97
- 2. create a branch `feature/your_feature`
98
- 3. commit - push - pull request
99
-
100
- Thanks :)
101
-
@@ -1,14 +0,0 @@
1
- MANIFEST.in
2
- README.md
3
- requirements.txt
4
- setup.cfg
5
- setup.py
6
- test-requirements.txt
7
- onecache/__init__.py
8
- onecache/cache_value.py
9
- onecache/utils.py
10
- onecache.egg-info/PKG-INFO
11
- onecache.egg-info/SOURCES.txt
12
- onecache.egg-info/dependency_links.txt
13
- onecache.egg-info/requires.txt
14
- onecache.egg-info/top_level.txt
@@ -1,42 +0,0 @@
1
-
2
- [test]
3
- astroid==2.6.2
4
- attrs==21.2.0
5
- autopep8==1.5.7
6
- black==23.1.0
7
- certifi==2021.5.30
8
- charset-normalizer==2.0.2
9
- click==8.1.3
10
- coverage==5.5
11
- coveralls==3.1.0
12
- docopt==0.6.2
13
- flake8==3.9.2
14
- flake8-docstrings==1.6.0
15
- idna==3.2
16
- iniconfig==1.1.1
17
- isort==5.9.2
18
- lazy-object-proxy==1.6.0
19
- mccabe==0.6.1
20
- mypy-extensions==1.0.0
21
- packaging==23.0
22
- pathspec==0.11.1
23
- platformdirs==3.2.0
24
- pluggy==0.13.1
25
- py==1.10.0
26
- pycodestyle==2.7.0
27
- pydocstyle==6.1.1
28
- pyflakes==2.3.1
29
- pylint==2.9.3
30
- pytest==6.2.4
31
- pytest-asyncio==0.15.1
32
- pytest-black==0.3.12
33
- pytest-cov==2.12.1
34
- pytest-sugar==0.9.4
35
- requests==2.26.0
36
- snowballstemmer==2.1.0
37
- termcolor==1.1.0
38
- toml==0.10.2
39
- tomli==2.0.1
40
- typing-extensions==4.5.0
41
- urllib3==1.26.6
42
- wrapt==1.12.1
@@ -1 +0,0 @@
1
- onecache
@@ -1,6 +0,0 @@
1
- #
2
- # This file is autogenerated by pip-compile
3
- # To update, run:
4
- #
5
- # pip-compile --output-file requirements.txt requirements.in
6
- #
onecache-0.5.1/setup.cfg DELETED
@@ -1,19 +0,0 @@
1
- [metadata]
2
- description-file = Readme.md
3
-
4
- [aliases]
5
- test = pytest
6
-
7
- [tool:pytest]
8
- python_files = **/*.py
9
- testpaths = tests/
10
- python_functions = test_*
11
- addopts = --cov=onecache --cov-report term --cov-report html --black
12
-
13
- [coverage:run]
14
- relative_files = True
15
-
16
- [egg_info]
17
- tag_build =
18
- tag_date = 0
19
-
onecache-0.5.1/setup.py DELETED
@@ -1,94 +0,0 @@
1
- """Setup module."""
2
- import os
3
- import sys
4
- from shutil import which
5
-
6
- from pkg_resources import parse_requirements
7
- from setuptools import Extension, setup
8
-
9
- try:
10
- from Cython.Build import cythonize
11
- except ImportError:
12
- cythonize = None
13
-
14
-
15
- NO_EXTENSIONS: bool = bool(os.environ.get("ONECACHE_NO_EXTENSIONS"))
16
-
17
-
18
- if sys.implementation.name != "cpython":
19
- NO_EXTENSIONS = True
20
-
21
-
22
- def no_extensions():
23
- is_compiler = False
24
- for compiler in ["gcc", "clang"]:
25
- is_compiler = which(compiler) is not None
26
- return NO_EXTENSIONS or not is_compiler
27
-
28
-
29
- # https://cython.readthedocs.io/en/latest/src/userguide/source_files_and_compilation.html#distributing-cython-modules
30
- def no_cythonize(extensions, **_ignore):
31
- for extension in extensions:
32
- sources = []
33
- for sfile in extension.sources:
34
- path, ext = os.path.splitext(sfile)
35
- if ext in (".pyx", ".py"):
36
- if extension.language == "c++":
37
- ext = ".cpp"
38
- else:
39
- ext = ".c"
40
- sfile = path + ext
41
- sources.append(sfile)
42
- extension.sources[:] = sources
43
- return extensions
44
-
45
-
46
- extensions = [
47
- Extension("onecache.cache_value", ["onecache/cache_value.pyx"]),
48
- ]
49
-
50
- CYTHONIZE = bool(int(os.getenv("CYTHONIZE", 0))) and cythonize is not None
51
-
52
- if CYTHONIZE:
53
- compiler_directives = {"language_level": 3, "embedsignature": True}
54
- extensions = cythonize(extensions, compiler_directives=compiler_directives)
55
- else:
56
- extensions = no_cythonize(extensions)
57
-
58
-
59
- def read_file(filename):
60
- """Read file correctly."""
61
- with open(filename) as _file:
62
- return _file.read().strip()
63
-
64
-
65
- def requirements(filename):
66
- """Parse requirements from file."""
67
- return [str(req) for req in parse_requirements(read_file(filename))]
68
-
69
-
70
- setup(
71
- name="onecache",
72
- version="0.5.1",
73
- description="Python cache for sync and async code",
74
- long_description=read_file("README.md"),
75
- long_description_content_type="text/markdown",
76
- author="Johanderson Mogollon",
77
- author_email="johander1822@gmail.com",
78
- license="MIT",
79
- packages=["onecache"],
80
- ext_modules=[] if no_extensions() else extensions,
81
- classifiers=[
82
- "Development Status :: 5 - Production/Stable",
83
- "Intended Audience :: Developers",
84
- "Operating System :: OS Independent",
85
- "License :: OSI Approved :: MIT License",
86
- "Programming Language :: Python :: 3.6",
87
- "Programming Language :: Python :: 3.7",
88
- "Programming Language :: Python :: 3.8",
89
- "Programming Language :: Python :: 3.9",
90
- "Programming Language :: Python :: Implementation :: PyPy",
91
- ],
92
- install_requires=requirements("./requirements.txt"),
93
- extras_require={"test": requirements("./test-requirements.txt")},
94
- )
@@ -1,107 +0,0 @@
1
- #
2
- # This file is autogenerated by pip-compile with Python 3.9
3
- # by the following command:
4
- #
5
- # pip-compile test-requirements.in
6
- #
7
- astroid==2.6.2
8
- # via pylint
9
- attrs==21.2.0
10
- # via pytest
11
- autopep8==1.5.7
12
- # via -r test-requirements.in
13
- black==23.1.0
14
- # via pytest-black
15
- certifi==2021.5.30
16
- # via requests
17
- charset-normalizer==2.0.2
18
- # via requests
19
- click==8.1.3
20
- # via black
21
- coverage==5.5
22
- # via
23
- # coveralls
24
- # pytest-cov
25
- coveralls==3.1.0
26
- # via -r test-requirements.in
27
- docopt==0.6.2
28
- # via coveralls
29
- flake8==3.9.2
30
- # via
31
- # -r test-requirements.in
32
- # flake8-docstrings
33
- flake8-docstrings==1.6.0
34
- # via -r test-requirements.in
35
- idna==3.2
36
- # via requests
37
- iniconfig==1.1.1
38
- # via pytest
39
- isort==5.9.2
40
- # via pylint
41
- lazy-object-proxy==1.6.0
42
- # via astroid
43
- mccabe==0.6.1
44
- # via
45
- # flake8
46
- # pylint
47
- mypy-extensions==1.0.0
48
- # via black
49
- packaging==23.0
50
- # via
51
- # black
52
- # pytest
53
- # pytest-sugar
54
- pathspec==0.11.1
55
- # via black
56
- platformdirs==3.2.0
57
- # via black
58
- pluggy==0.13.1
59
- # via pytest
60
- py==1.10.0
61
- # via pytest
62
- pycodestyle==2.7.0
63
- # via
64
- # autopep8
65
- # flake8
66
- pydocstyle==6.1.1
67
- # via flake8-docstrings
68
- pyflakes==2.3.1
69
- # via flake8
70
- pylint==2.9.3
71
- # via -r test-requirements.in
72
- pytest==6.2.4
73
- # via
74
- # -r test-requirements.in
75
- # pytest-asyncio
76
- # pytest-black
77
- # pytest-cov
78
- # pytest-sugar
79
- pytest-asyncio==0.15.1
80
- # via -r test-requirements.in
81
- pytest-black==0.3.12
82
- # via -r test-requirements.in
83
- pytest-cov==2.12.1
84
- # via -r test-requirements.in
85
- pytest-sugar==0.9.4
86
- # via -r test-requirements.in
87
- requests==2.26.0
88
- # via coveralls
89
- snowballstemmer==2.1.0
90
- # via pydocstyle
91
- termcolor==1.1.0
92
- # via pytest-sugar
93
- toml==0.10.2
94
- # via
95
- # autopep8
96
- # pylint
97
- # pytest
98
- # pytest-black
99
- # pytest-cov
100
- tomli==2.0.1
101
- # via black
102
- typing-extensions==4.5.0
103
- # via black
104
- urllib3==1.26.6
105
- # via requests
106
- wrapt==1.12.1
107
- # via astroid