From bd2812ed9dae356dce359b4c91a53788c3c589d6 Mon Sep 17 00:00:00 2001 From: Ronen Lubin Date: Tue, 23 Jan 2024 15:44:58 +0200 Subject: [PATCH 1/5] create the migrations manually instead of using the createmigration cmd --- .../commands/atlas-provider-django.py | 36 ++++++------------- .../management/commands/migrations.py | 21 +++++++++++ atlas_provider_django/settings.py | 2 +- tests/{app => app1}/__init__.py | 0 tests/{app => app1}/apps.py | 4 +-- tests/{app => app1}/migrations/__init__.py | 0 tests/{app => app1}/models.py | 0 tests/app2/__init__.py | 0 tests/app2/apps.py | 6 ++++ tests/app2/migrations/__init__.py | 0 tests/app2/models.py | 14 ++++++++ 11 files changed, 55 insertions(+), 28 deletions(-) create mode 100644 atlas_provider_django/management/commands/migrations.py rename tests/{app => app1}/__init__.py (100%) rename tests/{app => app1}/apps.py (63%) rename tests/{app => app1}/migrations/__init__.py (100%) rename tests/{app => app1}/models.py (100%) create mode 100644 tests/app2/__init__.py create mode 100644 tests/app2/apps.py create mode 100644 tests/app2/migrations/__init__.py create mode 100644 tests/app2/models.py diff --git a/atlas_provider_django/management/commands/atlas-provider-django.py b/atlas_provider_django/management/commands/atlas-provider-django.py index 61a0854..25dd423 100644 --- a/atlas_provider_django/management/commands/atlas-provider-django.py +++ b/atlas_provider_django/management/commands/atlas-provider-django.py @@ -17,6 +17,8 @@ from django.db.backends.mysql.schema import DatabaseSchemaEditor as MySQLDatabaseSchemaEditor from django.db.backends.mysql.features import DatabaseFeatures as MySQLDatabaseFeatures +from atlas_provider_django.management.commands.migrations import get_migrations + class Dialect(str, Enum): mysql = "mysql" @@ -98,15 +100,17 @@ def get_connection_by_dialect(dialect): # MockMigrationLoader loads migrations without db connection. class MockMigrationLoader(MigrationLoader): - def __init__(self, connection, replace_migrations=False, load=True): + def __init__(self, connection, replace_migrations=False, load=False): super().__init__(connection, replace_migrations, load) # The method is almost the same as the original one, but it doesn't check if the migrations are applied or not. # Copied from Django's MigrationLoader class: https://github.com/django/django/blob/8a1727dc7f66db7f0131d545812f77544f35aa57/django/db/migrations/loader.py#L222-L305 # Code licensed under the BSD 3-Clause License: https://github.com/django/django/blob/main/LICENSE def build_graph(self): - self.load_disk() + self.disk_migrations = get_migrations() self.applied_migrations = {} + self.unmigrated_apps = set() + self.migrated_apps = set() self.graph = MigrationGraph() self.replacements = {} for key, migration in self.disk_migrations.items(): @@ -188,18 +192,11 @@ def mock_handle(self, *args, **options): apps.get_app_config(app_label) except LookupError as err: raise CommandError(str(err)) - if app_label not in loader.migrated_apps: - raise CommandError("App '%s' does not have migrations" % app_label) try: migration = loader.get_migration_by_prefix(app_label, migration_name) - except AmbiguityError: - raise CommandError( - "More than one migration matches '%s' in app '%s'. Please be more " - "specific." % (migration_name, app_label) - ) except KeyError: raise CommandError( - "Cannot find a migration matching '%s' from app '%s'. Is it in " + "Cannot find a migration matching '%s' from app1 '%s'. Is it in " "INSTALLED_APPS?" % (migration_name, app_label) ) @@ -210,13 +207,6 @@ def mock_handle(self, *args, **options): return "\n".join(sql_statements) -def order_migrations_by_dependency(): - loader = MigrationLoader(None) - graph = loader.graph - all_nodes = graph.nodes - return graph._generate_plan(nodes=all_nodes, at_end=True) - - class Command(BaseCommand): help = "Import Django migrations into Atlas" @@ -229,7 +219,6 @@ def add_arguments(self, parser): def handle(self, *args, **options): global current_dialect current_dialect = options.get("dialect", Dialect.sqlite) - self.create_migrations() print(self.get_ddl()) def create_migrations(self): @@ -247,11 +236,8 @@ def create_migrations(self): # Load migrations and get the sql statements describing the migrations. def get_ddl(self): - migration_loader = MigrationLoader(None, ignore_no_migrations=True) - migration_loader.load_disk() - migrations = "" - ordered_migrations = order_migrations_by_dependency() - for app_name, migration_name in ordered_migrations: + ddl = "" + for app_name, migration_name in get_migrations(): try: out = StringIO() call_command( @@ -261,7 +247,7 @@ def get_ddl(self): stdout=out, stderr=StringIO(), ) - migrations += out.getvalue() + ddl += out.getvalue() except Exception as e: traceback.print_exc() self.stderr.write( @@ -269,4 +255,4 @@ def get_ddl(self): ) exit(1) - return migrations + return ddl diff --git a/atlas_provider_django/management/commands/migrations.py b/atlas_provider_django/management/commands/migrations.py new file mode 100644 index 0000000..85e74b6 --- /dev/null +++ b/atlas_provider_django/management/commands/migrations.py @@ -0,0 +1,21 @@ +from django.db.migrations.autodetector import MigrationAutodetector +from django.db.migrations.state import ProjectState +from django.db.migrations.loader import MigrationLoader +from django.apps import apps + + +def get_migrations(): + autodetector = MigrationAutodetector( + ProjectState(), + ProjectState.from_apps(apps), + ) + loader = MigrationLoader(None, ignore_no_migrations=True) + changes = autodetector.changes( + graph=loader.graph, + trim_to_apps=None, + convert_apps=None, + ) + migrations = {} + for app_label, app_migrations in changes.items(): + migrations[(app_label, app_migrations[0].name)] = app_migrations[0] + return migrations diff --git a/atlas_provider_django/settings.py b/atlas_provider_django/settings.py index b5abbc1..db074e3 100644 --- a/atlas_provider_django/settings.py +++ b/atlas_provider_django/settings.py @@ -1 +1 @@ -INSTALLED_APPS = ["atlas_provider_django", "tests.app"] +INSTALLED_APPS = ["atlas_provider_django", "tests.app1", "tests.app2"] diff --git a/tests/app/__init__.py b/tests/app1/__init__.py similarity index 100% rename from tests/app/__init__.py rename to tests/app1/__init__.py diff --git a/tests/app/apps.py b/tests/app1/apps.py similarity index 63% rename from tests/app/apps.py rename to tests/app1/apps.py index 40424a3..85b7aca 100644 --- a/tests/app/apps.py +++ b/tests/app1/apps.py @@ -1,6 +1,6 @@ from django.apps import AppConfig -class AppConfig(AppConfig): +class App1Config(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "tests.app" + name = "tests.app1" diff --git a/tests/app/migrations/__init__.py b/tests/app1/migrations/__init__.py similarity index 100% rename from tests/app/migrations/__init__.py rename to tests/app1/migrations/__init__.py diff --git a/tests/app/models.py b/tests/app1/models.py similarity index 100% rename from tests/app/models.py rename to tests/app1/models.py diff --git a/tests/app2/__init__.py b/tests/app2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/app2/apps.py b/tests/app2/apps.py new file mode 100644 index 0000000..03cc00f --- /dev/null +++ b/tests/app2/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class App2Config(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "tests.app2" diff --git a/tests/app2/migrations/__init__.py b/tests/app2/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/app2/models.py b/tests/app2/models.py new file mode 100644 index 0000000..4005f39 --- /dev/null +++ b/tests/app2/models.py @@ -0,0 +1,14 @@ +from django.db import models + + +class User(models.Model): + first_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50) + roll = models.CharField(max_length=100) + + +class Blog(models.Model): + author = models.ForeignKey(User, on_delete=models.CASCADE) + name = models.CharField(max_length=100) + created_at = models.DateField() + num_stars = models.IntegerField() \ No newline at end of file From 496476e7edb2212e97a159434f8fd9d9e7731da1 Mon Sep 17 00:00:00 2001 From: Ronen Lubin Date: Tue, 23 Jan 2024 16:12:56 +0200 Subject: [PATCH 2/5] cleanups --- .../commands/atlas-provider-django.py | 55 ++----------------- .../management/commands/migrations.py | 1 + tests/app2/models.py | 2 +- 3 files changed, 7 insertions(+), 51 deletions(-) diff --git a/atlas_provider_django/management/commands/atlas-provider-django.py b/atlas_provider_django/management/commands/atlas-provider-django.py index 25dd423..7e48cf0 100644 --- a/atlas_provider_django/management/commands/atlas-provider-django.py +++ b/atlas_provider_django/management/commands/atlas-provider-django.py @@ -4,9 +4,8 @@ from django.apps import apps from django.core.management import call_command -from django.db.migrations.exceptions import NodeNotFoundError from django.db.migrations.graph import MigrationGraph -from django.db.migrations.loader import MigrationLoader, AmbiguityError +from django.db.migrations.loader import MigrationLoader from django.core.management.base import BaseCommand, CommandError from django.core.management.commands.sqlmigrate import Command as SqlMigrateCommand from django.db.backends.sqlite3.base import DatabaseWrapper as Sqlite3DatabaseWrapper @@ -103,64 +102,20 @@ class MockMigrationLoader(MigrationLoader): def __init__(self, connection, replace_migrations=False, load=False): super().__init__(connection, replace_migrations, load) - # The method is almost the same as the original one, but it doesn't check if the migrations are applied or not. - # Copied from Django's MigrationLoader class: https://github.com/django/django/blob/8a1727dc7f66db7f0131d545812f77544f35aa57/django/db/migrations/loader.py#L222-L305 - # Code licensed under the BSD 3-Clause License: https://github.com/django/django/blob/main/LICENSE def build_graph(self): self.disk_migrations = get_migrations() self.applied_migrations = {} self.unmigrated_apps = set() self.migrated_apps = set() self.graph = MigrationGraph() - self.replacements = {} for key, migration in self.disk_migrations.items(): self.graph.add_node(key, migration) - if migration.replaces: - self.replacements[key] = migration - for key, migration in self.disk_migrations.items(): - self.add_internal_dependencies(key, migration) - for key, migration in self.disk_migrations.items(): - self.add_external_dependencies(key, migration) - if self.replace_migrations: - for key, migration in self.replacements.items(): - applied_statuses = [ - (target in self.applied_migrations) for target in migration.replaces - ] - if all(applied_statuses): - self.applied_migrations[key] = migration - else: - self.applied_migrations.pop(key, None) - if all(applied_statuses) or (not any(applied_statuses)): - self.graph.remove_replaced_nodes(key, migration.replaces) - else: - self.graph.remove_replacement_node(key, migration.replaces) - try: - self.graph.validate_consistency() - except NodeNotFoundError as exc: - reverse_replacements = {} - for key, migration in self.replacements.items(): - for replaced in migration.replaces: - reverse_replacements.setdefault(replaced, set()).add(key) - if exc.node in reverse_replacements: - candidates = reverse_replacements.get(exc.node, set()) - is_replaced = any( - candidate in self.graph.nodes for candidate in candidates - ) - if not is_replaced: - tries = ", ".join("%s.%s" % c for c in candidates) - raise NodeNotFoundError( - "Migration {0} depends on nonexistent node ('{1}', '{2}'). " - "Django tried to replace migration {1}.{2} with any of [{3}] " - "but wasn't able to because some of the replaced migrations " - "are already applied.".format( - exc.origin, exc.node[0], exc.node[1], tries - ), - exc.node, - ) from exc - raise + self.graph.validate_consistency() self.graph.ensure_not_cyclic() # The method is almost the same as the original one, but it doesn't check if atomic transactions are enabled or not. + # Copied from Django's MigrationLoader class: https://github.com/django/django/blob/8a1727dc7f66db7f0131d545812f77544f35aa57/django/db/migrations/loader.py#L365-L385 + # Code licensed under the BSD 3-Clause License: https://github.com/django/django/blob/main/LICENSE def collect_sql(self, plan): statements = [] state = None @@ -196,7 +151,7 @@ def mock_handle(self, *args, **options): migration = loader.get_migration_by_prefix(app_label, migration_name) except KeyError: raise CommandError( - "Cannot find a migration matching '%s' from app1 '%s'. Is it in " + "Cannot find a migration matching '%s' from app '%s'. Is it in " "INSTALLED_APPS?" % (migration_name, app_label) ) diff --git a/atlas_provider_django/management/commands/migrations.py b/atlas_provider_django/management/commands/migrations.py index 85e74b6..d43cb5e 100644 --- a/atlas_provider_django/management/commands/migrations.py +++ b/atlas_provider_django/management/commands/migrations.py @@ -4,6 +4,7 @@ from django.apps import apps +# Creates the migrations of the installed apps from empty baseline and returns them as a dictionary def get_migrations(): autodetector = MigrationAutodetector( ProjectState(), diff --git a/tests/app2/models.py b/tests/app2/models.py index 4005f39..29327bb 100644 --- a/tests/app2/models.py +++ b/tests/app2/models.py @@ -11,4 +11,4 @@ class Blog(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=100) created_at = models.DateField() - num_stars = models.IntegerField() \ No newline at end of file + num_stars = models.IntegerField() From 6eb0ac334eebdf4b8bd29c8047953cbd05c70a36 Mon Sep 17 00:00:00 2001 From: Ronen Lubin Date: Tue, 23 Jan 2024 16:46:49 +0200 Subject: [PATCH 3/5] atlas.hcl file --- tests/app2/models.py | 5 +-- tests/atlas.hcl | 35 +++++++++++++++++++++ tests/migrations/sqlite/20240123144148.sql | 36 ++++++++++++++++++++++ tests/migrations/sqlite/atlas.sum | 2 ++ 4 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 tests/atlas.hcl create mode 100644 tests/migrations/sqlite/20240123144148.sql create mode 100644 tests/migrations/sqlite/atlas.sum diff --git a/tests/app2/models.py b/tests/app2/models.py index 29327bb..82cfbe3 100644 --- a/tests/app2/models.py +++ b/tests/app2/models.py @@ -2,9 +2,10 @@ class User(models.Model): + Rolls = {"student": "student", "teacher": "teacher"} first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - roll = models.CharField(max_length=100) + last_name = models.CharField(max_length=50, null=True) + roll = models.CharField(choices=Rolls, max_length=10, default=Rolls["student"]) class Blog(models.Model): diff --git a/tests/atlas.hcl b/tests/atlas.hcl new file mode 100644 index 0000000..0137397 --- /dev/null +++ b/tests/atlas.hcl @@ -0,0 +1,35 @@ +variable "dialect" { + type = string +} + +locals { + dev_url = { + mysql = "docker://mysql/8/dev" + postgresql = "docker://postgres/15" + sqlite = "sqlite://?mode=memory&_fk=1" + }[var.dialect] +} + +data "external_schema" "django" { + program = [ + "poetry", + "run", + "python3", + "../manage.py", + "atlas-provider-django", + "--dialect", var.dialect, // mysql | postgresql | sqlite + ] +} + +env "django" { + src = data.external_schema.django.url + dev = local.dev_url + migration { + dir = "file://migrations/${var.dialect}" + } + format { + migrate { + diff = "{{ sql . \" \" }}" + } + } +} \ No newline at end of file diff --git a/tests/migrations/sqlite/20240123144148.sql b/tests/migrations/sqlite/20240123144148.sql new file mode 100644 index 0000000..256542c --- /dev/null +++ b/tests/migrations/sqlite/20240123144148.sql @@ -0,0 +1,36 @@ +-- Create "app1_musician" table +CREATE TABLE `app1_musician` ( + `id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, + `first_name` varchar NOT NULL, + `last_name` varchar NOT NULL, + `instrument` varchar NOT NULL +); +-- Create "app1_album" table +CREATE TABLE `app1_album` ( + `id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, + `name` varchar NOT NULL, + `release_date` date NOT NULL, + `num_stars` integer NOT NULL, + `artist_id` bigint NOT NULL, + CONSTRAINT `0` FOREIGN KEY (`artist_id`) REFERENCES `app1_musician` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create index "app1_album_artist_id_aed0987a" to table: "app1_album" +CREATE INDEX `app1_album_artist_id_aed0987a` ON `app1_album` (`artist_id`); +-- Create "app2_user" table +CREATE TABLE `app2_user` ( + `id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, + `first_name` varchar NOT NULL, + `last_name` varchar NULL, + `roll` varchar NOT NULL +); +-- Create "app2_blog" table +CREATE TABLE `app2_blog` ( + `id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, + `name` varchar NOT NULL, + `created_at` date NOT NULL, + `num_stars` integer NOT NULL, + `author_id` bigint NOT NULL, + CONSTRAINT `0` FOREIGN KEY (`author_id`) REFERENCES `app2_user` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create index "app2_blog_author_id_1675e606" to table: "app2_blog" +CREATE INDEX `app2_blog_author_id_1675e606` ON `app2_blog` (`author_id`); diff --git a/tests/migrations/sqlite/atlas.sum b/tests/migrations/sqlite/atlas.sum new file mode 100644 index 0000000..617bc4d --- /dev/null +++ b/tests/migrations/sqlite/atlas.sum @@ -0,0 +1,2 @@ +h1:jI5Gdg90nJnGY0NKrYUt2P1TTR06vJ3Ru7QUjLOj5Ds= +20240123144148.sql h1:MzpmTij4257m5ygT9yNVtEFQILZio2D3eX+FjOjR0sI= From 32faf9bc9b803a6fa2dbc5aa50f4b63396685b8f Mon Sep 17 00:00:00 2001 From: Ronen Lubin Date: Tue, 23 Jan 2024 17:07:18 +0200 Subject: [PATCH 4/5] add ci and integration tests --- .github/workflows/ci.yaml | 69 +++++++++++++++++++ tests/app2/models.py | 3 +- tests/atlas.hcl | 2 +- tests/migrations/mysql/20240123150434.sql | 38 ++++++++++ tests/migrations/mysql/atlas.sum | 2 + .../migrations/postgresql/20240123150442.sql | 40 +++++++++++ tests/migrations/postgresql/atlas.sum | 2 + ...{20240123144148.sql => 20240123150447.sql} | 0 tests/migrations/sqlite/atlas.sum | 4 +- 9 files changed, 155 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/ci.yaml create mode 100644 tests/migrations/mysql/20240123150434.sql create mode 100644 tests/migrations/mysql/atlas.sum create mode 100644 tests/migrations/postgresql/20240123150442.sql create mode 100644 tests/migrations/postgresql/atlas.sum rename tests/migrations/sqlite/{20240123144148.sql => 20240123150447.sql} (100%) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..d4115c3 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,69 @@ +name: Continuous Integration +on: + pull_request: + +jobs: + ci-python: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + - name: Install poetry + uses: abatilo/actions-poetry@v2 + - name: Setup a local virtual environment (if no poetry.toml file) + run: | + poetry config virtualenvs.create true --local + poetry config virtualenvs.in-project true --local + - uses: actions/cache@v3 + name: Define a cache for the virtual environment based on the dependencies lock file + with: + path: ./.venv + key: venv-${{ hashFiles('poetry.lock') }} + - name: Install the project dependencies + run: poetry install + - name: Run lint + run: poetry run ruff --output-format=github . + + integration-tests: + strategy: + matrix: + dialect: [ mysql, postgresql, sqlite ] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + - name: Install poetry + uses: abatilo/actions-poetry@v2 + - name: Setup a local virtual environment (if no poetry.toml file) + run: | + poetry config virtualenvs.create true --local + poetry config virtualenvs.in-project true --local + - uses: actions/cache@v3 + name: Define a cache for the virtual environment based on the dependencies lock file + with: + path: ./.venv + key: venv-${{ hashFiles('poetry.lock') }} + - name: Install the project dependencies + run: poetry install + - name: Install atlas + uses: ariga/setup-atlas@master + - name: Run Test as Standalone + working-directory: ./tests + run: | + atlas migrate diff --env django --var dialect=${{ matrix.dialect }} + - name: Verify migrations generated + working-directory: ./tests + run: | + status=$(git status . --porcelain) + if [ -n "$status" ]; then + echo "you need to run 'atlas migrate diff --env django and commit the changes" + echo "$status" + git --no-pager diff + exit 1 + fi diff --git a/tests/app2/models.py b/tests/app2/models.py index 82cfbe3..9c62e2d 100644 --- a/tests/app2/models.py +++ b/tests/app2/models.py @@ -2,10 +2,9 @@ class User(models.Model): - Rolls = {"student": "student", "teacher": "teacher"} first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50, null=True) - roll = models.CharField(choices=Rolls, max_length=10, default=Rolls["student"]) + roll = models.CharField(max_length=100) class Blog(models.Model): diff --git a/tests/atlas.hcl b/tests/atlas.hcl index 0137397..c3168d9 100644 --- a/tests/atlas.hcl +++ b/tests/atlas.hcl @@ -32,4 +32,4 @@ env "django" { diff = "{{ sql . \" \" }}" } } -} \ No newline at end of file +} diff --git a/tests/migrations/mysql/20240123150434.sql b/tests/migrations/mysql/20240123150434.sql new file mode 100644 index 0000000..6c8dfb6 --- /dev/null +++ b/tests/migrations/mysql/20240123150434.sql @@ -0,0 +1,38 @@ +-- Create "app1_musician" table +CREATE TABLE `app1_musician` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `first_name` varchar(50) NOT NULL, + `last_name` varchar(50) NOT NULL, + `instrument` varchar(100) NOT NULL, + PRIMARY KEY (`id`) +) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci; +-- Create "app1_album" table +CREATE TABLE `app1_album` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `release_date` date NOT NULL, + `num_stars` int NOT NULL, + `artist_id` bigint NOT NULL, + PRIMARY KEY (`id`), + INDEX `app1_album_artist_id_aed0987a_fk_app1_musician_id` (`artist_id`), + CONSTRAINT `app1_album_artist_id_aed0987a_fk_app1_musician_id` FOREIGN KEY (`artist_id`) REFERENCES `app1_musician` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION +) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci; +-- Create "app2_user" table +CREATE TABLE `app2_user` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `first_name` varchar(50) NOT NULL, + `last_name` varchar(50) NULL, + `roll` varchar(100) NOT NULL, + PRIMARY KEY (`id`) +) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci; +-- Create "app2_blog" table +CREATE TABLE `app2_blog` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `created_at` date NOT NULL, + `num_stars` int NOT NULL, + `author_id` bigint NOT NULL, + PRIMARY KEY (`id`), + INDEX `app2_blog_author_id_1675e606_fk_app2_user_id` (`author_id`), + CONSTRAINT `app2_blog_author_id_1675e606_fk_app2_user_id` FOREIGN KEY (`author_id`) REFERENCES `app2_user` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION +) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci; diff --git a/tests/migrations/mysql/atlas.sum b/tests/migrations/mysql/atlas.sum new file mode 100644 index 0000000..f3c2523 --- /dev/null +++ b/tests/migrations/mysql/atlas.sum @@ -0,0 +1,2 @@ +h1:t+fHYX8aCiiNQ7IoDKRSIdnAeO9Mp7o6Eug9hhCCTTE= +20240123150434.sql h1:wZOaDDiz5ov9fn+bBctKy0/HoDZ4QL6VTzk58TialGg= diff --git a/tests/migrations/postgresql/20240123150442.sql b/tests/migrations/postgresql/20240123150442.sql new file mode 100644 index 0000000..1d277e4 --- /dev/null +++ b/tests/migrations/postgresql/20240123150442.sql @@ -0,0 +1,40 @@ +-- Create "app1_musician" table +CREATE TABLE "public"."app1_musician" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "first_name" character varying(50) NOT NULL, + "last_name" character varying(50) NOT NULL, + "instrument" character varying(100) NOT NULL, + PRIMARY KEY ("id") +); +-- Create "app1_album" table +CREATE TABLE "public"."app1_album" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" character varying(100) NOT NULL, + "release_date" date NOT NULL, + "num_stars" integer NOT NULL, + "artist_id" bigint NOT NULL, + PRIMARY KEY ("id"), + CONSTRAINT "app1_album_artist_id_aed0987a_fk_app1_musician_id" FOREIGN KEY ("artist_id") REFERENCES "public"."app1_musician" ("id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create index "app1_album_artist_id_aed0987a" to table: "app1_album" +CREATE INDEX "app1_album_artist_id_aed0987a" ON "public"."app1_album" ("artist_id"); +-- Create "app2_user" table +CREATE TABLE "public"."app2_user" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "first_name" character varying(50) NOT NULL, + "last_name" character varying(50) NULL, + "roll" character varying(100) NOT NULL, + PRIMARY KEY ("id") +); +-- Create "app2_blog" table +CREATE TABLE "public"."app2_blog" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" character varying(100) NOT NULL, + "created_at" date NOT NULL, + "num_stars" integer NOT NULL, + "author_id" bigint NOT NULL, + PRIMARY KEY ("id"), + CONSTRAINT "app2_blog_author_id_1675e606_fk_app2_user_id" FOREIGN KEY ("author_id") REFERENCES "public"."app2_user" ("id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create index "app2_blog_author_id_1675e606" to table: "app2_blog" +CREATE INDEX "app2_blog_author_id_1675e606" ON "public"."app2_blog" ("author_id"); diff --git a/tests/migrations/postgresql/atlas.sum b/tests/migrations/postgresql/atlas.sum new file mode 100644 index 0000000..3037927 --- /dev/null +++ b/tests/migrations/postgresql/atlas.sum @@ -0,0 +1,2 @@ +h1:wPrdpJIc9fRclW3cMGAqDMqK22dhVkEahLLae2v2Jp4= +20240123150442.sql h1:OssKCxrsi6AnIM5iRKN/lrbHEzgehNTrR0t+AIefm1I= diff --git a/tests/migrations/sqlite/20240123144148.sql b/tests/migrations/sqlite/20240123150447.sql similarity index 100% rename from tests/migrations/sqlite/20240123144148.sql rename to tests/migrations/sqlite/20240123150447.sql diff --git a/tests/migrations/sqlite/atlas.sum b/tests/migrations/sqlite/atlas.sum index 617bc4d..d68f6a9 100644 --- a/tests/migrations/sqlite/atlas.sum +++ b/tests/migrations/sqlite/atlas.sum @@ -1,2 +1,2 @@ -h1:jI5Gdg90nJnGY0NKrYUt2P1TTR06vJ3Ru7QUjLOj5Ds= -20240123144148.sql h1:MzpmTij4257m5ygT9yNVtEFQILZio2D3eX+FjOjR0sI= +h1:BH7VCgohPrXE2+BAyinbXWinObUasKWvewdQX0rUxJ4= +20240123150447.sql h1:dvS9iDdf9wRJYX8t883ehkjEuXqmkvbOIYE+3x0tmlg= From e8dfab992434c044b9f4fc25f8e9d71fdccfa013 Mon Sep 17 00:00:00 2001 From: Ronen Lubin Date: Tue, 23 Jan 2024 23:55:24 +0200 Subject: [PATCH 5/5] add dev dpes --- poetry.lock | 127 ++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 4 ++ 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 7c8195c..c77d231 100644 --- a/poetry.lock +++ b/poetry.lock @@ -34,6 +34,131 @@ tzdata = {version = "*", markers = "sys_platform == \"win32\""} argon2 = ["argon2-cffi (>=19.1.0)"] bcrypt = ["bcrypt"] +[[package]] +name = "mysqlclient" +version = "2.2.1" +description = "Python interface to MySQL" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mysqlclient-2.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:c5a293baebbfcfa2905545198a54e90f1cf00f211eae6637d24930abb6432cba"}, + {file = "mysqlclient-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:8f40c872f19639366e3df27bef2ff087be0e3ee0bd3453470bd29f46b54a90f6"}, + {file = "mysqlclient-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:45600f4f321096bd1ead3355bc62cfcf8d97dc78df94e4ab5db72ecb5db1bd04"}, + {file = "mysqlclient-2.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:1f8889cc5f0141bb307b915e981a66793df663ace92259344661084a7dd8d12a"}, + {file = "mysqlclient-2.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:9db6305cdf2a1da350f827d2a19be7f2666eafd9eb8d4f7cbbac5df847d61b99"}, + {file = "mysqlclient-2.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:97eee76818774bb695e018ff4c3dafaab74b9a0b0cf32c90b02caeec3b19cd8e"}, + {file = "mysqlclient-2.2.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4fabe1f4b545ed6244ad0ff426e6b27054b7e5c5b1392be0de2e5f2f59be0392"}, + {file = "mysqlclient-2.2.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:641a7c9de443ddef186a0e89f24b4251ad44f4ddc5e7094332bf2d286d7c9e33"}, + {file = "mysqlclient-2.2.1.tar.gz", hash = "sha256:2c7ad15b87293b12fd44b47c46879ec95ec647f4567e866ccd70b8337584e9b2"}, +] + +[[package]] +name = "psycopg2-binary" +version = "2.9.9" +description = "psycopg2 - Python-PostgreSQL Database Adapter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "psycopg2-binary-2.9.9.tar.gz", hash = "sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-win32.whl", hash = "sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-win32.whl", hash = "sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0605eaed3eb239e87df0d5e3c6489daae3f7388d455d0c0b4df899519c6a38d"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-win32.whl", hash = "sha256:64cf30263844fa208851ebb13b0732ce674d8ec6a0c86a4e160495d299ba3c93"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-win_amd64.whl", hash = "sha256:81ff62668af011f9a48787564ab7eded4e9fb17a4a6a74af5ffa6a457400d2ab"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-win32.whl", hash = "sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-win_amd64.whl", hash = "sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-win32.whl", hash = "sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-win32.whl", hash = "sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957"}, +] + +[[package]] +name = "ruff" +version = "0.1.14" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.1.14-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:96f76536df9b26622755c12ed8680f159817be2f725c17ed9305b472a757cdbb"}, + {file = "ruff-0.1.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ab3f71f64498c7241123bb5a768544cf42821d2a537f894b22457a543d3ca7a9"}, + {file = "ruff-0.1.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7060156ecc572b8f984fd20fd8b0fcb692dd5d837b7606e968334ab7ff0090ab"}, + {file = "ruff-0.1.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a53d8e35313d7b67eb3db15a66c08434809107659226a90dcd7acb2afa55faea"}, + {file = "ruff-0.1.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bea9be712b8f5b4ebed40e1949379cfb2a7d907f42921cf9ab3aae07e6fba9eb"}, + {file = "ruff-0.1.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2270504d629a0b064247983cbc495bed277f372fb9eaba41e5cf51f7ba705a6a"}, + {file = "ruff-0.1.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80258bb3b8909b1700610dfabef7876423eed1bc930fe177c71c414921898efa"}, + {file = "ruff-0.1.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:653230dd00aaf449eb5ff25d10a6e03bc3006813e2cb99799e568f55482e5cae"}, + {file = "ruff-0.1.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b3acc6c4e6928459ba9eb7459dd4f0c4bf266a053c863d72a44c33246bfdbf"}, + {file = "ruff-0.1.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6b3dadc9522d0eccc060699a9816e8127b27addbb4697fc0c08611e4e6aeb8b5"}, + {file = "ruff-0.1.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1c8eca1a47b4150dc0fbec7fe68fc91c695aed798532a18dbb1424e61e9b721f"}, + {file = "ruff-0.1.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:62ce2ae46303ee896fc6811f63d6dabf8d9c389da0f3e3f2bce8bc7f15ef5488"}, + {file = "ruff-0.1.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b2027dde79d217b211d725fc833e8965dc90a16d0d3213f1298f97465956661b"}, + {file = "ruff-0.1.14-py3-none-win32.whl", hash = "sha256:722bafc299145575a63bbd6b5069cb643eaa62546a5b6398f82b3e4403329cab"}, + {file = "ruff-0.1.14-py3-none-win_amd64.whl", hash = "sha256:e3d241aa61f92b0805a7082bd89a9990826448e4d0398f0e2bc8f05c75c63d99"}, + {file = "ruff-0.1.14-py3-none-win_arm64.whl", hash = "sha256:269302b31ade4cde6cf6f9dd58ea593773a37ed3f7b97e793c8594b262466b67"}, + {file = "ruff-0.1.14.tar.gz", hash = "sha256:ad3f8088b2dfd884820289a06ab718cde7d38b94972212cc4ba90d5fbc9955f3"}, +] + [[package]] name = "sqlparse" version = "0.4.4" @@ -64,4 +189,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "395b61e6a4b2b849554904c24dec560e83466330d25df8fa30193d63e6837b0d" +content-hash = "dd165cd42dfaeec167310a9595a2b25d881a776666a3b9943f004baf14330e6b" diff --git a/pyproject.toml b/pyproject.toml index 37509e8..1aea9f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,10 @@ readme = "README.md" python = "^3.11" django = ">=4.2" +[tool.poetry.group.dev.dependencies] +ruff = "^0.1.14" +psycopg2-binary = "^2.9.9" +mysqlclient = "^2.2.1" [build-system] requires = ["poetry-core"]