Hello community, here is the log from the commit of package python-django-extensions for openSUSE:Factory checked in at 2019-10-30 14:48:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-django-extensions (Old) and /work/SRC/openSUSE:Factory/.python-django-extensions.new.2990 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-extensions" Wed Oct 30 14:48:55 2019 rev:4 rq:744146 version:2.2.5 Changes: -------- --- /work/SRC/openSUSE:Factory/python-django-extensions/python-django-extensions.changes 2019-10-08 19:57:54.788200576 +0200 +++ /work/SRC/openSUSE:Factory/.python-django-extensions.new.2990/python-django-extensions.changes 2019-10-30 14:48:59.926257569 +0100 @@ -1,0 +2,7 @@ +Wed Oct 30 12:02:11 UTC 2019 - Tomáš Chvátal <tchva...@suse.com> + +- Update to 2.2.5: + * RandomCharField, Support unique_together + * export_emails, add settings for overriding queryset fields, order_by and the full_name function + +------------------------------------------------------------------- Old: ---- django-extensions-2.2.3.tar.gz New: ---- django-extensions-2.2.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-django-extensions.spec ++++++ --- /var/tmp/diff_new_pack.JcNE4J/_old 2019-10-30 14:49:00.634258321 +0100 +++ /var/tmp/diff_new_pack.JcNE4J/_new 2019-10-30 14:49:00.638258325 +0100 @@ -18,7 +18,7 @@ %define skip_python2 1 Name: python-django-extensions -Version: 2.2.3 +Version: 2.2.5 Release: 0 Summary: Extensions for Django License: BSD-3-Clause ++++++ django-extensions-2.2.3.tar.gz -> django-extensions-2.2.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-extensions-2.2.3/.travis.yml new/django-extensions-2.2.5/.travis.yml --- old/django-extensions-2.2.3/.travis.yml 2019-10-02 22:08:52.000000000 +0200 +++ new/django-extensions-2.2.5/.travis.yml 2019-10-20 17:41:01.000000000 +0200 @@ -13,15 +13,15 @@ env: TOXENV=py36-flake8 - python: 3.7 env: TOXENV=py37-flake8 - dist: xenial - sudo: required - - python: 3.6 + - python: 3.8 + env: TOXENV=py38-flake8 + - python: 3.7 env: TOXENV=precommit - - python: 3.6 + - python: 3.7 env: TOXENV=safety - - python: 3.6 + - python: 3.7 env: TOXENV=mypy - - python: 3.6 + - python: 3.7 env: TOXENV=compile-catalog - python: 2.7 env: TOXENV=py27-dj111 @@ -37,48 +37,56 @@ env: TOXENV=py36-djmaster - python: 3.7 env: TOXENV=py37-dj21 - dist: xenial - sudo: required - python: 3.7 env: TOXENV=py37-dj22 - dist: xenial - sudo: required + - python: 3.8 + env: TOXENV=py38-dj22 - python: 3.7 env: TOXENV=py37-dj30 - dist: xenial - sudo: required + - python: 3.8 + env: TOXENV=py38-dj30 - python: 3.7 env: TOXENV=py37-dj22-postgres - dist: xenial - sudo: required + services: + - postgresql + - python: 3.8 + env: TOXENV=py38-dj22-postgres services: - postgresql - python: 3.7 env: TOXENV=py37-dj30-postgres - dist: xenial - sudo: required + services: + - postgresql + - python: 3.8 + env: TOXENV=py38-dj30-postgres services: - postgresql - python: 3.7 env: TOXENV=py37-dj22-mysql - dist: xenial - sudo: required + services: + - mysql + - python: 3.8 + env: TOXENV=py38-dj22-mysql services: - mysql - python: 3.7 env: TOXENV=py37-dj30-mysql - dist: xenial - sudo: required + services: + - mysql + - python: 3.8 + env: TOXENV=py38-dj30-mysql services: - mysql - python: 3.7 env: TOXENV=py37-djmaster - dist: xenial - sudo: required + - python: 3.8 + env: TOXENV=py38-djmaster - python: 3.7 env: TOXENV=py37-djmaster-postgres - dist: xenial - sudo: required + services: + - postgresql + - python: 3.8 + env: TOXENV=py38-djmaster-postgres services: - postgresql - python: pypy2.7-5.10.0 @@ -97,8 +105,12 @@ env: TOXENV=py36-djmaster - python: 3.7 env: TOXENV=py37-djmaster + - python: 3.8 + env: TOXENV=py38-djmaster - python: 3.7 env: TOXENV=py37-djmaster-postgres + - python: 3.8 + env: TOXENV=py38-djmaster-postgres - python: pypy3.5-5.10.1 env: TOXENV=pypy3-djmaster - python: pypy2.7-5.10.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-extensions-2.2.3/CHANGELOG.md new/django-extensions-2.2.5/CHANGELOG.md --- old/django-extensions-2.2.3/CHANGELOG.md 2019-10-02 22:08:52.000000000 +0200 +++ new/django-extensions-2.2.5/CHANGELOG.md 2019-10-20 17:41:01.000000000 +0200 @@ -1,6 +1,22 @@ Changelog ========= +2.2.5 +----- + +Changes: + - Improvement: travis, add Python 3.8 + - Improvement: setup.py, update classifiers + + +2.2.4 +----- + +Changes: + - Improvement: RandomCharField, Support unique_together + - Improvement: export_emails, add settings for overriding queryset fields, order_by and the full_name function + + 2.2.3 ----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-extensions-2.2.3/django_extensions/__init__.py new/django-extensions-2.2.5/django_extensions/__init__.py --- old/django-extensions-2.2.3/django_extensions/__init__.py 2019-10-02 22:08:52.000000000 +0200 +++ new/django-extensions-2.2.5/django_extensions/__init__.py 2019-10-20 17:41:01.000000000 +0200 @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -VERSION = (2, 2, 3) +VERSION = (2, 2, 5) def get_version(version): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-extensions-2.2.3/django_extensions/db/fields/__init__.py new/django-extensions-2.2.5/django_extensions/db/fields/__init__.py --- old/django-extensions-2.2.3/django_extensions/db/fields/__init__.py 2019-10-02 22:08:52.000000000 +0200 +++ new/django-extensions-2.2.5/django_extensions/db/fields/__init__.py 2019-10-20 17:41:01.000000000 +0200 @@ -340,6 +340,12 @@ yield ''.join(get_random_string(self.length, chars)) raise RuntimeError('max random character attempts exceeded (%s)' % self.max_unique_query_attempts) + def in_unique_together(self, model_instance): + for params in model_instance._meta.unique_together: + if self.attname in params: + return True + return False + def pre_save(self, model_instance, add): if not add and getattr(model_instance, self.attname) != '': return getattr(model_instance, self.attname) @@ -360,7 +366,7 @@ population += string.punctuation random_chars = self.random_char_generator(population) - if not self.unique: + if not self.unique and not self.in_unique_together(model_instance): new = six.next(random_chars) setattr(model_instance, self.attname, new) return new diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-extensions-2.2.3/django_extensions/management/commands/export_emails.py new/django-extensions-2.2.5/django_extensions/management/commands/export_emails.py --- old/django-extensions-2.2.3/django_extensions/management/commands/export_emails.py 2019-10-02 22:08:52.000000000 +0200 +++ new/django-extensions-2.2.5/django_extensions/management/commands/export_emails.py 2019-10-20 17:41:01.000000000 +0200 @@ -2,6 +2,7 @@ from __future__ import unicode_literals, print_function import sys +from django.conf import settings from django.contrib.auth import get_user_model from django.contrib.auth.models import Group from django.core.management.base import BaseCommand, CommandError @@ -20,12 +21,24 @@ ] -def full_name(first_name, last_name, username, **extra): +def full_name(**kwargs): """Return full name or username.""" + first_name = kwargs.get('first_name') + last_name = kwargs.get('last_name') + name = " ".join(n for n in [first_name, last_name] if n) - if not name: + if name: + return name + + name = kwargs.get('name') + if name: + return name + + username = kwargs.get('username') + if username: return username - return name + + return "" class Command(BaseCommand): @@ -51,6 +64,9 @@ help="output format. May be one of %s." % ", ".join(FORMATS), ) + def full_name(self, **kwargs): + return getattr(settings, 'EXPORT_EMAILS_FULL_NAME_FUNC', full_name)(**kwargs) + @signalcommand def handle(self, *args, **options): if len(args) > 1: @@ -63,10 +79,13 @@ raise CommandError("Unknown group '" + group + "'. Valid group names are: " + names) UserModel = get_user_model() - qs = UserModel.objects.all().order_by('last_name', 'first_name', 'username', 'email') + order_by = getattr(settings, 'EXPORT_EMAILS_ORDER_BY', ['last_name', 'first_name', 'username', 'email']) + fields = getattr(settings, 'EXPORT_EMAILS_FIELDS', ['last_name', 'first_name', 'username', 'email']) + + qs = UserModel.objects.all().order_by(*order_by) if group: qs = qs.filter(groups__name=group).distinct() - qs = qs.values('last_name', 'first_name', 'username', 'email') + qs = qs.values(*fields) getattr(self, options['format'])(qs) def address(self, qs): @@ -74,7 +93,7 @@ Single entry per line in the format of: "full name" <m...@address.com>; """ - self.stdout.write("\n".join('"%s" <%s>;' % (full_name(**ent), ent['email']) for ent in qs)) + self.stdout.write("\n".join('"%s" <%s>;' % (self.full_name(**ent), ent.get('email', '')) for ent in qs)) self.stdout.write("\n") def emails(self, qs): @@ -82,7 +101,7 @@ Single entry with email only in the format of: m...@address.com, """ - self.stdout.write(",\n".join(ent['email'] for ent in qs)) + self.stdout.write(",\n".join(ent['email'] for ent in qs if ent.get('email'))) self.stdout.write("\n") def google(self, qs): @@ -90,7 +109,7 @@ csvf = writer(sys.stdout) csvf.writerow(['Name', 'Email']) for ent in qs: - csvf.writerow([full_name(**ent), ent['email']]) + csvf.writerow([self.full_name(**ent), ent.get('email', '')]) def linkedin(self, qs): """ @@ -100,7 +119,7 @@ csvf = writer(sys.stdout) csvf.writerow(['First Name', 'Last Name', 'Email']) for ent in qs: - csvf.writerow([ent['first_name'], ent['last_name'], ent['email']]) + csvf.writerow([ent.get('first_name', ''), ent.get('last_name', ''), ent.get('email', '')]) def outlook(self, qs): """CSV format suitable for importing into outlook""" @@ -112,7 +131,7 @@ csvf.writerow(columns) empty = [''] * (len(columns) - 2) for ent in qs: - csvf.writerow([full_name(**ent), ent['email']] + empty) + csvf.writerow([self.full_name(**ent), ent.get('email', '')] + empty) def vcard(self, qs): """VCARD format.""" @@ -125,14 +144,15 @@ out = sys.stdout for ent in qs: card = vobject.vCard() - card.add('fn').value = full_name(**ent) - if not ent['last_name'] and not ent['first_name']: - # fallback to fullname, if both first and lastname are not declared - card.add('n').value = vobject.vcard.Name(full_name(**ent)) - else: + card.add('fn').value = self.full_name(**ent) + if ent.get('last_name') and ent.get('first_name'): card.add('n').value = vobject.vcard.Name(ent['last_name'], ent['first_name']) - emailpart = card.add('email') - emailpart.value = ent['email'] - emailpart.type_param = 'INTERNET' + else: + # fallback to fullname, if both first and lastname are not declared + card.add('n').value = vobject.vcard.Name(self.full_name(**ent)) + if ent.get('email'): + emailpart = card.add('email') + emailpart.value = ent['email'] + emailpart.type_param = 'INTERNET' out.write(card.serialize()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-extensions-2.2.3/docs/conf.py new/django-extensions-2.2.5/docs/conf.py --- old/django-extensions-2.2.3/docs/conf.py 2019-10-02 22:08:52.000000000 +0200 +++ new/django-extensions-2.2.5/docs/conf.py 2019-10-20 17:41:01.000000000 +0200 @@ -47,7 +47,7 @@ # The short X.Y version. version = '2.2' # The full version, including alpha/beta/rc tags. -release = '2.2.3' +release = '2.2.5' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-extensions-2.2.3/docs/export_emails.rst new/django-extensions-2.2.5/docs/export_emails.rst --- old/django-extensions-2.2.3/docs/export_emails.rst 2019-10-02 22:08:52.000000000 +0200 +++ new/django-extensions-2.2.5/docs/export_emails.rst 2019-10-20 17:41:01.000000000 +0200 @@ -78,4 +78,40 @@ A vCard format which Apple Address Book can parse and import. + +Settings +-------- + +There are a couple of settings keys which can be configured in `settings.py`. +Below the default values are shown: + +``` +EXPORT_EMAILS_ORDER_BY = ['last_name', 'first_name', 'username', 'email'] +EXPORT_EMAILS_FIELDS = ['last_name', 'first_name', 'username', 'email'] +EXPORT_EMAILS_FULL_NAME_FUNC = None +``` + +EXPORT_EMAILS_ORDER_BY +~~~~~~~~~~~~~~~~~~~~~~ + +Specifies the `order_by(...)` clause on the query being done into the databse to +retreive the users. This determines the order of the output. + + +EXPORT_EMAILS_FIELDS +~~~~~~~~~~~~~~~~~~~~ + +Specifies which fields will be selected from the database. This is most useful in +combination with `EXPORT_EMAILS_FULL_NAME_FUNC` to select other fields you might +want to use inside the custom function or when using a custom User model which +does not have fields like 'first_name' and 'last_name'. + +EXPORT_EMAILS_FULL_NAME_FUNC +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A function to use to create a full name based on the database fields selected by +`EXPORT_EMAILS_FULL_NAME_FUNC`. The default implementation can be looked up in +https://github.com/django-extensions/django-extensions/blob/master/django_extensions/management/commands/export_emails.py#L23 + + .. _`LinkedIn Groups`: http://www.linkedin.com/static?key=groups_info diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-extensions-2.2.3/docs/index.rst new/django-extensions-2.2.5/docs/index.rst --- old/django-extensions-2.2.3/docs/index.rst 2019-10-02 22:08:52.000000000 +0200 +++ new/django-extensions-2.2.5/docs/index.rst 2019-10-20 17:41:01.000000000 +0200 @@ -77,6 +77,7 @@ sqldsn validate_templates validators + admin_generator Indices and tables diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-extensions-2.2.3/setup.py new/django-extensions-2.2.5/setup.py --- old/django-extensions-2.2.3/setup.py 2019-10-02 22:08:52.000000000 +0200 +++ new/django-extensions-2.2.5/setup.py 2019-10-20 17:41:01.000000000 +0200 @@ -171,8 +171,8 @@ 'Environment :: Web Environment', 'Framework :: Django', 'Framework :: Django :: 1.11', - 'Framework :: Django :: 2.0', 'Framework :: Django :: 2.1', + 'Framework :: Django :: 2.2', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', @@ -180,10 +180,10 @@ 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Utilities', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-extensions-2.2.3/tests/test_randomchar_field.py new/django-extensions-2.2.5/tests/test_randomchar_field.py --- old/django-extensions-2.2.3/tests/test_randomchar_field.py 2019-10-02 22:08:52.000000000 +0200 +++ new/django-extensions-2.2.5/tests/test_randomchar_field.py 2019-10-20 17:41:01.000000000 +0200 @@ -7,6 +7,7 @@ from .testapp.models import RandomCharTestModel, RandomCharTestModelUnique, RandomCharTestModelLowercase from .testapp.models import RandomCharTestModelUppercase, RandomCharTestModelAlpha, RandomCharTestModelDigits from .testapp.models import RandomCharTestModelPunctuation, RandomCharTestModelLowercaseAlphaDigits, RandomCharTestModelUppercaseAlphaDigits +from .testapp.models import RandomCharTestModelUniqueTogether try: from unittest import mock @@ -86,3 +87,15 @@ m = RandomCharTestModelUnique() with pytest.raises(RuntimeError): m.save() + + def testRandomCharTestModelUniqueTogether(self): + with mock.patch('django_extensions.db.fields.get_random_string') as mock_sample: + mock_sample.return_value = 'aaa' + m = RandomCharTestModelUniqueTogether() + m.common_field = 'bbb' + m.save() + + m = RandomCharTestModelUniqueTogether() + m.common_field = 'bbb' + with pytest.raises(RuntimeError): + m.save() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-extensions-2.2.3/tests/testapp/models.py new/django-extensions-2.2.5/tests/testapp/models.py --- old/django-extensions-2.2.3/tests/testapp/models.py 2019-10-02 22:08:52.000000000 +0200 +++ new/django-extensions-2.2.5/tests/testapp/models.py 2019-10-20 17:41:01.000000000 +0200 @@ -351,6 +351,15 @@ app_label = 'django_extensions' +class RandomCharTestModelUniqueTogether(models.Model): + random_char_field = RandomCharField(length=8) + common_field = models.CharField(max_length=10) + + class Meta: + app_label = 'django_extensions' + unique_together = ('random_char_field', 'common_field') + + class TimestampedTestModel(TimeStampedModel): class Meta: app_label = 'django_extensions'