cachier 2.1.1__tar.gz → 2.2.1__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.
Files changed (49) hide show
  1. {cachier-2.1.1 → cachier-2.2.1}/.coveragerc +3 -0
  2. {cachier-2.1.1 → cachier-2.2.1}/.github/workflows/lint.yml +6 -4
  3. {cachier-2.1.1 → cachier-2.2.1}/.github/workflows/test.yml +2 -2
  4. {cachier-2.1.1 → cachier-2.2.1}/PKG-INFO +8 -5
  5. {cachier-2.1.1 → cachier-2.2.1}/README.rst +6 -1
  6. {cachier-2.1.1 → cachier-2.2.1}/cachier/_version.py +2 -2
  7. {cachier-2.1.1 → cachier-2.2.1}/cachier/core.py +54 -27
  8. {cachier-2.1.1 → cachier-2.2.1}/cachier.egg-info/PKG-INFO +8 -5
  9. {cachier-2.1.1 → cachier-2.2.1}/cachier.egg-info/SOURCES.txt +2 -0
  10. cachier-2.2.1/cachier.egg-info/entry_points.txt +2 -0
  11. {cachier-2.1.1 → cachier-2.2.1}/cachier.egg-info/requires.txt +3 -0
  12. cachier-2.2.1/mypy.ini +11 -0
  13. {cachier-2.1.1 → cachier-2.2.1}/setup.py +4 -3
  14. cachier-2.2.1/tests/__init__.py +0 -0
  15. {cachier-2.1.1 → cachier-2.2.1}/tests/test_core_lookup.py +1 -0
  16. {cachier-2.1.1 → cachier-2.2.1}/tests/test_defaults.py +37 -4
  17. {cachier-2.1.1 → cachier-2.2.1}/tests/test_general.py +38 -3
  18. {cachier-2.1.1 → cachier-2.2.1}/tests/test_mongo_core.py +8 -10
  19. {cachier-2.1.1 → cachier-2.2.1}/tests/test_pickle_core.py +5 -7
  20. {cachier-2.1.1 → cachier-2.2.1}/versioneer.py +3 -2
  21. cachier-2.1.1/cachier.egg-info/entry_points.txt +0 -4
  22. {cachier-2.1.1 → cachier-2.2.1}/.codecov.yml +0 -0
  23. {cachier-2.1.1 → cachier-2.2.1}/.deepsource.toml +0 -0
  24. {cachier-2.1.1 → cachier-2.2.1}/.fdignore +0 -0
  25. {cachier-2.1.1 → cachier-2.2.1}/.flake8 +0 -0
  26. {cachier-2.1.1 → cachier-2.2.1}/.gitattributes +0 -0
  27. {cachier-2.1.1 → cachier-2.2.1}/.github/workflows/checkdocs.yml +0 -0
  28. {cachier-2.1.1 → cachier-2.2.1}/.gitignore +0 -0
  29. {cachier-2.1.1 → cachier-2.2.1}/.ignore +0 -0
  30. {cachier-2.1.1 → cachier-2.2.1}/.pylintrc +0 -0
  31. {cachier-2.1.1 → cachier-2.2.1}/LICENSE +0 -0
  32. {cachier-2.1.1 → cachier-2.2.1}/MANIFEST.in +0 -0
  33. {cachier-2.1.1 → cachier-2.2.1}/cachier/__init__.py +0 -0
  34. {cachier-2.1.1 → cachier-2.2.1}/cachier/base_core.py +0 -0
  35. {cachier-2.1.1 → cachier-2.2.1}/cachier/memory_core.py +0 -0
  36. {cachier-2.1.1 → cachier-2.2.1}/cachier/mongo_core.py +0 -0
  37. {cachier-2.1.1 → cachier-2.2.1}/cachier/pickle_core.py +0 -0
  38. /cachier-2.1.1/cachier/scripts/__init__.py → /cachier-2.2.1/cachier/py.typed +0 -0
  39. {cachier-2.1.1/tests → cachier-2.2.1/cachier/scripts}/__init__.py +0 -0
  40. {cachier-2.1.1 → cachier-2.2.1}/cachier/scripts/cli.py +0 -0
  41. {cachier-2.1.1 → cachier-2.2.1}/cachier.egg-info/dependency_links.txt +0 -0
  42. {cachier-2.1.1 → cachier-2.2.1}/cachier.egg-info/top_level.txt +0 -0
  43. {cachier-2.1.1 → cachier-2.2.1}/pytest.ini +0 -0
  44. {cachier-2.1.1 → cachier-2.2.1}/setup.cfg +0 -0
  45. {cachier-2.1.1 → cachier-2.2.1}/tests/speed_eval.py +0 -0
  46. {cachier-2.1.1 → cachier-2.2.1}/tests/standalone_script.py +0 -0
  47. {cachier-2.1.1 → cachier-2.2.1}/tests/test_memory_core.py +0 -0
  48. {cachier-2.1.1 → cachier-2.2.1}/tests/test_quality.py +0 -0
  49. {cachier-2.1.1 → cachier-2.2.1}/tests/test_security.py +0 -0
