Skip to content

Commit e9d4bff

Browse files
committed
new field ConditionalVersionField
1 parent 0b4c499 commit e9d4bff

File tree

21 files changed

+377
-340
lines changed

21 files changed

+377
-340
lines changed

.travis.yml

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
language: python
22
sudo: false
3+
python:
4+
- 3.5
35

46
cache:
57
directories:
@@ -16,37 +18,34 @@ services:
1618
- PostgreSQL
1719

1820
env:
19-
# Travis give a TemplateDoesNotExist exception with django==1.6.x
20-
# - TOXENV=py27-d16-pg
21-
# - TOXENV=py27-d16-sqlite
22-
# - TOXENV=py27-d16-mysql
23-
- TOXENV=py27-d17-pg
24-
- TOXENV=py27-d17-sqlite
25-
- TOXENV=py27-d17-mysql
26-
- TOXENV=py27-d18-pg
27-
- TOXENV=py27-d18-sqlite
28-
- TOXENV=py27-d18-mysql
29-
- TOXENV=py27-d19-pg
30-
- TOXENV=py27-d19-sqlite
31-
- TOXENV=py27-d19-mysql
32-
- TOXENV=py33-d17-pg
33-
- TOXENV=py33-d17-sqlite
34-
- TOXENV=py33-d18-pg
35-
- TOXENV=py33-d18-sqlite
36-
- TOXENV=py34-d17-pg
37-
- TOXENV=py34-d17-sqlite
38-
- TOXENV=py34-d18-pg
39-
- TOXENV=py34-d18-sqlite
40-
- TOXENV=py34-d19-pg
41-
- TOXENV=py34-d19-sqlite
42-
# - TOXENV=py35-d19-pg
43-
# - TOXENV=py35-d19-sqlite
21+
- py27-d18-pg
22+
- py27-d18-sqlite
23+
- py27-d18-mysql
24+
- py27-d19-pg
25+
- py27-d19-sqlite
26+
- py27-d19-mysql
27+
- py33-d18-pg
28+
- py33-d18-sqlite
29+
- py34-d18-pg
30+
- py34-d18-sqlite
31+
- py34-d19-pg
32+
- py34-d19-sqlite
33+
- py35-d18-pg
34+
- py35-d18-sqlite
35+
- py35-d19-pg
36+
- py35-d19-sqlite
37+
- pypy-d18-pg
38+
- pypy-d18-sqlite
39+
- pypy-d19-pg
40+
- pypy-d19-sqlite
41+
4442

4543
install:
4644
- pip install tox coverage python-coveralls>=2.5 coveralls>=0.5 codecov
4745

4846
script:
49-
- tox -e $TOXENV -- tests -vv --capture=no --cov=concurrency --cov-report=xml --cov-config=tests/.coveragerc
47+
- tox -e $TOXENV -- tests -vv --capture=no --cov=concurrency \
48+
--cov-report=xml --cov-config=tests/.coveragerc
5049

5150
before_success:
5251
- coverage erase
@@ -55,3 +54,12 @@ after_success:
5554
- coverage combine
5655
- coveralls
5756
- codecov
57+
58+
59+
notifications:
60+
webhooks:
61+
urls:
62+
- https://webhooks.gitter.im/e/bf3806c14c6efcff7da1
63+
on_success: always # options: [always|never|change] default: always
64+
on_failure: always # options: [always|never|change] default: always
65+
on_start: never # options: [always|never|change] default: always

CHANGES

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1+
Release 1.1 (dev)
2+
-----------------
3+
* drop support for django<1.7
4+
* add support for pypy
5+
* new :class:`concurrency.fields.ConditionalVersionField`
6+
* new decorator :class:`concurrency.api.concurrency_disable_increment`
7+
18
Release 1.0.1
29
-------------
310
* fixes :issue:`56` (thanks oppianmatt).
411

12+
513
Release 1.0
614
-----------
715
* **BACKWARD INCOMPATIBLE**:: dropped support for Django prior 1.6
@@ -18,6 +26,7 @@ Release 1.0
1826
* new :setting:`CONCURRECY_ENABLED` to fully disable concurrency
1927
* new :setting:`CONCURRECY_MANUAL_TRIGGERS` to disable triggers auto creation fixes :issue:`41` (thanks Naddiseo)
2028

29+
2130
Release 0.9
2231
-----------
2332
* Django 1.8 compatibility
@@ -92,6 +101,5 @@ Release 0.4.0
92101

93102
Release 0.3.2
94103
---------------------------------
95-
96104
* fixed :issue:`3` (thanks pombredanne)
97105
* fixed :issue:`1` (thanks mbrochh)

