From 9e0b8dfa0b574dab107ea58c62b323fafa2ab293 Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Wed, 7 Jun 2023 19:23:21 -0400 Subject: [PATCH 1/7] chore(deps): upgrade sqlalchemy Signed-off-by: Mike Fiedler --- requirements/main.in | 2 +- requirements/main.txt | 85 ++++++++++++++++++++++--------------------- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/requirements/main.in b/requirements/main.in index 65a16b0a8547..bbb740a973fe 100644 --- a/requirements/main.in +++ b/requirements/main.in @@ -61,7 +61,7 @@ redis>=2.8.0,<5.0.0 rfc3986 sentry-sdk setuptools -sqlalchemy[asyncio]>=0.9,<1.5.0 # https://github.com/pypi/warehouse/pull/9228 +sqlalchemy[asyncio]>=2.0,<3.0 sqlalchemy-citext stdlib-list stripe diff --git a/requirements/main.txt b/requirements/main.txt index 74512512181b..5866544d9dc6 100644 --- a/requirements/main.txt +++ b/requirements/main.txt @@ -1411,48 +1411,48 @@ six==1.16.0 \ # pymacaroons # python-dateutil # requests-aws4auth -sqlalchemy[asyncio]==1.4.48 \ - --hash=sha256:005e942b451cad5285015481ae4e557ff4154dde327840ba91b9ac379be3b6ce \ - --hash=sha256:066c2b0413e8cb980e6d46bf9d35ca83be81c20af688fedaef01450b06e4aa5e \ - --hash=sha256:0817c181271b0ce5df1aa20949f0a9e2426830fed5ecdcc8db449618f12c2730 \ - --hash=sha256:11c6b1de720f816c22d6ad3bbfa2f026f89c7b78a5c4ffafb220e0183956a92a \ - --hash=sha256:1fd8b5ee5a3acc4371f820934b36f8109ce604ee73cc668c724abb054cebcb6e \ - --hash=sha256:25887b4f716e085a1c5162f130b852f84e18d2633942c8ca40dfb8519367c14f \ - --hash=sha256:2b562e9d1e59be7833edf28b0968f156683d57cabd2137d8121806f38a9d58f4 \ - --hash=sha256:2b9af65cc58726129d8414fc1a1a650dcdd594ba12e9c97909f1f57d48e393d3 \ - --hash=sha256:2ee26276f12614d47cc07bc85490a70f559cba965fb178b1c45d46ffa8d73fda \ - --hash=sha256:2fc2ab4d9f6d9218a5caa4121bdcf1125303482a1cdcfcdbd8567be8518969c0 \ - --hash=sha256:3509159e050bd6d24189ec7af373359f07aed690db91909c131e5068176c5a5d \ - --hash=sha256:4355e5915844afdc5cf22ec29fba1010166e35dd94a21305f49020022167556b \ - --hash=sha256:44d29a3fc6d9c45962476b470a81983dd8add6ad26fdbfae6d463b509d5adcda \ - --hash=sha256:49c312bcff4728bffc6fb5e5318b8020ed5c8b958a06800f91859fe9633ca20e \ - --hash=sha256:4bac3aa3c3d8bc7408097e6fe8bf983caa6e9491c5d2e2488cfcfd8106f13b6a \ - --hash=sha256:5381ddd09a99638f429f4cbe1b71b025bed318f6a7b23e11d65f3eed5e181c33 \ - --hash=sha256:627e04a5d54bd50628fc8734d5fc6df2a1aa5962f219c44aad50b00a6cdcf965 \ - --hash=sha256:68413aead943883b341b2b77acd7a7fe2377c34d82e64d1840860247cec7ff7c \ - --hash=sha256:6dab89874e72a9ab5462997846d4c760cdb957958be27b03b49cf0de5e5c327c \ - --hash=sha256:6f82d8efea1ca92b24f51d3aea1a82897ed2409868a0af04247c8c1e4fef5890 \ - --hash=sha256:7ad2b0f6520ed5038e795cc2852eb5c1f20fa6831d73301ced4aafbe3a10e1f6 \ - --hash=sha256:87609f6d4e81a941a17e61a4c19fee57f795e96f834c4f0a30cee725fc3f81d9 \ - --hash=sha256:92e6133cf337c42bfee03ca08c62ba0f2d9695618c8abc14a564f47503157be9 \ - --hash=sha256:9af1db7a287ef86e0f5cd990b38da6bd9328de739d17e8864f1817710da2d217 \ - --hash=sha256:9c8cfe951ed074ba5e708ed29c45397a95c4143255b0d022c7c8331a75ae61f3 \ - --hash=sha256:9d9b55252d2ca42a09bcd10a697fa041e696def9dfab0b78c0aaea1485551a08 \ - --hash=sha256:a1fc046756cf2a37d7277c93278566ddf8be135c6a58397b4c940abf837011f4 \ - --hash=sha256:b47bc287096d989a0838ce96f7d8e966914a24da877ed41a7531d44b55cdb8df \ - --hash=sha256:c99bf13e07140601d111a7c6f1fc1519914dd4e5228315bbda255e08412f61a4 \ - --hash=sha256:cbbe8b8bffb199b225d2fe3804421b7b43a0d49983f81dc654d0431d2f855543 \ - --hash=sha256:ce7915eecc9c14a93b73f4e1c9d779ca43e955b43ddf1e21df154184f39748e5 \ - --hash=sha256:cef2e2abc06eab187a533ec3e1067a71d7bbec69e582401afdf6d8cad4ba3515 \ - --hash=sha256:d53cd8bc582da5c1c8c86b6acc4ef42e20985c57d0ebc906445989df566c5603 \ - --hash=sha256:dbcae0e528d755f4522cad5842f0942e54b578d79f21a692c44d91352ea6d64e \ - --hash=sha256:e1ddbbcef9bcedaa370c03771ebec7e39e3944782bef49e69430383c376a250b \ - --hash=sha256:e3e98d4907805b07743b583a99ecc58bf8807ecb6985576d82d5e8ae103b5272 \ - --hash=sha256:eb5464ee8d4bb6549d368b578e9529d3c43265007193597ddca71c1bae6174e6 \ - --hash=sha256:eee09350fd538e29cfe3a496ec6f148504d2da40dbf52adefb0d2f8e4d38ccc4 \ - --hash=sha256:fb0808ad34167f394fea21bd4587fc62f3bd81bba232a1e7fbdfa17e6cfa7cd7 \ - --hash=sha256:fbde5642104ac6e95f96e8ad6d18d9382aa20672008cf26068fe36f3004491df \ - --hash=sha256:fe1dd2562313dd9fe1778ed56739ad5d9aae10f9f43d9f4cf81d65b0c85168bb +sqlalchemy[asyncio]==2.0.16 \ + --hash=sha256:0db6734cb5644c55d0262a813b764c6e2cda1e66e939a488b3d6298cdc7344c2 \ + --hash=sha256:0e4645b260cfe375a0603aa117f0a47680864cf37833129da870919e88b08d8f \ + --hash=sha256:131f0c894c6572cb1bdcf97c92d999d3128c4ff1ca13061296057072f61afe13 \ + --hash=sha256:1e2caba78e7d1f5003e88817b7a1754d4e58f4a8f956dc423bf8e304c568ab09 \ + --hash=sha256:2de1477af7f48c633b8ecb88245aedd811dca88e88aee9e9d787b388abe74c44 \ + --hash=sha256:2f3b6c31b915159b96b68372212fa77f69230b0a32acab40cf539d2823954f5a \ + --hash=sha256:3ef876615ff4b53e2033022195830ec4941a6e21068611f8d77de60203b90a98 \ + --hash=sha256:43e69c8c1cea0188b7094e22fb93ae1a1890aac748628b7e925024a206f75368 \ + --hash=sha256:53081c6fce0d49bb36d05f12dc87e008c9b0df58a163b792c5fc4ac638925f98 \ + --hash=sha256:5a934eff1a2882137be3384826f997db8441d43b61fda3094923e69fffe474be \ + --hash=sha256:5e8522b49e0e640287308b68f71cc338446bbe1c226c8f81743baa91b0246e92 \ + --hash=sha256:61f2035dea56ff1a429077e481496f813378beb02b823d2e3e7eb05bc1a7a8ca \ + --hash=sha256:63ea36c08792a7a8a08958bc806ecff6b491386feeaf14607c3d9d2d9325e67f \ + --hash=sha256:6e85e315725807c127ad8ba3d628fdb861cf9ebfb0e10c39a97c01e257cdd71b \ + --hash=sha256:7641f6ed2682de84d77c4894cf2e43700f3cf7a729361d7f9cac98febf3d8614 \ + --hash=sha256:7be04dbe3470fe8dd332fdb48c979887c381ef6c635eddf2dec43d2766111be4 \ + --hash=sha256:81d867c1be5abd49f7e547c108391f371a9d980ba7ec34666c50d683f782b754 \ + --hash=sha256:8544c6e62eacb77d5106e2055ef10f2407fc0dbd547e879f8745b2032eefd2bc \ + --hash=sha256:8d3cbdb2f07fb0e4b897dc1df39166735e194fb946f28f26f4c9f9801c8b24f7 \ + --hash=sha256:8d6ef848e5afcd1bda3e9a843751f845c0ca888b61e669237680e913d84ec206 \ + --hash=sha256:8e2569dac4e3cb85365b91ab569d06a221e0e17e65ce59949d00c3958946282b \ + --hash=sha256:90d320fde566b864adbc19abb40ecb80f4e25d6f084639969bb972d5cca16858 \ + --hash=sha256:91eb8f89fcce8f709f8a4d65d265bc48a80264ee14c7c9e955f3222f19b4b39c \ + --hash=sha256:a08a791c75d6154d46914d1e23bd81d9455f2950ec1de81f2723848c593d2c8b \ + --hash=sha256:a2e9f50a906d0b81292576a9fb458f8cace904c81a67088f4a2ca9ff2856f55d \ + --hash=sha256:a5a2856e12cf5f54301ddf043bcbf0552561d61555e1bcf348b63f42b8e1eec2 \ + --hash=sha256:b2801f85c5c0293aa710f8aa5262c707a83c1c203962ae5a22b4d9095e71aa9d \ + --hash=sha256:b72f4e4def50414164a1d899f2ce4e782a029fad0ed5585981d1611e8ae29a74 \ + --hash=sha256:bdaf89dd82f4a0e1b8b5ffc9cdc0c9551be6175f7eee5af6a838e92ba2e57100 \ + --hash=sha256:c5e333b81fe10d14efebd4e9429b7bb865ed9463ca8bef07a7136dfa1fd4a37b \ + --hash=sha256:ce1fc3f64fd42d5f763d6b83651471f32920338a1ba107a3186211474861af57 \ + --hash=sha256:d0c96592f54edd571e00ba6b1ed5df8263328ca1da9e78088c0ebc93c2e6562c \ + --hash=sha256:dc97238fa44be86971270943a0c21c19ce18b8d1596919048e57912e8abc02cc \ + --hash=sha256:e19546924f0cf2ec930d1faf318b7365e5827276410a513340f31a2b423e96a4 \ + --hash=sha256:f2938edc512dd1fa48653e14c1655ab46144d4450f0e6b33da7acd8ba77fbfd7 \ + --hash=sha256:f387b496a4c9474d8580195bb2660264a3f295a04d3a9d00f4fa15e9e597427e \ + --hash=sha256:f409f35a0330ab0cb18ece736b86d8b8233c64f4461fcb10993f67afc0ac7e5a \ + --hash=sha256:f662cf69484c59f8a3435902c40dfc34d86050bdb15e23d437074ce9f153306b \ + --hash=sha256:fbcc51fdbc89fafe4f4fe66f59372a8be88ded04de34ef438ab04f980beb12d4 \ + --hash=sha256:fc1dae11bd5167f9eb53b3ccad24a79813004612141e76de21cf4c028dc30b34 \ + --hash=sha256:ff6496ad5e9dc8baeb93a151cc2f599d01e5f8928a2aaf0b09a06428fdbaf553 # via # -r requirements/main.in # alembic @@ -1514,6 +1514,7 @@ typing-extensions==4.6.3 \ # alembic # limits # pydantic + # sqlalchemy ua-parser==0.16.1 \ --hash=sha256:ed3efc695f475ffe56248c9789b3016247e9c20e3556cfa4d5aadc78ab4b26c6 \ --hash=sha256:f97126300df8ac0f8f2c9d8559669532d626a1af529265fd253cba56e73ab36e From bb83a751fc101830dfe9f20143a4844da8c9b1be Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Wed, 14 Jun 2023 12:02:27 -0400 Subject: [PATCH 2/7] refactor: use sqlalchemy CITEXT We no longer need the unmaintained extension, as SQLAlchemy 2.0 provides the CITEXT extension. Signed-off-by: Mike Fiedler --- pyproject.toml | 2 -- requirements/main.in | 1 - requirements/main.txt | 4 --- warehouse/accounts/models.py | 5 ++- warehouse/cli/db/dbml.py | 5 ++- ...1ff3d24c22_add_malware_detection_tables.py | 3 +- ...0977b97fce94_add_file_blake2_256_digest.py | 4 +-- .../versions/283c68f2ab2_initial_migration.py | 34 +++++++++---------- ...de1_add_metadata_digest_column_to_files.py | 6 ++-- ...adcb_make_users_optional_with_macaroons.py | 9 +++-- ...36b1853f0_remove_malware_infrastructure.py | 3 +- ...a1bf519_add_a_column_for_sha256_digests.py | 6 ++-- ...ensure_file_md5_blake2_256__digest_are_.py | 6 ++-- warehouse/packaging/models.py | 13 ++++--- 14 files changed, 45 insertions(+), 56 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7b6b46f6270b..a33d4ac3f36e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,6 @@ module = [ "b2sdk.*", # https://github.com/Backblaze/b2-sdk-python/issues/148 "celery.app.backends.*", "celery.backends.redis.*", - "citext.*", "disposable_email_domains.*", "elasticsearch_dsl.*", # https://github.com/elastic/elasticsearch-dsl-py/issues/1533 "github_reserved_names.*", @@ -70,5 +69,4 @@ filterwarnings = [ 'ignore::warehouse.admin.services.InsecureStorageWarning', 'ignore::warehouse.utils.exceptions.InsecureOIDCPublisherWarning', 'ignore::warehouse.packaging.services.InsecureStorageWarning', - 'ignore:UserDefinedType CIText.*:sqlalchemy.exc.SAWarning' # See https://github.com/mahmoudimus/sqlalchemy-citext/issues/25 ] diff --git a/requirements/main.in b/requirements/main.in index bbb740a973fe..71aa865f1220 100644 --- a/requirements/main.in +++ b/requirements/main.in @@ -62,7 +62,6 @@ rfc3986 sentry-sdk setuptools sqlalchemy[asyncio]>=2.0,<3.0 -sqlalchemy-citext stdlib-list stripe structlog diff --git a/requirements/main.txt b/requirements/main.txt index 5866544d9dc6..1f95c8426564 100644 --- a/requirements/main.txt +++ b/requirements/main.txt @@ -1457,11 +1457,7 @@ sqlalchemy[asyncio]==2.0.16 \ # -r requirements/main.in # alembic # paginate-sqlalchemy - # sqlalchemy-citext # zope-sqlalchemy -sqlalchemy-citext==1.8.0 \ - --hash=sha256:a1740e693a9a334e7c8f60ae731083fe75ce6c1605bb9ca6644a6f1f63b15b77 - # via -r requirements/main.in stdlib-list==0.8.0 \ --hash=sha256:2ae0712a55b68f3fbbc9e58d6fa1b646a062188f49745b495f94d3310a9fdd3e \ --hash=sha256:a1e503719720d71e2ed70ed809b385c60cd3fb555ba7ec046b96360d30b16d9f diff --git a/warehouse/accounts/models.py b/warehouse/accounts/models.py index 5aad274d43f5..19a4321f154e 100644 --- a/warehouse/accounts/models.py +++ b/warehouse/accounts/models.py @@ -13,7 +13,6 @@ import datetime import enum -from citext import CIText from pyramid.authorization import Allow, Authenticated from sqlalchemy import ( Boolean, @@ -32,7 +31,7 @@ select, sql, ) -from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.dialects.postgresql import CITEXT, UUID from sqlalchemy.exc import NoResultFound from sqlalchemy.ext.hybrid import hybrid_property @@ -71,7 +70,7 @@ class User(SitemapMixin, HasEvents, db.Model): __repr__ = make_repr("username") - username = Column(CIText, nullable=False, unique=True) + username = Column(CITEXT, nullable=False, unique=True) name = Column(String(length=100), nullable=False) password = Column(String(length=128), nullable=False) password_date = Column(TZDateTime, nullable=True, server_default=sql.func.now()) diff --git a/warehouse/cli/db/dbml.py b/warehouse/cli/db/dbml.py index 058e4b44c272..e8f3a3c37a79 100644 --- a/warehouse/cli/db/dbml.py +++ b/warehouse/cli/db/dbml.py @@ -17,9 +17,8 @@ import click -from citext import CIText from sqlalchemy.dialects.postgresql.array import ARRAY -from sqlalchemy.dialects.postgresql.base import INET, TIMESTAMP, UUID +from sqlalchemy.dialects.postgresql.base import CITEXT, INET, TIMESTAMP, UUID from sqlalchemy.dialects.postgresql.json import JSONB from sqlalchemy.sql.schema import ForeignKey, Table from sqlalchemy.sql.sqltypes import ( @@ -66,7 +65,7 @@ UUID: "varchar", INET: "varchar", JSONB: "text", - CIText: "text", + CITEXT: "text", TZDateTime: "datetime", ARRAY: '"string[]"', TIMESTAMP: "datetime", diff --git a/warehouse/migrations/versions/061ff3d24c22_add_malware_detection_tables.py b/warehouse/migrations/versions/061ff3d24c22_add_malware_detection_tables.py index e7f930cb721e..3fbb144782ee 100644 --- a/warehouse/migrations/versions/061ff3d24c22_add_malware_detection_tables.py +++ b/warehouse/migrations/versions/061ff3d24c22_add_malware_detection_tables.py @@ -16,7 +16,6 @@ Revises: b5bb5d08543d Create Date: 2019-12-18 17:27:00.183542 """ -import citext import sqlalchemy as sa from alembic import op @@ -50,7 +49,7 @@ def upgrade(): server_default=sa.text("gen_random_uuid()"), nullable=False, ), - sa.Column("name", citext.CIText(), nullable=False), + sa.Column("name", postgresql.CITEXT(), nullable=False), sa.Column("version", sa.Integer(), default=1, nullable=False), sa.Column("short_description", sa.String(length=128), nullable=False), sa.Column("long_description", sa.Text(), nullable=False), diff --git a/warehouse/migrations/versions/0977b97fce94_add_file_blake2_256_digest.py b/warehouse/migrations/versions/0977b97fce94_add_file_blake2_256_digest.py index b1a6c789b90e..e205faf44fef 100644 --- a/warehouse/migrations/versions/0977b97fce94_add_file_blake2_256_digest.py +++ b/warehouse/migrations/versions/0977b97fce94_add_file_blake2_256_digest.py @@ -17,10 +17,10 @@ Create Date: 2016-04-18 20:40:22.101245 """ -import citext import sqlalchemy as sa from alembic import op +from sqlalchemy.dialects.postgresql import CITEXT revision = "0977b97fce94" down_revision = "f46672a776f1" @@ -28,7 +28,7 @@ def upgrade(): op.add_column( - "release_files", sa.Column("blake2_256_digest", citext.CIText(), nullable=True) + "release_files", sa.Column("blake2_256_digest", CITEXT(), nullable=True) ) op.create_unique_constraint(None, "release_files", ["blake2_256_digest"]) op.create_check_constraint( diff --git a/warehouse/migrations/versions/283c68f2ab2_initial_migration.py b/warehouse/migrations/versions/283c68f2ab2_initial_migration.py index 02240ec87ff5..c6f7653a07b5 100644 --- a/warehouse/migrations/versions/283c68f2ab2_initial_migration.py +++ b/warehouse/migrations/versions/283c68f2ab2_initial_migration.py @@ -17,10 +17,10 @@ Create Date: 2015-02-01 14:07:10.983672 """ -import citext import sqlalchemy as sa from alembic import op +from sqlalchemy.dialects.postgresql import CITEXT revision = "283c68f2ab2" down_revision = None @@ -45,7 +45,7 @@ def upgrade(): sa.Column("password", sa.String(length=128), nullable=False), sa.Column("last_login", sa.DateTime(), nullable=False), sa.Column("is_superuser", sa.Boolean(), nullable=False), - sa.Column("username", citext.CIText(), nullable=False), + sa.Column("username", CITEXT(), nullable=False), sa.Column("name", sa.String(length=100), nullable=False), sa.Column("is_staff", sa.Boolean(), nullable=False), sa.Column("is_active", sa.Boolean(), nullable=False), @@ -249,7 +249,7 @@ def upgrade(): op.create_table( "mirrors", sa.Column("ip", sa.Text(), nullable=False), - sa.Column("user_name", citext.CIText(), nullable=True), + sa.Column("user_name", CITEXT(), nullable=True), sa.Column("index_url", sa.Text(), nullable=True), sa.Column("last_modified_url", sa.Text(), nullable=True), sa.Column("local_stats_url", sa.Text(), nullable=True), @@ -264,7 +264,7 @@ def upgrade(): sa.Column("consumer", sa.String(length=32), nullable=False), sa.Column("secret", sa.String(length=64), nullable=False), sa.Column("date_created", sa.Date(), nullable=False), - sa.Column("created_by", citext.CIText(), nullable=True), + sa.Column("created_by", CITEXT(), nullable=True), sa.Column("last_modified", sa.Date(), nullable=False), sa.Column("description", sa.String(length=255), nullable=False), sa.ForeignKeyConstraint( @@ -302,7 +302,7 @@ def upgrade(): sa.Column("consumer", sa.String(length=32), nullable=False), sa.Column("date_created", sa.Date(), nullable=False), sa.Column("last_modified", sa.Date(), nullable=False), - sa.Column("user_name", citext.CIText(), nullable=True), + sa.Column("user_name", CITEXT(), nullable=True), sa.ForeignKeyConstraint( ["user_name"], ["accounts_user.username"], @@ -314,7 +314,7 @@ def upgrade(): op.create_table( "csrf_tokens", - sa.Column("name", citext.CIText(), nullable=False), + sa.Column("name", CITEXT(), nullable=False), sa.Column("token", sa.Text(), nullable=True), sa.Column("end_date", sa.DateTime(), nullable=True), sa.ForeignKeyConstraint( @@ -330,7 +330,7 @@ def upgrade(): sa.Column("consumer", sa.String(length=32), nullable=False), sa.Column("callback", sa.Text(), nullable=True), sa.Column("date_created", sa.Date(), nullable=False), - sa.Column("user_name", citext.CIText(), nullable=True), + sa.Column("user_name", CITEXT(), nullable=True), sa.ForeignKeyConstraint( ["user_name"], ["accounts_user.username"], @@ -343,7 +343,7 @@ def upgrade(): op.create_table( "cookies", sa.Column("cookie", sa.Text(), nullable=False), - sa.Column("name", citext.CIText(), nullable=True), + sa.Column("name", CITEXT(), nullable=True), sa.Column("last_seen", sa.DateTime(), nullable=True), sa.ForeignKeyConstraint( ["name"], ["accounts_user.username"], onupdate="CASCADE", ondelete="CASCADE" @@ -356,7 +356,7 @@ def upgrade(): op.create_table( "openids", sa.Column("id", sa.Text(), nullable=False), - sa.Column("name", citext.CIText(), nullable=True), + sa.Column("name", CITEXT(), nullable=True), sa.ForeignKeyConstraint( ["name"], ["accounts_user.username"], onupdate="CASCADE", ondelete="CASCADE" ), @@ -366,7 +366,7 @@ def upgrade(): op.create_table( "sshkeys", sa.Column("id", sa.Integer(), nullable=False), - sa.Column("name", citext.CIText(), nullable=True), + sa.Column("name", CITEXT(), nullable=True), sa.Column("key", sa.Text(), nullable=True), sa.ForeignKeyConstraint( ["name"], ["accounts_user.username"], onupdate="CASCADE", ondelete="CASCADE" @@ -378,7 +378,7 @@ def upgrade(): op.create_table( "rego_otk", - sa.Column("name", citext.CIText(), nullable=True), + sa.Column("name", CITEXT(), nullable=True), sa.Column("otk", sa.Text(), nullable=True), sa.Column("date", sa.DateTime(), nullable=True), sa.ForeignKeyConstraint( @@ -405,7 +405,7 @@ def upgrade(): "accounts_gpgkey", sa.Column("id", sa.Integer(), nullable=False), sa.Column("user_id", sa.Integer(), nullable=False), - sa.Column("key_id", citext.CIText(), nullable=False), + sa.Column("key_id", CITEXT(), nullable=False), sa.Column("verified", sa.Boolean(), nullable=False), sa.CheckConstraint( "key_id ~* '^[A-F0-9]{8}$'::citext", name="accounts_gpgkey_valid_key_id" @@ -424,7 +424,7 @@ def upgrade(): op.create_table( "roles", sa.Column("role_name", sa.Text(), nullable=True), - sa.Column("user_name", citext.CIText(), nullable=True), + sa.Column("user_name", CITEXT(), nullable=True), sa.Column("package_name", sa.Text(), nullable=True), sa.ForeignKeyConstraint( ["package_name"], ["packages.name"], onupdate="CASCADE" @@ -445,7 +445,7 @@ def upgrade(): sa.Column("version", sa.Text(), nullable=True), sa.Column("action", sa.Text(), nullable=True), sa.Column("submitted_date", sa.DateTime(), nullable=True), - sa.Column("submitted_by", citext.CIText(), nullable=True), + sa.Column("submitted_by", CITEXT(), nullable=True), sa.Column("submitted_from", sa.Text(), nullable=True), sa.ForeignKeyConstraint( ["submitted_by"], ["accounts_user.username"], onupdate="CASCADE" @@ -481,7 +481,7 @@ def upgrade(): sa.Column("id", sa.Integer(), nullable=False), sa.Column("name", sa.Text(), nullable=False), sa.Column("version", sa.Text(), nullable=False), - sa.Column("user_name", citext.CIText(), nullable=False), + sa.Column("user_name", CITEXT(), nullable=False), sa.Column("date", sa.DateTime(), nullable=True), sa.Column("rating", sa.Integer(), nullable=True), sa.ForeignKeyConstraint( @@ -586,7 +586,7 @@ def upgrade(): sa.Column("name", sa.Text(), nullable=True), sa.Column("version", sa.Text(), nullable=True), sa.Column("id", sa.Integer(), nullable=True), - sa.Column("submitted_by", citext.CIText(), nullable=True), + sa.Column("submitted_by", CITEXT(), nullable=True), sa.Column("date", sa.DateTime(), nullable=True), sa.Column("action", sa.Text(), nullable=True), sa.ForeignKeyConstraint( @@ -698,7 +698,7 @@ def upgrade(): "comments", sa.Column("id", sa.Integer(), nullable=False), sa.Column("rating", sa.Integer(), nullable=True), - sa.Column("user_name", citext.CIText(), nullable=True), + sa.Column("user_name", CITEXT(), nullable=True), sa.Column("date", sa.DateTime(), nullable=True), sa.Column("message", sa.Text(), nullable=True), sa.Column("in_reply_to", sa.Integer(), nullable=True), diff --git a/warehouse/migrations/versions/2b2f58288de1_add_metadata_digest_column_to_files.py b/warehouse/migrations/versions/2b2f58288de1_add_metadata_digest_column_to_files.py index 4e0cf2d884ef..4239cc9e4d60 100644 --- a/warehouse/migrations/versions/2b2f58288de1_add_metadata_digest_column_to_files.py +++ b/warehouse/migrations/versions/2b2f58288de1_add_metadata_digest_column_to_files.py @@ -17,10 +17,10 @@ Create Date: 2023-05-11 14:25:53.582849 """ -import citext import sqlalchemy as sa from alembic import op +from sqlalchemy.dialects.postgresql import CITEXT revision = "2b2f58288de1" down_revision = "fd0479fed881" @@ -29,11 +29,11 @@ def upgrade(): op.add_column( "release_files", - sa.Column("metadata_file_sha256_digest", citext.CIText(), nullable=True), + sa.Column("metadata_file_sha256_digest", CITEXT(), nullable=True), ) op.add_column( "release_files", - sa.Column("metadata_file_blake2_256_digest", citext.CIText(), nullable=True), + sa.Column("metadata_file_blake2_256_digest", CITEXT(), nullable=True), ) diff --git a/warehouse/migrations/versions/43bf0b6badcb_make_users_optional_with_macaroons.py b/warehouse/migrations/versions/43bf0b6badcb_make_users_optional_with_macaroons.py index 135891fbf34b..47be10cdbc06 100644 --- a/warehouse/migrations/versions/43bf0b6badcb_make_users_optional_with_macaroons.py +++ b/warehouse/migrations/versions/43bf0b6badcb_make_users_optional_with_macaroons.py @@ -20,7 +20,6 @@ import sqlalchemy as sa from alembic import op -from citext import CIText from sqlalchemy.dialects import postgresql revision = "43bf0b6badcb" @@ -49,7 +48,9 @@ def upgrade(): ) # JournalEvent users are now optional. - op.alter_column("journals", "submitted_by", existing_type=CIText(), nullable=True) + op.alter_column( + "journals", "submitted_by", existing_type=postgresql.CITEXT(), nullable=True + ) # Macaroon -> (User XOR OIDCProvider) op.create_check_constraint( @@ -64,4 +65,6 @@ def downgrade(): "macaroons", "user_id", existing_type=postgresql.UUID(), nullable=False ) - op.alter_column("journals", "submitted_by", existing_type=CIText(), nullable=False) + op.alter_column( + "journals", "submitted_by", existing_type=postgresql.CITEXT(), nullable=False + ) diff --git a/warehouse/migrations/versions/ab536b1853f0_remove_malware_infrastructure.py b/warehouse/migrations/versions/ab536b1853f0_remove_malware_infrastructure.py index f36c86990742..f4e2f9e9eded 100644 --- a/warehouse/migrations/versions/ab536b1853f0_remove_malware_infrastructure.py +++ b/warehouse/migrations/versions/ab536b1853f0_remove_malware_infrastructure.py @@ -17,7 +17,6 @@ Create Date: 2023-05-19 13:46:26.093351 """ -import citext import sqlalchemy as sa from alembic import op @@ -130,7 +129,7 @@ def downgrade(): autoincrement=False, nullable=False, ), - sa.Column("name", citext.CIText(), autoincrement=False, nullable=False), + sa.Column("name", postgresql.CITEXT(), autoincrement=False, nullable=False), sa.Column("version", sa.INTEGER(), autoincrement=False, nullable=False), sa.Column( "short_description", diff --git a/warehouse/migrations/versions/d8301a1bf519_add_a_column_for_sha256_digests.py b/warehouse/migrations/versions/d8301a1bf519_add_a_column_for_sha256_digests.py index c8834044148b..2b26b2c21b5f 100644 --- a/warehouse/migrations/versions/d8301a1bf519_add_a_column_for_sha256_digests.py +++ b/warehouse/migrations/versions/d8301a1bf519_add_a_column_for_sha256_digests.py @@ -17,19 +17,17 @@ Create Date: 2016-01-04 13:51:16.931595 """ -import citext import sqlalchemy as sa from alembic import op +from sqlalchemy.dialects.postgresql import CITEXT revision = "d8301a1bf519" down_revision = "477bc785c999" def upgrade(): - op.add_column( - "release_files", sa.Column("sha256_digest", citext.CIText(), nullable=True) - ) + op.add_column("release_files", sa.Column("sha256_digest", CITEXT(), nullable=True)) op.create_unique_constraint(None, "release_files", ["sha256_digest"]) op.create_check_constraint( None, "release_files", "sha256_digest ~* '^[A-F0-9]{64}$'" diff --git a/warehouse/migrations/versions/fb3278418206_ensure_file_md5_blake2_256__digest_are_.py b/warehouse/migrations/versions/fb3278418206_ensure_file_md5_blake2_256__digest_are_.py index c64f82eaef77..b21889c2d25b 100644 --- a/warehouse/migrations/versions/fb3278418206_ensure_file_md5_blake2_256__digest_are_.py +++ b/warehouse/migrations/versions/fb3278418206_ensure_file_md5_blake2_256__digest_are_.py @@ -17,10 +17,10 @@ Create Date: 2016-04-25 11:09:54.284023 """ -import citext import sqlalchemy as sa from alembic import op +from sqlalchemy.dialects.postgresql import CITEXT revision = "fb3278418206" down_revision = "0977b97fce94" @@ -30,7 +30,7 @@ def upgrade(): op.alter_column( "release_files", "blake2_256_digest", - existing_type=citext.CIText(), + existing_type=CITEXT(), nullable=False, ) op.alter_column( @@ -45,6 +45,6 @@ def downgrade(): op.alter_column( "release_files", "blake2_256_digest", - existing_type=citext.CIText(), + existing_type=CITEXT(), nullable=True, ) diff --git a/warehouse/packaging/models.py b/warehouse/packaging/models.py index f2ec348080b4..4bae76b2b2b1 100644 --- a/warehouse/packaging/models.py +++ b/warehouse/packaging/models.py @@ -17,7 +17,6 @@ import packaging.utils -from citext import CIText from github_reserved_names import ALL as GITHUB_RESERVED_NAMES from pyramid.authorization import Allow from pyramid.threadlocal import get_current_request @@ -40,7 +39,7 @@ orm, sql, ) -from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.dialects.postgresql import CITEXT, UUID from sqlalchemy.exc import MultipleResultsFound, NoResultFound from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.declarative import declared_attr # type: ignore @@ -664,14 +663,14 @@ def __table_args__(cls): # noqa path = Column(Text, unique=True, nullable=False) size = Column(Integer) md5_digest = Column(Text, unique=True, nullable=False) - sha256_digest = Column(CIText, unique=True, nullable=False) - blake2_256_digest = Column(CIText, unique=True, nullable=False) + sha256_digest = Column(CITEXT, unique=True, nullable=False) + blake2_256_digest = Column(CITEXT, unique=True, nullable=False) upload_time = Column(DateTime(timezone=False), server_default=func.now()) uploaded_via = Column(Text) # PEP 658 - metadata_file_sha256_digest = Column(CIText, nullable=True) - metadata_file_blake2_256_digest = Column(CIText, nullable=True) + metadata_file_sha256_digest = Column(CITEXT, nullable=True) + metadata_file_blake2_256_digest = Column(CITEXT, nullable=True) # We need this column to allow us to handle the currently existing "double" # sdists that exist in our database. Eventually we should try to get rid @@ -747,7 +746,7 @@ def __table_args__(cls): # noqa ) _submitted_by = Column( "submitted_by", - CIText, + CITEXT, ForeignKey("users.username", onupdate="CASCADE"), nullable=True, ) From 343bec66fbf510eacdf64cd8866d1a2b396512e8 Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Tue, 13 Jun 2023 11:45:15 -0400 Subject: [PATCH 3/7] refactor: update orm imports Per https://docs.sqlalchemy.org/en/20/changelog/migration_20.html#declarative-becomes-a-first-class-api Signed-off-by: Mike Fiedler --- warehouse/organizations/models.py | 2 +- warehouse/packaging/models.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/warehouse/organizations/models.py b/warehouse/organizations/models.py index 5a258597d760..216acabc62a7 100644 --- a/warehouse/organizations/models.py +++ b/warehouse/organizations/models.py @@ -32,7 +32,7 @@ ) from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.exc import NoResultFound -from sqlalchemy.ext.declarative import declared_attr +from sqlalchemy.orm import declared_attr from warehouse import db from warehouse.accounts.models import User diff --git a/warehouse/packaging/models.py b/warehouse/packaging/models.py index 4bae76b2b2b1..ce64284ef8b0 100644 --- a/warehouse/packaging/models.py +++ b/warehouse/packaging/models.py @@ -42,10 +42,8 @@ from sqlalchemy.dialects.postgresql import CITEXT, UUID from sqlalchemy.exc import MultipleResultsFound, NoResultFound from sqlalchemy.ext.associationproxy import association_proxy -from sqlalchemy.ext.declarative import declared_attr # type: ignore from sqlalchemy.ext.hybrid import hybrid_property -from sqlalchemy.orm import validates -from sqlalchemy.orm.collections import attribute_mapped_collection +from sqlalchemy.orm import attribute_keyed_dict, declared_attr, validates from warehouse import db from warehouse.accounts.models import User @@ -487,7 +485,7 @@ def __table_args__(cls): # noqa _project_urls = orm.relationship( ReleaseURL, backref="release", - collection_class=attribute_mapped_collection("name"), + collection_class=attribute_keyed_dict("name"), cascade="all, delete-orphan", order_by=lambda: ReleaseURL.name.asc(), passive_deletes=True, From 7ffb872bcfdad7cc743fa459d37b486a14a294a8 Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Wed, 14 Jun 2023 16:08:17 -0400 Subject: [PATCH 4/7] test: update value order post-upgrade Signed-off-by: Mike Fiedler --- tests/unit/cli/test_db.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/cli/test_db.py b/tests/unit/cli/test_db.py index da2528d0256f..c8ce709390a1 100644 --- a/tests/unit/cli/test_db.py +++ b/tests/unit/cli/test_db.py @@ -364,20 +364,20 @@ def test_dbml_command(monkeypatch, cli): EXPECTED_DBML = """Table _clan { - id varchar [pk, not null, default: `gen_random_uuid()`] name text [unique, not null] fetched text [default: `FetchedValue()`, Note: "fetched value"] for_the_children boolean [default: `True`] nice varchar + id varchar [pk, not null, default: `gen_random_uuid()`] Note: "various clans" } Table _clan_member { - id varchar [pk, not null, default: `gen_random_uuid()`] name text [not null] clan_id varchar joined datetime [not null, default: `now()`] departed datetime + id varchar [pk, not null, default: `gen_random_uuid()`] } Ref: _clan_member.clan_id > _clan.id From 45a6bea0ac406e328fa72edc6bd8d4f3810632bd Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Tue, 13 Jun 2023 11:10:17 -0400 Subject: [PATCH 5/7] lint: add sqlalchemy built-in plugin Add comment about order. If reversed, then we get 300+ errors about interface signature mismatches wanting to have `self` which they shouldn't. Signed-off-by: Mike Fiedler --- pyproject.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a33d4ac3f36e..0560c126f761 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,9 @@ known_first_party = ['warehouse', 'tests'] python_version = "3.11" namespace_packages = true warn_unused_configs = true -plugins = ["mypy_zope:plugin"] +# Plugin order matters. `mypy_zope` must come before `sqlalchemy` to prevent +# false-positive signature mismatch errors for `zope.interface` instances. +plugins = ["mypy_zope:plugin", "sqlalchemy.ext.mypy.plugin"] exclude = ["warehouse/locale/.*", "warehouse/migrations/versions.*"] [[tool.mypy.overrides]] @@ -45,7 +47,6 @@ module = [ "pyqrcode.*", "requests_aws4auth.*", # https://github.com/tedder/requests-aws4auth/issues/53 "rfc3986.*", - "sqlalchemy.*", # https://docs.sqlalchemy.org/en/14/orm/extensions/mypy.html "transaction.*", "ua_parser.*", # https://github.com/ua-parser/uap-python/issues/110 "venusian.*", From aac9dba1f619ee0bfd4a597c6763fcac9fab7fde Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Wed, 14 Jun 2023 16:29:55 -0400 Subject: [PATCH 6/7] lint: disable model violations SQLAchemy 2.0 wants us to use the `DeclarativeBase` approach to take advantage of PEP-484 type hints and mappings. The way we implemented `Event/HasEvents` makes this upgrade path challenging - the code works, but the type hints don't match up yet. Disable all the violations surfaced from our lint step, as a deferral to come back and convert more of the models over to 2.0 declarative style. Refs: https://docs.sqlalchemy.org/en/20/changelog/whatsnew_20.html Signed-off-by: Mike Fiedler --- warehouse/accounts/models.py | 4 +- warehouse/cli/db/dbml.py | 8 ++-- warehouse/email/ses/models.py | 8 ++-- warehouse/events/models.py | 4 +- .../integrations/vulnerabilities/models.py | 6 +-- warehouse/ip_addresses/models.py | 2 +- warehouse/organizations/models.py | 42 +++++++++---------- warehouse/packaging/models.py | 24 +++++------ warehouse/subscriptions/models.py | 4 +- 9 files changed, 51 insertions(+), 51 deletions(-) diff --git a/warehouse/accounts/models.py b/warehouse/accounts/models.py index 19a4321f154e..cac718b9373c 100644 --- a/warehouse/accounts/models.py +++ b/warehouse/accounts/models.py @@ -85,7 +85,7 @@ class User(SitemapMixin, HasEvents, db.Model): hide_avatar = Column(Boolean, nullable=False, server_default=sql.false()) date_joined = Column(DateTime, server_default=sql.func.now()) last_login = Column(TZDateTime, nullable=False, server_default=sql.func.now()) - disabled_for = Column( + disabled_for = Column( # type: ignore[var-annotated] Enum(DisableReason, values_callable=lambda x: [e.value for e in x]), nullable=True, ) @@ -270,7 +270,7 @@ class Email(db.ModelBase): public = Column(Boolean, nullable=False, server_default=sql.false()) # Deliverability information - unverify_reason = Column( + unverify_reason = Column( # type: ignore[var-annotated] Enum(UnverifyReasons, values_callable=lambda x: [e.value for e in x]), nullable=True, ) diff --git a/warehouse/cli/db/dbml.py b/warehouse/cli/db/dbml.py index e8f3a3c37a79..5b622dfed4e1 100644 --- a/warehouse/cli/db/dbml.py +++ b/warehouse/cli/db/dbml.py @@ -157,11 +157,11 @@ def extract_table_info(table: Table) -> TableInfo: raise TypeError(type(column.type)) if column.default is not None: - default = column.default.arg + default = column.default.arg # type: ignore[attr-defined] elif column.server_default is not None: match str(type(column.server_default)): case "": - default = column.server_default.arg + default = column.server_default.arg # type: ignore[attr-defined] case _: default = column.server_default else: @@ -171,9 +171,9 @@ def extract_table_info(table: Table) -> TableInfo: "type": SQLALCHEMY_TO_DBML[column_type], "pk": column.primary_key, "unique": column.unique, - "nullable": column.nullable, + "nullable": column.nullable, # type: ignore[typeddict-item] "default": default, - "comment": column.comment, + "comment": column.comment, # type: ignore[typeddict-item] } for foreign_key in column.foreign_keys: table_info["relationships"].append( diff --git a/warehouse/email/ses/models.py b/warehouse/email/ses/models.py index 3fc5a2252a97..706d9c67b7a6 100644 --- a/warehouse/email/ses/models.py +++ b/warehouse/email/ses/models.py @@ -230,7 +230,7 @@ class EmailMessage(db.Model): __tablename__ = "ses_emails" created = Column(DateTime, nullable=False, server_default=sql.func.now()) - status = Column( + status = Column( # type: ignore[var-annotated] Enum(EmailStatuses, values_callable=lambda x: [e.value for e in x]), nullable=False, server_default=EmailStatuses.Accepted.value, @@ -273,10 +273,10 @@ class Event(db.Model): ) event_id = Column(Text, nullable=False, unique=True, index=True) - event_type = Column( + event_type = Column( # type: ignore[var-annotated] Enum(EventTypes, values_callable=lambda x: [e.value for e in x]), nullable=False ) - data = Column( - MutableDict.as_mutable(JSONB), nullable=False, server_default=sql.text("'{}'") + data = Column( # type: ignore[var-annotated] + MutableDict.as_mutable(JSONB), nullable=False, server_default=sql.text("'{}'") # type: ignore[arg-type] # noqa: E501 ) diff --git a/warehouse/events/models.py b/warehouse/events/models.py index fd65d3c88b25..e6f2a01fa267 100644 --- a/warehouse/events/models.py +++ b/warehouse/events/models.py @@ -176,7 +176,7 @@ def location_info(cls) -> str: # noqa: N805 Otherwise, return the `ip_address` and let its repr decide. """ if cls.additional is not None and "geoip_info" in cls.additional: - g = GeoIPInfo(**cls.additional["geoip_info"]) + g = GeoIPInfo(**cls.additional["geoip_info"]) # type: ignore[arg-type] if g.display(): return g.display() @@ -190,7 +190,7 @@ def user_agent_info(cls) -> str: # noqa: N805 Dig into `.additional` for `user_agent_info` and return that if it exists. """ if cls.additional is not None and "user_agent_info" in cls.additional: - return UserAgentInfo(**cls.additional["user_agent_info"]).display() + return UserAgentInfo(**cls.additional["user_agent_info"]).display() # type: ignore[arg-type] # noqa: E501 return "No User-Agent" diff --git a/warehouse/integrations/vulnerabilities/models.py b/warehouse/integrations/vulnerabilities/models.py index 8d8e8dc6ec45..c25b63c93f5a 100644 --- a/warehouse/integrations/vulnerabilities/models.py +++ b/warehouse/integrations/vulnerabilities/models.py @@ -44,7 +44,7 @@ ) -class VulnerabilityRecord(db.Model): +class VulnerabilityRecord(db.ModelBase): __tablename__ = "vulnerabilities" source = Column(String, primary_key=True) @@ -56,7 +56,7 @@ class VulnerabilityRecord(db.Model): # Alternative IDs for this vulnerability # e.g. "CVE-2021-12345" - aliases = Column(ARRAY(String)) + aliases = Column(ARRAY(String)) # type: ignore[var-annotated] # Details about the vulnerability details = Column(String) @@ -65,7 +65,7 @@ class VulnerabilityRecord(db.Model): summary = Column(String) # Events of introduced/fixed versions - fixed_in = Column(ARRAY(String)) + fixed_in = Column(ARRAY(String)) # type: ignore[var-annotated] # When the vulnerability was withdrawn, if it has been withdrawn. withdrawn = Column(TIMESTAMP, nullable=True) diff --git a/warehouse/ip_addresses/models.py b/warehouse/ip_addresses/models.py index 7c14b0438fd6..a1bf5f65e435 100644 --- a/warehouse/ip_addresses/models.py +++ b/warehouse/ip_addresses/models.py @@ -69,7 +69,7 @@ def __lt__(self, other): server_default=sql.false(), comment="If True, this IP Address will be marked as banned", ) - ban_reason = Column( + ban_reason = Column( # type: ignore[var-annotated] Enum(BanReason, values_callable=lambda x: [e.value for e in x]), nullable=True, comment="Reason for banning, must be in the BanReason enumeration", diff --git a/warehouse/organizations/models.py b/warehouse/organizations/models.py index 216acabc62a7..09e68321b13a 100644 --- a/warehouse/organizations/models.py +++ b/warehouse/organizations/models.py @@ -64,14 +64,14 @@ class OrganizationRole(db.Model): __repr__ = make_repr("role_name") - role_name = Column( + role_name = Column( # type: ignore[var-annotated] Enum(OrganizationRoleType, values_callable=lambda x: [e.value for e in x]), nullable=False, ) - user_id = Column( + user_id = Column( # type: ignore[var-annotated] ForeignKey("users.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False ) - organization_id = Column( + organization_id = Column( # type: ignore[var-annotated] ForeignKey("organizations.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) @@ -94,11 +94,11 @@ class OrganizationProject(db.Model): __repr__ = make_repr("project_id", "organization_id") - organization_id = Column( + organization_id = Column( # type: ignore[var-annotated] ForeignKey("organizations.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) - project_id = Column( + project_id = Column( # type: ignore[var-annotated] ForeignKey("projects.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) @@ -125,11 +125,11 @@ class OrganizationStripeSubscription(db.Model): __repr__ = make_repr("organization_id", "subscription_id") - organization_id = Column( + organization_id = Column( # type: ignore[var-annotated] ForeignKey("organizations.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) - subscription_id = Column( + subscription_id = Column( # type: ignore[var-annotated] ForeignKey("stripe_subscriptions.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) @@ -154,11 +154,11 @@ class OrganizationStripeCustomer(db.Model): __repr__ = make_repr("organization_id", "stripe_customer_id") - organization_id = Column( + organization_id = Column( # type: ignore[var-annotated] ForeignKey("organizations.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) - stripe_customer_id = Column( + stripe_customer_id = Column( # type: ignore[var-annotated] ForeignKey("stripe_customers.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) @@ -236,7 +236,7 @@ def normalized_name(cls): # noqa: N805 return orm.column_property(func.normalize_pep426_name(cls.name)) display_name = Column(Text, nullable=False, comment="Display name used in UI") - orgtype = Column( + orgtype = Column( # type: ignore[var-annotated] Enum(OrganizationType, values_callable=lambda x: [e.value for e in x]), nullable=False, comment="What type of organization such as Community or Company", @@ -525,19 +525,19 @@ class OrganizationInvitation(db.Model): __repr__ = make_repr("invite_status", "user", "organization") - invite_status = Column( + invite_status = Column( # type: ignore[var-annotated] Enum( OrganizationInvitationStatus, values_callable=lambda x: [e.value for e in x] ), nullable=False, ) token = Column(Text, nullable=False) - user_id = Column( + user_id = Column( # type: ignore[var-annotated] ForeignKey("users.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, index=True, ) - organization_id = Column( + organization_id = Column( # type: ignore[var-annotated] ForeignKey("organizations.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, index=True, @@ -565,14 +565,14 @@ class TeamRole(db.Model): __repr__ = make_repr("role_name", "team", "user") - role_name = Column( + role_name = Column( # type: ignore[var-annotated] Enum(TeamRoleType, values_callable=lambda x: [e.value for e in x]), nullable=False, ) - user_id = Column( + user_id = Column( # type: ignore[var-annotated] ForeignKey("users.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False ) - team_id = Column( + team_id = Column( # type: ignore[var-annotated] ForeignKey("teams.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) @@ -600,15 +600,15 @@ class TeamProjectRole(db.Model): __repr__ = make_repr("role_name", "team", "project") - role_name = Column( + role_name = Column( # type: ignore[var-annotated] Enum(TeamProjectRoleType, values_callable=lambda x: [e.value for e in x]), nullable=False, ) - project_id = Column( + project_id = Column( # type: ignore[var-annotated] ForeignKey("projects.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) - team_id = Column( + team_id = Column( # type: ignore[var-annotated] ForeignKey("teams.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) @@ -659,8 +659,8 @@ class Team(HasEvents, db.Model): __repr__ = make_repr("name", "organization") name = Column(Text, nullable=False) - normalized_name = orm.column_property(func.normalize_team_name(name)) - organization_id = Column( + normalized_name = orm.column_property(func.normalize_team_name(name)) # type: ignore[var-annotated] # noqa: E501 + organization_id = Column( # type: ignore[var-annotated] ForeignKey("organizations.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) diff --git a/warehouse/packaging/models.py b/warehouse/packaging/models.py index ce64284ef8b0..7471d2d49e5c 100644 --- a/warehouse/packaging/models.py +++ b/warehouse/packaging/models.py @@ -73,10 +73,10 @@ class Role(db.Model): __repr__ = make_repr("role_name") role_name = Column(Text, nullable=False) - user_id = Column( + user_id = Column( # type: ignore[var-annotated] ForeignKey("users.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False ) - project_id = Column( + project_id = Column( # type: ignore[var-annotated] ForeignKey("projects.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) @@ -101,17 +101,17 @@ class RoleInvitation(db.Model): __repr__ = make_repr("invite_status", "user", "project") - invite_status = Column( + invite_status = Column( # type: ignore[var-annotated] Enum(RoleInvitationStatus, values_callable=lambda x: [e.value for e in x]), nullable=False, ) token = Column(Text, nullable=False) - user_id = Column( + user_id = Column( # type: ignore[var-annotated] ForeignKey("users.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, index=True, ) - project_id = Column( + project_id = Column( # type: ignore[var-annotated] ForeignKey("projects.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, index=True, @@ -364,7 +364,7 @@ class Dependency(db.Model): ) __repr__ = make_repr("release", "kind", "specifier") - release_id = Column( + release_id = Column( # type: ignore[var-annotated] ForeignKey("releases.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) @@ -402,7 +402,7 @@ class ReleaseURL(db.Model): ) __repr__ = make_repr("name", "url") - release_id = Column( + release_id = Column( # type: ignore[var-annotated] ForeignKey("releases.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, index=True, @@ -429,7 +429,7 @@ def __table_args__(cls): # noqa __parent__ = dotted_navigator("project") __name__ = dotted_navigator("version") - project_id = Column( + project_id = Column( # type: ignore[var-annotated] ForeignKey("projects.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) @@ -452,7 +452,7 @@ def __table_args__(cls): # noqa DateTime(timezone=False), nullable=False, server_default=sql.func.now() ) - description_id = Column( + description_id = Column( # type: ignore[var-annotated] ForeignKey("release_descriptions.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, index=True, @@ -540,7 +540,7 @@ def __table_args__(cls): # noqa _requires_external = _dependency_relation(DependencyKind.requires_external) requires_external = association_proxy("_requires_external", "specifier") - uploader_id = Column( + uploader_id = Column( # type: ignore[var-annotated] ForeignKey("users.id", onupdate="CASCADE", ondelete="SET NULL"), nullable=True, index=True, @@ -638,13 +638,13 @@ def __table_args__(cls): # noqa Index("release_files_cached_idx", "cached"), ) - release_id = Column( + release_id = Column( # type: ignore[var-annotated] ForeignKey("releases.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) python_version = Column(Text) requires_python = Column(Text) - packagetype = Column( + packagetype = Column( # type: ignore[var-annotated] Enum( "bdist_dmg", "bdist_dumb", diff --git a/warehouse/subscriptions/models.py b/warehouse/subscriptions/models.py index ce24aeadb1dd..fa7c859c6f92 100644 --- a/warehouse/subscriptions/models.py +++ b/warehouse/subscriptions/models.py @@ -108,7 +108,7 @@ class StripeSubscription(db.Model): ), nullable=False, ) - status = Column( + status = Column( # type: ignore[var-annotated] Enum(StripeSubscriptionStatus, values_callable=lambda x: [e.value for e in x]), nullable=False, ) @@ -170,7 +170,7 @@ class StripeSubscriptionPrice(db.Model): ) unit_amount = Column(Integer, nullable=False) # positive integer in cents is_active = Column(Boolean, nullable=False, server_default=sql.true()) - recurring = Column( + recurring = Column( # type: ignore[var-annotated] Enum( StripeSubscriptionPriceInterval, values_callable=lambda x: [e.value for e in x], From 7cc98674362a9775f5176ef53040ec986eae8934 Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Wed, 14 Jun 2023 17:43:37 -0400 Subject: [PATCH 7/7] refactor: replace session usage Since we already have the `request` available in scope, use it instead of finding a new session object. Signed-off-by: Mike Fiedler --- tests/unit/accounts/test_services.py | 2 ++ warehouse/events/models.py | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/accounts/test_services.py b/tests/unit/accounts/test_services.py index 1ebcfe0f0874..0904e50e36de 100644 --- a/tests/unit/accounts/test_services.py +++ b/tests/unit/accounts/test_services.py @@ -480,6 +480,7 @@ def test_is_disabled(self, user_service, disabled, reason): remote_addr="127.0.0.1", ip_address=IpAddressFactory.create(), headers=dict(), + db=pretend.stub(add=lambda *a: None), ) user = UserFactory.create() user_service.update_user(user.id, password="foo") @@ -496,6 +497,7 @@ def test_updating_password_undisables(self, user_service): remote_addr="127.0.0.1", ip_address=IpAddressFactory.create(), headers=dict(), + db=pretend.stub(add=lambda *a: None), ) user = UserFactory.create() user_service.disable_password( diff --git a/warehouse/events/models.py b/warehouse/events/models.py index e6f2a01fa267..fe2f80af2d20 100644 --- a/warehouse/events/models.py +++ b/warehouse/events/models.py @@ -221,8 +221,6 @@ def events(cls): # noqa: N805 def record_event(self, *, tag, request: Request, additional=None): """Records an Event record on the associated model.""" - session = orm.object_session(self) - assert session is not None # Get-or-create a new IpAddress object ip_address = request.ip_address @@ -270,6 +268,6 @@ def record_event(self, *, tag, request: Request, additional=None): additional=additional, ) - session.add(event) + request.db.add(event) return event