@@ -15,3 +15,6 @@ exclude_lines =
15
15
 
16
16
  # Don't complain if tests don't hit defensive assertion code:
17
17
  raise NotImplementedError
18
+
19
+ # Is only true when running mypy, not tests
20
+ if TYPE_CHECKING:
@@ -12,7 +12,7 @@ jobs:
12
12
  strategy:
13
13
  fail-fast: false
14
14
  matrix:
15
- python-version: ['3.10']
15
+ python-version: ["3.10"]
16
16
  os: [ubuntu-latest]
17
17
 
18
18
  steps:
@@ -22,15 +22,17 @@ jobs:
22
22
  - name: set up python '3.10'
23
23
  uses: actions/setup-python@v4.5.0
24
24
  with:
25
- python-version: '3.10'
25
+ python-version: "3.10"
26
26
 
27
27
  # Install your linters here
28
- - name: Install flake8
28
+ - name: Install linters
29
29
  run: |
30
- python -m pip install flake8
30
+ python -m pip install -e ".[test]"
31
+
31
32
  - name: Run linters
32
33
  uses: wearerequired/lint-action@v2.3.0
33
34
  with:
34
35
  flake8: true
36
+ mypy: true
35
37
  continue_on_error: false
36
38
  # Enable your linters here
@@ -16,7 +16,7 @@ jobs:
16
16
  strategy:
17
17
  fail-fast: false
18
18
  matrix:
19
- python-version: [3.7, 3.8, 3.9, '3.10']
19
+ python-version: [3.8, 3.9, '3.10', '3.11']
20
20
  os: [ubuntu-latest, macOS-latest, windows-latest]
21
21
 
22
22
  steps:
@@ -35,6 +35,6 @@ jobs:
35
35
  run: |
36
36
  pytest
37
37
  - name: "Upload coverage to Codecov"
38
- uses: codecov/codecov-action@v3.1.1
38
+ uses: codecov/codecov-action@v3
39
39
  with:
40
40
  fail_ci_if_error: true
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cachier
3
- Version: 2.1.1
3
+ Version: 2.2.1
4
4
  Summary: Persistent, stale-free, local and cross-machine caching for Python functions.
5
5
  Home-page: https://github.com/python-cachier/cachier
6
6
  Author: Shay Palachy
@@ -14,10 +14,10 @@ Classifier: Development Status :: 4 - Beta
14
14
  Classifier: License :: OSI Approved :: MIT License
15
15
  Classifier: Programming Language :: Python
16
16
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.7
18
17
  Classifier: Programming Language :: Python :: 3.8
19
18
  Classifier: Programming Language :: Python :: 3.9
20
19
  Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
21
  Classifier: Topic :: Software Development :: Libraries
22
22
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
23
  Classifier: Topic :: Utilities
@@ -72,7 +72,7 @@ Features
72
72
  ========
73
73
 
74
74
  * Pure Python.
75
- * Compatible with Python 3.5+ (and Python 2.7 up until version 1.2.8).
75
+ * Compatible with Python 3.8+ (Python 2.7 was discontinued in version 1.2.8).
76
76
  * Supported and `tested on Linux, OS X and Windows <https://travis-ci.org/shaypal5/cachier>`_.
77
77
  * A simple interface.
78
78
  * Defining "shelf life" for cached values.
