Skip to content

Commit 4babaff

Browse files
committed
refresh / python 3.8 / 1.3.0
do a full bump of everything, flake8, black etc. and get minimum version on python 3.8. pep-621 also enabled as this is very standard now. Also pifpaf requires pkg_resources which was removed from python 3.12 so do some rearrangement to get that in the dependencies. Fix really old and sort of pointless(?) test that loads the "mako" entrypoint to use importlib.metadata (standard as of Python 3.8, so we're good). Apply a hardening of the distributed lock for memcached, using a mutex when calling client.add() so that multiple threads calling on this python method are also synchronized Change-Id: Ic3986070e21c84cdea12d8cfa01cc353f21adf0f
1 parent efa73d3 commit 4babaff

16 files changed

Lines changed: 139 additions & 103 deletions

File tree

.pre-commit-config.yaml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# See https://pre-commit.com/hooks.html for more hooks
33
repos:
44
- repo: https://github.com/python/black
5-
rev: 22.3.0
5+
rev: 23.12.0
66
hooks:
77
- id: black
88

@@ -14,14 +14,18 @@ repos:
1414
- --keep-unused-type-checking
1515

1616
- repo: https://github.com/pycqa/flake8
17-
rev: 4.0.1
17+
rev: 6.1.0
1818
hooks:
1919
- id: flake8
2020
additional_dependencies:
2121
- flake8-import-order
22+
- flake8-import-single==0.1.5
2223
- flake8-builtins
24+
- flake8-future-annotations>=0.0.5
2325
- flake8-docstrings>=1.6.0
26+
- flake8-unused-arguments
2427
- flake8-rst-docstrings
28+
# flake8-rst-docstrings dependency, leaving it here
29+
# in case it requires a version pin
2530
- pydocstyle
2631
- pygments
27-

docs/build/changelog.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Changelog
33
=========
44

55
.. changelog::
6-
:version: 1.2.3
6+
:version: 1.3.0
77
:include_notes_from: unreleased
88

99
.. changelog::

docs/build/unreleased/38.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.. change::
2+
:tags: change, setup
3+
4+
Minimum Python version is now Python 3.8; prior versions Python 3.7 and 3.6
5+
are EOL.
6+
7+
8+
.. change::
9+
:tags: change, setup
10+
11+
Project setup is now based on pep-621 ``pyproject.toml`` configuration.

dogpile/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "1.2.3"
1+
__version__ = "1.3.0"
22

33
from .lock import Lock # noqa
44
from .lock import NeedRegenerationException # noqa

dogpile/cache/api.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import abc
24
import pickle
35
from typing import Any

dogpile/cache/backends/memcached.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,25 +41,27 @@
4141
)
4242

4343

44-
class MemcachedLock(object):
44+
class MemcachedLock:
4545
"""Simple distributed lock using memcached."""
4646

4747
def __init__(self, client_fn, key, timeout=0):
4848
self.client_fn = client_fn
4949
self.key = "_lock" + key
5050
self.timeout = timeout
51+
self._mutex = threading.Lock()
5152

5253
def acquire(self, wait=True):
5354
client = self.client_fn()
5455
i = 0
5556
while True:
56-
if client.add(self.key, 1, self.timeout):
57-
return True
58-
elif not wait:
59-
return False
60-
else:
61-
sleep_time = (((i + 1) * random.random()) + 2**i) / 2.5
62-
time.sleep(sleep_time)
57+
with self._mutex:
58+
if client.add(self.key, 1, self.timeout):
59+
return True
60+
elif not wait:
61+
return False
62+
63+
sleep_time = (((i + 1) * random.random()) + 2**i) / 2.5
64+
time.sleep(sleep_time)
6365
if i < 15:
6466
i += 1
6567

