From 4f83cbf4edc407476378dbefcc15b6b4c5ee1fe2 Mon Sep 17 00:00:00 2001 From: Cristi Ingineru Date: Thu, 16 Aug 2018 14:27:38 +0300 Subject: [PATCH 1/4] Add LocalizedIntegerFieldWidget --- localized_fields/fields/integer_field.py | 10 ++++++++++ localized_fields/forms.py | 12 ++++++++++-- localized_fields/value.py | 5 +++++ localized_fields/widgets.py | 4 ++++ tests/test_integer_field.py | 1 + 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/localized_fields/fields/integer_field.py b/localized_fields/fields/integer_field.py index c91e0dc..6374aa1 100644 --- a/localized_fields/fields/integer_field.py +++ b/localized_fields/fields/integer_field.py @@ -5,6 +5,7 @@ from django.db.utils import IntegrityError from .field import LocalizedField from ..value import LocalizedValue, LocalizedIntegerValue +from ..forms import LocalizedIntegerFieldForm class LocalizedIntegerField(LocalizedField): @@ -63,6 +64,15 @@ class LocalizedIntegerField(LocalizedField): return prepped_value + def formfield(self, **kwargs): + """Gets the form field associated with this field.""" + defaults = { + 'form_class': LocalizedIntegerFieldForm + } + + defaults.update(kwargs) + return super().formfield(**defaults) + @staticmethod def _convert_localized_value(value: LocalizedValue) -> LocalizedIntegerValue: """Converts from :see:LocalizedValue to :see:LocalizedIntegerValue.""" diff --git a/localized_fields/forms.py b/localized_fields/forms.py index 21606cf..1077591 100644 --- a/localized_fields/forms.py +++ b/localized_fields/forms.py @@ -6,9 +6,9 @@ from django.core.exceptions import ValidationError from django.forms.widgets import FILE_INPUT_CONTRADICTION from .value import LocalizedValue, LocalizedStringValue, \ - LocalizedFileValue + LocalizedFileValue, LocalizedIntegerValue from .widgets import LocalizedFieldWidget, LocalizedCharFieldWidget, \ - LocalizedFileWidget + LocalizedFileWidget, AdminLocalizedIntegerFieldWidget class LocalizedFieldForm(forms.MultiValueField): @@ -79,6 +79,14 @@ class LocalizedTextFieldForm(LocalizedFieldForm): value_class = LocalizedStringValue +class LocalizedIntegerFieldForm(LocalizedFieldForm): + """Form for a localized integer field, allows editing + the field in multiple languages.""" + + widget = AdminLocalizedIntegerFieldWidget + value_class = LocalizedIntegerValue + + class LocalizedFileFieldForm(LocalizedFieldForm, forms.FileField): """Form for a localized file field, allows editing the field in multiple languages.""" diff --git a/localized_fields/value.py b/localized_fields/value.py index 65f2a0c..948ac91 100644 --- a/localized_fields/value.py +++ b/localized_fields/value.py @@ -228,3 +228,8 @@ class LocalizedIntegerValue(LocalizedValue): return self.default_value return int(value) + + def __str__(self) -> str: + """Returns string representation of value""" + + return str(self.get(translation.get_language())) diff --git a/localized_fields/widgets.py b/localized_fields/widgets.py index 57ed392..f48bf5a 100644 --- a/localized_fields/widgets.py +++ b/localized_fields/widgets.py @@ -120,3 +120,7 @@ class AdminLocalizedCharFieldWidget(AdminLocalizedFieldWidget): class AdminLocalizedFileFieldWidget(AdminLocalizedFieldWidget): widget = widgets.AdminFileWidget + + +class AdminLocalizedIntegerFieldWidget(AdminLocalizedFieldWidget): + widget = widgets.AdminIntegerFieldWidget diff --git a/tests/test_integer_field.py b/tests/test_integer_field.py index d7c5a06..f365ef8 100644 --- a/tests/test_integer_field.py +++ b/tests/test_integer_field.py @@ -4,6 +4,7 @@ from django.conf import settings from django.db import connection from django.utils import translation +from localized_fields.value import LocalizedIntegerValue from localized_fields.fields import LocalizedIntegerField from .fake_model import get_fake_model From 4922a1b93fec5929798d0bc3e207eb85ea0488dd Mon Sep 17 00:00:00 2001 From: Cristi Ingineru Date: Mon, 24 Sep 2018 12:57:46 +0300 Subject: [PATCH 2/4] self.translate() --- localized_fields/value.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/localized_fields/value.py b/localized_fields/value.py index 948ac91..85c90cc 100644 --- a/localized_fields/value.py +++ b/localized_fields/value.py @@ -232,4 +232,5 @@ class LocalizedIntegerValue(LocalizedValue): def __str__(self) -> str: """Returns string representation of value""" - return str(self.get(translation.get_language())) + value = self.translate() + return str(value) if value is not None else None From b2f50ec82bdf44a99a3192b1af1f1d4b92057086 Mon Sep 17 00:00:00 2001 From: Swen Kooij Date: Fri, 11 Jan 2019 14:37:03 +0200 Subject: [PATCH 3/4] Convert to use CircleCI and run tests against Django 2.1/Python 3.7 --- .circleci/config.yml | 92 +++++++++++++++++++++++++++++++++++++ .coveragerc | 2 - .gitignore | 1 + .scrutinizer.yml | 34 -------------- requirements/test.txt | 4 +- setup.cfg | 1 + setup.py | 38 +++++++++++++-- tests/test_field.py | 1 - tests/test_form.py | 1 - tests/test_integer_field.py | 3 +- tests/test_query_set.py | 2 - tests/test_value.py | 4 +- tox.ini | 3 +- 13 files changed, 135 insertions(+), 51 deletions(-) create mode 100644 .circleci/config.yml delete mode 100644 .scrutinizer.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..532811c --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,92 @@ +version: 2 +jobs: + test-python35: + docker: + - image: python:3.5-alpine + - image: postgres:11.0 + environment: + POSTGRES_DB: 'localizedfields' + POSTGRES_USER: 'localizedfields' + POSTGRES_PASSWORD: 'localizedfields' + steps: + - checkout + - run: + name: Install packages + command: apk add postgresql-libs gcc musl-dev postgresql-dev git + - run: + name: Install Python packages + command: pip install -r requirements/test.txt + - run: + name: Run tests + command: tox -e 'py35-dj{111,20,21}' + environment: + DATABASE_URL: 'postgres://localizedfields:localizedfields@localhost:5432/localizedfields' + + test-python36: + docker: + - image: python:3.6-alpine + - image: postgres:11.0 + environment: + POSTGRES_DB: 'localizedfields' + POSTGRES_USER: 'localizedfields' + POSTGRES_PASSWORD: 'localizedfields' + steps: + - checkout + - run: + name: Install packages + command: apk add postgresql-libs gcc musl-dev postgresql-dev git + - run: + name: Install Python packages + command: pip install -r requirements/test.txt + - run: + name: Run tests + command: tox -e 'py36-dj{111,20,21}' + environment: + DATABASE_URL: 'postgres://localizedfields:localizedfields@localhost:5432/localizedfields' + + test-python37: + docker: + - image: python:3.7-alpine + - image: postgres:11.0 + environment: + POSTGRES_DB: 'localizedfields' + POSTGRES_USER: 'localizedfields' + POSTGRES_PASSWORD: 'localizedfields' + steps: + - checkout + - run: + name: Install packages + command: apk add postgresql-libs gcc musl-dev postgresql-dev git + - run: + name: Install Python packages + command: pip install -r requirements/test.txt + - run: + name: Run tests + command: tox -e 'py37-dj{111,20,21}' + environment: + DATABASE_URL: 'postgres://localizedfields:localizedfields@localhost:5432/localizedfields' + + lint: + docker: + - image: python:3.5-alpine + steps: + - checkout + - run: + name: Install packages + command: apk add postgresql-libs gcc musl-dev postgresql-dev git + - run: + name: Install Python packages + command: pip install -r requirements/test.txt + - run: + name: Lint code + command: python setup.py lint + + +workflows: + version: 2 + build: + jobs: + - test-python35 + - test-python36 + - test-python37 + - lint diff --git a/.coveragerc b/.coveragerc index 4ebca25..281acfa 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,5 +1,3 @@ [run] include = localized_fields/* omit = *migrations*, *tests* -plugins = - django_coverage_plugin diff --git a/.gitignore b/.gitignore index bf2f15f..0b8aef4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Ignore virtual environments env/ +.env/ # Ignore Python byte code cache *.pyc diff --git a/.scrutinizer.yml b/.scrutinizer.yml deleted file mode 100644 index 9b56ffa..0000000 --- a/.scrutinizer.yml +++ /dev/null @@ -1,34 +0,0 @@ -checks: - python: - code_rating: true - duplicate_code: true -tools: - pylint: - python_version: '3' - config_file: .pylintrc -filter: - excluded_paths: - - '*/tests/*' - - '*/migrations/*' -build: - environment: - python: '3.5.0' - variables: - DJANGO_SETTINGS_MODULES: settings - DATABASE_URL: postgres://scrutinizer:scrutinizer@localhost:5434/localized_fields - postgresql: true - - dependencies: - override: - - 'pip install -r requirements/test.txt' - tests: - override: - - - command: pep8 ./localized_fields/ - - - command: flake8 ./localized_fields/ - - - command: tox - coverage: - file: '.coverage' - format: 'py-cc' diff --git a/requirements/test.txt b/requirements/test.txt index d3b114c..01b4197 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -2,15 +2,13 @@ django-autoslug==1.9.3 django-bleach==0.3.0 -django-coverage-plugin==1.3.1 psycopg2==2.7.3.2 pylint==1.8.1 pylint-common==0.2.5 pylint-django==0.8.0 pylint-plugin-utils==0.2.6 coverage==4.4.2 -django-coverage-plugin==1.3.1 -flake8==3.5.0 +flake8==3.6.0 pep8==1.7.1 dj-database-url==0.4.2 tox==2.9.1 diff --git a/setup.cfg b/setup.cfg index a30ab0e..0326805 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,6 @@ [flake8] max-line-length = 120 +ignore = E252, W605 exclude = env,.tox,.git,config/settings,*/migrations/*,*/static/CACHE/*,docs,node_modules [pep8] diff --git a/setup.py b/setup.py index a67c603..14f0c49 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,39 @@ import os +import distutils.cmd +import subprocess from setuptools import find_packages, setup + +class BaseCommand(distutils.cmd.Command): + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + +def create_command(text, commands): + """Creates a custom setup.py command.""" + + class CustomCommand(BaseCommand): + description = text + + def run(self): + for cmd in commands: + subprocess.check_call(cmd) + + return CustomCommand + + with open(os.path.join(os.path.dirname(__file__), 'README.rst'), encoding='utf-8') as readme: README = readme.read() setup( name='django-localized-fields', - version='5.0a3', + version='5.0a5', packages=find_packages(exclude=['tests']), include_package_data=True, license='MIT License', @@ -18,7 +44,7 @@ setup( author_email='open-source@sectorlabs.ro', keywords=['django', 'localized', 'language', 'models', 'fields'], install_requires=[ - 'django-postgres-extra>=1.21a11', + 'django-postgres-extra>=1.21a14', 'Django>=1.11', 'deprecation==2.0.3' ], @@ -32,5 +58,11 @@ setup( 'Programming Language :: Python :: 3.5', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', - ] + ], + cmdclass={ + 'lint': create_command( + 'Lints the code', + [['flake8', 'setup.py', 'localized_fields', 'tests']], + ), + }, ) diff --git a/tests/test_field.py b/tests/test_field.py index 3bd896c..ff9d693 100644 --- a/tests/test_field.py +++ b/tests/test_field.py @@ -33,7 +33,6 @@ class LocalizedFieldTestCase(TestCase): field = LocalizedField(required=False) assert field.required == [] - @staticmethod def test_from_db_value(): """Tests whether the :see:from_db_value function diff --git a/tests/test_form.py b/tests/test_form.py index 0bedcc1..5c235fa 100644 --- a/tests/test_form.py +++ b/tests/test_form.py @@ -40,7 +40,6 @@ class LocalizedFieldFormTestCase(TestCase): for field in form.fields: assert not field.required - @staticmethod def test_compress(): """Tests whether the :see:compress function diff --git a/tests/test_integer_field.py b/tests/test_integer_field.py index f365ef8..57dd199 100644 --- a/tests/test_integer_field.py +++ b/tests/test_integer_field.py @@ -4,7 +4,6 @@ from django.conf import settings from django.db import connection from django.utils import translation -from localized_fields.value import LocalizedIntegerValue from localized_fields.fields import LocalizedIntegerField from .fake_model import get_fake_model @@ -149,7 +148,7 @@ class LocalizedIntegerFieldTestCase(TestCase): with connection.cursor() as cursor: table_name = self.TestModel._meta.db_table - cursor.execute("update %s set score = 'en=>haha'" % table_name); + cursor.execute("update %s set score = 'en=>haha'" % table_name) obj.refresh_from_db() assert obj.score.get(settings.LANGUAGE_CODE) is None diff --git a/tests/test_query_set.py b/tests/test_query_set.py index 3ed9c79..2406404 100644 --- a/tests/test_query_set.py +++ b/tests/test_query_set.py @@ -1,6 +1,4 @@ -from django.conf import settings from django.test import TestCase -from django.utils import translation from localized_fields.fields import LocalizedField diff --git a/tests/test_value.py b/tests/test_value.py index e722a46..c9a6622 100644 --- a/tests/test_value.py +++ b/tests/test_value.py @@ -152,7 +152,7 @@ class LocalizedValueTestCase(TestCase): # with no value, we always expect it to return None localized_value = LocalizedValue() - assert localized_value.translate() == None + assert localized_value.translate() is None assert str(localized_value) == '' # with no value for the default language, the default @@ -164,7 +164,7 @@ class LocalizedValueTestCase(TestCase): }) translation.activate(settings.LANGUAGE_CODE) - assert localized_value.translate() == None + assert localized_value.translate() is None assert str(localized_value) == '' @staticmethod diff --git a/tox.ini b/tox.ini index a7f9784..be5c493 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,11 @@ [tox] -envlist = py35-dj{111,20} +envlist = py35-dj{111,20,21}, py36-dj{111,20,21}, py37-dj{111,20,21} [testenv] deps = dj111: Django>=1.11,<1.12 dj20: Django>=2.0,<2.1 + dj21: Django>=2.1,<2.2 -rrequirements/test.txt setenv = DJANGO_SETTINGS_MODULE=settings From c6e8321ae7038ed6d9152d46891f21743aa33da6 Mon Sep 17 00:00:00 2001 From: Swen Kooij Date: Fri, 11 Jan 2019 14:40:27 +0200 Subject: [PATCH 4/4] Add CircleCI badge to README --- README.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index cb6afa8..b5f3bec 100644 --- a/README.rst +++ b/README.rst @@ -1,11 +1,8 @@ django-localized-fields ======================= -.. image:: https://scrutinizer-ci.com/g/SectorLabs/django-localized-fields/badges/quality-score.png - :target: https://scrutinizer-ci.com/g/SectorLabs/django-localized-fields/ - -.. image:: https://scrutinizer-ci.com/g/SectorLabs/django-localized-fields/badges/coverage.png - :target: https://scrutinizer-ci.com/g/SectorLabs/django-localized-fields/ +.. image:: https://circleci.com/gh/SectorLabs/django-localized-fields.svg?style=svg + :target: https://circleci.com/gh/SectorLabs/django-localized-fields .. image:: https://img.shields.io/github/license/SectorLabs/django-localized-fields.svg :target: https://github.com/SectorLabs/django-localized-fields/blob/master/LICENSE.md