@@ -167,6 +167,7 @@ The following parameters will only be applied to decorators defined after `set_d
167
167
 
168
168
  These parameters can be changed at any time and they will apply to all decorators:
169
169
 
170
+ * `allow_none`
170
171
  * `caching_enabled`
171
172
  * `stale_after`
172
173
  * `next_time`
@@ -284,6 +285,10 @@ Verbose Cache Call
284
285
 
285
286
  You can have ``cachier`` print out a detailed explanation of the logic of a specific call by passing ``verbose_cache=True`` to the function call. This can be useful if you are not sure why a certain function result is, or is not, returned.
286
287
 
288
+ Cache `None` Values
289
+ ~~~~~~~~~~~~~~~~~~~
290
+
291
+ By default, ``cachier`` does not cache ``None`` values. You can override this behaviour by passing ``allow_none=True`` to the function call.
287
292
 
288
293
 
289
294
  Cachier Cores
@@ -492,5 +497,3 @@ Notable bugfixers:
492
497
  .. links:
493
498
  .. _pymongo: https://api.mongodb.com/python/current/
494
499
  .. _watchdog: https://github.com/gorakhargosh/watchdog
495
-
496
-
@@ -44,7 +44,7 @@ Features
44
44
  ========
45
45
 
46
46
  * Pure Python.
47
- * Compatible with Python 3.5+ (and Python 2.7 up until version 1.2.8).
47
+ * Compatible with Python 3.8+ (Python 2.7 was discontinued in version 1.2.8).
48
48
  * Supported and `tested on Linux, OS X and Windows <https://travis-ci.org/shaypal5/cachier>`_.
49
49
  * A simple interface.
50
50
  * Defining "shelf life" for cached values.