dogpile/cache/proxy.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
.. versionadded:: 0.5.0 Added support for the :class:`.ProxyBackend` class.
1010
1111
"""
12+
13+
from __future__ import annotations
14+
1215
from typing import Mapping
1316
from typing import Optional
1417
from typing import Sequence

dogpile/cache/region.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import contextlib
24
import datetime
35
from functools import partial
@@ -897,7 +899,6 @@ def get_or_create(
897899
should_cache_fn: Optional[Callable[[ValuePayload], bool]] = None,
898900
creator_args: Optional[Tuple[Any, Mapping[str, Any]]] = None,
899901
) -> ValuePayload:
900-
901902
"""Return a cached value based on the given key.
902903
903904
If the value does not exist or is considered to be expired
@@ -1035,7 +1036,6 @@ def gen_value():
10351036

10361037
def async_creator(mutex):
10371038
if creator_args:
1038-
10391039
ca = creator_args
10401040

10411041
@wraps(creator)

dogpile/cache/util.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ def generate_key(*args, **kw):
4646

4747

4848
def function_multi_key_generator(namespace, fn, to_str=str):
49-
5049
if namespace is None:
5150
namespace = "%s:%s" % (fn.__module__, fn.__name__)
5251
else:
@@ -163,7 +162,6 @@ def mangle(key):
163162

164163

165164
class repr_obj:
166-
167165
__slots__ = ("value", "max_chars")
168166

169167
def __init__(self, value, max_chars=300):

pyproject.toml

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,75 @@
1+
[build-system]
2+
requires = ["setuptools>=61.2"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "dogpile.cache"
7+
description = "A caching front-end based on the Dogpile lock."
8+
readme = "README.rst"
9+
keywords = ["caching"]
10+
authors = [{name = "Mike Bayer", email = "mike_mp@zzzcomputing.com"}]
11+
license = {text = "MIT"}
12+
classifiers = [
13+
"Development Status :: 5 - Production/Stable",
14+
"Intended Audience :: Developers",
15+
"License :: OSI Approved :: MIT License",
16+
"Programming Language :: Python",
17+
"Programming Language :: Python :: 3",
18+
]
19+
requires-python = ">=3.8"
20+
dependencies = [
21+
"decorator>=4.0.0",
22+
"stevedore>=3.0.0",
23+
"typing_extensions>=4.0.1;python_version<'3.11'",
24+
]
25+
dynamic = ["version"]
26+
27+
[project.urls]
28+
Homepage = "https://github.com/sqlalchemy/dogpile.cache"
29+
Documentation = "https://dogpilecache.sqlalchemy.org"
30+
"Issue Tracker" = "https://github.com/sqlalchemy/dogpile.cache/"
31+
32+
[project.optional-dependencies]
33+
pifpaf = [
34+
"pifpaf>=2.5.0",
35+
"setuptools;python_version>='3.12'",
36+
]
37+
38+
[project.entry-points."mako.cache"]
39+
"dogpile.cache" = "dogpile.cache.plugins.mako_cache:MakoPlugin"
40+
41+
42+
[tool.setuptools]
43+
zip-safe = false
44+
include-package-data = true
45+
package-dir = {"" = "."}
46+
license-files = ["LICENSE"]
47+
48+
[tool.setuptools.packages.find]
49+
exclude = [
50+
"tests",
51+
"tests.*",
52+
]
53+
namespaces = false
54+
55+
[tool.setuptools.exclude-package-data]
56+
dogpile = ["tests*"]
57+
58+
[tool.setuptools.package-data]
59+
dogpile = ["py.typed"]
60+
61+
[tool.setuptools.dynamic]
62+
version = {attr = "dogpile.__version__"}
63+
164
[tool.black]
265
line-length = 79
3-
target-version = ['py36']
66+
target-version = ['py38']
67+
68+
69+
[tool.pytest.ini_options]
70+
addopts = "--tb native -v -r fxX -p no:logging -p no:warnings -m 'not time_intensive'"
71+
python_files = "tests/*test_*.py"
72+
filterwarnings = [
73+
"error"
74+
]
75+

0 commit comments

Comments
 (0)