From 37a4fa3cb53e73298a20f4a2f0af419bc02b3d81 Mon Sep 17 00:00:00 2001 From: Clemens Wolff Date: Fri, 25 Oct 2019 12:35:20 -0400 Subject: [PATCH 1/2] Remove unused db_options variable --- app/app/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/app/settings.py b/app/app/settings.py index c4f0a8fa..c54f5da0 100644 --- a/app/app/settings.py +++ b/app/app/settings.py @@ -265,7 +265,7 @@ if DATABASES['default'].get('ENGINE') == 'django.db.backends.sqlite3': # default to a sensible modern driver for Azure SQL if DATABASES['default'].get('ENGINE') == 'sql_server.pyodbc': - db_options = DATABASES['default'].setdefault('OPTIONS', {})\ + DATABASES['default'].setdefault('OPTIONS', {})\ .setdefault('driver', 'ODBC Driver 17 for SQL Server') # Honor the 'X-Forwarded-Proto' header for request.is_secure() From 1dd2e2b1cfd54e980daf5b9a81df76600804789a Mon Sep 17 00:00:00 2001 From: Clemens Wolff Date: Fri, 25 Oct 2019 12:35:10 -0400 Subject: [PATCH 2/2] Add support for MySQL --- .travis.yml | 5 ++ app/api/migrations/0001_initial.py | 51 +++++++++++++++++-- .../0002_approve_document_labels.py | 21 -------- app/api/migrations/0003_support_sql_server.py | 28 ---------- .../0004_project_collaborative_annotation.py | 18 ------- app/api/migrations/0004_roles.py | 43 ---------------- .../migrations/0005_merge_20191021_1548.py | 14 ----- app/app/settings.py | 7 +++ requirements.txt | 1 + 9 files changed, 60 insertions(+), 128 deletions(-) delete mode 100644 app/api/migrations/0002_approve_document_labels.py delete mode 100644 app/api/migrations/0003_support_sql_server.py delete mode 100644 app/api/migrations/0004_project_collaborative_annotation.py delete mode 100644 app/api/migrations/0004_roles.py delete mode 100644 app/api/migrations/0005_merge_20191021_1548.py diff --git a/.travis.yml b/.travis.yml index 73c1356a..fc287d37 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ env: - DATABASE=sqlite - DATABASE=postgres - DATABASE=mssql + - DATABASE=mysql services: - docker @@ -22,6 +23,10 @@ before_install: docker run --rm --name=mssql --network=doccano -d -e ACCEPT_EULA=y -e SA_PASSWORD=sUp3rS3cr3t mcr.microsoft.com/mssql/server:2017-latest docker exec -it mssql sh -c "while ! /opt/mssql-tools/bin/sqlcmd -U SA -P sUp3rS3cr3t -Q 'CREATE DATABASE db;'; do sleep 3; done" export DATABASE_URL="mssql://SA:sUp3rS3cr3t@mssql:1433/db?sslmode=disable" + + elif [[ "${DATABASE}" = "mysql" ]]; then + docker run --rm --name=mysql --network=doccano -d -e MYSQL_DATABASE=db -e MYSQL_ROOT_PASSWORD=mysqlr00t mysql:5.7 + export DATABASE_URL="mysql://root:mysqlr00t@mysql:3306/db" fi install: diff --git a/app/api/migrations/0001_initial.py b/app/api/migrations/0001_initial.py index ee8a325b..855e6e37 100644 --- a/app/api/migrations/0001_initial.py +++ b/app/api/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 2.1.7 on 2019-06-21 06:05 +# Generated by Django 2.1.7 on 2019-10-25 16:26 from django.conf import settings from django.db import migrations, models @@ -10,8 +10,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('contenttypes', '0002_remove_content_type_name'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('contenttypes', '0002_remove_content_type_name'), ] operations = [ @@ -23,6 +23,7 @@ class Migration(migrations.Migration): ('meta', models.TextField(default='{}')), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), + ('annotations_approved_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), ], ), migrations.CreateModel( @@ -60,12 +61,31 @@ class Migration(migrations.Migration): ('updated_at', models.DateTimeField(auto_now=True)), ('project_type', models.CharField(choices=[('DocumentClassification', 'document classification'), ('SequenceLabeling', 'sequence labeling'), ('Seq2seq', 'sequence to sequence')], max_length=30)), ('randomize_document_order', models.BooleanField(default=False)), + ('collaborative_annotation', models.BooleanField(default=False)), ], options={ 'abstract': False, 'base_manager_name': 'objects', }, ), + migrations.CreateModel( + name='Role', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, unique=True)), + ('description', models.TextField(default='')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + ), + migrations.CreateModel( + name='RoleMapping', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + ), migrations.CreateModel( name='Seq2seqAnnotation', fields=[ @@ -74,7 +94,7 @@ class Migration(migrations.Migration): ('manual', models.BooleanField(default=False)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), - ('text', models.TextField()), + ('text', models.CharField(max_length=500)), ('document', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='seq2seq_annotations', to='api.Document')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], @@ -127,6 +147,21 @@ class Migration(migrations.Migration): }, bases=('api.project',), ), + migrations.AddField( + model_name='rolemapping', + name='project', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='role_mappings', to='api.Project'), + ), + migrations.AddField( + model_name='rolemapping', + name='role', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Role'), + ), + migrations.AddField( + model_name='rolemapping', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='role_mappings', to=settings.AUTH_USER_MODEL), + ), migrations.AddField( model_name='project', name='polymorphic_ctype', @@ -161,9 +196,17 @@ class Migration(migrations.Migration): name='sequenceannotation', unique_together={('document', 'user', 'label', 'start_offset', 'end_offset')}, ), + migrations.AlterUniqueTogether( + name='seq2seqannotation', + unique_together={('document', 'user', 'text')}, + ), + migrations.AlterUniqueTogether( + name='rolemapping', + unique_together={('user', 'project', 'role')}, + ), migrations.AlterUniqueTogether( name='label', - unique_together={('project', 'text'), ('project', 'prefix_key', 'suffix_key')}, + unique_together={('project', 'text')}, ), migrations.AlterUniqueTogether( name='documentannotation', diff --git a/app/api/migrations/0002_approve_document_labels.py b/app/api/migrations/0002_approve_document_labels.py deleted file mode 100644 index 9d284a2e..00000000 --- a/app/api/migrations/0002_approve_document_labels.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-26 13:24 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('api', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='document', - name='annotations_approved_by', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/app/api/migrations/0003_support_sql_server.py b/app/api/migrations/0003_support_sql_server.py deleted file mode 100644 index 38befbfe..00000000 --- a/app/api/migrations/0003_support_sql_server.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-26 13:20 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('api', '0002_approve_document_labels'), - ] - - operations = [ - migrations.AlterField( - model_name='seq2seqannotation', - name='text', - field=models.CharField(max_length=500), - ), - migrations.AlterUniqueTogether( - name='seq2seqannotation', - unique_together={('document', 'user', 'text')}, - ), - migrations.AlterUniqueTogether( - name='label', - unique_together={('project', 'text')}, - ), - ] diff --git a/app/api/migrations/0004_project_collaborative_annotation.py b/app/api/migrations/0004_project_collaborative_annotation.py deleted file mode 100644 index 953192f3..00000000 --- a/app/api/migrations/0004_project_collaborative_annotation.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-08-01 18:12 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0003_support_sql_server'), - ] - - operations = [ - migrations.AddField( - model_name='project', - name='collaborative_annotation', - field=models.BooleanField(default=False), - ), - ] diff --git a/app/api/migrations/0004_roles.py b/app/api/migrations/0004_roles.py deleted file mode 100644 index fec81310..00000000 --- a/app/api/migrations/0004_roles.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-25 03:33 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('api', '0003_support_sql_server'), - ] - - operations = [ - migrations.CreateModel( - name='Role', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100, unique=True)), - ('description', models.TextField(default='', null=True)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ], - ), - migrations.CreateModel( - name='RoleMapping', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, - related_name='role_mappings', to='api.Project')), - ('role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Role')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, - related_name='role_mappings', to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.AlterUniqueTogether( - name='rolemapping', - unique_together={('user', 'project', 'role')}, - ), - ] diff --git a/app/api/migrations/0005_merge_20191021_1548.py b/app/api/migrations/0005_merge_20191021_1548.py deleted file mode 100644 index 481f400d..00000000 --- a/app/api/migrations/0005_merge_20191021_1548.py +++ /dev/null @@ -1,14 +0,0 @@ -# Generated by Django 2.1.7 on 2019-10-21 15:48 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0004_project_collaborative_annotation'), - ('api', '0004_roles'), - ] - - operations = [ - ] diff --git a/app/app/settings.py b/app/app/settings.py index c54f5da0..c9ee99d6 100644 --- a/app/app/settings.py +++ b/app/app/settings.py @@ -263,6 +263,13 @@ DATABASES['default'].update(dj_database_url.config( if DATABASES['default'].get('ENGINE') == 'django.db.backends.sqlite3': DATABASES['default'].get('OPTIONS', {}).pop('sslmode', None) +# work-around for dj-database-url: patch ssl for mysql +if DATABASES['default'].get('ENGINE') == 'django.db.backends.mysql': + DATABASES['default'].get('OPTIONS', {}).pop('sslmode', None) + if env('MYSQL_SSL_CA', None): + DATABASES['default'].setdefault('OPTIONS', {})\ + .setdefault('ssl', {}).setdefault('ca', env('MYSQL_SSL_CA', None)) + # default to a sensible modern driver for Azure SQL if DATABASES['default'].get('ENGINE') == 'sql_server.pyodbc': DATABASES['default'].setdefault('OPTIONS', {})\ diff --git a/requirements.txt b/requirements.txt index 1981b52b..76608e1d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,6 +24,7 @@ gunicorn==19.9.0 lockfile==0.12.2 mixer==6.1.3 model-mommy==1.6.0 +mysqlclient==1.4.2.post1 psycopg2-binary==2.7.7 pyexcel==0.5.14 pyexcel-xlsx==0.5.7