diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000..2bcd70e
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+max-line-length = 88
diff --git a/.therapist.yml b/.therapist.yml
new file mode 100644
index 0000000..5a3caa8
--- /dev/null
+++ b/.therapist.yml
@@ -0,0 +1,9 @@
+actions:
+ black:
+ run: black --check --diff {files}
+ fix: black {files}
+ include: "*.py"
+
+ flake8:
+ run: flake8 {files}
+ include: "*.py"
diff --git a/README.rst b/README.rst
index 8359364..22b75d5 100644
--- a/README.rst
+++ b/README.rst
@@ -14,6 +14,8 @@ django-cache-memoize
:alt: Code Coverage
:target: https://codecov.io/gh/peterbe/django-cache-memoize
+.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
+ :target: https://github.com/ambv/black
Django utility for a memoization decorator that uses the Django cache framework.
@@ -387,3 +389,39 @@ The most basic thing is to clone the repo and run:
pip install -e ".[dev]"
tox
+
+
+Code style is all black
+~~~~~~~~~~~~~~~~~~~~~~~
+
+All code has to be formatted with `Black `_
+and the best tool for checking this is
+`therapist `_ since it can help you run
+all, help you fix things, and help you make sure linting is passing before
+you git commit. This project also uses ``flake8`` to check other things
+Black can't check.
+
+To check linting with ``tox`` use:
+
+.. code:: bash
+
+ tox -e lint-py36
+
+To install the ``therapist`` pre-commit hook simply run:
+
+.. code:: bash
+
+ therapist install
+
+When you run ``therapist run`` it will only check the files you've touched.
+To run it for all files use:
+
+.. code:: bash
+
+ therapist run --use-tracked-files
+
+And to fix all/any issues run:
+
+.. code:: bash
+
+ therapist run --use-tracked-files --fix
diff --git a/docs/conf.py b/docs/conf.py
index eceb66f..bf493f6 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -34,30 +34,30 @@
extensions = []
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
+source_suffix = ".rst"
# The master toctree document.
-master_doc = 'index'
+master_doc = "index"
# General information about the project.
-project = 'django-cache-memoize'
-copyright = '2017, Peter Bengtsson'
-author = 'Peter Bengtsson'
+project = "django-cache-memoize"
+copyright = "2017, Peter Bengtsson"
+author = "Peter Bengtsson"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = ''
+version = ""
# The full version, including alpha/beta/rc tags.
-release = ''
+release = ""
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -69,10 +69,10 @@
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
-exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
@@ -83,7 +83,7 @@
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
-html_theme = 'alabaster'
+html_theme = "alabaster"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -94,7 +94,7 @@
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = ["_static"]
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
@@ -102,9 +102,9 @@
# This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
html_sidebars = {
- '**': [
- 'relations.html', # needs 'show_related': True theme option to display
- 'searchbox.html',
+ "**": [
+ "relations.html", # needs 'show_related': True theme option to display
+ "searchbox.html",
]
}
@@ -112,7 +112,7 @@
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
-htmlhelp_basename = 'django-cache-memoizedoc'
+htmlhelp_basename = "django-cache-memoizedoc"
# -- Options for LaTeX output ---------------------------------------------
@@ -121,15 +121,12 @@
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
-
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
-
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
-
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
@@ -139,8 +136,13 @@
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- (master_doc, 'django-cache-memoize.tex', 'django-cache-memoize Documentation',
- 'Peter Bengtsson', 'manual'),
+ (
+ master_doc,
+ "django-cache-memoize.tex",
+ "django-cache-memoize Documentation",
+ "Peter Bengtsson",
+ "manual",
+ )
]
@@ -149,8 +151,13 @@
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
- (master_doc, 'django-cache-memoize', 'django-cache-memoize Documentation',
- [author], 1)
+ (
+ master_doc,
+ "django-cache-memoize",
+ "django-cache-memoize Documentation",
+ [author],
+ 1,
+ )
]
@@ -160,10 +167,13 @@
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- (master_doc, 'django-cache-memoize', 'django-cache-memoize Documentation',
- author, 'django-cache-memoize', 'One line description of project.',
- 'Miscellaneous'),
+ (
+ master_doc,
+ "django-cache-memoize",
+ "django-cache-memoize Documentation",
+ author,
+ "django-cache-memoize",
+ "One line description of project.",
+ "Miscellaneous",
+ )
]
-
-
-
diff --git a/setup.py b/setup.py
index 5103a14..9fbc057 100644
--- a/setup.py
+++ b/setup.py
@@ -5,33 +5,31 @@
setup(
- name='django-cache-memoize',
- version='0.1.4',
+ name="django-cache-memoize",
+ version="0.1.4",
description=(
- 'Django utility for a memoization decorator that uses the Django '
- 'cache framework.'
+ "Django utility for a memoization decorator that uses the Django "
+ "cache framework."
),
- long_description=open(path.join(_here, 'README.rst')).read(),
- author='Peter Bengtsson',
- author_email='mail@peterbe.com',
- license='MPL 2.0',
- url='https://github.com/peterbe/django-cache-memoize',
- packages=find_packages(where='src'),
- package_dir={'': 'src'},
+ long_description=open(path.join(_here, "README.rst")).read(),
+ author="Peter Bengtsson",
+ author_email="mail@peterbe.com",
+ license="MPL 2.0",
+ url="https://github.com/peterbe/django-cache-memoize",
+ packages=find_packages(where="src"),
+ package_dir={"": "src"},
classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Environment :: Web Environment :: Mozilla',
- 'Framework :: Django',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
- 'License :: OSI Approved :: MIT License',
- 'Programming Language :: Python :: 2.7',
- 'Programming Language :: Python :: 3',
- 'Topic :: Internet :: WWW/HTTP',
+ "Development Status :: 5 - Production/Stable",
+ "Environment :: Web Environment :: Mozilla",
+ "Framework :: Django",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
+ "License :: OSI Approved :: MIT License",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Topic :: Internet :: WWW/HTTP",
],
- keywords=['django', 'memoize', 'cache', 'decorator'],
+ keywords=["django", "memoize", "cache", "decorator"],
zip_safe=False,
- extras_require={
- 'dev': ['flake8', 'tox', 'twine'],
- }
+ extras_require={"dev": ["flake8", "tox", "twine", "therapist", "black"]},
)
diff --git a/src/cache_memoize/__init__.py b/src/cache_memoize/__init__.py
index ed63516..411bfc3 100644
--- a/src/cache_memoize/__init__.py
+++ b/src/cache_memoize/__init__.py
@@ -82,22 +82,23 @@ def callmeonce(arg1):
"""
if args_rewrite is None:
+
def noop(*args):
return args
+
args_rewrite = noop
cache = caches[cache_alias]
def decorator(func):
-
def _make_cache_key(*args, **kwargs):
- cache_key = ':'.join(
- [force_text(x) for x in args_rewrite(*args)] +
- [force_text('{}={}'.format(k, v)) for k, v in kwargs.items()]
+ cache_key = ":".join(
+ [force_text(x) for x in args_rewrite(*args)]
+ + [force_text("{}={}".format(k, v)) for k, v in kwargs.items()]
)
- return hashlib.md5(force_bytes(
- 'cache_memoize' + (prefix or func.__name__) + cache_key
- )).hexdigest()
+ return hashlib.md5(
+ force_bytes("cache_memoize" + (prefix or func.__name__) + cache_key)
+ ).hexdigest()
@wraps(func)
def inner(*args, **kwargs):
@@ -105,7 +106,7 @@ def inner(*args, **kwargs):
cache_key = _make_cache_key(*args, **kwargs)
else:
cache_key = key_generator_callable(*args, **kwargs)
- if kwargs.pop('_refresh', False):
+ if kwargs.pop("_refresh", False):
result = MARKER
else:
result = cache.get(cache_key, MARKER)
diff --git a/tests/conftest.py b/tests/conftest.py
index 7e4723b..157f161 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -4,5 +4,6 @@
@pytest.fixture(autouse=True)
def clear_cache():
from django.core.cache import caches
- caches['default'].clear()
- caches['locmem'].clear()
+
+ caches["default"].clear()
+ caches["locmem"].clear()
diff --git a/tests/settings.py b/tests/settings.py
index 175bf60..61a1cf9 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -3,9 +3,9 @@
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-ROOT_URLCONF = 'tests.urls'
+ROOT_URLCONF = "tests.urls"
-SECRET_KEY = 'z$uhu93+ydzttmn6l2ky834&p$78)h*945w-srqjpbs!x!b)hy'
+SECRET_KEY = "z$uhu93+ydzttmn6l2ky834&p$78)h*945w-srqjpbs!x!b)hy"
DEBUG = True
@@ -13,56 +13,49 @@
INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
+ "django.contrib.admin",
+ "django.contrib.auth",
+ "django.contrib.contenttypes",
+ "django.contrib.sessions",
+ "django.contrib.messages",
+ "django.contrib.staticfiles",
]
MIDDLEWARE = [
- 'django.middleware.security.SecurityMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+ "django.middleware.security.SecurityMiddleware",
+ "django.contrib.sessions.middleware.SessionMiddleware",
+ "django.middleware.common.CommonMiddleware",
+ "django.middleware.csrf.CsrfViewMiddleware",
+ "django.contrib.auth.middleware.AuthenticationMiddleware",
+ "django.contrib.messages.middleware.MessageMiddleware",
+ "django.middleware.clickjacking.XFrameOptionsMiddleware",
]
TEMPLATES = [
{
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [],
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.debug',
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- ],
+ "BACKEND": "django.template.backends.django.DjangoTemplates",
+ "DIRS": [],
+ "APP_DIRS": True,
+ "OPTIONS": {
+ "context_processors": [
+ "django.template.context_processors.debug",
+ "django.template.context_processors.request",
+ "django.contrib.auth.context_processors.auth",
+ "django.contrib.messages.context_processors.messages",
+ ]
},
- },
+ }
]
-DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.sqlite3',
- 'NAME': ':memory:',
- }
-}
+DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}}
CACHES = {
- 'default': {
- 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
- 'LOCATION': '127.0.0.1:11211',
- },
- 'locmem': {
- 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
+ "default": {
+ "BACKEND": "django.core.cache.backends.memcached.MemcachedCache",
+ "LOCATION": "127.0.0.1:11211",
},
+ "locmem": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"},
}
diff --git a/tests/test_cache_memoize.py b/tests/test_cache_memoize.py
index 31af572..6de095f 100644
--- a/tests/test_cache_memoize.py
+++ b/tests/test_cache_memoize.py
@@ -8,9 +8,9 @@ def test_cache_memoize():
calls_made = []
@cache_memoize(10)
- def runmeonce(a, b, k='bla'):
+ def runmeonce(a, b, k="bla"):
calls_made.append((a, b, k))
- return '{} {} {}'.format(a, b, k) # sample implementation
+ return "{} {} {}".format(a, b, k) # sample implementation
runmeonce(1, 2)
runmeonce(1, 2)
@@ -18,37 +18,38 @@ def runmeonce(a, b, k='bla'):
runmeonce(1, 3)
assert len(calls_made) == 2
# should work with most basic types
- runmeonce(1.1, 'foo')
- runmeonce(1.1, 'foo')
+ runmeonce(1.1, "foo")
+ runmeonce(1.1, "foo")
assert len(calls_made) == 3
# even more "advanced" types
- runmeonce(1.1, 'foo', k=list('åäö'))
- runmeonce(1.1, 'foo', k=list('åäö'))
+ runmeonce(1.1, "foo", k=list("åäö"))
+ runmeonce(1.1, "foo", k=list("åäö"))
assert len(calls_made) == 4
# And shouldn't be a problem even if the arguments are really long
- runmeonce('A' * 200, 'B' * 200, {'C' * 100: 'D' * 100})
+ runmeonce("A" * 200, "B" * 200, {"C" * 100: "D" * 100})
assert len(calls_made) == 5
# different prefixes
- @cache_memoize(10, prefix='first')
+ @cache_memoize(10, prefix="first")
def foo(value):
calls_made.append(value)
- return 'ho'
+ return "ho"
- @cache_memoize(10, prefix='second')
+ @cache_memoize(10, prefix="second")
def bar(value):
calls_made.append(value)
- return 'ho'
+ return "ho"
- foo('hey')
- bar('hey')
+ foo("hey")
+ bar("hey")
assert len(calls_made) == 7
# Test when you don't care about the result
- @cache_memoize(10, store_result=False, prefix='different')
- def returnnothing(a, b, k='bla'):
+ @cache_memoize(10, store_result=False, prefix="different")
+ def returnnothing(a, b, k="bla"):
calls_made.append((a, b, k))
# note it returns None
+
returnnothing(1, 2)
returnnothing(1, 2)
assert len(calls_made) == 8
@@ -66,11 +67,7 @@ def hit_callable(arg):
def miss_callable(arg):
misses.append(arg)
- @cache_memoize(
- 10,
- hit_callable=hit_callable,
- miss_callable=miss_callable,
- )
+ @cache_memoize(10, hit_callable=hit_callable, miss_callable=miss_callable)
def runmeonce(arg):
calls_made.append(arg)
return arg * 2
@@ -192,7 +189,7 @@ def runmeonce(a):
return a * 2
runmeonce_default = cache_memoize(10)(runmeonce)
- runmeonce_locmem = cache_memoize(10, cache_alias='locmem')(runmeonce)
+ runmeonce_locmem = cache_memoize(10, cache_alias="locmem")(runmeonce)
runmeonce_default(10)
assert len(calls_made) == 1
@@ -209,8 +206,8 @@ def test_cache_memoize_works_with_custom_key_generator():
calls_made = []
def key_generator(*args):
- key = (':{}' * len(args)).format(*args)
- return 'custom_namespace:{}'.format(key)
+ key = (":{}" * len(args)).format(*args)
+ return "custom_namespace:{}".format(key)
@cache_memoize(10, key_generator_callable=key_generator)
def runmeonce(arg1, arg2):
diff --git a/tox.ini b/tox.ini
index ae04b23..5803f43 100644
--- a/tox.ini
+++ b/tox.ini
@@ -3,7 +3,7 @@ skipsdist = True
usedevelop = True
minversion = 1.8
envlist =
- flake8-py36,
+ lint-py36,
readme-py27,
docs-py27-dj{18,110},
py27-django{18,19,110,111},
@@ -39,11 +39,6 @@ commands =
commands = python setup.py check -r -s
deps = readme_renderer
-[testenv:flake8-py36]
-commands = flake8 src tests
-deps =
- flake8
-
-[flake8]
-exclude=.tox
-#ignore=E501,E127,E128,E124
+[testenv:lint-py36]
+extras = dev
+commands=therapist run --use-tracked-files