feat(dev): Migrate to pytest

This commit is contained in:
Serg Tereshchenko 2022-07-12 00:54:26 +03:00
parent 8535a4ee23
commit d3e2396be6
13 changed files with 1358 additions and 376 deletions

View file

@ -95,7 +95,7 @@ jobs:
if [[ $DB == postgres ]]; then
pip install -q psycopg2-binary
fi
pip install coverage six $(./get-django-version.py ${{ matrix.django }})
pip install coverage six pytest pytest-django pytest-cov $(./get-django-version.py ${{ matrix.django }})
- name: Run tests
run: |
coverage run --source=modeltranslation ./runtests.py
pytest --cov-report term

View file

@ -0,0 +1,988 @@
# Generated by Django 3.2.14 on 2022-07-11 16:41
import django.contrib.auth.models
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import modeltranslation.tests.models
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='AbstractConflictModelB',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title_de', models.IntegerField()),
('title', models.CharField(max_length=255, verbose_name='title')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='AbstractModelB',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('titlea', models.CharField(max_length=255, verbose_name='title a')),
('titlea_de', models.CharField(max_length=255, null=True, verbose_name='title a')),
('titlea_en', models.CharField(max_length=255, null=True, verbose_name='title a')),
('titleb', models.CharField(max_length=255, verbose_name='title b')),
('titleb_de', models.CharField(max_length=255, null=True, verbose_name='title b')),
('titleb_en', models.CharField(max_length=255, null=True, verbose_name='title b')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='ConflictModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.IntegerField()),
],
),
migrations.CreateModel(
name='CustomManager2TestModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
],
),
migrations.CreateModel(
name='CustomManagerChildTestModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('needs_translation', models.BooleanField(default=False)),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='CustomManagerTestModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
('description', models.CharField(db_column='xyz', max_length=255, null=True)),
],
),
migrations.CreateModel(
name='DataModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('data', models.TextField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='DescriptorModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('normal', modeltranslation.tests.models.FancyField(default='')),
('trans', modeltranslation.tests.models.FancyField(default='')),
('trans_de', modeltranslation.tests.models.FancyField(default='', null=True)),
('trans_en', modeltranslation.tests.models.FancyField(default='', null=True)),
],
),
migrations.CreateModel(
name='FallbackModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
('text', models.TextField(blank=True, null=True)),
('text_de', models.TextField(blank=True, null=True)),
('text_en', models.TextField(blank=True, null=True)),
('url', models.URLField(blank=True, null=True)),
('url_de', models.URLField(blank=True, null=True)),
('url_en', models.URLField(blank=True, null=True)),
('email', models.EmailField(blank=True, max_length=254, null=True)),
('email_de', models.EmailField(blank=True, max_length=254, null=True)),
('email_en', models.EmailField(blank=True, max_length=254, null=True)),
('description', models.CharField(max_length=255, null=True)),
('description_de', models.CharField(max_length=255, null=True)),
('description_en', models.CharField(max_length=255, null=True)),
],
),
migrations.CreateModel(
name='FallbackModel2',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
('text', models.TextField(blank=True, null=True)),
('text_de', models.TextField(blank=True, null=True)),
('text_en', models.TextField(blank=True, null=True)),
('url', models.URLField(blank=True, null=True)),
('url_de', models.URLField(blank=True, null=True)),
('url_en', models.URLField(blank=True, null=True)),
('email', models.EmailField(blank=True, max_length=254, null=True)),
('email_de', models.EmailField(blank=True, max_length=254, null=True)),
('email_en', models.EmailField(blank=True, max_length=254, null=True)),
],
),
migrations.CreateModel(
name='FileFieldsModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
(
'file',
models.FileField(blank=True, null=True, upload_to='modeltranslation_tests'),
),
(
'file_de',
models.FileField(blank=True, null=True, upload_to='modeltranslation_tests'),
),
(
'file_en',
models.FileField(blank=True, null=True, upload_to='modeltranslation_tests'),
),
('file2', models.FileField(upload_to='modeltranslation_tests')),
('file2_de', models.FileField(null=True, upload_to='modeltranslation_tests')),
('file2_en', models.FileField(null=True, upload_to='modeltranslation_tests')),
(
'image',
models.ImageField(blank=True, null=True, upload_to='modeltranslation_tests'),
),
(
'image_de',
models.ImageField(blank=True, null=True, upload_to='modeltranslation_tests'),
),
(
'image_en',
models.ImageField(blank=True, null=True, upload_to='modeltranslation_tests'),
),
],
),
migrations.CreateModel(
name='FilteredTestModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
],
),
migrations.CreateModel(
name='GroupFieldsetsModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255)),
('title_de', models.CharField(max_length=255, null=True)),
('title_en', models.CharField(max_length=255, null=True)),
('text', models.TextField(blank=True, null=True)),
('text_de', models.TextField(blank=True, null=True)),
('text_en', models.TextField(blank=True, null=True)),
('email', models.EmailField(blank=True, max_length=254, null=True)),
],
),
migrations.CreateModel(
name='InheritedPermission',
fields=[
(
'permission_ptr',
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to='auth.permission',
),
),
('translated_var', models.CharField(max_length=255)),
('translated_var_de', models.CharField(max_length=255, null=True)),
('translated_var_en', models.CharField(max_length=255, null=True)),
],
bases=('auth.permission',),
managers=[
('objects', django.contrib.auth.models.PermissionManager()),
],
),
migrations.CreateModel(
name='ManagerTestModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
('visits', models.IntegerField(default=0, verbose_name='visits')),
('visits_de', models.IntegerField(default=0, null=True, verbose_name='visits')),
('visits_en', models.IntegerField(default=0, null=True, verbose_name='visits')),
('description', models.CharField(max_length=255, null=True)),
('description_de', models.CharField(max_length=255, null=True)),
('description_en', models.CharField(max_length=255, null=True)),
],
options={
'ordering': ('-visits',),
},
),
migrations.CreateModel(
name='ModelX',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('name', models.CharField(max_length=255)),
('name_de', models.CharField(max_length=255, null=True)),
('name_en', models.CharField(max_length=255, null=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='ModelXY',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
(
'model_x',
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to='tests.modelx'
),
),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='MultitableConflictModelA',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title_de', models.IntegerField()),
],
),
migrations.CreateModel(
name='MultitableModelA',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('titlea', models.CharField(max_length=255, verbose_name='title a')),
('titlea_de', models.CharField(max_length=255, null=True, verbose_name='title a')),
('titlea_en', models.CharField(max_length=255, null=True, verbose_name='title a')),
],
),
migrations.CreateModel(
name='NameModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('firstname', models.CharField(max_length=50)),
('firstname_de', models.CharField(max_length=50, null=True)),
('firstname_en', models.CharField(max_length=50, null=True)),
('lastname', models.CharField(max_length=50)),
('lastname_de', models.CharField(max_length=50, null=True)),
('lastname_en', models.CharField(max_length=50, null=True)),
('age', models.CharField(max_length=50)),
('slug', models.SlugField(max_length=100)),
('slug2', models.SlugField(max_length=100)),
('slug2_de', models.SlugField(max_length=100, null=True)),
('slug2_en', models.SlugField(max_length=100, null=True)),
],
),
migrations.CreateModel(
name='NonTranslated',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
],
),
migrations.CreateModel(
name='OtherFieldsModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
(
'int',
models.PositiveIntegerField(
default=42, validators=[django.core.validators.MinValueValidator(0)]
),
),
(
'int_de',
models.PositiveIntegerField(
default=42,
null=True,
validators=[django.core.validators.MinValueValidator(0)],
),
),
(
'int_en',
models.PositiveIntegerField(
default=42,
null=True,
validators=[django.core.validators.MinValueValidator(0)],
),
),
('boolean', models.BooleanField(default=False)),
('boolean_de', models.BooleanField(default=False)),
('boolean_en', models.BooleanField(default=False)),
('float', models.FloatField(blank=True, null=True)),
('float_de', models.FloatField(blank=True, null=True)),
('float_en', models.FloatField(blank=True, null=True)),
(
'decimal',
models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True),
),
(
'decimal_de',
models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True),
),
(
'decimal_en',
models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True),
),
('date', models.DateField(blank=True, null=True)),
('date_de', models.DateField(blank=True, null=True)),
('date_en', models.DateField(blank=True, null=True)),
('datetime', models.DateTimeField(blank=True, null=True)),
('datetime_de', models.DateTimeField(blank=True, null=True)),
('datetime_en', models.DateTimeField(blank=True, null=True)),
('time', models.TimeField(blank=True, null=True)),
('time_de', models.TimeField(blank=True, null=True)),
('time_en', models.TimeField(blank=True, null=True)),
('genericip', models.GenericIPAddressField(blank=True, null=True)),
('genericip_de', models.GenericIPAddressField(blank=True, null=True)),
('genericip_en', models.GenericIPAddressField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='Page',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('slug', models.CharField(max_length=255)),
('slug_de', models.CharField(max_length=255, null=True)),
('slug_en', models.CharField(max_length=255, null=True)),
('keywords', models.CharField(max_length=255)),
('keywords_de', models.CharField(max_length=255, null=True)),
('keywords_en', models.CharField(max_length=255, null=True)),
('title', models.CharField(max_length=255)),
('title_de', models.CharField(max_length=255, null=True)),
('title_en', models.CharField(max_length=255, null=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='PlainChildTestModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('needs_translation', models.BooleanField(default=False)),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='RequiredModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('non_req', models.CharField(blank=True, max_length=10)),
('non_req_de', models.CharField(blank=True, max_length=10, null=True)),
('non_req_en', models.CharField(blank=True, max_length=10, null=True)),
('req', models.CharField(max_length=10)),
('req_de', models.CharField(max_length=10, null=True)),
('req_en', models.CharField(max_length=10, null=True)),
('req_reg', models.CharField(max_length=10)),
('req_reg_de', models.CharField(max_length=10, null=True)),
('req_reg_en', models.CharField(max_length=10, null=True)),
('req_en_reg', models.CharField(max_length=10)),
('req_en_reg_de', models.CharField(max_length=10, null=True)),
('req_en_reg_en', models.CharField(max_length=10, null=True)),
],
),
migrations.CreateModel(
name='TestModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
('text', models.TextField(blank=True, null=True)),
('text_de', models.TextField(blank=True, null=True)),
('text_en', models.TextField(blank=True, null=True)),
('url', models.URLField(blank=True, null=True)),
('url_de', models.URLField(blank=True, null=True)),
('url_en', models.URLField(blank=True, null=True)),
('email', models.EmailField(blank=True, max_length=254, null=True)),
('email_de', models.EmailField(blank=True, max_length=254, null=True)),
('email_en', models.EmailField(blank=True, max_length=254, null=True)),
],
),
migrations.CreateModel(
name='ThirdPartyModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('name', models.CharField(max_length=20)),
],
),
migrations.CreateModel(
name='ThirdPartyRegisteredModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('name', models.CharField(max_length=20)),
('name_de', models.CharField(max_length=20, null=True)),
('name_en', models.CharField(max_length=20, null=True)),
],
),
migrations.CreateModel(
name='UniqueNullableModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, null=True, unique=True)),
('title_de', models.CharField(max_length=255, null=True, unique=True)),
('title_en', models.CharField(max_length=255, null=True, unique=True)),
],
),
migrations.CreateModel(
name='MultitableConflictModelB',
fields=[
(
'multitableconflictmodela_ptr',
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to='tests.multitableconflictmodela',
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
],
bases=('tests.multitableconflictmodela',),
),
migrations.CreateModel(
name='MultitableModelB',
fields=[
(
'multitablemodela_ptr',
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to='tests.multitablemodela',
),
),
('titleb', models.CharField(max_length=255, verbose_name='title b')),
('titleb_de', models.CharField(max_length=255, null=True, verbose_name='title b')),
('titleb_en', models.CharField(max_length=255, null=True, verbose_name='title b')),
],
bases=('tests.multitablemodela',),
),
migrations.CreateModel(
name='RichTextPage',
fields=[
(
'page_ptr',
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to='tests.page',
),
),
('content', models.CharField(max_length=255)),
('content_de', models.CharField(max_length=255, null=True)),
('content_en', models.CharField(max_length=255, null=True)),
],
options={
'abstract': False,
},
bases=('tests.page', models.Model),
),
migrations.CreateModel(
name='OneToOneFieldModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
(
'non',
models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_o2o',
to='tests.nontranslated',
),
),
(
'non_de',
models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_o2o',
to='tests.nontranslated',
),
),
(
'non_en',
models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_o2o',
to='tests.nontranslated',
),
),
(
'optional',
models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to='tests.testmodel',
),
),
(
'optional_de',
models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to='tests.testmodel',
),
),
(
'optional_en',
models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to='tests.testmodel',
),
),
(
'test',
models.OneToOneField(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_o2o',
to='tests.testmodel',
),
),
(
'test_de',
models.OneToOneField(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_o2o',
to='tests.testmodel',
),
),
(
'test_en',
models.OneToOneField(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_o2o',
to='tests.testmodel',
),
),
],
),
migrations.CreateModel(
name='ModelY',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255)),
('title_de', models.CharField(max_length=255, null=True)),
('title_en', models.CharField(max_length=255, null=True)),
('xs', models.ManyToManyField(through='tests.ModelXY', to='tests.ModelX')),
],
options={
'abstract': False,
},
),
migrations.AddField(
model_name='modelxy',
name='model_y',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tests.modely'),
),
migrations.CreateModel(
name='ForeignKeyModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
(
'hidden',
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='+',
to='tests.testmodel',
),
),
(
'hidden_de',
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='+',
to='tests.testmodel',
),
),
(
'hidden_en',
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='+',
to='tests.testmodel',
),
),
(
'non',
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_fks',
to='tests.nontranslated',
),
),
(
'non_de',
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_fks',
to='tests.nontranslated',
),
),
(
'non_en',
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_fks',
to='tests.nontranslated',
),
),
(
'optional',
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to='tests.testmodel',
),
),
(
'optional_de',
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to='tests.testmodel',
),
),
(
'optional_en',
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to='tests.testmodel',
),
),
(
'test',
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_fks',
to='tests.testmodel',
),
),
(
'test_de',
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_fks',
to='tests.testmodel',
),
),
(
'test_en',
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_fks',
to='tests.testmodel',
),
),
(
'untrans',
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_fks_un',
to='tests.testmodel',
),
),
],
),
migrations.CreateModel(
name='ForeignKeyFilteredModel',
fields=[
(
'id',
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
),
),
('title', models.CharField(max_length=255, verbose_name='title')),
('title_de', models.CharField(max_length=255, null=True, verbose_name='title')),
('title_en', models.CharField(max_length=255, null=True, verbose_name='title')),
(
'test',
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='test_fks',
to='tests.filteredtestmodel',
),
),
],
),
migrations.CreateModel(
name='ProxyTestModel',
fields=[],
options={
'proxy': True,
'indexes': [],
'constraints': [],
},
bases=('tests.testmodel',),
),
migrations.CreateModel(
name='MultitableModelC',
fields=[
(
'multitablemodelb_ptr',
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to='tests.multitablemodelb',
),
),
('titlec', models.CharField(max_length=255, verbose_name='title c')),
('titlec_de', models.CharField(max_length=255, null=True, verbose_name='title c')),
('titlec_en', models.CharField(max_length=255, null=True, verbose_name='title c')),
],
bases=('tests.multitablemodelb',),
),
migrations.CreateModel(
name='MultitableModelD',
fields=[
(
'multitablemodelb_ptr',
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to='tests.multitablemodelb',
),
),
('titled', models.CharField(max_length=255, verbose_name='title d')),
],
bases=('tests.multitablemodelb',),
),
]