@@ -139,6 +139,7 @@ The following parameters will only be applied to decorators defined after `set_d
139
139
 
140
140
  These parameters can be changed at any time and they will apply to all decorators:
141
141
 
142
+ * `allow_none`
142
143
  * `caching_enabled`
143
144
  * `stale_after`
144
145
  * `next_time`
@@ -256,6 +257,10 @@ Verbose Cache Call
256
257
 
257
258
  You can have ``cachier`` print out a detailed explanation of the logic of a specific call by passing ``verbose_cache=True`` to the function call. This can be useful if you are not sure why a certain function result is, or is not, returned.
258
259
 
260
+ Cache `None` Values
261
+ ~~~~~~~~~~~~~~~~~~~
262
+
263
+ By default, ``cachier`` does not cache ``None`` values. You can override this behaviour by passing ``allow_none=True`` to the function call.
259
264
 
260
265
 
261
266
  Cachier Cores
@@ -11,8 +11,8 @@ version_json = '''
11
11
  {
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "7bd2c7797bad62a6fc4ba4ddc04289426ea1115c",
15
- "version": "2.1.1"
14
+ "full-revisionid": "5776ee8d63c8a5719ccd3737f0f504bc1a7eb679",
15
+ "version": "2.2.1"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -8,24 +8,25 @@
8
8
  # Copyright (c) 2016, Shay Palachy <shaypal5@gmail.com>
9
9
 
10
10
  # python 2 compatibility
11
- from __future__ import absolute_import
12
- from __future__ import division
13
- from __future__ import print_function
14
-
15
- import os
16
- from functools import wraps
17
- from warnings import warn
11
+ from __future__ import absolute_import, division, print_function
18
12
 
19
13
  import datetime
20
14
  import functools
21
15
  import hashlib
16
+ import os
22
17
  import pickle
23
18
  from concurrent.futures import ThreadPoolExecutor
19
+ from functools import wraps
20
+ from typing import TYPE_CHECKING, Callable, Literal, Optional, TypedDict, Union
21
+ from warnings import warn
24
22
 
25
- from .base_core import RecalculationNeeded
26
- from .pickle_core import _PickleCore
27
- from .mongo_core import _MongoCore
23
+ from .base_core import RecalculationNeeded, _BaseCore
28
24
  from .memory_core import _MemoryCore
25
+ from .mongo_core import _MongoCore
26
+ from .pickle_core import _PickleCore
27
+
28
+ if TYPE_CHECKING:
29
+ import pymongo.collection
29
30
 
30
31
 
31
32
  MAX_WORKERS_ENVAR_NAME = 'CACHIER_MAX_WORKERS'
@@ -92,7 +93,26 @@ class MissingMongetter(ValueError):
92
93
  """Thrown when the mongetter keyword argument is missing."""
93
94
 
94
95
 
95
- _default_params = {
96
+ HashFunc = Callable[..., str]
97
+ Mongetter = Callable[[], "pymongo.collection.Collection"]
98
+ Backend = Literal["pickle", "mongo", "memory"]
99
+
100
+
101
+ class Params(TypedDict):
102
+ caching_enabled: bool
103
+ hash_func: HashFunc
104
+ backend: Backend
105
+ mongetter: Optional[Mongetter]
106
+ stale_after: datetime.timedelta
107
+ next_time: bool
108
+ cache_dir: Union[str, os.PathLike]
109
+ pickle_reload: bool
110
+ separate_files: bool
111
+ wait_for_calc_timeout: int
112
+ allow_none: bool
113
+
114
+
115
+ _default_params: Params = {
96
116
  'caching_enabled': True,
97
117
  'hash_func': _default_hash_func,
98
118
  'backend': 'pickle',
@@ -103,20 +123,22 @@ _default_params = {
103
123
  'pickle_reload': True,
104
124
  'separate_files': False,
105
125
  'wait_for_calc_timeout': 0,
126
+ 'allow_none': False,
106
127
  }
107
128
 
108
129
 
109
130
  def cachier(
110
- hash_func=None,
111
- hash_params=None,
112
- backend=None,
113
- mongetter=None,
114
- stale_after=None,
115
- next_time=None,
116
- cache_dir=None,
117
- pickle_reload=None,
118
- separate_files=None,
119
- wait_for_calc_timeout=None,
131
+ hash_func: Optional[HashFunc] = None,
132
+ hash_params: Optional[HashFunc] = None,
133
+ backend: Optional[Backend] = None,
134
+ mongetter: Optional[Mongetter] = None,
135
+ stale_after: Optional[datetime.timedelta] = None,
136
+ next_time: Optional[bool] = None,
137
+ cache_dir: Optional[Union[str, os.PathLike]] = None,
138
+ pickle_reload: Optional[bool] = None,
139
+ separate_files: Optional[bool] = None,
140
+ wait_for_calc_timeout: Optional[int] = None,
141
+ allow_none: Optional[bool] = None,
120
142
  ):
121
143
  """A persistent, stale-free memoization decorator.
122
144
 
@@ -170,6 +192,9 @@ def cachier(
170
192
  True, any process trying to read the same entry will wait a maximum of
171
193
  seconds specified in this parameter. 0 means wait forever.
172
194
  Once the timeout expires the calculation will be triggered.
195
+ allow_none: bool, optional
196
+ Allows storing None values in the cache. If False, functions returning
197
+ None will not be cached and are recalculated every call.
173
198
  """
174
199
  # Check for deprecated parameters
175
200
  if hash_params is not None:
@@ -184,6 +209,7 @@ def cachier(
184
209
  backend = 'mongo'
185
210
  if backend is None:
186
211
  backend = _default_params['backend']
212
+ core: _BaseCore
187
213
  if backend == 'pickle':
188
214
  core = _PickleCore( # pylint: disable=R0204
189
215
  hash_func=hash_func,
@@ -208,11 +234,6 @@ def cachier(
208
234
  hash_func=hash_func,
209
235
  default_params=_default_params,
210
236
  )
211
- elif backend == 'redis':
212
- raise NotImplementedError(
213
- 'A Redis backend has not yet been implemented. '
214
- 'Please see https://github.com/python-cachier/cachier/issues/4'
215
- )
216
237
  else:
217
238
  raise ValueError('specified an invalid core: {}'.format(backend))
218
239
 
@@ -221,6 +242,12 @@ def cachier(
221
242
 
222
243
  @wraps(func)
223
244
  def func_wrapper(*args, **kwds): # pylint: disable=C0111,R0911
245
+ nonlocal allow_none
246
+ _allow_none = (
247
+ allow_none
248
+ if allow_none is not None else
249
+ _default_params['allow_none']
250
+ )
224
251
  # print('Inside general wrapper for {}.'.format(func.__name__))
225
252
  ignore_cache = kwds.pop('ignore_cache', False)
226
253
  overwrite_cache = kwds.pop('overwrite_cache', False)
@@ -238,7 +265,7 @@ def cachier(
238
265
  return _calc_entry(core, key, func, args, kwds)
239
266
  if entry is not None: # pylint: disable=R0101
240
267
  _print('Entry found.')
241
- if entry.get('value', None) is not None:
268
+ if (_allow_none or entry.get('value', None) is not None):
242
269
  _print('Cached result found.')
243
270
  local_stale_after = stale_after if stale_after is not None else _default_params['stale_after'] # noqa: E501
244
271
  local_next_time = next_time if next_time is not None else _default_params['next_time'] # noqa: E501
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cachier
3
- Version: 2.1.1
3
+ Version: 2.2.1
4
4
  Summary: Persistent, stale-free, local and cross-machine caching for Python functions.
5
5
  Home-page: https://github.com/python-cachier/cachier
6
6
  Author: Shay Palachy
@@ -14,10 +14,10 @@ Classifier: Development Status :: 4 - Beta
14
14
  Classifier: License :: OSI Approved :: MIT License
15
15
  Classifier: Programming Language :: Python
16
16
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.7
18
17
  Classifier: Programming Language :: Python :: 3.8
19
18
  Classifier: Programming Language :: Python :: 3.9
20
19
  Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
21
  Classifier: Topic :: Software Development :: Libraries
22
22
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
23
  Classifier: Topic :: Utilities
@@ -72,7 +72,7 @@ Features
72
72
  ========
73
73
 
74
74
  * Pure Python.
75
- * Compatible with Python 3.5+ (and Python 2.7 up until version 1.2.8).
75
+ * Compatible with Python 3.8+ (Python 2.7 was discontinued in version 1.2.8).
76
76
  * Supported and `tested on Linux, OS X and Windows <https://travis-ci.org/shaypal5/cachier>`_.
