diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index d53e56b..9b9dc82 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -18,28 +18,17 @@ jobs: strategy: fail-fast: false matrix: - debian-version: [ "10", "11" ] - sqlalchemy-version: [ "1.3", "1.4" ] + debian-version: [ "11", "12" ] + sqlalchemy-version: [ "1.4" ] include: - - debian-version: "10" - python-version: "3.7" - postgres-version: 11 - postgis-version: 2.5 - debian-version: "11" python-version: "3.9" - postgres-version: 13 - postgis-version: 3.2 - - sqlalchemy-version: '1.3' - sqlalchemy-lt-version: '1.4' - flask-sqlalchemy-version: '2' - flask-sqlalchemy-lt-version: '3' - - sqlalchemy-version: '1.4' - sqlalchemy-lt-version: '2' - flask-sqlalchemy-version: '3' - flask-sqlalchemy-lt-version: '4' - exclude: - - debian-version: "10" - sqlalchemy-version: "1.4" + postgres-version: "13" + postgis-version: "3.2" + - debian-version: "12" + python-version: "3.11" + postgres-version: "15" + postgis-version: "3.3" name: Debian ${{ matrix.debian-version }} - SQLAlchemy ${{ matrix.sqlalchemy-version }} @@ -59,16 +48,12 @@ jobs: --health-retries 5 steps: - - name: Add postgis_raster database extension - if: ${{ matrix.postgis-version >= 3 }} - run: | - psql -h localhost -U postgres -d postgres -tc 'CREATE EXTENSION "postgis_raster";' - env: - PGPASSWORD: postgres - name: Add database extensions run: | + psql -h localhost -U postgres -d postgres -tc 'CREATE EXTENSION "postgis_raster";' psql -h localhost -U postgres -d postgres -tc 'CREATE EXTENSION "uuid-ossp";' psql -h localhost -U postgres -d postgres -tc 'CREATE EXTENSION "pg_trgm";' + psql -h localhost -U postgres -d postgres -tc 'CREATE EXTENSION "unaccent";' env: PGPASSWORD: postgres - uses: actions/checkout@v2 @@ -86,11 +71,10 @@ jobs: -e .[tests] \ -e file:dependencies/Utils-Flask-SQLAlchemy#egg=utils-flask-sqlalchemy \ -e file:dependencies/TaxHub#egg=taxhub \ - -e file:dependencies/UsersHub-authentification-module#egg=pypnusershub \ - "sqlalchemy>=${{ matrix.sqlalchemy-version }},<${{ matrix.sqlalchemy-lt-version }}" \ - "flask-sqlalchemy>=${{ matrix.flask-sqlalchemy-version }},<${{ matrix.flask-sqlalchemy-lt-version }}" + -e file:dependencies/UsersHub-authentification-module#egg=pypnusershub - name: Install database run: | + flask db upgrade taxonomie@head -x local-srid=2154 flask db upgrade ref_geo@head -x local-srid=2154 flask db upgrade nomenclatures_taxonomie@head flask db autoupgrade @@ -104,7 +88,7 @@ jobs: env: NOMENCLATURE_SETTINGS: test_settings.py - name: Upload coverage to Codecov - if: ${{ matrix.debian-version == '11' && matrix.sqlalchemy-version == '1.4' }} + if: ${{ matrix.debian-version == '12' && matrix.sqlalchemy-version == '1.4' }} uses: codecov/codecov-action@v3 with: flags: pytest diff --git a/dependencies/TaxHub b/dependencies/TaxHub index c08e8f3..2dfde0d 160000 --- a/dependencies/TaxHub +++ b/dependencies/TaxHub @@ -1 +1 @@ -Subproject commit c08e8f3f2248a8cc493136b6a2285bc513024a9f +Subproject commit 2dfde0d4433255b211a80a26ed49f10dbeb54f75 diff --git a/dependencies/UsersHub-authentification-module b/dependencies/UsersHub-authentification-module index 0d269c8..5e85d6c 160000 --- a/dependencies/UsersHub-authentification-module +++ b/dependencies/UsersHub-authentification-module @@ -1 +1 @@ -Subproject commit 0d269c8323e441b13fe8ffd7ca99ec36178c6415 +Subproject commit 5e85d6c736232728a3d6c03c22bfbde34daeb40f diff --git a/dependencies/Utils-Flask-SQLAlchemy b/dependencies/Utils-Flask-SQLAlchemy index 6fc91a7..6b9c13e 160000 --- a/dependencies/Utils-Flask-SQLAlchemy +++ b/dependencies/Utils-Flask-SQLAlchemy @@ -1 +1 @@ -Subproject commit 6fc91a7314936c50f5b35cf0829abd1fa93f03df +Subproject commit 6b9c13e844b0d43cc7b5fa532222c45e3444d8c7 diff --git a/docs/changelog.rst b/docs/changelog.rst index 1ca6131..cf31dd5 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -2,23 +2,34 @@ CHANGELOG ========= +1.6.0 (2024-01-30) +------------------ + +**🚀 NouveautĂ©s** + +- Mise Ă  jour de SQLAlchemy version 1.3 Ă  1.4 (#52 et #54) +- ArrĂȘt du support de Debian 10 (#54) +- Ajout du support de Debian 12 dans les tests automatisĂ©s (#54) +- Ajout de la possibilitĂ© d'associer des nomenclatures Ă  des Group3 INPN, en ajoutant le champs ``group3_inpn`` Ă  la table ``cor_taxref_nomenclature`` (#53) +- Mise Ă  jour des dĂ©pendances Python: TaxHub, Utils-Flask-SQLAlchemy, UsersHub-authentification-module + 1.5.4 (2023-03-04) ------------------ **🚀 NouveautĂ©s** -* CompatibilitĂ© SQLAlchemy 1.4 -* AmĂ©lioration de la documentation de ``NomenclaturesMixin`` -* Simplification des modĂšles et de leur homologue Flask-Admin -* Mise Ă  jour des dĂ©pendances : +- CompatibilitĂ© SQLAlchemy 1.4 +- AmĂ©lioration de la documentation de ``NomenclaturesMixin`` +- Simplification des modĂšles et de leur homologue Flask-Admin +- Mise Ă  jour des dĂ©pendances : - * TaxHub 1.11.1 - * UsersHub-authentification-module 1.6.5 - * Utils-Flask-SQLAlchemy 0.3.2 + - TaxHub 1.11.1 + - UsersHub-authentification-module 1.6.5 + - Utils-Flask-SQLAlchemy 0.3.2 **🐛 Corrections** -* Ajout de shapely<2 aux requirements +- Ajout de shapely<2 aux requirements 1.5.3 (2022-09-01) @@ -26,20 +37,21 @@ CHANGELOG **🚀 NouveautĂ©s** -* Ajout du type de nomenclature « CatĂ©gorie de liste rouge » et des nomenclatures associĂ©es. -* La branche ``nomenclature_taxonomie_inpn_data`` est renommĂ©e en ``nomenclature_taxonomie_data``, et ne dĂ©pend plus du rĂ©fĂ©rentiel TaxRef qui doit ĂȘtre importĂ© manuellement. -* Le code est dĂ©sormais formatĂ© avec Black et une Github Action y veille. -* PossibilitĂ© de filtrer les nomenclatures par code (``cd_nomenclature``). -* Mise Ă  jour des dĂ©pendances : +- Ajout du type de nomenclature « CatĂ©gorie de liste rouge » et des nomenclatures associĂ©es. +- La branche ``nomenclature_taxonomie_inpn_data`` est renommĂ©e en ``nomenclature_taxonomie_data``, et ne dĂ©pend plus du rĂ©fĂ©rentiel TaxRef qui doit ĂȘtre importĂ© manuellement. +- Le code est dĂ©sormais formatĂ© avec Black et une Github Action y veille. +- PossibilitĂ© de filtrer les nomenclatures par code (``cd_nomenclature``). +- Mise Ă  jour des dĂ©pendances : - * Utils-Flask-SQLAlchemy 0.3.0 - * TaxHub 1.10.0 - * UsersHub-authentification-module 1.6.0 + - Utils-Flask-SQLAlchemy 0.3.0 + - TaxHub 1.10.0 + - UsersHub-authentification-module 1.6.0 **🐛 Corrections** -* Correction de la dĂ©finition d’un type de nomenclature -* Correction des tests unitaires +- Correction de la dĂ©finition d’un type de nomenclature +- Correction des tests unitaires + 1.5.1 (2022-01-12) ------------------ diff --git a/requirements.in b/requirements.in index ee6cae2..ba756d7 100755 --- a/requirements.in +++ b/requirements.in @@ -6,9 +6,8 @@ flask-migrate psycopg2 flask-marshmallow marshmallow-sqlalchemy -shapely<2 -sqlalchemy>=1.3,<2 +sqlalchemy -utils-flask-sqlalchemy>=0.3.0 -taxhub>=1.10.0 -pypnusershub>=1.6.0 +utils-flask-sqlalchemy>=0.4.1 +taxhub>=1.13.2 +pypnusershub>=2.1.1 diff --git a/requirements.txt b/requirements.txt old mode 100755 new mode 100644 index 68ab56e..de9546a --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,213 @@ -Flask-Admin>=1.5.6 -flask-sqlalchemy>=2.3.2 -flask>=1.1.1 -psycopg2>=2.8.5 -sqlalchemy>=1.3.19 -utils-flask-sqlalchemy>=0.1.2 -flask-marshmallow>=0.12.0 +# +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: +# +# pip-compile requirements.in +# +alembic==1.13.1 + # via + # flask-migrate + # pypn-ref-geo + # pypnusershub +attrs==23.2.0 + # via fiona +authlib==1.3.0 + # via pypnusershub +bcrypt==4.1.2 + # via pypnusershub +blinker==1.7.0 + # via flask +boto3==1.34.30 + # via taxhub +botocore==1.34.30 + # via + # boto3 + # s3transfer +certifi==2023.11.17 + # via + # fiona + # requests +cffi==1.16.0 + # via cryptography +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via + # click-plugins + # cligj + # fiona + # flask + # taxhub +click-plugins==1.1.1 + # via fiona +cligj==0.7.2 + # via fiona +cryptography==42.0.1 + # via authlib +fiona==1.9.5 + # via utils-flask-sqlalchemy-geo +flask==3.0.1 + # via + # -r requirements.in + # flask-admin + # flask-cors + # flask-login + # flask-marshmallow + # flask-migrate + # flask-sqlalchemy + # pypn-ref-geo + # pypnusershub + # taxhub + # utils-flask-sqlalchemy +flask-admin==1.6.1 + # via -r requirements.in +flask-cors==4.0.0 + # via taxhub +flask-login==0.6.3 + # via pypnusershub +flask-marshmallow==1.1.0 + # via + # -r requirements.in + # pypn-ref-geo + # pypnusershub +flask-migrate==4.0.5 + # via + # -r requirements.in + # taxhub + # utils-flask-sqlalchemy +flask-sqlalchemy==3.0.5 + # via + # -r requirements.in + # flask-migrate + # pypn-ref-geo + # pypnusershub + # taxhub + # utils-flask-sqlalchemy +geoalchemy2==0.14.3 + # via utils-flask-sqlalchemy-geo +geojson==3.1.0 + # via utils-flask-sqlalchemy-geo +greenlet==3.0.3 + # via sqlalchemy +gunicorn==21.2.0 + # via taxhub +idna==3.6 + # via requests +importlib-metadata==7.0.1 + # via + # fiona + # flask +itsdangerous==2.1.2 + # via flask +jinja2==3.1.3 + # via flask +jmespath==1.0.1 + # via + # boto3 + # botocore +mako==1.3.2 + # via alembic +markupsafe==2.1.4 + # via + # jinja2 + # mako + # werkzeug + # wtforms +marshmallow==3.20.2 + # via + # flask-marshmallow + # marshmallow-geojson + # marshmallow-sqlalchemy + # utils-flask-sqlalchemy +marshmallow-geojson==0.5.0 + # via utils-flask-sqlalchemy-geo +marshmallow-sqlalchemy==0.30.0 + # via + # -r requirements.in + # pypnusershub + # taxhub + # utils-flask-sqlalchemy-geo +numpy==1.26.3 + # via shapely +packaging==23.2 + # via + # geoalchemy2 + # gunicorn + # marshmallow + # marshmallow-sqlalchemy +pillow==10.2.0 + # via taxhub +psycopg2==2.9.9 + # via + # -r requirements.in + # pypn-ref-geo + # pypnusershub + # taxhub +pycparser==2.21 + # via cffi +pypn-ref-geo==1.5.1 + # via taxhub +pypnusershub==2.1.1 + # via + # -r requirements.in + # taxhub +python-dateutil==2.8.2 + # via + # botocore + # utils-flask-sqlalchemy +python-dotenv==1.0.1 + # via + # -r requirements.in + # pypn-ref-geo + # taxhub +requests==2.31.0 + # via pypnusershub +s3transfer==0.10.0 + # via boto3 +shapely==2.0.2 + # via utils-flask-sqlalchemy-geo +six==1.16.0 + # via + # fiona + # python-dateutil +sqlalchemy==1.4.51 + # via + # -r requirements.in + # alembic + # flask-sqlalchemy + # geoalchemy2 + # marshmallow-sqlalchemy + # pypn-ref-geo + # pypnusershub + # taxhub + # utils-flask-sqlalchemy + # utils-flask-sqlalchemy-geo +taxhub==1.13.2 + # via -r requirements.in +typing-extensions==4.9.0 + # via alembic +urllib3==1.26.18 + # via + # botocore + # requests + # taxhub +utils-flask-sqlalchemy==0.4.1 + # via + # -r requirements.in + # pypn-ref-geo + # pypnusershub + # taxhub + # utils-flask-sqlalchemy-geo +utils-flask-sqlalchemy-geo==0.3.1 + # via pypn-ref-geo +werkzeug==3.0.1 + # via + # flask + # flask-login +wtforms==3.1.2 + # via flask-admin +zipp==3.17.0 + # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/src/pypnnomenclature/admin.py b/src/pypnnomenclature/admin.py index cc7b44b..4092758 100644 --- a/src/pypnnomenclature/admin.py +++ b/src/pypnnomenclature/admin.py @@ -6,6 +6,7 @@ from flask_admin.contrib.sqla.filters import BaseSQLAFilter from .models import TNomenclatures, BibNomenclaturesTypes from .env import db +from sqlalchemy import select # https://github.com/flask-admin/flask-admin/issues/1807 @@ -31,11 +32,12 @@ def operation(self): def get_dynamic_options(self, view): if has_app_context(): if not hasattr(g, "TNomenclatureFiltersType"): + bib_nomenc_labels = db.session.scalars( + db.select(BibNomenclaturesTypes).order_by(BibNomenclaturesTypes.label_default) + ).all() g.TNomenclatureFiltersType = [ (nomenclature.id_type, nomenclature.label_default) - for nomenclature in db.session.query(BibNomenclaturesTypes).order_by( - BibNomenclaturesTypes.label_default - ) # noqa + for nomenclature in bib_nomenc_labels # noqa ] yield from g.TNomenclatureFiltersType @@ -56,11 +58,12 @@ def operation(self): def get_dynamic_options(self, view): if has_app_context(): if not hasattr(g, "TNomenclatureFiltersMnemonique"): + bib_nomenc_type = db.session.scalars( + db.select(BibNomenclaturesTypes).order_by(BibNomenclaturesTypes.mnemonique) + ).all() g.TNomenclatureFiltersMnemonique = [ (nomenclature.id_type, nomenclature.mnemonique) - for nomenclature in db.session.query(BibNomenclaturesTypes).order_by( - BibNomenclaturesTypes.mnemonique - ) # noqa + for nomenclature in bib_nomenc_type # noqa ] yield from g.TNomenclatureFiltersMnemonique @@ -129,11 +132,12 @@ def operation(self): def get_dynamic_options(self, view): if has_app_context(): if not hasattr(g, "BibNomenclatureFiltersLabel"): + nomenc_def_label = db.session.scalars( + select(BibNomenclaturesTypes).order_by(BibNomenclaturesTypes.label_default) + ).all() g.BibNomenclatureFiltersLabel = [ (nomenclature.label_default, nomenclature.label_default) - for nomenclature in db.session.query(BibNomenclaturesTypes).order_by( - BibNomenclaturesTypes.label_default - ) # noqa + for nomenclature in nomenc_def_label # noqa ] yield from g.BibNomenclatureFiltersLabel @@ -161,11 +165,12 @@ def apply(self, query, value, alias=None): def get_dynamic_options(self, view): if has_app_context(): if not hasattr(g, "BibNomenclatureFiltersMnemonique"): + nomenc_mnemonique = db.session.scalars( + select(BibNomenclaturesTypes).order_by(BibNomenclaturesTypes.mnemonique) + ).all() g.BibNomenclatureFiltersMnemonique = [ (nomenclature.mnemonique, nomenclature.mnemonique) - for nomenclature in db.session.query(BibNomenclaturesTypes).order_by( - BibNomenclaturesTypes.mnemonique - ) # noqa + for nomenclature in nomenc_mnemonique # noqa ] yield from g.BibNomenclatureFiltersMnemonique diff --git a/src/pypnnomenclature/migrations/versions/11e7741319fd_get_default_nomenclature_value.py b/src/pypnnomenclature/migrations/versions/11e7741319fd_get_default_nomenclature_value.py index b3bdaeb..b086902 100644 --- a/src/pypnnomenclature/migrations/versions/11e7741319fd_get_default_nomenclature_value.py +++ b/src/pypnnomenclature/migrations/versions/11e7741319fd_get_default_nomenclature_value.py @@ -5,6 +5,7 @@ Create Date: 2021-10-04 17:51:48.491261 """ + from alembic import op import sqlalchemy as sa diff --git a/src/pypnnomenclature/migrations/versions/6015397d686a_nomenclatures.py b/src/pypnnomenclature/migrations/versions/6015397d686a_nomenclatures.py index 3a0ade1..99d9baf 100644 --- a/src/pypnnomenclature/migrations/versions/6015397d686a_nomenclatures.py +++ b/src/pypnnomenclature/migrations/versions/6015397d686a_nomenclatures.py @@ -5,6 +5,7 @@ Create Date: 2021-09-16 14:15:57.784074 """ + import importlib.resources from alembic import op diff --git a/src/pypnnomenclature/migrations/versions/618542880d1f_fix_typo_nomenc_type_def.py b/src/pypnnomenclature/migrations/versions/618542880d1f_fix_typo_nomenc_type_def.py index 2b403e5..4c68ddf 100644 --- a/src/pypnnomenclature/migrations/versions/618542880d1f_fix_typo_nomenc_type_def.py +++ b/src/pypnnomenclature/migrations/versions/618542880d1f_fix_typo_nomenc_type_def.py @@ -5,6 +5,7 @@ Create Date: 2022-07-28 14:43:31.883082 """ + from alembic import op import sqlalchemy as sa diff --git a/src/pypnnomenclature/migrations/versions/803524258bd3_add_group3_inpn_cor_taxref.py b/src/pypnnomenclature/migrations/versions/803524258bd3_add_group3_inpn_cor_taxref.py new file mode 100644 index 0000000..6315621 --- /dev/null +++ b/src/pypnnomenclature/migrations/versions/803524258bd3_add_group3_inpn_cor_taxref.py @@ -0,0 +1,136 @@ +"""add group3_inpn cor_taxref_nomenclature + +Revision ID: 803524258bd3 +Revises: f5436084bf17 +Create Date: 2023-09-04 07:57:35.371378 + +""" + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "803524258bd3" +down_revision = "f5436084bf17" +branch_labels = None +depends_on = "33e20a7682b4" + + +def upgrade(): + op.add_column( + table_name="cor_taxref_nomenclature", + column=sa.Column("group3_inpn", sa.VARCHAR(255), server_default="all"), + schema="ref_nomenclatures", + ) + op.execute( + """ALTER TABLE ref_nomenclatures.cor_taxref_nomenclature + ADD CONSTRAINT check_cor_taxref_nomenclature_isgroup3inpn + CHECK ((taxonomie.check_is_group3inpn((group3_inpn)::text) OR ((group3_inpn)::text = 'all'::text))) NOT VALID + """ + ) + with op.batch_alter_table( + table_name="cor_taxref_nomenclature", schema="ref_nomenclatures" + ) as batch: + batch.drop_constraint("pk_cor_taxref_nomenclature") + batch.create_primary_key( + constraint_name="pk_cor_taxref_nomenclature", + columns=["id_nomenclature", "regne", "group2_inpn", "group3_inpn"], + ) + op.execute("DROP VIEW ref_nomenclatures.v_nomenclature_taxonomie") + op.execute( + """ +CREATE OR REPLACE VIEW ref_nomenclatures.v_nomenclature_taxonomie +AS SELECT tn.id_type, + tn.label_default AS type_label, + tn.definition_default AS type_definition, + tn.label_fr AS type_label_fr, + tn.definition_fr AS type_definition_fr, + tn.label_en AS type_label_en, + tn.definition_en AS type_definition_en, + tn.label_es AS type_label_es, + tn.definition_es AS type_definition_es, + tn.label_de AS type_label_de, + tn.definition_de AS type_definition_de, + tn.label_it AS type_label_it, + tn.definition_it AS type_definition_it, + ctn.regne, + ctn.group2_inpn, + ctn.group3_inpn, + n.id_nomenclature, + n.mnemonique, + n.label_default AS nomenclature_label, + n.definition_default AS nomenclature_definition, + n.label_fr AS nomenclature_label_fr, + n.definition_fr AS nomenclature_definition_fr, + n.label_en AS nomenclature_label_en, + n.definition_en AS nomenclature_definition_en, + n.label_es AS nomenclature_label_es, + n.definition_es AS nomenclature_definition_es, + n.label_de AS nomenclature_label_de, + n.definition_de AS nomenclature_definition_de, + n.label_it AS nomenclature_label_it, + n.definition_it AS nomenclature_definition_it, + n.id_broader, + n.hierarchy + FROM ref_nomenclatures.t_nomenclatures n + JOIN ref_nomenclatures.bib_nomenclatures_types tn ON tn.id_type = n.id_type + JOIN ref_nomenclatures.cor_taxref_nomenclature ctn ON ctn.id_nomenclature = n.id_nomenclature + WHERE n.active = true + ORDER BY tn.id_type, ctn.regne, ctn.group2_inpn, n.id_nomenclature; + """ + ) + + +def downgrade(): + with op.batch_alter_table( + table_name="cor_taxref_nomenclature", schema="ref_nomenclatures" + ) as batch: + batch.drop_constraint("check_cor_taxref_nomenclature_isgroup3inpn") + batch.drop_constraint("pk_cor_taxref_nomenclature") + batch.create_primary_key( + constraint_name="pk_cor_taxref_nomenclature", + columns=["id_nomenclature", "regne", "group2_inpn"], + ) + op.execute("DROP VIEW ref_nomenclatures.v_nomenclature_taxonomie") + op.drop_column("cor_taxref_nomenclature", "group3_inpn", schema="ref_nomenclatures") + op.execute( + """ + CREATE VIEW ref_nomenclatures.v_nomenclature_taxonomie +AS SELECT tn.id_type, + tn.label_default AS type_label, + tn.definition_default AS type_definition, + tn.label_fr AS type_label_fr, + tn.definition_fr AS type_definition_fr, + tn.label_en AS type_label_en, + tn.definition_en AS type_definition_en, + tn.label_es AS type_label_es, + tn.definition_es AS type_definition_es, + tn.label_de AS type_label_de, + tn.definition_de AS type_definition_de, + tn.label_it AS type_label_it, + tn.definition_it AS type_definition_it, + ctn.regne, + ctn.group2_inpn, + n.id_nomenclature, + n.mnemonique, + n.label_default AS nomenclature_label, + n.definition_default AS nomenclature_definition, + n.label_fr AS nomenclature_label_fr, + n.definition_fr AS nomenclature_definition_fr, + n.label_en AS nomenclature_label_en, + n.definition_en AS nomenclature_definition_en, + n.label_es AS nomenclature_label_es, + n.definition_es AS nomenclature_definition_es, + n.label_de AS nomenclature_label_de, + n.definition_de AS nomenclature_definition_de, + n.label_it AS nomenclature_label_it, + n.definition_it AS nomenclature_definition_it, + n.id_broader, + n.hierarchy + FROM ref_nomenclatures.t_nomenclatures n + JOIN ref_nomenclatures.bib_nomenclatures_types tn ON tn.id_type = n.id_type + JOIN ref_nomenclatures.cor_taxref_nomenclature ctn ON ctn.id_nomenclature = n.id_nomenclature + WHERE n.active = true + ORDER BY tn.id_type, ctn.regne, ctn.group2_inpn, n.id_nomenclature;""" + ) diff --git a/src/pypnnomenclature/migrations/versions/96a713739fdd_nomenclatures_inpn_data.py b/src/pypnnomenclature/migrations/versions/96a713739fdd_nomenclatures_inpn_data.py index f37e93e..83c4021 100644 --- a/src/pypnnomenclature/migrations/versions/96a713739fdd_nomenclatures_inpn_data.py +++ b/src/pypnnomenclature/migrations/versions/96a713739fdd_nomenclatures_inpn_data.py @@ -4,6 +4,7 @@ Revises: Create Date: 2021-09-16 15:36:57.784074 """ + import importlib.resources from alembic import op, context diff --git a/src/pypnnomenclature/migrations/versions/a763fb554ff2_nomenclatures_taxonomie_data.py b/src/pypnnomenclature/migrations/versions/a763fb554ff2_nomenclatures_taxonomie_data.py index a89bf07..ca57506 100644 --- a/src/pypnnomenclature/migrations/versions/a763fb554ff2_nomenclatures_taxonomie_data.py +++ b/src/pypnnomenclature/migrations/versions/a763fb554ff2_nomenclatures_taxonomie_data.py @@ -4,6 +4,7 @@ Revises: Create Date: 2021-09-16 15:36:57.784074 """ + import importlib.resources from alembic import op diff --git a/src/pypnnomenclature/migrations/versions/b820c66d8daa_get_nomenclature_label.py b/src/pypnnomenclature/migrations/versions/b820c66d8daa_get_nomenclature_label.py index cfddfc7..f42143f 100644 --- a/src/pypnnomenclature/migrations/versions/b820c66d8daa_get_nomenclature_label.py +++ b/src/pypnnomenclature/migrations/versions/b820c66d8daa_get_nomenclature_label.py @@ -5,6 +5,7 @@ Create Date: 2021-12-10 10:07:09.478526 """ + from alembic import op import sqlalchemy as sa diff --git a/src/pypnnomenclature/migrations/versions/ee1146f6c0f4_add_uicn_rl.py b/src/pypnnomenclature/migrations/versions/ee1146f6c0f4_add_uicn_rl.py index bf8d8e6..cf4dcd3 100644 --- a/src/pypnnomenclature/migrations/versions/ee1146f6c0f4_add_uicn_rl.py +++ b/src/pypnnomenclature/migrations/versions/ee1146f6c0f4_add_uicn_rl.py @@ -5,6 +5,7 @@ Create Date: 2022-07-28 15:01:47.927979 """ + from alembic import op import sqlalchemy as sa diff --git a/src/pypnnomenclature/migrations/versions/f5436084bf17_nomenclatures_taxonomie.py b/src/pypnnomenclature/migrations/versions/f5436084bf17_nomenclatures_taxonomie.py index 4e9d388..f11f687 100644 --- a/src/pypnnomenclature/migrations/versions/f5436084bf17_nomenclatures_taxonomie.py +++ b/src/pypnnomenclature/migrations/versions/f5436084bf17_nomenclatures_taxonomie.py @@ -4,6 +4,7 @@ Create Date: 2021-09-16 15:08:57.784074 """ + import importlib.resources from alembic import op diff --git a/src/pypnnomenclature/migrations/versions/f8c2c8482419_get_default_nomenclature_value.py b/src/pypnnomenclature/migrations/versions/f8c2c8482419_get_default_nomenclature_value.py index a7a157e..20ba674 100644 --- a/src/pypnnomenclature/migrations/versions/f8c2c8482419_get_default_nomenclature_value.py +++ b/src/pypnnomenclature/migrations/versions/f8c2c8482419_get_default_nomenclature_value.py @@ -5,6 +5,7 @@ Create Date: 2021-10-06 10:45:42.264034 """ + from alembic import op import sqlalchemy as sa diff --git a/src/pypnnomenclature/models.py b/src/pypnnomenclature/models.py index b64e389..0363b2f 100644 --- a/src/pypnnomenclature/models.py +++ b/src/pypnnomenclature/models.py @@ -24,6 +24,7 @@ class CorTaxrefNomenclature(db.Model): ) regne = db.Column(db.Unicode, primary_key=True) group2_inpn = db.Column(db.Unicode, primary_key=True) + group3_inpn = db.Column(db.Unicode, primary_key=True) @serializable( @@ -47,7 +48,10 @@ class TNomenclatures(db.Model): id_type = db.Column( db.Integer, ForeignKey("ref_nomenclatures.bib_nomenclatures_types.id_type") ) - nomenclature_type = relationship("BibNomenclaturesTypes", backref="nomenclatures") + nomenclature_type = relationship( + "BibNomenclaturesTypes", + backref="nomenclatures", + ) cd_nomenclature = db.Column(db.Unicode) mnemonique = db.Column(db.Unicode) label_default = db.Column(db.Unicode) @@ -73,14 +77,12 @@ class TNomenclatures(db.Model): @staticmethod def get_default_nomenclature(mnemonique, id_organism=0): q = select( - [ - func.ref_nomenclatures.get_default_nomenclature_value( - mnemonique, id_organism - ).label("default") - ] + func.ref_nomenclatures.get_default_nomenclature_value(mnemonique, id_organism).label( + "default" + ) ) result = db.session.execute(q) - return result.fetchone()["default"] + return result.fetchone().default class TNomenclatureTaxonomy(TNomenclatures): @@ -127,7 +129,7 @@ def get_default_nomenclature(mnemonique, id_organism=0): ] ) result = db.session.execute(q) - return result.fetchone()["default"] + return result.fetchone().default class BibNomenclaturesTypeTaxo(BibNomenclaturesTypes): @@ -140,6 +142,7 @@ class BibNomenclaturesTypeTaxo(BibNomenclaturesTypes): primaryjoin="and_(TNomenclatureTaxonomy.id_type == BibNomenclaturesTypes.id_type, TNomenclatureTaxonomy.active == True)", lazy="joined", order_by="TNomenclatureTaxonomy.hierarchy", + viewonly=True, ) @@ -164,6 +167,7 @@ class VNomenclatureTaxonomie(db.Model): type_definition_it = db.Column(db.Unicode) regne = db.Column(db.Unicode, primary_key=True) group2_inpn = db.Column(db.Unicode, primary_key=True) + group3_inpn = db.Column(db.Unicode, primary_key=True) id_nomenclature = db.Column(db.Integer, primary_key=True) mnemonique = db.Column(db.Unicode) nomenclature_label = db.Column(db.Unicode) diff --git a/src/pypnnomenclature/repository.py b/src/pypnnomenclature/repository.py index bdc2468..b34c35d 100644 --- a/src/pypnnomenclature/repository.py +++ b/src/pypnnomenclature/repository.py @@ -1,6 +1,7 @@ """ MĂ©thode permettant de manipuler les objets de la nomenclature """ + from importlib import import_module from flask import current_app @@ -11,7 +12,7 @@ VNomenclatureTaxonomie, BibNomenclaturesTypeTaxo, ) -from sqlalchemy import text +from sqlalchemy import text, select from .env import db @@ -21,6 +22,7 @@ def get_nomenclature_list( code_type=None, regne=None, group2_inpn=None, + group3_inpn=None, hierarchy=None, filter_params=None, ): @@ -28,14 +30,14 @@ def get_nomenclature_list( RĂ©cupĂ©ration de la liste des termes d'un type de nomenclature """ - q = db.session.query(BibNomenclaturesTypes) + q = select(BibNomenclaturesTypes) if filter_params is None: filter_params = [] if code_type: - nomenclature = q.filter_by(mnemonique=code_type).first() + nomenclature = db.session.scalars(q.filter_by(mnemonique=code_type).limit(1)).first() elif id_type: - nomenclature = q.filter_by(id_type=id_type).first() + nomenclature = db.session.scalars(q.filter_by(id_type=id_type).limit(1)).first() else: nomenclature = None @@ -43,26 +45,25 @@ def get_nomenclature_list( return None # Terme de nomenclatures - q = ( - db.session.query(TNomenclatures) - .filter_by(id_type=nomenclature.id_type) - .filter_by(active=True) - ) + q = select(TNomenclatures).filter_by(id_type=nomenclature.id_type).filter_by(active=True) # Filtrer sur la hiĂ©rarchie if hierarchy: - q = q.filter(TNomenclatures.hierarchy.like("{}%".format(hierarchy))) + q = q.where(TNomenclatures.hierarchy.like("{}%".format(hierarchy))) if current_app.config["ENABLE_NOMENCLATURE_TAXONOMIC_FILTERS"]: # Filtrer en fonction du groupe taxonomie if regne: q = q.join( VNomenclatureTaxonomie, VNomenclatureTaxonomie.id_nomenclature == TNomenclatures.id_nomenclature, - ).filter(VNomenclatureTaxonomie.regne.in_(("all", regne))) + ).where(VNomenclatureTaxonomie.regne.in_(("all", regne))) if group2_inpn: q = q.filter(VNomenclatureTaxonomie.group2_inpn.in_(("all", group2_inpn))) + if group3_inpn: + q = q.where(VNomenclatureTaxonomie.group3_inpn.in_(("all", group3_inpn))) + if "cd_nomenclature" in filter_params: - q = q.filter(TNomenclatures.cd_nomenclature.in_(filter_params.getlist("cd_nomenclature"))) + q = q.where(TNomenclatures.cd_nomenclature.in_(filter_params.getlist("cd_nomenclature"))) # Ordonnancement if "orderby" in filter_params: order_col = getattr(TNomenclatures, filter_params["orderby"]) @@ -73,7 +74,7 @@ def get_nomenclature_list( q = q.order_by(order_col) # @TODO Autres filtres - data = q.all() + data = db.session.scalars(q).all() response = nomenclature.as_dict() if data: @@ -113,9 +114,9 @@ def get_nomenclature_with_taxonomy_list(): Fetch nomenclature definition list with taxonomy """ - q = db.session.query(BibNomenclaturesTypeTaxo).order_by("mnemonique") + q = select(BibNomenclaturesTypeTaxo).order_by("mnemonique") - nomenclature_types = q.all() + nomenclature_types = db.session.scalars(q).unique().all() data = list() for t in nomenclature_types: @@ -150,7 +151,7 @@ def get_nomenclature_with_taxonomy_list(): ] ) nomenclature_dict["taxref"] = [ - tr.as_dict(fields=["regne", "group2_inpn"]) for tr in n.taxref + tr.as_dict(fields=["regne", "group2_inpn", "group3_inpn"]) for tr in n.taxref ] nomenclatures.append(nomenclature_dict) @@ -177,11 +178,9 @@ def get_nomenclature_id_term(cd_type, cd_term, raise_exp=True): t = text("SELECT ref_nomenclatures.get_id_nomenclature(:cd_type, :cd_term) as id") try: - value = ( - db.session.query("id") - .from_statement(t.params(cd_type=cd_type, cd_term=cd_term)) - .first() - ) + value = db.session.scalars( + select("id").from_statement(t.params(cd_type=cd_type, cd_term=cd_term).limit(1)) + ).first() return value except Exception as e: if raise_exp: diff --git a/src/pypnnomenclature/routes.py b/src/pypnnomenclature/routes.py index 565be07..3841a61 100644 --- a/src/pypnnomenclature/routes.py +++ b/src/pypnnomenclature/routes.py @@ -24,12 +24,14 @@ def get_nomenclature_by_type_and_taxonomy(id_type): """ regne = request.args.get("regne") group2inpn = request.args.get("group2_inpn") + group3inpn = request.args.get("group3_inpn") response = repository.get_nomenclature_list( **{ "id_type": id_type, "regne": regne, "group2_inpn": group2inpn, + "group3_inpn": group3inpn, "filter_params": request.args, } ) @@ -50,12 +52,14 @@ def get_nomenclature_by_mnemonique_and_taxonomy(code_type): """ regne = request.args.get("regne") group2inpn = request.args.get("group2_inpn") + group3inpn = request.args.get("group3_inpn") response = repository.get_nomenclature_list( **{ "code_type": code_type, "regne": regne, "group2_inpn": group2inpn, + "group3_inpn": group3inpn, "filter_params": request.args, } ) @@ -75,6 +79,7 @@ def get_nomenclature_by_type_list_and_taxonomy(): """ regne = request.args.get("regne") group2inpn = request.args.get("group2_inpn") + group3inpn = request.args.get("group3_inpn") types = [] if "id_type" in request.args: types = request.args.getlist("id_type") @@ -90,6 +95,7 @@ def get_nomenclature_by_type_list_and_taxonomy(): param: id_type, "regne": regne, "group2_inpn": group2inpn, + "group3_inpn": group3inpn, "filter_params": request.args, } )