View file

@ -1,10 +1,8 @@
# -*- coding: utf-8 -*-
import six
from django.conf import settings
from django.contrib.auth.models import Permission
from django.core import validators
from django.db import models
from django.utils.translation import gettext_lazy
from modeltranslation.manager import MultilingualManager
@ -128,9 +126,6 @@ class OtherFieldsModel(models.Model):
# That's rich! PositiveIntegerField is only validated in forms, not in models.
int = models.PositiveIntegerField(default=42, validators=[validators.MinValueValidator(0)])
boolean = models.BooleanField(default=False)
nullboolean = models.NullBooleanField()
csi = models.CommaSeparatedIntegerField(max_length=255)
ip = models.IPAddressField(blank=True, null=True)
float = models.FloatField(blank=True, null=True)
decimal = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
date = models.DateField(blank=True, null=True)
@ -495,8 +490,5 @@ class ModelY(AbstractModelY):
# Non-abstract base models whos Manager is not allowed to be overwritten
if "django.contrib.auth" in settings.INSTALLED_APPS:
from django.contrib.auth.models import Permission
class InheritedPermission(Permission):
translated_var = models.CharField(max_length=255)
class InheritedPermission(Permission):
translated_var = models.CharField(max_length=255)

View file

@ -1,23 +1,62 @@
# -*- coding: utf-8 -*-
"""
Settings overrided for test time
"""
from django.conf import settings
import os
import warnings
warnings.simplefilter('always', DeprecationWarning)
INSTALLED_APPS = tuple(settings.INSTALLED_APPS) + ('modeltranslation.tests',)
def _get_database_config():
db = os.getenv('DB', 'sqlite')
host = os.getenv('DB_HOST', 'localhost')
conf = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
'TEST': {
'SERIALIZE': False,
},
}
if db == 'mysql':
conf.update(
{
'ENGINE': 'django.db.backends.mysql',
'NAME': os.getenv('MYSQL_DATABASE', 'modeltranslation'),
'USER': os.getenv('MYSQL_USER', 'root'),
'PASSWORD': os.getenv('MYSQL_PASSWORD', 'password'),
'HOST': host,
}
)
elif db == 'postgres':
conf.update(
{
'ENGINE': 'django.db.backends.postgresql',
'USER': os.getenv('POSTGRES_USER', 'postgres'),
'PASSWORD': os.getenv('POSTGRES_DB', 'postgres'),
'NAME': os.getenv('POSTGRES_DB', 'modeltranslation'),
'HOST': host,
}
)
return conf
DATABASES = {"default": _get_database_config()}
INSTALLED_APPS = (
'django.contrib.contenttypes',
'django.contrib.auth',
'modeltranslation',
'modeltranslation.tests',
)
LANGUAGES = (('de', 'Deutsch'), ('en', 'English'))
LANGUAGE_CODE = 'de'
MODELTRANSLATION_DEFAULT_LANGUAGE = 'de'
USE_I18N = True
USE_TZ = False
MIDDLEWARE_CLASSES = ()
MODELTRANSLATION_DEFAULT_LANGUAGE = 'de'
MODELTRANSLATION_AUTO_POPULATE = False
MODELTRANSLATION_FALLBACK_LANGUAGES = ()
ROOT_URLCONF = 'modeltranslation.tests.urls'
MIGRATION_MODULES = {'auth': 'modeltranslation.tests.auth_migrations'}
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