77
77
  * A simple interface.
78
78
  * Defining "shelf life" for cached values.
@@ -167,6 +167,7 @@ The following parameters will only be applied to decorators defined after `set_d
167
167
 
168
168
  These parameters can be changed at any time and they will apply to all decorators:
169
169
 
170
+ * `allow_none`
170
171
  * `caching_enabled`
171
172
  * `stale_after`
172
173
  * `next_time`
@@ -284,6 +285,10 @@ Verbose Cache Call
284
285
 
285
286
  You can have ``cachier`` print out a detailed explanation of the logic of a specific call by passing ``verbose_cache=True`` to the function call. This can be useful if you are not sure why a certain function result is, or is not, returned.
286
287
 
288
+ Cache `None` Values
289
+ ~~~~~~~~~~~~~~~~~~~
290
+
291
+ By default, ``cachier`` does not cache ``None`` values. You can override this behaviour by passing ``allow_none=True`` to the function call.
287
292
 
288
293
 
289
294
  Cachier Cores
@@ -492,5 +497,3 @@ Notable bugfixers:
492
497
  .. links:
493
498
  .. _pymongo: https://api.mongodb.com/python/current/
494
499
  .. _watchdog: https://github.com/gorakhargosh/watchdog
495
-
496
-
@@ -10,6 +10,7 @@
10
10
  LICENSE
11
11
  MANIFEST.in
12
12
  README.rst
13
+ mypy.ini
13
14
  pytest.ini
14
15
  setup.cfg
15
16
  setup.py
@@ -24,6 +25,7 @@ cachier/core.py
24
25
  cachier/memory_core.py
25
26
  cachier/mongo_core.py
26
27
  cachier/pickle_core.py
28
+ cachier/py.typed
27
29
  cachier.egg-info/PKG-INFO
28
30
  cachier.egg-info/SOURCES.txt
29
31
  cachier.egg-info/dependency_links.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ cachier = cachier.scripts.cli:cli
@@ -11,6 +11,9 @@ bandit
11
11
  flake8
12
12
  pylint
13
13
  safety
14
+ mypy
15
+ types-setuptools
16
+ pandas-stubs
14
17
  pymongo
15
18
  dnspython
16
19
  pymongo-inmemory
cachier-2.2.1/mypy.ini ADDED
@@ -0,0 +1,11 @@
1
+ [mypy]
2
+ show_column_numbers=true
3
+ show_error_codes=true
4
+ strict_equality=true
5
+ warn_unused_ignores=true
6
+ warn_redundant_casts=true
7
+ warn_unreachable=true
8
+ warn_return_any=false
9
+
10
+ [mypy-pymongo_inmemory.*]
11
+ ignore_missing_imports = True
@@ -10,16 +10,17 @@
10
10
  try:
11
11
  from setuptools import setup
12
12
  except ImportError:
13
- from distutils.core import setup
13
+ from distutils.core import setup # type: ignore
14
14
 
15
15
  import versioneer
16
16
 
17
-
18
17
  TEST_REQUIRES = [
19
18
  # tests and coverages
20
19
  'pytest', 'coverage', 'pytest-cov',
21
20
  # linting and code quality
22
21
  'bandit', 'flake8', 'pylint', 'safety',
22
+ # type checking
23
+ 'mypy', 'types-setuptools', 'pandas-stubs',
23
24
  # to connect to the test mongodb server
24
25
  'pymongo', 'dnspython', 'pymongo-inmemory',
25
26
  # to test pandas dataframe as-param hashing with mongodb core
@@ -66,10 +67,10 @@ setup(
66
67
  'License :: OSI Approved :: MIT License',
67
68
  'Programming Language :: Python',
68
69
  'Programming Language :: Python :: 3',
69
- 'Programming Language :: Python :: 3.7',
70
70
  'Programming Language :: Python :: 3.8',
71
71
  'Programming Language :: Python :: 3.9',
72
72
  'Programming Language :: Python :: 3.10',
73
+ 'Programming Language :: Python :: 3.11',
73
74
  'Topic :: Software Development :: Libraries',
74
75
  'Topic :: Software Development :: Libraries :: Python Modules',
75
76
  'Topic :: Utilities',
File without changes
@@ -7,6 +7,7 @@ from cachier.core import MissingMongetter
7
7
  def test_get_default_params():
8
8
  params = get_default_params()
9
9
  assert tuple(sorted(params)) == (
10
+ 'allow_none',
10
11
  'backend',
11
12
  'cache_dir',
12
13
  'caching_enabled',
@@ -1,16 +1,15 @@
1
1
  import datetime
2
2
  import os
3
- import pytest
4
3
  import queue
5
4
  import random
6
5
  import tempfile
7
6
  import threading
8
7
  import time
9
8
 
10
- import cachier
11
-
12
- from tests.test_mongo_core import _test_mongetter, MONGO_DELTA
9
+ import pytest
13
10
 
11
+ import cachier
12
+ from tests.test_mongo_core import MONGO_DELTA, _test_mongetter
14
13
 
15
14
  _default_params = cachier.get_default_params().copy()
16
15
 
@@ -125,6 +124,40 @@ def test_separate_files_default_param():
125
124
  assert len(os.listdir(cache_dir_2)) == 1
126
125
 
127
126
 
127
+ def test_allow_none_default_param():
128
+ cachier.set_default_params(
129
+ allow_none=True,
130
+ separate_files=True,
131
+ verbose_cache=True,
132
+ )
133
+ allow_count = 0
134
+ disallow_count = 0
135
+
136
+ @cachier.cachier(cache_dir=tempfile.mkdtemp())
137
+ def allow_none():
138
+ nonlocal allow_count
139
+ allow_count += 1
140
+ return None
141
+
142
+ @cachier.cachier(cache_dir=tempfile.mkdtemp(), allow_none=False)
143
+ def disallow_none():
144
+ nonlocal disallow_count
145
+ disallow_count += 1
146
+ return None
147
+
148
+ allow_none.clear_cache()
149
+ assert allow_count == 0
150
+ allow_none()
151
+ allow_none()
152
+ assert allow_count == 1
153
+
154
+ disallow_none.clear_cache()
155
+ assert disallow_count == 0
156
+ disallow_none()
157
+ disallow_none()
158
+ assert disallow_count == 2
159
+
160
+
128
161
  parametrize_keys = 'backend,mongetter'
129
162
  parametrize_values = [
130
163
  pytest.param('pickle', None, marks=pytest.mark.pickle),
@@ -1,6 +1,7 @@
1
1
  """Non-core-specific tests for cachier."""
2
2
 
3
3
  from __future__ import print_function
4
+
4
5
  import functools
5
6
  import os
6
7
  import queue
@@ -8,18 +9,20 @@ import subprocess # nosec: B404
8
9
  import threading
9
10
  from random import random
10
11
  from time import sleep, time
12
+
11
13
  import pytest
14
+
12
15
  import cachier
13
16
  from cachier.core import (
14
- MAX_WORKERS_ENVAR_NAME,
15
17
  DEFAULT_MAX_WORKERS,
18
+ MAX_WORKERS_ENVAR_NAME,
19
+ _get_executor,
16
20
  _max_workers,
17
21
  _set_max_workers,
18
- _get_executor
19
22
  )
20
23
  from tests.test_mongo_core import (
21
- _test_mongetter,
22
24
  MONGO_DELTA_LONG,
25
+ _test_mongetter,
23
26
  )
24
27
 
25
28
 
@@ -240,3 +243,35 @@ def test_global_disable():
240
243
  result_4 = get_random()
241
244
  assert result_1 == result_2 == result_4
242
245
  assert result_1 != result_3
246
+
247
+
248
+ def test_none_not_cached_by_default():
249
+ count = 0
250
+
251
+ @cachier.cachier()
252
+ def do_operation():
253
+ nonlocal count
254
+ count += 1
255
+ return None
256
+
257
+ do_operation.clear_cache()
258
+ assert count == 0
259
+ do_operation()
260
+ do_operation()
261
+ assert count == 2
262
+
263
+
264
+ def test_allow_caching_none():
265
+ count = 0
266
+
267
+ @cachier.cachier(allow_none=True)
268
+ def do_operation():
269
+ nonlocal count
270
+ count += 1
271
+ return None
272
+
273
+ do_operation.clear_cache()
274
+ assert count == 0
275
+ do_operation()
276
+ do_operation()
277
+ assert count == 1
@@ -1,27 +1,25 @@
1
1
  """Testing the MongoDB core of cachier."""
2
2
 
3
- import sys
4
- import platform
5
3
  import datetime
4
+ import hashlib
5
+ import platform
6
+ import queue
7
+ import sys
8
+ import threading
6
9
  from datetime import timedelta
7
10
  from random import random
8
11
  from time import sleep
9
- import threading
10
- import queue
11
12
 
12
- import pytest
13
- import pymongo
14
- import hashlib
15
13
  import pandas as pd
14
+ import pymongo
15
+ import pytest
16
16
  from pymongo.errors import OperationFailure
17
+ from pymongo_inmemory import MongoClient
17
18
 
18
19
  from cachier import cachier
19
20
  from cachier.base_core import RecalculationNeeded
20
21
  from cachier.mongo_core import _MongoCore
21
22
 
22
- from pymongo_inmemory import MongoClient
23
-
24
-
25
23
  _COLLECTION_NAME = 'cachier_test_{}_{}.{}.{}'.format(
26
24
  platform.system(), sys.version_info[0], sys.version_info[1],
27
25
  sys.version_info[2])
@@ -13,22 +13,20 @@
13
13
  # )
14
14
  import os
15
15
  import pickle
16
- from time import (
17
- time,
18
- sleep
19
- )
16
+ import threading
20
17
  from datetime import timedelta
21
18
  from random import random
22
- import threading
19
+ from time import sleep, time
23
20
 
24
21
  import pytest
25
22
 
26
23
  try:
27
24
  import queue
28
25
  except ImportError: # python 2
29
- import Queue as queue
26
+ import Queue as queue # type: ignore
30
27
 
31
28
  import hashlib
29
+
32
30
  import pandas as pd
33
31
 
34
32
  from cachier import cachier
@@ -376,7 +374,7 @@ def _helper_bad_cache_file(sleeptime, separate_files):
376
374
  if not isinstance(res1, float):
377
375
  return False
378
376
  res2 = res_queue.get()
379
- if not (res2 is None) or isinstance(res2, KeyError):
377
+ if res2 is not None or isinstance(res2, KeyError):
380
378
  return False
381
379
  return True
382
380
 
@@ -349,10 +349,11 @@ https://creativecommons.org/publicdomain/zero/1.0/ .
349
349
  """
350
350
 
351
351
  from __future__ import print_function
352
+
352
353
  try:
353
354
  import configparser
354
355
  except ImportError:
355
- import ConfigParser as configparser
356
+ import ConfigParser as configparser # type: ignore
356
357
  import errno
357
358
  import json
358
359
  import os
@@ -1547,7 +1548,7 @@ def get_cmdclass():
1547
1548
  cmds["build_py"] = cmd_build_py
1548
1549
 
1549
1550
  if "cx_Freeze" in sys.modules: # cx_freeze enabled?
1550
- from cx_Freeze.dist import build_exe as _build_exe
1551
+ from cx_Freeze.dist import build_exe as _build_exe # type: ignore[import]
1551
1552
 
1552
1553
  class cmd_build_exe(_build_exe):
1553
1554
  def run(self):
@@ -1,4 +0,0 @@
1
-
2
- [console_scripts]
3
- cachier=cachier.scripts.cli:cli
4
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes