From 619eca8ae159f04735d7b5df78857a19d07db803 Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Tue, 12 Sep 2017 13:39:59 +0300 Subject: [PATCH 01/13] Swich to Prequ as requirement compiler Re-compile the requirements*.txt with Prequ and update the instructions on how to compile the requirements. --- README.md | 8 +++----- requirements-dev.txt | 12 +++++------- requirements.txt | 10 ++++------ 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index b59993ae..c0568dc6 100644 --- a/README.md +++ b/README.md @@ -84,15 +84,13 @@ Run migrations ### Updating requirements files -Use `pip-tools` to update the `requirements*.txt` files. +Use Prequ to update the `requirements*.txt` files. - pip install -U pip # pip-tools needs pip==6.1 or higher (!) - pip install pip-tools + pip install prequ When you change requirements, set them in `requirements.in` or `requirements-dev.in`. Then run: - pip-compile requirements.in - pip-compile requirements-dev.in + prequ update ### Running tests diff --git a/requirements-dev.txt b/requirements-dev.txt index fbf7dd9f..b2373fe1 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,10 +1,7 @@ +# This file is autogenerated by Prequ. To update, run: # -# This file is autogenerated by pip-compile -# To update, run: +# prequ update # -# pip-compile --output-file requirements-dev.txt requirements-dev.in -# -appnope==0.1.0 # via ipython autoflake==0.7 autopep8==1.3.2 coverage==4.4.1 # via pytest-cov @@ -15,8 +12,8 @@ faker==0.7.18 # via factory-boy flake8==3.4.1 freezegun==0.3.9 inflection==0.3.1 # via pytest-factoryboy -ipython-genutils==0.2.0 # via traitlets ipython==6.1.0 +ipython-genutils==0.2.0 # via traitlets isort==4.2.15 jedi==0.10.2 # via ipython mccabe==0.6.1 # via flake8 @@ -29,14 +26,15 @@ pycodestyle==2.3.1 # via autopep8, flake8 pydocstyle==2.0.0 pyflakes==1.5.0 # via autoflake, flake8 pygments==2.2.0 # via ipython +pytest==3.2.1 pytest-cov==2.5.1 pytest-django==3.1.2 pytest-factoryboy==1.3.1 -pytest==3.2.1 python-dateutil==2.6.1 # via faker, freezegun simplegeneric==0.8.1 # via ipython six==1.10.0 # via django-extensions, faker, freezegun, prompt-toolkit, pydocstyle, python-dateutil, traitlets snowballstemmer==1.2.1 # via pydocstyle traitlets==4.3.2 # via ipython +typing==3.6.2 # via ipython wcwidth==0.1.7 # via prompt-toolkit werkzeug==0.12.2 diff --git a/requirements.txt b/requirements.txt index 423d0576..3672bc8c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,17 +1,15 @@ +# This file is autogenerated by Prequ. To update, run: # -# This file is autogenerated by pip-compile -# To update, run: -# -# pip-compile --output-file requirements.txt requirements.in +# prequ update # certifi==2017.7.27.1 # via requests chardet==3.0.4 # via requests contextlib2==0.5.5 # via raven +django==1.11.4 django-environ==0.4.4 django-filter==1.0.4 -django==1.11.4 # via django-environ -djangorestframework-gis==0.11.2 djangorestframework==3.6.4 +djangorestframework-gis==0.11.2 idna==2.6 # via requests lxml==3.8.0 owslib==0.14.0 From 6680d47e98c16a5e7412633f374064c640fdbdb1 Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Tue, 12 Sep 2017 13:44:38 +0300 Subject: [PATCH 02/13] Ignore requirements-local.* This allows having some personal tools in requirements-local.in alongside the project requirements (in requirements.in and requirement-dev.in) and still be able to do "prequ sync req*.txt" to update the packages in the virtual environment. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8d9dc8c3..8146570c 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,7 @@ var/ *.egg-info/ .installed.cfg *.egg +requirements-local.* # PyInstaller # Usually these files are written by a python script from a template From d33a8c7ec76fff64bdaf7911278fa5856e62e49d Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Tue, 12 Sep 2017 13:47:52 +0300 Subject: [PATCH 03/13] setup.cfg: Configure Prequ to annotate --- setup.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.cfg b/setup.cfg index 27130ce5..a4b13812 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,6 @@ +[prequ] +annotate = yes + [pep8] max-line-length = 120 exclude = *migrations* From 188e91631b5a993f61476d93c8ed288d8484fc7d Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Tue, 12 Sep 2017 13:51:51 +0300 Subject: [PATCH 04/13] Travis: Add "prequ check" test Run the "prequ check" to make sure that requirements are compiled correctly. This test fails if requirements.in is updated, but the updater forgot to run "prequ update" or commit the requirements.txt changes. The check is ran only with Python 3.4 as the requirements.txt is compiled for Python 3.4. --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 2ec2a418..df1ea53d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,11 @@ before_script: script: - flake8 - pytest -ra -vvv --cov + - | + if [ "$TRAVIS_PYTHON_VERSION" = "3.4" ]; then + pip install -q prequ + prequ check -v + fi after_success: codecov From f2f70ff10cc3d8de98d60908b1d65e44afe36960 Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Tue, 12 Sep 2017 13:55:14 +0300 Subject: [PATCH 05/13] requirements: Update Django to 1.11.5 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 3672bc8c..d83e917f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ certifi==2017.7.27.1 # via requests chardet==3.0.4 # via requests contextlib2==0.5.5 # via raven -django==1.11.4 +django==1.11.5 django-environ==0.4.4 django-filter==1.0.4 djangorestframework==3.6.4 From 29eac9c587da590a1c2cea1fbf97b05f25bbe357 Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Tue, 12 Sep 2017 13:55:22 +0300 Subject: [PATCH 06/13] requirements-dev: Update dev requirements Note: factory-boy was not updated, because the newest version 2.9.2 seemes to fail the tests. --- requirements-dev.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index b2373fe1..5a511f68 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -6,13 +6,16 @@ autoflake==0.7 autopep8==1.3.2 coverage==4.4.1 # via pytest-cov decorator==4.1.2 # via ipython, traitlets -django-extensions==1.9.0 +django-extensions==1.9.1 +dnspython==1.15.0 # via email-validator +email-validator==1.0.2 # via faker factory-boy==2.8.1 # via pytest-factoryboy -faker==0.7.18 # via factory-boy +faker==0.8.3 # via factory-boy flake8==3.4.1 freezegun==0.3.9 +idna==2.6 # via email-validator inflection==0.3.1 # via pytest-factoryboy -ipython==6.1.0 +ipython==6.2.0 ipython-genutils==0.2.0 # via traitlets isort==4.2.15 jedi==0.10.2 # via ipython @@ -26,7 +29,7 @@ pycodestyle==2.3.1 # via autopep8, flake8 pydocstyle==2.0.0 pyflakes==1.5.0 # via autoflake, flake8 pygments==2.2.0 # via ipython -pytest==3.2.1 +pytest==3.2.2 pytest-cov==2.5.1 pytest-django==3.1.2 pytest-factoryboy==1.3.1 From 5b79b13545c26d283f28814b6a2a54537c4d5084 Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Wed, 20 Sep 2017 10:47:23 +0300 Subject: [PATCH 07/13] requirements: Update lxml, owslib and six Update the production requirements to latest versions. I checked the changelogs too and all of these seem pretty safe. Change logs of the upgraded packages follows: ============================================================================ lxml 4.0.0 ========== Features added -------------- * The ElementPath implementation is now compiled using Cython, which speeds up the ``.find*()`` methods quite significantly. * The modules ``lxml.builder``, ``lxml.html.diff`` and ``lxml.html.clean`` are also compiled using Cython in order to speed them up. * ``xmlfile()`` supports async coroutines using ``async with`` and ``await``. * ``iterwalk()`` has a new method ``skip_subtree()`` that prevents walking into the descendants of the current element. * ``RelaxNG.from_rnc_string()`` accepts a ``base_url`` argument to allow relative resource lookups. * The XSLT result object has a new method ``.write_output(file)`` that serialises output data into a file according to the ```` configuration. Bugs fixed ---------- * GH251: HTML comments were handled incorrectly by the soupparser. Patch by mozbugbox. * LP1654544: The html5parser no longer passes the ``useChardet`` option if the input is a Unicode string, unless explicitly requested. When parsing files, the default is to enable it when a URL or file path is passed (because the file is then opened in binary mode), and to disable it when reading from a file(-like) object. Note: This is a backwards incompatible change of the default configuration. If your code parses byte strings/streams and depends on character detection, please pass the option ``guess_charset=True`` explicitly, which already worked in older lxml versions. * LP1703810: ``etree.fromstring()`` failed to parse UTF-32 data with BOM. * LP1526522: Some RelaxNG errors were not reported in the error log. * LP1567526: Empty and plain text input raised a TypeError in soupparser. * LP1710429: Uninitialised variable usage in HTML diff. * LP1415643: The closing tags context manager in ``xmlfile()`` could continue to output end tags even after writing failed with an exception. * LP1465357: ``xmlfile.write()`` now accepts and ignores None as input argument. * Compilation under Py3.7-pre failed due to a modified function signature. Other changes ------------- * The main module source files were renamed from ``lxml.*.pyx`` to plain ``*.pyx`` (e.g. ``etree.pyx``) to simplify their handling in the build process. Care was taken to keep the old header files as fallbacks for code that compiles against the public C-API of lxml, but it might still be worth validating that third-party code does not notice this change. ============================================================================ six 1.11.0 ---------- - Pull request 178: `with_metaclass` now properly proxies `__prepare__` to the underlying metaclass. - Pull request 191: Allow `with_metaclass` to work with metaclasses implemented in C. - Pull request 203: Add parse_http_list and parse_keqv_list to moved urllib.request. - Pull request 172 and issue 171: Add unquote_to_bytes to moved urllib.parse. - Pull request 167: Add `six.moves.getoutput`. - Pull request 80: Add `six.moves.urllib_parse.splitvalue`. - Pull request 75: Add `six.moves.email_mime_image`. - Pull request 72: Avoid creating reference cycles through tracebacks in `reraise`. ============================================================================ owslib 0.15.0 ============= Alessio Fabiani (1): fixes #382: WPS DescribeProcess issue on DataType (#383) Benjamin Adams (1): Swe fixes (#359) Carsten Ehbrecht (3): added BoundingBoxDataInput and fix boundingbox parsing added a test for wps BoundingBoxDataInput fixed bbox lower/upper_corner conversion Davide Muraro (1): Support for missing style elements. Filipe (1): concatenate bytes with bytes (#380) Lauri Junkkari (1): Add doseq to WFS request qyery urlencode Tom Kralidis (11): back to dev fix WMS Dimension handling to explicitly look for name=time when setting time-based properties fix double ampersands in layer (#363) Update ows.py add support for GM03 as ISO profile add ISO locale support fix GM03 ref WFS: handle non-existing bounding boxes in feature types Sanitize URL for services (#374) fix tests update release version pesekon2 (1): SOS handle username and password --- requirements-dev.txt | 2 +- requirements.txt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 5a511f68..f460386f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -35,7 +35,7 @@ pytest-django==3.1.2 pytest-factoryboy==1.3.1 python-dateutil==2.6.1 # via faker, freezegun simplegeneric==0.8.1 # via ipython -six==1.10.0 # via django-extensions, faker, freezegun, prompt-toolkit, pydocstyle, python-dateutil, traitlets +six==1.11.0 # via django-extensions, faker, freezegun, prompt-toolkit, pydocstyle, python-dateutil, traitlets snowballstemmer==1.2.1 # via pydocstyle traitlets==4.3.2 # via ipython typing==3.6.2 # via ipython diff --git a/requirements.txt b/requirements.txt index d83e917f..dbf9d902 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,13 +11,13 @@ django-filter==1.0.4 djangorestframework==3.6.4 djangorestframework-gis==0.11.2 idna==2.6 # via requests -lxml==3.8.0 -owslib==0.14.0 +lxml==4.0.0 +owslib==0.15.0 psycopg2==2.7.3.1 pyproj==1.9.5.1 # via owslib python-dateutil==2.6.1 # via owslib pytz==2017.2 raven==6.1.0 requests==2.18.4 # via owslib -six==1.10.0 # via django-environ, python-dateutil +six==1.11.0 # via django-environ, python-dateutil urllib3==1.22 # via requests From 618b72dec1341e200d22c81a9dfa4bbb85fec801 Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Mon, 11 Dec 2017 14:18:48 +0200 Subject: [PATCH 08/13] parking area importer: Fix bare excepts Newer flake8 complains about these (for a good reason, since they're masking things like SystemExit or KeyboardInterrupt). --- parkings/importers/parking_areas.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parkings/importers/parking_areas.py b/parkings/importers/parking_areas.py index cbb1c9d9..ea043e29 100644 --- a/parkings/importers/parking_areas.py +++ b/parkings/importers/parking_areas.py @@ -149,7 +149,7 @@ def _download(self): typename='avoindata:liikennemerkkipilotti_pysakointipaikat', ) return etree.fromstring(bytes(response.getvalue(), 'UTF-8')) - except: + except Exception: logger.error('Unable to get data from the server.', exc_info=True) def _parse_member(self, member): @@ -187,7 +187,7 @@ def _parse_member(self, member): self.ns, ).text ) - except: + except Exception: capacity_estimate = None geom = self._get_polygons(data.find('avoindata:geom', self.ns)) From aba8a5e09bbe779704ccfabb0cd1c5e0be89756b Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Mon, 11 Dec 2017 14:09:47 +0200 Subject: [PATCH 09/13] requirements: Update versions Update required Python packages to newest available versions. Highlights from production requirements changes: * Django 1.11.5 -> 1.11.8 * Django Rest Framework 3.6.4 -> 3.7.3 * Django Rest Framework GIS 0.11.2 -> 0.12 * Django Filer 1.0.4 -> 1.1.0 --- requirements-dev.in | 4 ++++ requirements-dev.txt | 41 +++++++++++++++++++++-------------------- requirements.in | 2 +- requirements.txt | 21 ++++++++++----------- 4 files changed, 36 insertions(+), 32 deletions(-) diff --git a/requirements-dev.in b/requirements-dev.in index 8900195b..41f9a446 100644 --- a/requirements-dev.in +++ b/requirements-dev.in @@ -11,3 +11,7 @@ pytest-cov pytest-django pytest-factoryboy werkzeug + +# Factory Boy 2.9.0 to 2.9.2 don't seem to work. See +# https://github.com/pytest-dev/pytest-factoryboy/issues/47 +factory-boy!=2.9.0,!=2.9.1,!=2.9.2 diff --git a/requirements-dev.txt b/requirements-dev.txt index f460386f..4a2e038e 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,42 +2,43 @@ # # prequ update # -autoflake==0.7 -autopep8==1.3.2 -coverage==4.4.1 # via pytest-cov +attrs==17.3.0 # via pytest +autoflake==1.0 +autopep8==1.3.3 +coverage==4.4.2 # via pytest-cov decorator==4.1.2 # via ipython, traitlets -django-extensions==1.9.1 -dnspython==1.15.0 # via email-validator -email-validator==1.0.2 # via faker -factory-boy==2.8.1 # via pytest-factoryboy -faker==0.8.3 # via factory-boy -flake8==3.4.1 +django-extensions==1.9.8 +factory-boy==2.8.1 +faker==0.8.7 # via factory-boy +flake8==3.5.0 freezegun==0.3.9 -idna==2.6 # via email-validator inflection==0.3.1 # via pytest-factoryboy -ipython==6.2.0 +ipython==6.2.1 ipython-genutils==0.2.0 # via traitlets isort==4.2.15 -jedi==0.10.2 # via ipython +jedi==0.11.0 # via ipython mccabe==0.6.1 # via flake8 -pexpect==4.2.1 # via ipython +parso==0.1.0 # via jedi +pexpect==4.3.0 # via ipython pickleshare==0.7.4 # via ipython +pluggy==0.6.0 # via pytest prompt-toolkit==1.0.15 # via ipython ptyprocess==0.5.2 # via pexpect -py==1.4.34 # via pytest +py==1.5.2 # via pytest pycodestyle==2.3.1 # via autopep8, flake8 -pydocstyle==2.0.0 -pyflakes==1.5.0 # via autoflake, flake8 +pydocstyle==2.1.1 +pyflakes==1.6.0 # via autoflake, flake8 pygments==2.2.0 # via ipython -pytest==3.2.2 +pytest==3.3.1 pytest-cov==2.5.1 pytest-django==3.1.2 pytest-factoryboy==1.3.1 python-dateutil==2.6.1 # via faker, freezegun simplegeneric==0.8.1 # via ipython -six==1.11.0 # via django-extensions, faker, freezegun, prompt-toolkit, pydocstyle, python-dateutil, traitlets +six==1.11.0 # via django-extensions, faker, freezegun, prompt-toolkit, pydocstyle, pytest, python-dateutil, traitlets snowballstemmer==1.2.1 # via pydocstyle +text-unidecode==1.1 # via faker traitlets==4.3.2 # via ipython -typing==3.6.2 # via ipython +typing==3.6.2 # via django-extensions, ipython wcwidth==0.1.7 # via prompt-toolkit -werkzeug==0.12.2 +werkzeug==0.13 diff --git a/requirements.in b/requirements.in index 7836f290..7a35fe74 100644 --- a/requirements.in +++ b/requirements.in @@ -1,5 +1,5 @@ # Django -Django +Django~=1.11 # Settings django-environ diff --git a/requirements.txt b/requirements.txt index dbf9d902..bf3b14d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,22 +2,21 @@ # # prequ update # -certifi==2017.7.27.1 # via requests +certifi==2017.11.5 # via requests chardet==3.0.4 # via requests -contextlib2==0.5.5 # via raven -django==1.11.5 +django==1.11.8 django-environ==0.4.4 -django-filter==1.0.4 -djangorestframework==3.6.4 -djangorestframework-gis==0.11.2 +django-filter==1.1.0 +djangorestframework==3.7.3 +djangorestframework-gis==0.12 idna==2.6 # via requests -lxml==4.0.0 +lxml==4.1.1 owslib==0.15.0 -psycopg2==2.7.3.1 +psycopg2==2.7.3.2 pyproj==1.9.5.1 # via owslib python-dateutil==2.6.1 # via owslib -pytz==2017.2 -raven==6.1.0 +pytz==2017.3 +raven==6.3.0 requests==2.18.4 # via owslib -six==1.11.0 # via django-environ, python-dateutil +six==1.11.0 # via django-environ, djangorestframework-gis, python-dateutil urllib3==1.22 # via requests From 02cc12724f66ba6b466d6f45aea18ade703aecfe Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Mon, 11 Dec 2017 14:48:12 +0200 Subject: [PATCH 10/13] settings: DRF: Set DEFAULT_PAGINATION_CLASS This is needed with newer Django Rest Framework. --- parkkihubi/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/parkkihubi/settings.py b/parkkihubi/settings.py index e950ac7a..f8f98c22 100644 --- a/parkkihubi/settings.py +++ b/parkkihubi/settings.py @@ -159,6 +159,7 @@ 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',), 'EXCEPTION_HANDLER': 'parkings.exception_handler.parkings_exception_handler', 'PAGE_SIZE': 20, + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'TEST_REQUEST_DEFAULT_FORMAT': 'json', } From 49c25235d427d9b49001a473aee236a0c8490c98 Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Mon, 11 Dec 2017 15:02:15 +0200 Subject: [PATCH 11/13] Amend tests for changes is timestamp formatting The last DRF update changed how timestamps are returned from the endpoints. Previously they were formatted as 2017-12-11T13:01:23Z and now they are formatted as 2017-12-11T15:01:23+02:00 I.e. they use the timezone configured in the settings rather than UTC. See https://github.com/encode/django-rest-framework/pull/5435 for more info. --- parkings/tests/api/enforcement/test_valid_parking.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/parkings/tests/api/enforcement/test_valid_parking.py b/parkings/tests/api/enforcement/test_valid_parking.py index b3d2ce55..1e9abd4b 100644 --- a/parkings/tests/api/enforcement/test_valid_parking.py +++ b/parkings/tests/api/enforcement/test_valid_parking.py @@ -2,7 +2,7 @@ import pytest from django.core.urlresolvers import reverse -from django.utils.timezone import utc +from django.utils.timezone import localtime, utc from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN from ..utils import ( @@ -97,11 +97,17 @@ def check_parking_data_matches_parking_object(parking_data, parking_obj): def iso8601(dt): - return dt.strftime('%Y-%m-%dT%H:%M:%SZ') + return add_colon_to_tz(localtime(dt).strftime('%Y-%m-%dT%H:%M:%S%z')) def iso8601_us(dt): - return dt.strftime('%Y-%m-%dT%H:%M:%S.%fZ') + return add_colon_to_tz(localtime(dt).strftime('%Y-%m-%dT%H:%M:%S.%f%z')) + + +def add_colon_to_tz(timestamp_string): + assert isinstance(timestamp_string, str) + assert timestamp_string[-4:].isdigit(), "Last 4 chars should be digits" + return timestamp_string[:-2] + ':' + timestamp_string[-2:] def test_registration_number_filter(operator, staff_api_client, parking_factory): From 5760537da67ccf33003467d4ae18832b336279f0 Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Tue, 12 Dec 2017 13:28:36 +0200 Subject: [PATCH 12/13] Revert "Amend tests for changes is timestamp formatting" This reverts commit 49c25235d427d9b49001a473aee236a0c8490c98. --- parkings/tests/api/enforcement/test_valid_parking.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/parkings/tests/api/enforcement/test_valid_parking.py b/parkings/tests/api/enforcement/test_valid_parking.py index 1e9abd4b..b3d2ce55 100644 --- a/parkings/tests/api/enforcement/test_valid_parking.py +++ b/parkings/tests/api/enforcement/test_valid_parking.py @@ -2,7 +2,7 @@ import pytest from django.core.urlresolvers import reverse -from django.utils.timezone import localtime, utc +from django.utils.timezone import utc from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN from ..utils import ( @@ -97,17 +97,11 @@ def check_parking_data_matches_parking_object(parking_data, parking_obj): def iso8601(dt): - return add_colon_to_tz(localtime(dt).strftime('%Y-%m-%dT%H:%M:%S%z')) + return dt.strftime('%Y-%m-%dT%H:%M:%SZ') def iso8601_us(dt): - return add_colon_to_tz(localtime(dt).strftime('%Y-%m-%dT%H:%M:%S.%f%z')) - - -def add_colon_to_tz(timestamp_string): - assert isinstance(timestamp_string, str) - assert timestamp_string[-4:].isdigit(), "Last 4 chars should be digits" - return timestamp_string[:-2] + ':' + timestamp_string[-2:] + return dt.strftime('%Y-%m-%dT%H:%M:%S.%fZ') def test_registration_number_filter(operator, staff_api_client, parking_factory): From adb42316b5b7a198d536b2afeab95b6cf616b2bb Mon Sep 17 00:00:00 2001 From: Tuomas Suutari Date: Tue, 12 Dec 2017 14:03:39 +0200 Subject: [PATCH 13/13] Re-configure timezones for API and Admin Use UTC as Django default timezone so that Django Rest Framework will use it for the API endpoints, but override the timezone in Django Admin to still be Europe/Helsinki with a middleware. --- parkkihubi/middleware.py | 31 +++++++++++++++++++++++++++++++ parkkihubi/settings.py | 6 ++++-- 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 parkkihubi/middleware.py diff --git a/parkkihubi/middleware.py b/parkkihubi/middleware.py new file mode 100644 index 00000000..6faa2744 --- /dev/null +++ b/parkkihubi/middleware.py @@ -0,0 +1,31 @@ +import contextlib +from functools import lru_cache + +from django.conf import settings +from django.urls import reverse +from django.utils import timezone + +# No-op context manager +# +# Usable like the one coming in Python 3.7, see +# https://github.com/python/cpython/commit/0784a2e5b174d2dbf7b144d480559e650c5cf64c +nullcontext = contextlib.ExitStack + + +class AdminTimezoneMiddleware: + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + tz_overrider = nullcontext() + if request.path.startswith(get_admin_url_path_prefix()): + admin_tz = getattr(settings, 'ADMIN_TIME_ZONE', None) + if admin_tz: + tz_overrider = timezone.override(admin_tz) + with tz_overrider: + return self.get_response(request) + + +@lru_cache() +def get_admin_url_path_prefix(): + return reverse('admin:index') diff --git a/parkkihubi/settings.py b/parkkihubi/settings.py index f8f98c22..365f874a 100644 --- a/parkkihubi/settings.py +++ b/parkkihubi/settings.py @@ -87,10 +87,11 @@ ############## # Middleware # ############## -MIDDLEWARE_CLASSES = [ +MIDDLEWARE = [ 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', + 'parkkihubi.middleware.AdminTimezoneMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', @@ -133,7 +134,8 @@ # Languages & Localization # ############################ LANGUAGE_CODE = 'en' -TIME_ZONE = 'Europe/Helsinki' +TIME_ZONE = 'UTC' +ADMIN_TIME_ZONE = 'Europe/Helsinki' USE_I18N = True USE_L10N = True USE_TZ = True