View file

@ -1,6 +0,0 @@
"""
Get test settings in dict format (for use with settings_override).
"""
from . import settings as _settings
TEST_SETTINGS = dict((k, getattr(_settings, k)) for k in dir(_settings) if k == k.upper())

View file

@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# pyright: reportGeneralTypeIssues=warning, reportOptionalMemberAccess=warning, reportOptionalOperand=warning
from decimal import Decimal
from unittest import skipUnless
import datetime
import fnmatch
import imp
import io
import importlib
import sys
import os
import shutil
@ -30,7 +29,6 @@ from modeltranslation import admin, settings as mt_settings, translator
from modeltranslation.forms import TranslationModelForm
from modeltranslation.manager import MultilingualManager
from modeltranslation.models import autodiscover
from modeltranslation.tests.test_settings import TEST_SETTINGS
from modeltranslation.utils import (
build_css_class,
build_localized_fieldname,
@ -38,16 +36,14 @@ from modeltranslation.utils import (
fallbacks,
)
MIGRATIONS = "django.contrib.auth" in TEST_SETTINGS['INSTALLED_APPS']
models = translation = None
from modeltranslation.tests import models, translation
# None of the following tests really depend on the content of the request,
# so we'll just pass in None.
request = None
# How many models are registered for tests.
TEST_MODELS = 35 + (1 if MIGRATIONS else 0)
TEST_MODELS = 36
class reload_override_settings(override_settings):
@ -55,11 +51,11 @@ class reload_override_settings(override_settings):
def __enter__(self):
super(reload_override_settings, self).__enter__()
imp.reload(mt_settings)
importlib.reload(mt_settings)
def __exit__(self, exc_type, exc_value, traceback):
super(reload_override_settings, self).__exit__(exc_type, exc_value, traceback)
imp.reload(mt_settings)
importlib.reload(mt_settings)
# In this test suite fallback language is turned off. This context manager temporarily turns it on.
@ -84,124 +80,32 @@ def get_field_names(model):
return names
@override_settings(**TEST_SETTINGS)
class ModeltranslationTransactionTestBase(TransactionTestCase):
cache = django_apps
synced = False
@classmethod
def _get_migrations_path(cls):
return os.path.join(os.path.dirname(os.path.abspath(__file__)), "auth_migrations")
@classmethod
def _copy_migrations(cls):
# Locate the original contrib.auth migrations files
import django.contrib.auth.migrations as auth_migrations
source_dir_path = os.path.dirname(auth_migrations.__file__)
# Copy them to the local auth_migrations directory
target_dir_path = cls._get_migrations_path()
for f in os.listdir(source_dir_path):
source_path = os.path.join(source_dir_path, f)
target_path = os.path.join(target_dir_path, f)
# Only migration files get copied
if os.path.isfile(source_path) and not fnmatch.fnmatch(f, "__init__.py"):
shutil.copyfile(source_path, target_path)
@classmethod
def _clean_migrations(cls):
target_dir_path = cls._get_migrations_path()
for f in os.listdir(target_dir_path):
target_path = os.path.join(target_dir_path, f)
if os.path.isfile(target_path) and not fnmatch.fnmatch(f, "__init__.py"):
os.remove(target_path)
@classmethod
def setUpClass(cls):
"""
Prepare database:
* Call syncdb to create tables for tests.models (since during
default testrunner's db creation modeltranslation.tests was not in INSTALLED_APPS
"""
super(ModeltranslationTransactionTestBase, cls).setUpClass()
if not ModeltranslationTransactionTestBase.synced:
# In order to perform only one syncdb
ModeltranslationTransactionTestBase.synced = True
# 0. Render initial migration of auth
if MIGRATIONS:
# Make copies of auth migrations in the (local) auth_migrations
# module to setup test database
cls._copy_migrations()
call_command('makemigrations', 'auth', verbosity=2, interactive=False)
"""Save registry (and restore it after tests)."""
super().setUpClass()
from copy import copy
from modeltranslation.translator import translator
# 1. Reload translation in case USE_I18N was False
from django.utils import translation as dj_trans
cls.registry_cpy = copy(translator._registry)
imp.reload(dj_trans)
@classmethod
def tearDownClass(cls):
from modeltranslation.translator import translator
# 2. Reload MT because LANGUAGES likely changed.
imp.reload(mt_settings)
imp.reload(translator)
imp.reload(admin)
# 3. Reset test models (because autodiscover have already run, those models
# have translation fields, but for languages previously defined. We want
# to be sure that 'de' and 'en' are available)
del cls.cache.all_models['tests']
if MIGRATIONS:
del cls.cache.all_models['auth']
import sys
sys.modules.pop('modeltranslation.tests.models', None)
sys.modules.pop('modeltranslation.tests.translation', None)
if MIGRATIONS:
sys.modules.pop('django.contrib.auth.models', None)
cls.cache.get_app_config('tests').import_models()
if MIGRATIONS:
cls.cache.get_app_config('auth').import_models()
# 4. Autodiscover
from modeltranslation.models import handle_translation_registrations
handle_translation_registrations()
# 5. makemigrations (``migrate=False`` in case of south)
if MIGRATIONS:
call_command('makemigrations', 'auth', verbosity=2, interactive=False)
# At this point there should not be any migrations to generate
out = io.StringIO()
call_command(
'makemigrations',
'auth',
verbosity=3,
dry_run=True,
interactive=False,
stdout=out,
)
assert "No changes detected in app 'auth'\n" == out.getvalue(), (
"Unexpected auth migration:\n %s" % out.getvalue()
)
# 6. Syncdb (``migrate=False`` in case of south)
call_command('migrate', verbosity=0, interactive=False, run_syncdb=True)
# 7. clean migrations
if MIGRATIONS:
cls._clean_migrations()
# A rather dirty trick to import models into module namespace, but not before
# tests app has been added into INSTALLED_APPS and loaded
# (that's why this is not imported in normal import section)
global models, translation
from modeltranslation.tests import models, translation # NOQA
translator._registry = cls.registry_cpy
super().tearDownClass()
def setUp(self):
super().setUp()
self._old_language = get_language()
trans_real.activate('de')
def tearDown(self):
super().tearDown()
trans_real.activate(self._old_language)
@ -224,33 +128,15 @@ class TestAutodiscover(ModeltranslationTestBase):
def _post_teardown(self):
self.__override.disable()
imp.reload(mt_settings) # restore mt_settings.FALLBACK_LANGUAGES
importlib.reload(mt_settings) # restore mt_settings.FALLBACK_LANGUAGES
super(TestAutodiscover, self)._post_teardown()
@classmethod
def setUpClass(cls):
"""Save registry (and restore it after tests)."""
super(TestAutodiscover, cls).setUpClass()
from copy import copy
from modeltranslation.translator import translator
cls.registry_cpy = copy(translator._registry)
@classmethod
def tearDownClass(cls):
from modeltranslation.translator import translator
translator._registry = cls.registry_cpy
super(TestAutodiscover, cls).tearDownClass()
def tearDown(self):
import sys
# Rollback model classes
del self.cache.all_models['test_app']
from .test_app import models
imp.reload(models)
importlib.reload(models)
# Delete translation modules from import cache
sys.modules.pop('modeltranslation.tests.test_app.translation', None)
sys.modules.pop('modeltranslation.tests.project_translation', None)
@ -622,8 +508,8 @@ class FallbackTests(ModeltranslationTestBase):
# Improper language raises error
config = {'default': (), 'fr': ('en',)}
with override_settings(MODELTRANSLATION_FALLBACK_LANGUAGES=config):
self.assertRaises(ImproperlyConfigured, lambda: imp.reload(mt_settings))
imp.reload(mt_settings)
self.assertRaises(ImproperlyConfigured, lambda: importlib.reload(mt_settings))
importlib.reload(mt_settings)
def test_resolution_order(self):
from modeltranslation.utils import resolution_order
@ -1299,15 +1185,6 @@ class OtherFieldsTest(ModeltranslationTestBase):
self.assertTrue('boolean' in field_names)
self.assertTrue('boolean_de' in field_names)
self.assertTrue('boolean_en' in field_names)
self.assertTrue('nullboolean' in field_names)
self.assertTrue('nullboolean_de' in field_names)
self.assertTrue('nullboolean_en' in field_names)
self.assertTrue('csi' in field_names)
self.assertTrue('csi_de' in field_names)
self.assertTrue('csi_en' in field_names)
self.assertTrue('ip' in field_names)
self.assertTrue('ip_de' in field_names)
self.assertTrue('ip_en' in field_names)
self.assertTrue('genericip' in field_names)
self.assertTrue('genericip_de' in field_names)
self.assertTrue('genericip_en' in field_names)
@ -1363,82 +1240,6 @@ class OtherFieldsTest(ModeltranslationTestBase):
self.assertEqual(False, inst.boolean_de)
self.assertEqual(True, inst.boolean_en)
def test_translated_models_nullboolean_instance(self):
inst = models.OtherFieldsModel()
inst.nullboolean = True
self.assertEqual('de', get_language())
self.assertEqual(True, inst.nullboolean)
self.assertEqual(True, inst.nullboolean_de)
self.assertEqual(None, inst.nullboolean_en)
inst.nullboolean = False
inst.save()
self.assertEqual(False, inst.nullboolean)
self.assertEqual(False, inst.nullboolean_de)
self.assertEqual(None, inst.nullboolean_en)
trans_real.activate('en')
inst.nullboolean = True
self.assertEqual(True, inst.nullboolean)
self.assertEqual(False, inst.nullboolean_de)
self.assertEqual(True, inst.nullboolean_en)
inst.nullboolean = None
self.assertEqual(None, inst.nullboolean)
self.assertEqual(False, inst.nullboolean_de)
self.assertEqual(None, inst.nullboolean_en)
def test_translated_models_commaseparatedinteger_instance(self):
inst = models.OtherFieldsModel()
inst.csi = '4,8,15,16,23,42'
self.assertEqual('de', get_language())
self.assertEqual('4,8,15,16,23,42', inst.csi)
self.assertEqual('4,8,15,16,23,42', inst.csi_de)
self.assertEqual(None, inst.csi_en)
inst.csi = '23,42'
inst.save()
self.assertEqual('23,42', inst.csi)
self.assertEqual('23,42', inst.csi_de)
self.assertEqual(None, inst.csi_en)
trans_real.activate('en')
inst.csi = '4,8,15,16,23,42'
self.assertEqual('4,8,15,16,23,42', inst.csi)
self.assertEqual('23,42', inst.csi_de)
self.assertEqual('4,8,15,16,23,42', inst.csi_en)
# Now that we have covered csi, lost, illuminati and hitchhiker
# compliance in a single test, do something useful...
# Check if validation is preserved
inst.csi = '1;2'
self.assertRaises(ValidationError, inst.full_clean)
def test_translated_models_ipaddress_instance(self):
inst = models.OtherFieldsModel()
inst.ip = '192.0.1.42'
self.assertEqual('de', get_language())
self.assertEqual('192.0.1.42', inst.ip)
self.assertEqual('192.0.1.42', inst.ip_de)
self.assertEqual(None, inst.ip_en)
inst.ip = '192.0.23.1'
inst.save()
self.assertEqual('192.0.23.1', inst.ip)
self.assertEqual('192.0.23.1', inst.ip_de)
self.assertEqual(None, inst.ip_en)
trans_real.activate('en')
inst.ip = '192.0.1.42'
self.assertEqual('192.0.1.42', inst.ip)
self.assertEqual('192.0.23.1', inst.ip_de)
self.assertEqual('192.0.1.42', inst.ip_en)
# Check if validation is preserved
inst.ip = '1;2'
self.assertRaises(ValidationError, inst.full_clean)
def test_translated_models_genericipaddress_instance(self):
inst = models.OtherFieldsModel()
inst.genericip = '2a02:42fe::4'
@ -2105,7 +1906,7 @@ class UpdateCommandTest(ModeltranslationTestBase):
self.assertEqual('already', obj2['title_de'])
self.assertEqual('initial', obj2['title'])
call_command('update_translation_fields', verbosity=0)
call_command('update_translation_fields', 'tests', verbosity=0)
obj1 = models.TestModel.objects.get(pk=pk1)
obj2 = models.TestModel.objects.get(pk=pk2)
@ -2119,7 +1920,7 @@ class UpdateCommandTest(ModeltranslationTestBase):
# Due to ``rewrite(False)`` here, original field will be affected.
models.TestModel.objects.all().rewrite(False).update(title='initial')
call_command('update_translation_fields', language='en', verbosity=0)
call_command('update_translation_fields', 'tests', language='en', verbosity=0)
obj1 = models.TestModel.objects.get(pk=pk1)
obj2 = models.TestModel.objects.get(pk=pk2)
@ -2978,9 +2779,9 @@ class TestManager(ModeltranslationTestBase):
qs = models.CustomManagerTestModel.objects.custom_qs()
self.assertIsInstance(qs, MultilingualQuerySet)
@skipUnless(MIGRATIONS, 'migrations/auth not available')
def test_3rd_party_custom_manager(self):
from django.contrib.auth.models import Group, GroupManager
from modeltranslation.manager import MultilingualManager
testmodel_fields = get_field_names(Group)
@ -2995,6 +2796,7 @@ class TestManager(ModeltranslationTestBase):
def test_multilingual_queryset_pickling(self):
import pickle
from modeltranslation.manager import MultilingualQuerySet
# typical
@ -3272,21 +3074,6 @@ class TestManager(ModeltranslationTestBase):
o.title = "bla"
self.assertEqual(o.title, "bla")
@skipUnless(django.VERSION[0] == 1, 'Applicable only to django 1.x')
def test_select_related_django_1(self):
test = models.TestModel.objects.create(title_de='title_de', title_en='title_en')
with auto_populate('all'):
models.ForeignKeyModel.objects.create(untrans=test)
fk_qs = models.ForeignKeyModel.objects.all()
self.assertNotIn('_untrans_cache', fk_qs[0].__dict__)
self.assertIn('_untrans_cache', fk_qs.select_related('untrans')[0].__dict__)
self.assertNotIn(
'_untrans_cache', fk_qs.select_related('untrans').select_related(None)[0].__dict__
)
# untrans is nullable so not included when select_related=True
self.assertNotIn('_untrans_cache', fk_qs.select_related()[0].__dict__)
@skipUnless(django.VERSION[0] >= 2, 'Applicable only to django > 2.x')
def test_select_related_django_2(self):
test = models.TestModel.objects.create(title_de='title_de', title_en='title_en')
@ -3303,7 +3090,7 @@ class TestManager(ModeltranslationTestBase):
self.assertNotIn('untrans', fk_qs.select_related()[0]._state.fields_cache)
def test_translation_fields_appending(self):
from modeltranslation.manager import append_lookup_keys, append_lookup_key
from modeltranslation.manager import append_lookup_key, append_lookup_keys
self.assertEqual(set(['untrans']), append_lookup_key(models.ForeignKeyModel, 'untrans'))
self.assertEqual(
@ -3540,11 +3327,12 @@ class M2MTest(ModeltranslationTestBase):
class InheritedPermissionTestCase(ModeltranslationTestBase):
@skipUnless(MIGRATIONS, 'migrations/auth not available')
def test_managers_failure(self):
"""This fails with 0.13b."""
from modeltranslation.manager import MultilingualManager
from django.contrib.auth.models import Permission, User
from modeltranslation.manager import MultilingualManager
from .models import InheritedPermission
self.assertFalse(

View file

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
from django.conf import settings
from django.contrib.auth.models import Group
from django.utils.translation import gettext_lazy
from modeltranslation.translator import translator, register, TranslationOptions
from modeltranslation.tests import models
from modeltranslation.tests.models import InheritedPermission
from modeltranslation.translator import TranslationOptions, register, translator
@register(models.TestModel)
@ -111,11 +111,8 @@ class OtherFieldsModelTranslationOptions(TranslationOptions):
fields = (
'int',
'boolean',
'nullboolean',
'csi',
'float',
'decimal',
'ip',
'genericip',
'date',
'datetime',
@ -286,15 +283,13 @@ class ModelYOptions(TranslationOptions):
# ######### 3-rd party with custom manager
if "django.contrib.auth" in settings.INSTALLED_APPS:
from django.contrib.auth.models import Group
from .models import InheritedPermission
@register(Group)
class GroupTranslationOptions(TranslationOptions):
fields = ('name',)
@register(Group)
class GroupTranslationOptions(TranslationOptions):
fields = ('name',)
@register(InheritedPermission)
class InheritedPermissionOptions(TranslationOptions):
fields = ('translated_var',)
required_languages = [x[0] for x in settings.LANGUAGES]
@register(InheritedPermission)
class InheritedPermissionOptions(TranslationOptions):
fields = ('translated_var',)
required_languages = [x[0] for x in settings.LANGUAGES]

View file

@ -1,16 +1 @@
# -*- coding: utf-8 -*-
try:
from django.conf.urls import include, patterns, url
# Workaround for pyflakes issue #13
assert (include, patterns, url) # noqa
except ImportError: # Django 1.3 fallback
from django.conf.urls.defaults import include, patterns, url # NOQA
from django.contrib import admin
urlpatterns = patterns(
'',
url(r'^set_language/$', 'django.views.i18n.set_language', {}, name='set_language'),
url(r'^admin/', include(admin.site.urls)),
)
urlpatterns = []

270
poetry.lock generated
View file

@ -12,6 +12,28 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
[package.extras]
tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"]
[[package]]
name = "atomicwrites"
version = "1.4.1"
description = "Atomic file writes."
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "attrs"
version = "21.4.0"
description = "Classes Without Boilerplate"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[package.extras]
dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"]
docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"]
[[package]]
name = "black"
version = "21.12b0"
@ -22,7 +44,6 @@ python-versions = ">=3.6.2"
[package.dependencies]
click = ">=7.1.2"
dataclasses = {version = ">=0.6", markers = "python_version < \"3.7\""}
mypy-extensions = ">=0.4.3"
pathspec = ">=0.9.0,<1"
platformdirs = ">=2"
@ -61,12 +82,18 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "dataclasses"
version = "0.8"
description = "A backport of the dataclasses module for Python 3.6"
name = "coverage"
version = "6.4.2"
description = "Code coverage measurement for Python"
category = "dev"
optional = false
python-versions = ">=3.6, <3.7"
python-versions = ">=3.7"
[package.dependencies]
tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
[package.extras]
toml = ["tomli"]
[[package]]
name = "django"
@ -85,6 +112,14 @@ sqlparse = ">=0.2.2"
argon2 = ["argon2-cffi (>=19.1.0)"]
bcrypt = ["bcrypt"]
[[package]]
name = "django-types"
version = "0.15.0"
description = "Type stubs for Django"
category = "dev"
optional = false
python-versions = ">=3.6.2,<4.0.0"
[[package]]
name = "fancycompleter"
version = "0.9.1"
@ -128,6 +163,14 @@ docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
perf = ["ipython"]
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
[[package]]
name = "iniconfig"
version = "1.1.1"
description = "iniconfig: brain-dead simple config-ini parsing"
category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "mccabe"
version = "0.6.1"
@ -144,6 +187,17 @@ category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "packaging"
version = "21.3"
description = "Core utilities for Python packages"
category = "dev"
optional = false
python-versions = ">=3.6"
[package.dependencies]
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
[[package]]
name = "pathspec"
version = "0.9.0"
@ -181,6 +235,29 @@ python-versions = ">=3.6"
docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
[[package]]
name = "pluggy"
version = "1.0.0"
description = "plugin and hook calling mechanisms for python"
category = "dev"
optional = false
python-versions = ">=3.6"
[package.dependencies]
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
[package.extras]
dev = ["pre-commit", "tox"]
testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "py"
version = "1.11.0"
description = "library with cross-python path, ini-parsing, io, code, log facilities"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "pycodestyle"
version = "2.7.0"
@ -205,6 +282,17 @@ category = "dev"
optional = false
python-versions = ">=3.6"
[[package]]
name = "pyparsing"
version = "3.0.9"
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
category = "dev"
optional = false
python-versions = ">=3.6.8"
[package.extras]
diagrams = ["railroad-diagrams", "jinja2"]
[[package]]
name = "pyreadline"
version = "2.1"
@ -221,6 +309,71 @@ category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "pytest"
version = "7.1.2"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.7"
[package.dependencies]
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
attrs = ">=19.2.0"
colorama = {version = "*", markers = "sys_platform == \"win32\""}
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
iniconfig = "*"
packaging = "*"
pluggy = ">=0.12,<2.0"
py = ">=1.8.2"
tomli = ">=1.0.0"
[package.extras]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
[[package]]
name = "pytest-cov"
version = "3.0.0"
description = "Pytest plugin for measuring coverage."
category = "dev"
optional = false
python-versions = ">=3.6"
[package.dependencies]
coverage = {version = ">=5.2.1", extras = ["toml"]}
pytest = ">=4.6"
[package.extras]
testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"]
[[package]]
name = "pytest-django"
version = "4.5.2"
description = "A Django plugin for pytest."
category = "dev"
optional = false
python-versions = ">=3.5"
[package.dependencies]
pytest = ">=5.4.0"
[package.extras]
docs = ["sphinx", "sphinx-rtd-theme"]
testing = ["django", "django-configurations (>=2.0)"]
[[package]]
name = "pytest-sugar"
version = "0.9.5"
description = "pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly)."
category = "dev"
optional = false
python-versions = "*"
[package.dependencies]
packaging = ">=14.1"
pytest = ">=2.9"
termcolor = ">=1.1.0"
[[package]]
name = "pytz"
version = "2022.1"
@ -245,6 +398,14 @@ category = "main"
optional = false
python-versions = ">=3.5"
[[package]]
name = "termcolor"
version = "1.1.0"
description = "ANSII Color formatting for output in terminal."
category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "tomli"
version = "1.2.3"
@ -291,14 +452,21 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes
[metadata]
lock-version = "1.1"
python-versions = ">=3.6.2"
content-hash = "2c90acbb650482a80f57421396f034a082b4f2d3dddc4f22bc8bb3d41a97c16e"
python-versions = ">=3.7,<4"
content-hash = "946cfcafe1b532f0f584925bfbcc9f47b5c1f58d42068518a1c57fffe67bd14c"
[metadata.files]
asgiref = [
{file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"},
{file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"},
]
atomicwrites = [
{file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"},
]
attrs = [
{file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
{file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
]
black = [
{file = "black-21.12b0-py3-none-any.whl", hash = "sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"},
{file = "black-21.12b0.tar.gz", hash = "sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3"},
@ -311,14 +479,57 @@ colorama = [
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
]
dataclasses = [
{file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"},
{file = "dataclasses-0.8.tar.gz", hash = "sha256:8479067f342acf957dc82ec415d355ab5edb7e7646b90dc6e2fd1d96ad084c97"},
coverage = [
{file = "coverage-6.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a9032f9b7d38bdf882ac9f66ebde3afb8145f0d4c24b2e600bc4c6304aafb87e"},
{file = "coverage-6.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e0524adb49c716ca763dbc1d27bedce36b14f33e6b8af6dba56886476b42957c"},
{file = "coverage-6.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4548be38a1c810d79e097a38107b6bf2ff42151900e47d49635be69943763d8"},
{file = "coverage-6.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f23876b018dfa5d3e98e96f5644b109090f16a4acb22064e0f06933663005d39"},
{file = "coverage-6.4.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fe75dcfcb889b6800f072f2af5a331342d63d0c1b3d2bf0f7b4f6c353e8c9c0"},
{file = "coverage-6.4.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2f8553878a24b00d5ab04b7a92a2af50409247ca5c4b7a2bf4eabe94ed20d3ee"},
{file = "coverage-6.4.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d774d9e97007b018a651eadc1b3970ed20237395527e22cbeb743d8e73e0563d"},
{file = "coverage-6.4.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d56f105592188ce7a797b2bd94b4a8cb2e36d5d9b0d8a1d2060ff2a71e6b9bbc"},
{file = "coverage-6.4.2-cp310-cp310-win32.whl", hash = "sha256:d230d333b0be8042ac34808ad722eabba30036232e7a6fb3e317c49f61c93386"},
{file = "coverage-6.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:5ef42e1db047ca42827a85e34abe973971c635f83aed49611b7f3ab49d0130f0"},
{file = "coverage-6.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:25b7ec944f114f70803d6529394b64f8749e93cbfac0fe6c5ea1b7e6c14e8a46"},
{file = "coverage-6.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bb00521ab4f99fdce2d5c05a91bddc0280f0afaee0e0a00425e28e209d4af07"},
{file = "coverage-6.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2dff52b3e7f76ada36f82124703f4953186d9029d00d6287f17c68a75e2e6039"},
{file = "coverage-6.4.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:147605e1702d996279bb3cc3b164f408698850011210d133a2cb96a73a2f7996"},
{file = "coverage-6.4.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:422fa44070b42fef9fb8dabd5af03861708cdd6deb69463adc2130b7bf81332f"},
{file = "coverage-6.4.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:8af6c26ba8df6338e57bedbf916d76bdae6308e57fc8f14397f03b5da8622b4e"},
{file = "coverage-6.4.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5336e0352c0b12c7e72727d50ff02557005f79a0b8dcad9219c7c4940a930083"},
{file = "coverage-6.4.2-cp37-cp37m-win32.whl", hash = "sha256:0f211df2cba951ffcae210ee00e54921ab42e2b64e0bf2c0befc977377fb09b7"},
{file = "coverage-6.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a13772c19619118903d65a91f1d5fea84be494d12fd406d06c849b00d31bf120"},
{file = "coverage-6.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f7bd0ffbcd03dc39490a1f40b2669cc414fae0c4e16b77bb26806a4d0b7d1452"},
{file = "coverage-6.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0895ea6e6f7f9939166cc835df8fa4599e2d9b759b02d1521b574e13b859ac32"},
{file = "coverage-6.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4e7ced84a11c10160c0697a6cc0b214a5d7ab21dfec1cd46e89fbf77cc66fae"},
{file = "coverage-6.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80db4a47a199c4563d4a25919ff29c97c87569130375beca3483b41ad5f698e8"},
{file = "coverage-6.4.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3def6791adf580d66f025223078dc84c64696a26f174131059ce8e91452584e1"},
{file = "coverage-6.4.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4f89d8e03c8a3757aae65570d14033e8edf192ee9298303db15955cadcff0c63"},
{file = "coverage-6.4.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6d0b48aff8e9720bdec315d67723f0babd936a7211dc5df453ddf76f89c59933"},
{file = "coverage-6.4.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2b20286c2b726f94e766e86a3fddb7b7e37af5d0c635bdfa7e4399bc523563de"},
{file = "coverage-6.4.2-cp38-cp38-win32.whl", hash = "sha256:d714af0bdba67739598849c9f18efdcc5a0412f4993914a0ec5ce0f1e864d783"},
{file = "coverage-6.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:5f65e5d3ff2d895dab76b1faca4586b970a99b5d4b24e9aafffc0ce94a6022d6"},
{file = "coverage-6.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a697977157adc052284a7160569b36a8bbec09db3c3220642e6323b47cec090f"},
{file = "coverage-6.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c77943ef768276b61c96a3eb854eba55633c7a3fddf0a79f82805f232326d33f"},
{file = "coverage-6.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54d8d0e073a7f238f0666d3c7c0d37469b2aa43311e4024c925ee14f5d5a1cbe"},
{file = "coverage-6.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f22325010d8824594820d6ce84fa830838f581a7fd86a9235f0d2ed6deb61e29"},
{file = "coverage-6.4.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24b04d305ea172ccb21bee5bacd559383cba2c6fcdef85b7701cf2de4188aa55"},
{file = "coverage-6.4.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:866ebf42b4c5dbafd64455b0a1cd5aa7b4837a894809413b930026c91e18090b"},
{file = "coverage-6.4.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e36750fbbc422c1c46c9d13b937ab437138b998fe74a635ec88989afb57a3978"},
{file = "coverage-6.4.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:79419370d6a637cb18553ecb25228893966bd7935a9120fa454e7076f13b627c"},
{file = "coverage-6.4.2-cp39-cp39-win32.whl", hash = "sha256:b5e28db9199dd3833cc8a07fa6cf429a01227b5d429facb56eccd765050c26cd"},
{file = "coverage-6.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:edfdabe7aa4f97ed2b9dd5dde52d2bb29cb466993bb9d612ddd10d0085a683cf"},
{file = "coverage-6.4.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:e2618cb2cf5a7cc8d698306e42ebcacd02fb7ef8cfc18485c59394152c70be97"},
{file = "coverage-6.4.2.tar.gz", hash = "sha256:6c3ccfe89c36f3e5b9837b9ee507472310164f352c9fe332120b764c9d60adbe"},
]
django = [
{file = "Django-3.2.14-py3-none-any.whl", hash = "sha256:a8681e098fa60f7c33a4b628d6fcd3fe983a0939ff1301ecacac21d0b38bad56"},
{file = "Django-3.2.14.tar.gz", hash = "sha256:677182ba8b5b285a4e072f3ac17ceee6aff1b5ce77fd173cc5b6a2d3dc022fcf"},
]
django-types = [
{file = "django-types-0.15.0.tar.gz", hash = "sha256:eade768d396b00d48eaca3b58e13217b6f11257d2070937e339e635f50004a62"},
{file = "django_types-0.15.0-py3-none-any.whl", hash = "sha256:105dad074bbe4b7ae49f3a516228d391b10f0b9084f7030b1b1425f4f89e17cc"},
]
fancycompleter = [
{file = "fancycompleter-0.9.1-py3-none-any.whl", hash = "sha256:dd076bca7d9d524cc7f25ec8f35ef95388ffef9ef46def4d3d25e9b044ad7080"},
{file = "fancycompleter-0.9.1.tar.gz", hash = "sha256:09e0feb8ae242abdfd7ef2ba55069a46f011814a80fe5476be48f51b00247272"},
@ -331,6 +542,10 @@ importlib-metadata = [
{file = "importlib_metadata-4.8.3-py3-none-any.whl", hash = "sha256:65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e"},
{file = "importlib_metadata-4.8.3.tar.gz", hash = "sha256:766abffff765960fcc18003801f7044eb6755ffae4521c8e8ce8e83b9c9b0668"},
]
iniconfig = [
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
]
mccabe = [
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
@ -339,6 +554,10 @@ mypy-extensions = [
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
]
packaging = [
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
]
pathspec = [
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
@ -351,6 +570,14 @@ platformdirs = [
{file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"},
{file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"},
]
pluggy = [
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
]
py = [
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
]
pycodestyle = [
{file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
{file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
@ -363,6 +590,10 @@ pygments = [
{file = "Pygments-2.12.0-py3-none-any.whl", hash = "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"},
{file = "Pygments-2.12.0.tar.gz", hash = "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb"},
]
pyparsing = [
{file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
{file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
]
pyreadline = [
{file = "pyreadline-2.1.win-amd64.exe", hash = "sha256:9ce5fa65b8992dfa373bddc5b6e0864ead8f291c94fbfec05fbd5c836162e67b"},
{file = "pyreadline-2.1.win32.exe", hash = "sha256:65540c21bfe14405a3a77e4c085ecfce88724743a4ead47c66b84defcf82c32e"},
@ -371,6 +602,22 @@ pyreadline = [
pyrepl = [
{file = "pyrepl-0.9.0.tar.gz", hash = "sha256:292570f34b5502e871bbb966d639474f2b57fbfcd3373c2d6a2f3d56e681a775"},
]
pytest = [
{file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"},
{file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"},
]
pytest-cov = [
{file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"},
{file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"},
]
pytest-django = [
{file = "pytest-django-4.5.2.tar.gz", hash = "sha256:d9076f759bb7c36939dbdd5ae6633c18edfc2902d1a69fdbefd2426b970ce6c2"},
{file = "pytest_django-4.5.2-py3-none-any.whl", hash = "sha256:c60834861933773109334fe5a53e83d1ef4828f2203a1d6a0fa9972f4f75ab3e"},
]
pytest-sugar = [
{file = "pytest-sugar-0.9.5.tar.gz", hash = "sha256:eea78b6f15b635277d3d90280cd386d8feea1cab0f9be75947a626e8b02b477d"},
{file = "pytest_sugar-0.9.5-py2.py3-none-any.whl", hash = "sha256:3da42de32ce4e1e95b448d61c92804433f5d4058c0a765096991c2e93d5a289f"},
]
pytz = [
{file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"},
{file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"},
@ -383,6 +630,9 @@ sqlparse = [
{file = "sqlparse-0.4.2-py3-none-any.whl", hash = "sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"},
{file = "sqlparse-0.4.2.tar.gz", hash = "sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae"},
]
termcolor = [
{file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"},
]
tomli = [
{file = "tomli-1.2.3-py3-none-any.whl", hash = "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"},
{file = "tomli-1.2.3.tar.gz", hash = "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f"},

View file

@ -9,7 +9,7 @@ packages = [
]
[tool.poetry.dependencies]
python = ">=3.6.2"
python = ">=3.7,<4"
django = ">=2.2"
six = "^1.15.0"
@ -17,6 +17,11 @@ six = "^1.15.0"
pdbpp = "^0.10.2"
flake8 = "^3.7.9"
black = "^21.9b0"
pytest-cov = "^3.0.0"
pytest = "^7.1.2"
pytest-sugar = "^0.9.5"
pytest-django = "^4.5.2"
django-types = "^0.15.0"
[tool.black]
line-length = 100

9
pytest.ini Normal file
View file

@ -0,0 +1,9 @@
[pytest]
DJANGO_SETTINGS_MODULE=modeltranslation.tests.settings
pythonpath = .
python_files = tests.py test_*.py
addopts =
--no-cov-on-fail
--cov-report=""
--cov modeltranslation
--maxfail=5

View file

@ -1,63 +0,0 @@
#!/usr/bin/env python
import os
import sys
import warnings
from optparse import OptionParser
import django
from django.conf import settings
from django.core.management import call_command
def runtests(test_path='modeltranslation'):
if not settings.configured:
# Choose database for settings
test_db = os.getenv('DB', 'sqlite')
test_db_host = os.getenv('DB_HOST', 'localhost')
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}}
if test_db == 'mysql':
DATABASES['default'].update(
{
'ENGINE': 'django.db.backends.mysql',
'NAME': os.getenv('MYSQL_DATABASE', 'modeltranslation'),
'USER': os.getenv('MYSQL_USER', 'root'),
'PASSWORD': os.getenv('MYSQL_PASSWORD', 'password'),
'HOST': test_db_host,
}
)
elif test_db == 'postgres':
DATABASES['default'].update(
{
'ENGINE': 'django.db.backends.postgresql',
'USER': os.getenv('POSTGRES_USER', 'postgres'),
'PASSWORD': os.getenv('POSTGRES_DB', 'postgres'),
'NAME': os.getenv('POSTGRES_DB', 'modeltranslation'),
'HOST': test_db_host,
}
)
# Configure test environment
settings.configure(
DATABASES=DATABASES,
INSTALLED_APPS=(
'django.contrib.contenttypes',
'django.contrib.auth',
'modeltranslation',
),
ROOT_URLCONF=None, # tests override urlconf, but it still needs to be defined
LANGUAGES=(('en', 'English'),),
MIDDLEWARE_CLASSES=(),
)
django.setup()
warnings.simplefilter('always', DeprecationWarning)
failures = call_command('test', test_path, interactive=False, failfast=False, verbosity=2)
sys.exit(bool(failures))
if __name__ == '__main__':
parser = OptionParser()
(options, args) = parser.parse_args()
runtests(*args)