MANIFEST.in

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ include CHANGES
44
include LICENSE
55
include MANIFEST.in
66
include setup.py
7+
include tox.ini
8+
include *.py
9+
10+
exclude Makefile
11+
exclude .editorconfig
12+
exclude .tx
13+
14+
recursive-exclude .tx *
15+
16+
recursive-include docs *
717
recursive-include src *
8-
recursive-exclude src/django_concurrency.egg-info *
9-
recursive-exclude src *.py[oc]
18+
recursive-include tests *

Makefile

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ develop:
1212
@pip install -U pip setuptools
1313
@sh -c "if [ '${DBENGINE}' = 'mysql' ]; then pip install MySQL-python; fi"
1414
@sh -c "if [ '${DBENGINE}' = 'pg' ]; then pip install -q psycopg2; fi"
15-
@sh -c "if [ '${DJANGO}' = '1.4.x' ]; then pip install 'django>=1.4,<1.5'; fi"
16-
@sh -c "if [ '${DJANGO}' = '1.5.x' ]; then pip install 'django>=1.5,<1.6'; fi"
17-
@sh -c "if [ '${DJANGO}' = '1.6.x' ]; then pip install 'django>=1.6,<1.7'; fi"
18-
@sh -c "if [ '${DJANGO}' = '1.7.x' ]; then pip install 'django>=1.7,<1.8'; fi"
19-
@sh -c "if [ '${DJANGO}' = '1.8.x' ]; then pip install 'django>=1.8,<1.9'; fi"
20-
@sh -c "if [ '${DJANGO}' = '1.9.x' ]; then pip install 'django>=1.9,<1.10'; fi"
21-
@sh -c "if [ '${DJANGO}' = 'last' ]; then pip install django; fi"
22-
@sh -c "if [ '${DJANGO}' = 'dev' ]; then pip install git+git://github.com/django/django.git; fi"
15+
# @sh -c "if [ '${DJANGO}' = '1.4.x' ]; then pip install 'django>=1.4,<1.5'; fi"
16+
# @sh -c "if [ '${DJANGO}' = '1.5.x' ]; then pip install 'django>=1.5,<1.6'; fi"
17+
# @sh -c "if [ '${DJANGO}' = '1.6.x' ]; then pip install 'django>=1.6,<1.7'; fi"
18+
# @sh -c "if [ '${DJANGO}' = '1.7.x' ]; then pip install 'django>=1.7,<1.8'; fi"
19+
# @sh -c "if [ '${DJANGO}' = '1.8.x' ]; then pip install 'django>=1.8,<1.9'; fi"
20+
# @sh -c "if [ '${DJANGO}' = '1.9.x' ]; then pip install 'django>=1.9,<1.10'; fi"
21+
# @sh -c "if [ '${DJANGO}' = 'last' ]; then pip install django; fi"
22+
# @sh -c "if [ '${DJANGO}' = 'dev' ]; then pip install git+git://github.com/django/django.git; fi"
2323
@pip install -e .[dev]
2424
$(MAKE) .init-db
2525

@@ -34,9 +34,16 @@ develop:
3434
test:
3535
py.test -v
3636

37+
qa:
38+
flake8 src/ tests/
39+
isort -rc src/ --check-only
40+
check-manifest
41+
42+
3743
clean:
3844
rm -fr ${BUILDDIR} dist *.egg-info .coverage coverage.xml
3945
find src -name __pycache__ -o -name "*.py?" -o -name "*.orig" -prune | xargs rm -rf
46+
find tests -name __pycache__ -o -name "*.py?" -o -name "*.orig" -prune | xargs rm -rf
4047
find src/concurrency/locale -name django.mo | xargs rm -f
4148

4249
fullclean:

docs/api.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,19 @@ examples
205205
deleted_version.revert()
206206
207207
208+
`concurrency_disable_increment()`
209+
---------------------------------
210+
211+
.. versionadded:: 1.1
212+
213+
214+
Context manager to temporary disable version increment.
215+
Concurrent save is still checked but no version increment is triggered,
216+
this creates 'shadow saves',
217+
218+
It accepts both a Model or an instance as target.
219+
220+
208221

209222
------------
210223
Templatetags

docs/fields.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,24 @@ example
8484
sax@: (concurrency) django-concurrency [feature/triggers*] $ ./demo/manage.py triggers create
8585
DATABASE TRIGGERS
8686
default concurrency_concurrency_triggerconcurrentmodel_u
87+
88+
89+
ConditionalVersionField
90+
-----------------------
91+
92+
.. versionadded:: 1.1
93+
94+
This field allow to configure which fields trigger the version increment so to limit
95+
the scope of the concurrency checks.
96+
97+
.. code-block:: python
98+
99+
class User(models.Model):
100+
version = ConditionalVersionField()
101+
username = models.CharField(...)
102+
password = models.PasswordField(...)
103+
104+
class ConcurrencyMeta:
105+
check_fields = ('username',)
106+
107+

docs/index.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ Overview
1212
:target: http://travis-ci.org/saxix/django-concurrency/
1313
:alt: Test status
1414

15-
.. image:: https://img.shields.io/coveralls/saxix/django-concurrency/master.svg
16-
:target: https://coveralls.io/r/saxix/django-concurrency
15+
.. image:: https://codecov.io/github/saxix/django-concurrency/coverage.svg?branch=master
16+
:target: https://codecov.io/github/saxix/django-concurrency?branch=master
1717
:alt: Coverage
1818

1919

@@ -79,4 +79,3 @@ Links
7979

8080

8181
.. [1] http://en.wikipedia.org/wiki/Optimistic_concurrency_control
82-

setup.cfg

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,3 @@ max-complexity = 12
1818
max-line-length = 160
1919
exclude = .tox,migrations,.git,docs,diff_match_patch.py, deploy/**,settings
2020
ignore = E501,E401,W391,E128,E261,D
21-
22-
[pytest]
23-
python_paths=./tests/demoapp/
24-
django_find_project = false
25-
DJANGO_SETTINGS_MODULE=demo.settings
26-
norecursedirs = .tox docs ./demoapp/
27-
python_files=tests/test_*.py
28-
addopts =
29-
-q
30-
; --reuse-db
31-
--tb=short
32-
--capture=no
33-
--echo-version django
34-
--echo-attr django.conf.settings.DATABASES.default.ENGINE
35-
36-
pep8ignore = * ALL
37-
markers =
38-
functional: mark a test as functional

setup.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python
22
import os
33
import sys
4+
import imp
45
from distutils import log
56
from distutils.command.clean import clean as CleanCommand
67
from distutils.dir_util import remove_tree
@@ -9,11 +10,26 @@
910
from setuptools.command.test import test as TestCommand
1011

1112
ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__)))
12-
sys.path.insert(0, os.path.join(ROOT, 'src'))
13+
init = os.path.join(ROOT, 'src', 'concurrency', '__init__.py')
14+
app = imp.load_source('concurrency', init)
15+
16+
reqs = 'install.py%d.pip' % sys.version_info[0]
17+
18+
# if sys.version_info[0] == 2:
19+
# reqs = 'install.py2.pip'
20+
# app = imp.load_source('concurrency', init)
21+
# elif sys.version_info[0] == 3:
22+
# reqs = 'install.py3.pip'
23+
# if sys.version_info[1] in [3,4]:
24+
# from importlib.machinery import SourceFileLoader
25+
# app = SourceFileLoader("adminactions", init).load_module()
26+
# elif sys.version_info[1] in [5]:
27+
# import importlib.util
28+
# spec = importlib.util.spec_from_file_location("concurrency", init)
29+
# app = importlib.util.module_from_spec(spec)
30+
# spec.loader.exec_module(app)
1331

14-
app = __import__('concurrency')
1532
base_url = 'https://github.com/saxix/django-concurrency/'
16-
install_requires = []
1733

1834

1935
class PyTest(TestCommand):
@@ -58,9 +74,10 @@ def run(self):
5874
remove_tree(self.build_help, dry_run=self.dry_run)
5975
CleanCommand.run(self)
6076

61-
install_requires = ["django"]
77+
install_requires = []
6278
test_requires = ["django-webtest>=1.7.5",
6379
"mock>=1.0.1",
80+
"check-manifest==0.30",
6481
"pytest-cache>=1.0",
6582
"pytest-cov>=1.6",
6683
"pytest-django>=2.8",
@@ -104,9 +121,8 @@ def run(self):
104121
'License :: OSI Approved :: BSD License',
105122
'Operating System :: OS Independent',
106123
'Programming Language :: Python',
107-
'Framework :: Django :: 1.6',
108-
'Framework :: Django :: 1.7',
109124
'Framework :: Django :: 1.8',
125+
'Framework :: Django :: 1.9',
110126
'Programming Language :: Python :: 2.7',
111127
'Programming Language :: Python :: 3',
112128
'Programming Language :: Python :: 3.3',

src/concurrency/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
__author__ = 'sax'
66
default_app_config = 'concurrency.apps.ConcurrencyConfig'
77

8-
VERSION = __version__ = (1, 0, 1, 'final', 0)
8+
VERSION = __version__ = (1, 1, 0, 'alpha', 0)
99
NAME = 'django-concurrency'
1010

1111

0 commit comments

Comments
 (0)