From 17f35bb5ac72c8f5cf016a201d9fbd439ce997ba Mon Sep 17 00:00:00 2001 From: Hans Keeler Date: Fri, 15 Mar 2024 20:13:06 -0400 Subject: [PATCH 01/12] Move code under top-level module --- src/{ => regtech_user_fi_management}/__init__.py | 0 src/{ => regtech_user_fi_management}/config.py | 0 src/{ => regtech_user_fi_management}/dependencies.py | 0 src/{ => regtech_user_fi_management}/entities/__init__.py | 0 src/{ => regtech_user_fi_management}/entities/engine/__init__.py | 0 src/{ => regtech_user_fi_management}/entities/engine/engine.py | 0 src/{ => regtech_user_fi_management}/entities/listeners.py | 0 src/{ => regtech_user_fi_management}/entities/models/__init__.py | 0 src/{ => regtech_user_fi_management}/entities/models/dao.py | 0 src/{ => regtech_user_fi_management}/entities/models/dto.py | 0 src/{ => regtech_user_fi_management}/entities/repos/__init__.py | 0 .../entities/repos/institutions_repo.py | 0 src/{ => regtech_user_fi_management}/entities/repos/repo_utils.py | 0 src/{ => regtech_user_fi_management}/main.py | 0 src/{ => regtech_user_fi_management}/routers/__init__.py | 0 src/{ => regtech_user_fi_management}/routers/admin.py | 0 src/{ => regtech_user_fi_management}/routers/institutions.py | 0 src/{ => regtech_user_fi_management}/util/__init__.py | 0 18 files changed, 0 insertions(+), 0 deletions(-) rename src/{ => regtech_user_fi_management}/__init__.py (100%) rename src/{ => regtech_user_fi_management}/config.py (100%) rename src/{ => regtech_user_fi_management}/dependencies.py (100%) rename src/{ => regtech_user_fi_management}/entities/__init__.py (100%) rename src/{ => regtech_user_fi_management}/entities/engine/__init__.py (100%) rename src/{ => regtech_user_fi_management}/entities/engine/engine.py (100%) rename src/{ => regtech_user_fi_management}/entities/listeners.py (100%) rename src/{ => regtech_user_fi_management}/entities/models/__init__.py (100%) rename src/{ => regtech_user_fi_management}/entities/models/dao.py (100%) rename src/{ => regtech_user_fi_management}/entities/models/dto.py (100%) rename src/{ => regtech_user_fi_management}/entities/repos/__init__.py (100%) rename src/{ => regtech_user_fi_management}/entities/repos/institutions_repo.py (100%) rename src/{ => regtech_user_fi_management}/entities/repos/repo_utils.py (100%) rename src/{ => regtech_user_fi_management}/main.py (100%) rename src/{ => regtech_user_fi_management}/routers/__init__.py (100%) rename src/{ => regtech_user_fi_management}/routers/admin.py (100%) rename src/{ => regtech_user_fi_management}/routers/institutions.py (100%) rename src/{ => regtech_user_fi_management}/util/__init__.py (100%) diff --git a/src/__init__.py b/src/regtech_user_fi_management/__init__.py similarity index 100% rename from src/__init__.py rename to src/regtech_user_fi_management/__init__.py diff --git a/src/config.py b/src/regtech_user_fi_management/config.py similarity index 100% rename from src/config.py rename to src/regtech_user_fi_management/config.py diff --git a/src/dependencies.py b/src/regtech_user_fi_management/dependencies.py similarity index 100% rename from src/dependencies.py rename to src/regtech_user_fi_management/dependencies.py diff --git a/src/entities/__init__.py b/src/regtech_user_fi_management/entities/__init__.py similarity index 100% rename from src/entities/__init__.py rename to src/regtech_user_fi_management/entities/__init__.py diff --git a/src/entities/engine/__init__.py b/src/regtech_user_fi_management/entities/engine/__init__.py similarity index 100% rename from src/entities/engine/__init__.py rename to src/regtech_user_fi_management/entities/engine/__init__.py diff --git a/src/entities/engine/engine.py b/src/regtech_user_fi_management/entities/engine/engine.py similarity index 100% rename from src/entities/engine/engine.py rename to src/regtech_user_fi_management/entities/engine/engine.py diff --git a/src/entities/listeners.py b/src/regtech_user_fi_management/entities/listeners.py similarity index 100% rename from src/entities/listeners.py rename to src/regtech_user_fi_management/entities/listeners.py diff --git a/src/entities/models/__init__.py b/src/regtech_user_fi_management/entities/models/__init__.py similarity index 100% rename from src/entities/models/__init__.py rename to src/regtech_user_fi_management/entities/models/__init__.py diff --git a/src/entities/models/dao.py b/src/regtech_user_fi_management/entities/models/dao.py similarity index 100% rename from src/entities/models/dao.py rename to src/regtech_user_fi_management/entities/models/dao.py diff --git a/src/entities/models/dto.py b/src/regtech_user_fi_management/entities/models/dto.py similarity index 100% rename from src/entities/models/dto.py rename to src/regtech_user_fi_management/entities/models/dto.py diff --git a/src/entities/repos/__init__.py b/src/regtech_user_fi_management/entities/repos/__init__.py similarity index 100% rename from src/entities/repos/__init__.py rename to src/regtech_user_fi_management/entities/repos/__init__.py diff --git a/src/entities/repos/institutions_repo.py b/src/regtech_user_fi_management/entities/repos/institutions_repo.py similarity index 100% rename from src/entities/repos/institutions_repo.py rename to src/regtech_user_fi_management/entities/repos/institutions_repo.py diff --git a/src/entities/repos/repo_utils.py b/src/regtech_user_fi_management/entities/repos/repo_utils.py similarity index 100% rename from src/entities/repos/repo_utils.py rename to src/regtech_user_fi_management/entities/repos/repo_utils.py diff --git a/src/main.py b/src/regtech_user_fi_management/main.py similarity index 100% rename from src/main.py rename to src/regtech_user_fi_management/main.py diff --git a/src/routers/__init__.py b/src/regtech_user_fi_management/routers/__init__.py similarity index 100% rename from src/routers/__init__.py rename to src/regtech_user_fi_management/routers/__init__.py diff --git a/src/routers/admin.py b/src/regtech_user_fi_management/routers/admin.py similarity index 100% rename from src/routers/admin.py rename to src/regtech_user_fi_management/routers/admin.py diff --git a/src/routers/institutions.py b/src/regtech_user_fi_management/routers/institutions.py similarity index 100% rename from src/routers/institutions.py rename to src/regtech_user_fi_management/routers/institutions.py diff --git a/src/util/__init__.py b/src/regtech_user_fi_management/util/__init__.py similarity index 100% rename from src/util/__init__.py rename to src/regtech_user_fi_management/util/__init__.py From 806887e1922c002c3ea9a2abc989cd68e37a8b57 Mon Sep 17 00:00:00 2001 From: Hans Keeler Date: Sun, 17 Mar 2024 14:31:01 -0400 Subject: [PATCH 02/12] Tweak project settings to be used as a package - Fix `packages` to match top-level module name - Set `authors` to be more generic - Upgrade to Python 3.12 --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2ab1f35..96bdb10 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,12 +2,12 @@ name = "regtech-user-fi-management" version = "0.1.0" description = "" -authors = ["lchen-2101 <73617864+lchen-2101@users.noreply.github.com>"] +authors = ["CFPB's RegTech Team"] readme = "README.md" -packages = [{ include = "regtech-user-fi-management" }] +packages = [{ include = "regtech_user_fi_management", from = "src" }] [tool.poetry.dependencies] -python = "^3.11" +python = "^3.12" fastapi = "^0.109.1" uvicorn = "^0.22.0" python-dotenv = "^1.0.0" From 992ebe5cbb6500af5ea5d333edb4e5cb4fc431eb Mon Sep 17 00:00:00 2001 From: Hans Keeler Date: Sun, 17 Mar 2024 14:37:56 -0400 Subject: [PATCH 03/12] fix _most_ of the type checker issues in `config.py` The `PostgresDsn.build()` type checker issue is a head-scratcher --- src/regtech_user_fi_management/config.py | 15 +++++++-------- .../entities/engine/engine.py | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/regtech_user_fi_management/config.py b/src/regtech_user_fi_management/config.py index 6b8cae6..4f29811 100644 --- a/src/regtech_user_fi_management/config.py +++ b/src/regtech_user_fi_management/config.py @@ -1,9 +1,8 @@ import os +from pathlib import Path from urllib import parse -from typing import Any -from pydantic import field_validator, ValidationInfo -from pydantic.networks import PostgresDsn +from pydantic import field_validator, PostgresDsn, ValidationInfo from pydantic_settings import BaseSettings, SettingsConfigDict from regtech_api_commons.oauth2.config import KeycloakSettings @@ -11,7 +10,7 @@ JWT_OPTS_PREFIX = "jwt_opts_" -env_files_to_load = [".env"] +env_files_to_load: list[Path|str] = [".env"] if os.getenv("ENV", "LOCAL") == "LOCAL": env_files_to_load.append(".env.local") @@ -23,22 +22,22 @@ class Settings(BaseSettings): inst_db_pwd: str inst_db_host: str inst_db_scheme: str = "postgresql+asyncpg" - inst_conn: PostgresDsn | None = None + inst_conn: str | None = None def __init__(self, **data): super().__init__(**data) @field_validator("inst_conn", mode="before") @classmethod - def build_postgres_dsn(cls, postgres_dsn, info: ValidationInfo) -> Any: + def build_postgres_dsn(cls, field_value, info: ValidationInfo) -> str: postgres_dsn = PostgresDsn.build( scheme=info.data.get("inst_db_scheme"), username=info.data.get("inst_db_user"), - password=parse.quote(info.data.get("inst_db_pwd"), safe=""), + password=parse.quote(str(info.data.get("inst_db_pwd")), safe=""), host=info.data.get("inst_db_host"), path=info.data.get("inst_db_name"), ) - return str(postgres_dsn) + return postgres_dsn.unicode_string() model_config = SettingsConfigDict(env_file=env_files_to_load, extra="allow") diff --git a/src/regtech_user_fi_management/entities/engine/engine.py b/src/regtech_user_fi_management/entities/engine/engine.py index 9a43682..b1cdff2 100644 --- a/src/regtech_user_fi_management/entities/engine/engine.py +++ b/src/regtech_user_fi_management/entities/engine/engine.py @@ -4,9 +4,9 @@ async_scoped_session, ) from asyncio import current_task -from config import settings +from regtech_user_fi_management.config import settings -engine = create_async_engine(settings.inst_conn.unicode_string(), echo=True).execution_options( +engine = create_async_engine(str(settings.inst_conn), echo=True).execution_options( schema_translate_map={None: settings.inst_db_schema} ) SessionLocal = async_scoped_session(async_sessionmaker(engine, expire_on_commit=False), current_task) From c77100952d9a2c82f2f8f00f932fe5114b62cdb4 Mon Sep 17 00:00:00 2001 From: Hans Keeler Date: Sun, 17 Mar 2024 14:39:05 -0400 Subject: [PATCH 04/12] Refactor imports to fully-qualified module names --- .../entities/engine/__init__.py | 3 -- .../entities/models/__init__.py | 53 ------------------- .../entities/repos/institutions_repo.py | 9 ++-- .../entities/repos/repo_utils.py | 3 +- src/regtech_user_fi_management/main.py | 8 +-- .../util/__init__.py | 1 - 6 files changed, 12 insertions(+), 65 deletions(-) diff --git a/src/regtech_user_fi_management/entities/engine/__init__.py b/src/regtech_user_fi_management/entities/engine/__init__.py index 1fa8193..e69de29 100644 --- a/src/regtech_user_fi_management/entities/engine/__init__.py +++ b/src/regtech_user_fi_management/entities/engine/__init__.py @@ -1,3 +0,0 @@ -__all__ = ["get_session"] - -from .engine import get_session diff --git a/src/regtech_user_fi_management/entities/models/__init__.py b/src/regtech_user_fi_management/entities/models/__init__.py index c043bea..e69de29 100644 --- a/src/regtech_user_fi_management/entities/models/__init__.py +++ b/src/regtech_user_fi_management/entities/models/__init__.py @@ -1,53 +0,0 @@ -__all__ = [ - "Base", - "FinancialInstitutionDao", - "FinancialInstitutionDomainDao", - "FinancialInstitutionDto", - "FinancialInstitutionWithRelationsDto", - "FinancialInsitutionDomainDto", - "FinancialInsitutionDomainCreate", - "FinancialInstitutionAssociationDto", - "DeniedDomainDao", - "DeniedDomainDto", - "UserProfile", - "FederalRegulatorDao", - "HMDAInstitutionTypeDao", - "SBLInstitutionTypeDao", - "AddressStateDao", - "FederalRegulatorDto", - "InstitutionTypeDto", - "AddressStateDto", - "SblTypeMappingDao", - "SblTypeAssociationDto", - "SblTypeAssociationDetailsDto", - "SblTypeAssociationPatchDto", - "VersionedData", -] - -from .dao import ( - Base, - FinancialInstitutionDao, - FinancialInstitutionDomainDao, - DeniedDomainDao, - FederalRegulatorDao, - HMDAInstitutionTypeDao, - SBLInstitutionTypeDao, - AddressStateDao, - SblTypeMappingDao, -) -from .dto import ( - FinancialInstitutionDto, - FinancialInstitutionWithRelationsDto, - FinancialInsitutionDomainDto, - FinancialInsitutionDomainCreate, - FinancialInstitutionAssociationDto, - DeniedDomainDto, - UserProfile, - FederalRegulatorDto, - InstitutionTypeDto, - AddressStateDto, - SblTypeAssociationDto, - SblTypeAssociationDetailsDto, - SblTypeAssociationPatchDto, - VersionedData, -) diff --git a/src/regtech_user_fi_management/entities/repos/institutions_repo.py b/src/regtech_user_fi_management/entities/repos/institutions_repo.py index 4d8f28c..263332e 100644 --- a/src/regtech_user_fi_management/entities/repos/institutions_repo.py +++ b/src/regtech_user_fi_management/entities/repos/institutions_repo.py @@ -8,16 +8,19 @@ from .repo_utils import get_associated_sbl_types, query_type -from entities.models import ( +from regtech_user_fi_management.entities.models.dao import ( FinancialInstitutionDao, FinancialInstitutionDomainDao, - FinancialInstitutionDto, - FinancialInsitutionDomainCreate, HMDAInstitutionTypeDao, SBLInstitutionTypeDao, DeniedDomainDao, AddressStateDao, FederalRegulatorDao, +) + +from regtech_user_fi_management.entities.models.dto import ( + FinancialInstitutionDto, + FinancialInsitutionDomainCreate, SblTypeAssociationDto, ) diff --git a/src/regtech_user_fi_management/entities/repos/repo_utils.py b/src/regtech_user_fi_management/entities/repos/repo_utils.py index 15c4b11..0ad6c28 100644 --- a/src/regtech_user_fi_management/entities/repos/repo_utils.py +++ b/src/regtech_user_fi_management/entities/repos/repo_utils.py @@ -1,7 +1,8 @@ from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from typing import Sequence, TypeVar, Type -from entities.models import Base, SblTypeMappingDao, SblTypeAssociationDto +from regtech_user_fi_management.entities.models.dao import Base, SblTypeMappingDao +from regtech_user_fi_management.entities.models.dto import SblTypeAssociationDto T = TypeVar("T", bound=Base) diff --git a/src/regtech_user_fi_management/main.py b/src/regtech_user_fi_management/main.py index abe88bf..f3c44a7 100644 --- a/src/regtech_user_fi_management/main.py +++ b/src/regtech_user_fi_management/main.py @@ -9,14 +9,14 @@ from starlette.middleware.authentication import AuthenticationMiddleware from alembic.config import Config from alembic import command -from entities.listeners import setup_dao_listeners - -from routers import admin_router, institutions_router from regtech_api_commons.oauth2.oauth2_backend import BearerTokenAuthBackend from regtech_api_commons.oauth2.oauth2_admin import OAuth2Admin -from config import kc_settings +from regtech_user_fi_management.config import kc_settings +from regtech_user_fi_management.entities.listeners import setup_dao_listeners +from regtech_user_fi_management.routers import admin_router, institutions_router + log = logging.getLogger() diff --git a/src/regtech_user_fi_management/util/__init__.py b/src/regtech_user_fi_management/util/__init__.py index 8b13789..e69de29 100644 --- a/src/regtech_user_fi_management/util/__init__.py +++ b/src/regtech_user_fi_management/util/__init__.py @@ -1 +0,0 @@ - From 66c780f8e324214b0958460938a193b7c938bf12 Mon Sep 17 00:00:00 2001 From: Hans Keeler Date: Sun, 17 Mar 2024 15:58:31 -0400 Subject: [PATCH 05/12] Allow for more flexible python versioning --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 96bdb10..b708656 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ readme = "README.md" packages = [{ include = "regtech_user_fi_management", from = "src" }] [tool.poetry.dependencies] -python = "^3.12" +python = ">=3.12" fastapi = "^0.109.1" uvicorn = "^0.22.0" python-dotenv = "^1.0.0" From 23ac7bf8f98725c930ab488dde4af907839ef700 Mon Sep 17 00:00:00 2001 From: Hans Keeler Date: Sun, 17 Mar 2024 16:19:51 -0400 Subject: [PATCH 06/12] Upgrade asyncpg to support Python 3.12 --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b708656..38418d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ readme = "README.md" packages = [{ include = "regtech_user_fi_management", from = "src" }] [tool.poetry.dependencies] -python = ">=3.12" +python = ">=3.12,<4" fastapi = "^0.109.1" uvicorn = "^0.22.0" python-dotenv = "^1.0.0" @@ -16,7 +16,7 @@ SQLAlchemy = "^2.0.16" psycopg2-binary = "^2.9.6" python-jose = "^3.3.0" requests = "^2.31.0" -asyncpg = "^0.27.0" +asyncpg = "^0.29.0" alembic = "^1.12.0" pydantic-settings = "^2.0.3" regtech-api-commons = {git = "https://github.com/cfpb/regtech-api-commons.git"} From 04e0b20dc714bcdb8ba6d1c1c01564658c7feafa Mon Sep 17 00:00:00 2001 From: lchen-2101 <73617864+lchen-2101@users.noreply.github.com> Date: Mon, 18 Mar 2024 18:21:02 -0400 Subject: [PATCH 07/12] fix: refactor fix --- Dockerfile | 2 +- db_revisions/env.py | 4 +- poetry.lock | 92 ++++++++++--------- .../.env.local | 0 .../.env.template | 0 src/regtech_user_fi_management/config.py | 4 +- .../dependencies.py | 6 +- .../entities/listeners.py | 2 +- src/regtech_user_fi_management/main.py | 6 +- .../routers/admin.py | 6 +- .../routers/institutions.py | 16 +++- tests/api/conftest.py | 8 +- tests/api/routers/test_institutions_api.py | 54 +++++++---- tests/app/conftest.py | 2 +- tests/app/test_config.py | 2 +- tests/app/test_dependencies.py | 10 +- tests/entities/conftest.py | 2 +- .../entities/repos/test_institutions_repo.py | 12 +-- tests/entities/test_listeners.py | 12 ++- 19 files changed, 136 insertions(+), 104 deletions(-) rename src/{ => regtech_user_fi_management}/.env.local (100%) rename src/{ => regtech_user_fi_management}/.env.template (100%) diff --git a/Dockerfile b/Dockerfile index daa34a0..97d6840 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ RUN poetry install --no-root COPY ./src ./src COPY ./db_revisions ./db_revisions -WORKDIR /usr/app/src +WORKDIR /usr/app/src/regtech_user_fi_management EXPOSE 8888 diff --git a/db_revisions/env.py b/db_revisions/env.py index b55c3ca..b2f8bb9 100644 --- a/db_revisions/env.py +++ b/db_revisions/env.py @@ -4,7 +4,7 @@ from logging.config import fileConfig from sqlalchemy import engine_from_config, pool from alembic import context -from entities.models import Base +from regtech_user_fi_management.entities.models.dao import Base # this is the Alembic Config object, which provides # access to the values within the .ini file in use. @@ -21,7 +21,7 @@ if ENV == "LOCAL": file_dir = os.path.dirname(os.path.realpath(__file__)) - load_dotenv(f"{file_dir}/../src/.env.local") + load_dotenv(f"{file_dir}/../src/regtech_user_fi_management/.env.local") else: load_dotenv() diff --git a/poetry.lock b/poetry.lock index dc16935..94a611f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "aiosqlite" @@ -67,53 +67,57 @@ trio = ["trio (>=0.23)"] [[package]] name = "asyncpg" -version = "0.27.0" +version = "0.29.0" description = "An asyncio PostgreSQL driver" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8.0" files = [ - {file = "asyncpg-0.27.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fca608d199ffed4903dce1bcd97ad0fe8260f405c1c225bdf0002709132171c2"}, - {file = "asyncpg-0.27.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:20b596d8d074f6f695c13ffb8646d0b6bb1ab570ba7b0cfd349b921ff03cfc1e"}, - {file = "asyncpg-0.27.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a6206210c869ebd3f4eb9e89bea132aefb56ff3d1b7dd7e26b102b17e27bbb1"}, - {file = "asyncpg-0.27.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7a94c03386bb95456b12c66026b3a87d1b965f0f1e5733c36e7229f8f137747"}, - {file = "asyncpg-0.27.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bfc3980b4ba6f97138b04f0d32e8af21d6c9fa1f8e6e140c07d15690a0a99279"}, - {file = "asyncpg-0.27.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9654085f2b22f66952124de13a8071b54453ff972c25c59b5ce1173a4283ffd9"}, - {file = "asyncpg-0.27.0-cp310-cp310-win32.whl", hash = "sha256:879c29a75969eb2722f94443752f4720d560d1e748474de54ae8dd230bc4956b"}, - {file = "asyncpg-0.27.0-cp310-cp310-win_amd64.whl", hash = "sha256:ab0f21c4818d46a60ca789ebc92327d6d874d3b7ccff3963f7af0a21dc6cff52"}, - {file = "asyncpg-0.27.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:18f77e8e71e826ba2d0c3ba6764930776719ae2b225ca07e014590545928b576"}, - {file = "asyncpg-0.27.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c2232d4625c558f2aa001942cac1d7952aa9f0dbfc212f63bc754277769e1ef2"}, - {file = "asyncpg-0.27.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a3a4ff43702d39e3c97a8786314123d314e0f0e4dabc8367db5b665c93914de"}, - {file = "asyncpg-0.27.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccddb9419ab4e1c48742457d0c0362dbdaeb9b28e6875115abfe319b29ee225d"}, - {file = "asyncpg-0.27.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:768e0e7c2898d40b16d4ef7a0b44e8150db3dd8995b4652aa1fe2902e92c7df8"}, - {file = "asyncpg-0.27.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:609054a1f47292a905582a1cfcca51a6f3f30ab9d822448693e66fdddde27920"}, - {file = "asyncpg-0.27.0-cp311-cp311-win32.whl", hash = "sha256:8113e17cfe236dc2277ec844ba9b3d5312f61bd2fdae6d3ed1c1cdd75f6cf2d8"}, - {file = "asyncpg-0.27.0-cp311-cp311-win_amd64.whl", hash = "sha256:bb71211414dd1eeb8d31ec529fe77cff04bf53efc783a5f6f0a32d84923f45cf"}, - {file = "asyncpg-0.27.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4750f5cf49ed48a6e49c6e5aed390eee367694636c2dcfaf4a273ca832c5c43c"}, - {file = "asyncpg-0.27.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:eca01eb112a39d31cc4abb93a5aef2a81514c23f70956729f42fb83b11b3483f"}, - {file = "asyncpg-0.27.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5710cb0937f696ce303f5eed6d272e3f057339bb4139378ccecafa9ee923a71c"}, - {file = "asyncpg-0.27.0-cp37-cp37m-win_amd64.whl", hash = "sha256:71cca80a056ebe19ec74b7117b09e650990c3ca535ac1c35234a96f65604192f"}, - {file = "asyncpg-0.27.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4bb366ae34af5b5cabc3ac6a5347dfb6013af38c68af8452f27968d49085ecc0"}, - {file = "asyncpg-0.27.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:16ba8ec2e85d586b4a12bcd03e8d29e3d99e832764d6a1d0b8c27dbbe4a2569d"}, - {file = "asyncpg-0.27.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d20dea7b83651d93b1eb2f353511fe7fd554752844523f17ad30115d8b9c8cd6"}, - {file = "asyncpg-0.27.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e56ac8a8237ad4adec97c0cd4728596885f908053ab725e22900b5902e7f8e69"}, - {file = "asyncpg-0.27.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bf21ebf023ec67335258e0f3d3ad7b91bb9507985ba2b2206346de488267cad0"}, - {file = "asyncpg-0.27.0-cp38-cp38-win32.whl", hash = "sha256:69aa1b443a182b13a17ff926ed6627af2d98f62f2fe5890583270cc4073f63bf"}, - {file = "asyncpg-0.27.0-cp38-cp38-win_amd64.whl", hash = "sha256:62932f29cf2433988fcd799770ec64b374a3691e7902ecf85da14d5e0854d1ea"}, - {file = "asyncpg-0.27.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fddcacf695581a8d856654bc4c8cfb73d5c9df26d5f55201722d3e6a699e9629"}, - {file = "asyncpg-0.27.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7d8585707ecc6661d07367d444bbaa846b4e095d84451340da8df55a3757e152"}, - {file = "asyncpg-0.27.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:975a320baf7020339a67315284a4d3bf7460e664e484672bd3e71dbd881bc692"}, - {file = "asyncpg-0.27.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2232ebae9796d4600a7819fc383da78ab51b32a092795f4555575fc934c1c89d"}, - {file = "asyncpg-0.27.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:88b62164738239f62f4af92567b846a8ef7cf8abf53eddd83650603de4d52163"}, - {file = "asyncpg-0.27.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:eb4b2fdf88af4fb1cc569781a8f933d2a73ee82cd720e0cb4edabbaecf2a905b"}, - {file = "asyncpg-0.27.0-cp39-cp39-win32.whl", hash = "sha256:8934577e1ed13f7d2d9cea3cc016cc6f95c19faedea2c2b56a6f94f257cea672"}, - {file = "asyncpg-0.27.0-cp39-cp39-win_amd64.whl", hash = "sha256:1b6499de06fe035cf2fa932ec5617ed3f37d4ebbf663b655922e105a484a6af9"}, - {file = "asyncpg-0.27.0.tar.gz", hash = "sha256:720986d9a4705dd8a40fdf172036f5ae787225036a7eb46e704c45aa8f62c054"}, + {file = "asyncpg-0.29.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72fd0ef9f00aeed37179c62282a3d14262dbbafb74ec0ba16e1b1864d8a12169"}, + {file = "asyncpg-0.29.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52e8f8f9ff6e21f9b39ca9f8e3e33a5fcdceaf5667a8c5c32bee158e313be385"}, + {file = "asyncpg-0.29.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e6823a7012be8b68301342ba33b4740e5a166f6bbda0aee32bc01638491a22"}, + {file = "asyncpg-0.29.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:746e80d83ad5d5464cfbf94315eb6744222ab00aa4e522b704322fb182b83610"}, + {file = "asyncpg-0.29.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ff8e8109cd6a46ff852a5e6bab8b0a047d7ea42fcb7ca5ae6eaae97d8eacf397"}, + {file = "asyncpg-0.29.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:97eb024685b1d7e72b1972863de527c11ff87960837919dac6e34754768098eb"}, + {file = "asyncpg-0.29.0-cp310-cp310-win32.whl", hash = "sha256:5bbb7f2cafd8d1fa3e65431833de2642f4b2124be61a449fa064e1a08d27e449"}, + {file = "asyncpg-0.29.0-cp310-cp310-win_amd64.whl", hash = "sha256:76c3ac6530904838a4b650b2880f8e7af938ee049e769ec2fba7cd66469d7772"}, + {file = "asyncpg-0.29.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4900ee08e85af01adb207519bb4e14b1cae8fd21e0ccf80fac6aa60b6da37b4"}, + {file = "asyncpg-0.29.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a65c1dcd820d5aea7c7d82a3fdcb70e096f8f70d1a8bf93eb458e49bfad036ac"}, + {file = "asyncpg-0.29.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b52e46f165585fd6af4863f268566668407c76b2c72d366bb8b522fa66f1870"}, + {file = "asyncpg-0.29.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc600ee8ef3dd38b8d67421359779f8ccec30b463e7aec7ed481c8346decf99f"}, + {file = "asyncpg-0.29.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:039a261af4f38f949095e1e780bae84a25ffe3e370175193174eb08d3cecab23"}, + {file = "asyncpg-0.29.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6feaf2d8f9138d190e5ec4390c1715c3e87b37715cd69b2c3dfca616134efd2b"}, + {file = "asyncpg-0.29.0-cp311-cp311-win32.whl", hash = "sha256:1e186427c88225ef730555f5fdda6c1812daa884064bfe6bc462fd3a71c4b675"}, + {file = "asyncpg-0.29.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfe73ffae35f518cfd6e4e5f5abb2618ceb5ef02a2365ce64f132601000587d3"}, + {file = "asyncpg-0.29.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6011b0dc29886ab424dc042bf9eeb507670a3b40aece3439944006aafe023178"}, + {file = "asyncpg-0.29.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b544ffc66b039d5ec5a7454667f855f7fec08e0dfaf5a5490dfafbb7abbd2cfb"}, + {file = "asyncpg-0.29.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d84156d5fb530b06c493f9e7635aa18f518fa1d1395ef240d211cb563c4e2364"}, + {file = "asyncpg-0.29.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54858bc25b49d1114178d65a88e48ad50cb2b6f3e475caa0f0c092d5f527c106"}, + {file = "asyncpg-0.29.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bde17a1861cf10d5afce80a36fca736a86769ab3579532c03e45f83ba8a09c59"}, + {file = "asyncpg-0.29.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:37a2ec1b9ff88d8773d3eb6d3784dc7e3fee7756a5317b67f923172a4748a175"}, + {file = "asyncpg-0.29.0-cp312-cp312-win32.whl", hash = "sha256:bb1292d9fad43112a85e98ecdc2e051602bce97c199920586be83254d9dafc02"}, + {file = "asyncpg-0.29.0-cp312-cp312-win_amd64.whl", hash = "sha256:2245be8ec5047a605e0b454c894e54bf2ec787ac04b1cb7e0d3c67aa1e32f0fe"}, + {file = "asyncpg-0.29.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0009a300cae37b8c525e5b449233d59cd9868fd35431abc470a3e364d2b85cb9"}, + {file = "asyncpg-0.29.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cad1324dbb33f3ca0cd2074d5114354ed3be2b94d48ddfd88af75ebda7c43cc"}, + {file = "asyncpg-0.29.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:012d01df61e009015944ac7543d6ee30c2dc1eb2f6b10b62a3f598beb6531548"}, + {file = "asyncpg-0.29.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000c996c53c04770798053e1730d34e30cb645ad95a63265aec82da9093d88e7"}, + {file = "asyncpg-0.29.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e0bfe9c4d3429706cf70d3249089de14d6a01192d617e9093a8e941fea8ee775"}, + {file = "asyncpg-0.29.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:642a36eb41b6313ffa328e8a5c5c2b5bea6ee138546c9c3cf1bffaad8ee36dd9"}, + {file = "asyncpg-0.29.0-cp38-cp38-win32.whl", hash = "sha256:a921372bbd0aa3a5822dd0409da61b4cd50df89ae85150149f8c119f23e8c408"}, + {file = "asyncpg-0.29.0-cp38-cp38-win_amd64.whl", hash = "sha256:103aad2b92d1506700cbf51cd8bb5441e7e72e87a7b3a2ca4e32c840f051a6a3"}, + {file = "asyncpg-0.29.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5340dd515d7e52f4c11ada32171d87c05570479dc01dc66d03ee3e150fb695da"}, + {file = "asyncpg-0.29.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e17b52c6cf83e170d3d865571ba574577ab8e533e7361a2b8ce6157d02c665d3"}, + {file = "asyncpg-0.29.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f100d23f273555f4b19b74a96840aa27b85e99ba4b1f18d4ebff0734e78dc090"}, + {file = "asyncpg-0.29.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48e7c58b516057126b363cec8ca02b804644fd012ef8e6c7e23386b7d5e6ce83"}, + {file = "asyncpg-0.29.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f9ea3f24eb4c49a615573724d88a48bd1b7821c890c2effe04f05382ed9e8810"}, + {file = "asyncpg-0.29.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8d36c7f14a22ec9e928f15f92a48207546ffe68bc412f3be718eedccdf10dc5c"}, + {file = "asyncpg-0.29.0-cp39-cp39-win32.whl", hash = "sha256:797ab8123ebaed304a1fad4d7576d5376c3a006a4100380fb9d517f0b59c1ab2"}, + {file = "asyncpg-0.29.0-cp39-cp39-win_amd64.whl", hash = "sha256:cce08a178858b426ae1aa8409b5cc171def45d4293626e7aa6510696d46decd8"}, + {file = "asyncpg-0.29.0.tar.gz", hash = "sha256:d1c49e1f44fffafd9a55e1a9b101590859d881d639ea2922516f5d9c512d354e"}, ] [package.extras] -dev = ["Cython (>=0.29.24,<0.30.0)", "Sphinx (>=4.1.2,<4.2.0)", "flake8 (>=5.0.4,<5.1.0)", "pytest (>=6.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "uvloop (>=0.15.3)"] -docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] -test = ["flake8 (>=5.0.4,<5.1.0)", "uvloop (>=0.15.3)"] +docs = ["Sphinx (>=5.3.0,<5.4.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] +test = ["flake8 (>=6.1,<7.0)", "uvloop (>=0.15.3)"] [[package]] name = "black" @@ -1502,5 +1506,5 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", [metadata] lock-version = "2.0" -python-versions = "^3.11" -content-hash = "1d7495f1e753d9e786ccee3d5c0b56dea2230511e82a49f2f475f08e3ebbf803" +python-versions = ">=3.12,<4" +content-hash = "9746ae6b352991413938db37bc3c35e51fcacd6b91650a377e1e5452742a03aa" diff --git a/src/.env.local b/src/regtech_user_fi_management/.env.local similarity index 100% rename from src/.env.local rename to src/regtech_user_fi_management/.env.local diff --git a/src/.env.template b/src/regtech_user_fi_management/.env.template similarity index 100% rename from src/.env.template rename to src/regtech_user_fi_management/.env.template diff --git a/src/regtech_user_fi_management/config.py b/src/regtech_user_fi_management/config.py index 4f29811..91c7cb6 100644 --- a/src/regtech_user_fi_management/config.py +++ b/src/regtech_user_fi_management/config.py @@ -1,5 +1,6 @@ import os from pathlib import Path +from typing import Set from urllib import parse from pydantic import field_validator, PostgresDsn, ValidationInfo @@ -10,7 +11,7 @@ JWT_OPTS_PREFIX = "jwt_opts_" -env_files_to_load: list[Path|str] = [".env"] +env_files_to_load: list[Path | str] = [".env"] if os.getenv("ENV", "LOCAL") == "LOCAL": env_files_to_load.append(".env.local") @@ -23,6 +24,7 @@ class Settings(BaseSettings): inst_db_host: str inst_db_scheme: str = "postgresql+asyncpg" inst_conn: str | None = None + admin_scopes: Set[str] = set(["query-groups", "manage-users"]) def __init__(self, **data): super().__init__(**data) diff --git a/src/regtech_user_fi_management/dependencies.py b/src/regtech_user_fi_management/dependencies.py index 3516557..76a01f5 100644 --- a/src/regtech_user_fi_management/dependencies.py +++ b/src/regtech_user_fi_management/dependencies.py @@ -7,10 +7,10 @@ from sqlalchemy.ext.asyncio import AsyncSession from typing import List, Optional from itertools import chain -from config import settings +from regtech_user_fi_management.config import settings -from entities.engine import get_session -from entities.repos import institutions_repo as repo +from regtech_user_fi_management.entities.engine.engine import get_session +import regtech_user_fi_management.entities.repos.institutions_repo as repo from starlette.authentication import AuthCredentials from regtech_api_commons.models.auth import AuthenticatedUser diff --git a/src/regtech_user_fi_management/entities/listeners.py b/src/regtech_user_fi_management/entities/listeners.py index 38b64a3..8083ba6 100644 --- a/src/regtech_user_fi_management/entities/listeners.py +++ b/src/regtech_user_fi_management/entities/listeners.py @@ -3,7 +3,7 @@ from sqlalchemy.orm import Mapper from .models.dao import Base, FinancialInstitutionDao, SblTypeMappingDao -from entities.engine.engine import engine +from .engine.engine import engine def inspect_fi(fi: FinancialInstitutionDao): diff --git a/src/regtech_user_fi_management/main.py b/src/regtech_user_fi_management/main.py index f3c44a7..fe88383 100644 --- a/src/regtech_user_fi_management/main.py +++ b/src/regtech_user_fi_management/main.py @@ -23,9 +23,9 @@ def run_migrations(): file_dir = os.path.dirname(os.path.realpath(__file__)) - alembic_cfg = Config(f"{file_dir}/../alembic.ini") - alembic_cfg.set_main_option("script_location", f"{file_dir}/../db_revisions") - alembic_cfg.set_main_option("prepend_sys_path", f"{file_dir}/../") + alembic_cfg = Config(f"{file_dir}/../../alembic.ini") + alembic_cfg.set_main_option("script_location", f"{file_dir}/../../db_revisions") + alembic_cfg.set_main_option("prepend_sys_path", f"{file_dir}/../../") command.upgrade(alembic_cfg, "head") diff --git a/src/regtech_user_fi_management/routers/admin.py b/src/regtech_user_fi_management/routers/admin.py index 6aea3bb..8feb0c1 100644 --- a/src/regtech_user_fi_management/routers/admin.py +++ b/src/regtech_user_fi_management/routers/admin.py @@ -2,14 +2,14 @@ from typing import Set from fastapi import Depends, Request from starlette.authentication import requires -from dependencies import check_domain +from regtech_user_fi_management.dependencies import check_domain from regtech_api_commons.api import Router -from entities.models import UserProfile +from regtech_user_fi_management.entities.models.dto import UserProfile from regtech_api_commons.models import RegTechUser from regtech_api_commons.oauth2 import OAuth2Admin -from config import kc_settings +from regtech_user_fi_management.config import kc_settings router = Router() diff --git a/src/regtech_user_fi_management/routers/institutions.py b/src/regtech_user_fi_management/routers/institutions.py index c9f339e..a0db2c3 100644 --- a/src/regtech_user_fi_management/routers/institutions.py +++ b/src/regtech_user_fi_management/routers/institutions.py @@ -1,13 +1,19 @@ from fastapi import Depends, Request, HTTPException, Response from http import HTTPStatus from regtech_api_commons.oauth2.oauth2_admin import OAuth2Admin -from config import kc_settings +from regtech_user_fi_management.config import kc_settings from regtech_api_commons.api import Router -from dependencies import check_domain, parse_leis, get_email_domain, lei_association_check, fi_search_association_check +from regtech_user_fi_management.dependencies import ( + check_domain, + parse_leis, + get_email_domain, + lei_association_check, + fi_search_association_check, +) from typing import Annotated, List, Tuple, Literal -from entities.engine import get_session -from entities.repos import institutions_repo as repo -from entities.models import ( +from regtech_user_fi_management.entities.engine.engine import get_session +import regtech_user_fi_management.entities.repos.institutions_repo as repo +from regtech_user_fi_management.entities.models.dto import ( FinancialInstitutionDto, FinancialInstitutionWithRelationsDto, FinancialInsitutionDomainDto, diff --git a/tests/api/conftest.py b/tests/api/conftest.py index 66e7f2d..ca27e49 100644 --- a/tests/api/conftest.py +++ b/tests/api/conftest.py @@ -5,7 +5,7 @@ from pytest_mock import MockerFixture from starlette.authentication import AuthCredentials, UnauthenticatedUser from regtech_api_commons.models import AuthenticatedUser -from entities.models import ( +from regtech_user_fi_management.entities.models.dao import ( FinancialInstitutionDao, FinancialInstitutionDomainDao, FederalRegulatorDao, @@ -22,9 +22,9 @@ def app_fixture(mocker: MockerFixture) -> FastAPI: MockedEngine = mocker.patch("sqlalchemy.ext.asyncio.AsyncEngine") mocked_engine.return_value = MockedEngine.return_value mocker.patch("fastapi.security.OAuth2AuthorizationCodeBearer") - domain_denied_mock = mocker.patch("dependencies.email_domain_denied") + domain_denied_mock = mocker.patch("regtech_user_fi_management.dependencies.email_domain_denied") domain_denied_mock.return_value = False - from main import app + from regtech_user_fi_management.main import app return app @@ -57,7 +57,7 @@ def unauthed_user_mock(auth_mock: Mock) -> Mock: @pytest.fixture def get_institutions_mock(mocker: MockerFixture, authed_user_mock: Mock) -> Mock: - mock = mocker.patch("entities.repos.institutions_repo.get_institutions") + mock = mocker.patch("regtech_user_fi_management.entities.repos.institutions_repo.get_institutions") mock.return_value = [ FinancialInstitutionDao( name="Test Bank 123", diff --git a/tests/api/routers/test_institutions_api.py b/tests/api/routers/test_institutions_api.py index 8220607..5590892 100644 --- a/tests/api/routers/test_institutions_api.py +++ b/tests/api/routers/test_institutions_api.py @@ -6,7 +6,7 @@ from pytest_mock import MockerFixture from starlette.authentication import AuthCredentials from regtech_api_commons.models.auth import AuthenticatedUser -from entities.models import ( +from regtech_user_fi_management.entities.models.dao import ( FinancialInstitutionDao, FinancialInstitutionDomainDao, FederalRegulatorDao, @@ -14,8 +14,8 @@ HMDAInstitutionTypeDao, SBLInstitutionTypeDao, SblTypeMappingDao, - SblTypeAssociationDto, ) +from regtech_user_fi_management.entities.models.dto import SblTypeAssociationDto class TestInstitutionsApi: @@ -123,7 +123,9 @@ def test_invalid_lei(self, mocker: MockerFixture, app_fixture: FastAPI, authed_u assert res.status_code == 422 def test_create_institution_authed(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): - upsert_institution_mock = mocker.patch("entities.repos.institutions_repo.upsert_institution") + upsert_institution_mock = mocker.patch( + "regtech_user_fi_management.entities.repos.institutions_repo.upsert_institution" + ) upsert_institution_mock.return_value = FinancialInstitutionDao( name="testName", lei="testLEI0000000000000", @@ -182,7 +184,9 @@ def test_create_institution_authed(self, mocker: MockerFixture, app_fixture: Fas def test_create_institution_only_required_fields( self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock ): - upsert_institution_mock = mocker.patch("entities.repos.institutions_repo.upsert_institution") + upsert_institution_mock = mocker.patch( + "regtech_user_fi_management.entities.repos.institutions_repo.upsert_institution" + ) upsert_institution_mock.return_value = FinancialInstitutionDao( name="testName", lei="testLEI0000000000000", @@ -293,7 +297,9 @@ def test_get_institution_unauthed(self, app_fixture: FastAPI, unauthed_user_mock assert res.status_code == 403 def test_get_institution_authed(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): - get_institution_mock = mocker.patch("entities.repos.institutions_repo.get_institution") + get_institution_mock = mocker.patch( + "regtech_user_fi_management.entities.repos.institutions_repo.get_institution" + ) get_institution_mock.return_value = FinancialInstitutionDao( name="Test Bank 123", lei="TESTBANK123000000000", @@ -326,7 +332,9 @@ def test_get_institution_authed(self, mocker: MockerFixture, app_fixture: FastAP assert res.json().get("name") == "Test Bank 123" def test_get_institution_not_exists(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): - get_institution_mock = mocker.patch("entities.repos.institutions_repo.get_institution") + get_institution_mock = mocker.patch( + "regtech_user_fi_management.entities.repos.institutions_repo.get_institution" + ) get_institution_mock.return_value = None client = TestClient(app_fixture) lei_path = "testLeiPath" @@ -342,7 +350,7 @@ def test_add_domains_unauthed(self, app_fixture: FastAPI, unauthed_user_mock: Mo assert res.status_code == 403 def test_add_domains_authed(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): - add_domains_mock = mocker.patch("entities.repos.institutions_repo.add_domains") + add_domains_mock = mocker.patch("regtech_user_fi_management.entities.repos.institutions_repo.add_domains") add_domains_mock.return_value = [FinancialInstitutionDomainDao(domain="test.bank", lei="TESTBANK123")] client = TestClient(app_fixture) @@ -370,7 +378,7 @@ def test_add_domains_authed_no_permission(self, app_fixture: FastAPI, auth_mock: def test_add_domains_authed_with_denied_email_domain( self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock ): - domain_denied_mock = mocker.patch("dependencies.email_domain_denied") + domain_denied_mock = mocker.patch("regtech_user_fi_management.dependencies.email_domain_denied") domain_denied_mock.return_value = True client = TestClient(app_fixture) lei_path = "testLeiPath" @@ -379,7 +387,9 @@ def test_add_domains_authed_with_denied_email_domain( assert "domain denied" in res.json()["detail"] def test_check_domain_allowed(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): - domain_allowed_mock = mocker.patch("entities.repos.institutions_repo.is_domain_allowed") + domain_allowed_mock = mocker.patch( + "regtech_user_fi_management.entities.repos.institutions_repo.is_domain_allowed" + ) domain_allowed_mock.return_value = True domain_to_check = "local.host" client = TestClient(app_fixture) @@ -485,13 +495,13 @@ def test_get_associated_institutions_with_no_institutions( assert res.json() == [] def test_get_institution_types(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): - mock = mocker.patch("entities.repos.institutions_repo.get_sbl_types") + mock = mocker.patch("regtech_user_fi_management.entities.repos.institutions_repo.get_sbl_types") mock.return_value = [] client = TestClient(app_fixture) res = client.get("/v1/institutions/types/sbl") assert res.status_code == 200 - mock = mocker.patch("entities.repos.institutions_repo.get_hmda_types") + mock = mocker.patch("regtech_user_fi_management.entities.repos.institutions_repo.get_hmda_types") mock.return_value = [] res = client.get("/v1/institutions/types/hmda") assert res.status_code == 200 @@ -500,14 +510,14 @@ def test_get_institution_types(self, mocker: MockerFixture, app_fixture: FastAPI assert res.status_code == 422 def test_get_address_states(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): - mock = mocker.patch("entities.repos.institutions_repo.get_address_states") + mock = mocker.patch("regtech_user_fi_management.entities.repos.institutions_repo.get_address_states") mock.return_value = [] client = TestClient(app_fixture) res = client.get("/v1/institutions/address-states") assert res.status_code == 200 def test_get_federal_regulators(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): - mock = mocker.patch("entities.repos.institutions_repo.get_federal_regulators") + mock = mocker.patch("regtech_user_fi_management.entities.repos.institutions_repo.get_federal_regulators") mock.return_value = [] client = TestClient(app_fixture) res = client.get("/v1/institutions/regulators") @@ -515,7 +525,9 @@ def test_get_federal_regulators(self, mocker: MockerFixture, app_fixture: FastAP def test_get_sbl_types(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): inst_version = 2 - get_institution_mock = mocker.patch("entities.repos.institutions_repo.get_institution") + get_institution_mock = mocker.patch( + "regtech_user_fi_management.entities.repos.institutions_repo.get_institution" + ) get_institution_mock.return_value = FinancialInstitutionDao( version=inst_version, name="Test Bank 123", @@ -552,7 +564,9 @@ def test_get_sbl_types(self, mocker: MockerFixture, app_fixture: FastAPI, authed assert result["data"][0] == {"sbl_type": {"id": "SIT1", "name": "SIT1"}, "details": None} def test_get_sbl_types_no_institution(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): - get_institution_mock = mocker.patch("entities.repos.institutions_repo.get_institution") + get_institution_mock = mocker.patch( + "regtech_user_fi_management.entities.repos.institutions_repo.get_institution" + ) get_institution_mock.return_value = None client = TestClient(app_fixture) test_lei = "TESTBANK123" @@ -566,7 +580,7 @@ def test_get_hmda_types(self, mocker: MockerFixture, app_fixture: FastAPI, authe assert res.status_code == HTTPStatus.NOT_IMPLEMENTED def test_update_institution_types(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): - mock = mocker.patch("entities.repos.institutions_repo.update_sbl_types") + mock = mocker.patch("regtech_user_fi_management.entities.repos.institutions_repo.update_sbl_types") client = TestClient(app_fixture) test_lei = "TESTBANK123" res = client.put( @@ -581,7 +595,9 @@ def test_update_institution_types(self, mocker: MockerFixture, app_fixture: Fast def test_update_non_existing_institution_types( self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock ): - get_institution_mock = mocker.patch("entities.repos.institutions_repo.get_institution") + get_institution_mock = mocker.patch( + "regtech_user_fi_management.entities.repos.institutions_repo.get_institution" + ) get_institution_mock.return_value = None client = TestClient(app_fixture) test_lei = "TESTBANK123" @@ -594,7 +610,7 @@ def test_update_non_existing_institution_types( def test_update_unsupported_institution_types( self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock ): - mock = mocker.patch("entities.repos.institutions_repo.update_sbl_types") + mock = mocker.patch("regtech_user_fi_management.entities.repos.institutions_repo.update_sbl_types") client = TestClient(app_fixture) test_lei = "TESTBANK123" res = client.put( @@ -605,7 +621,7 @@ def test_update_unsupported_institution_types( mock.assert_not_called() def test_update_wrong_institution_types(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): - mock = mocker.patch("entities.repos.institutions_repo.update_sbl_types") + mock = mocker.patch("regtech_user_fi_management.entities.repos.institutions_repo.update_sbl_types") client = TestClient(app_fixture) test_lei = "TESTBANK123" res = client.put( diff --git a/tests/app/conftest.py b/tests/app/conftest.py index 1a72ea3..141329c 100644 --- a/tests/app/conftest.py +++ b/tests/app/conftest.py @@ -13,7 +13,7 @@ def setup(mocker: MockerFixture): MockedEngine = mocker.patch("sqlalchemy.ext.asyncio.AsyncEngine") mocked_engine.return_value = MockedEngine.return_value mocker.patch("fastapi.security.OAuth2AuthorizationCodeBearer") - mocker.patch("entities.engine.get_session") + mocker.patch("regtech_user_fi_management.entities.engine.engine.get_session") @pytest.fixture diff --git a/tests/app/test_config.py b/tests/app/test_config.py index 9937ce7..71cf496 100644 --- a/tests/app/test_config.py +++ b/tests/app/test_config.py @@ -1,4 +1,4 @@ -from config import Settings +from regtech_user_fi_management.config import Settings def test_postgres_dsn_building(): diff --git a/tests/app/test_dependencies.py b/tests/app/test_dependencies.py index df47aa3..81df785 100644 --- a/tests/app/test_dependencies.py +++ b/tests/app/test_dependencies.py @@ -3,7 +3,7 @@ from fastapi import HTTPException, Request from pytest_mock import MockerFixture from sqlalchemy.ext.asyncio import AsyncSession -from dependencies import lei_association_check, fi_search_association_check +from regtech_user_fi_management.dependencies import lei_association_check, fi_search_association_check from starlette.authentication import AuthCredentials import pytest @@ -15,9 +15,9 @@ def mock_session(mocker: MockerFixture) -> AsyncSession: async def test_domain_denied(mocker: MockerFixture, mock_session: AsyncSession): - domain_allowed_mock = mocker.patch("entities.repos.institutions_repo.is_domain_allowed") + domain_allowed_mock = mocker.patch("regtech_user_fi_management.entities.repos.institutions_repo.is_domain_allowed") domain_allowed_mock.return_value = False - from dependencies import email_domain_denied + from regtech_user_fi_management.dependencies import email_domain_denied denied_domain = "denied.domain" @@ -26,9 +26,9 @@ async def test_domain_denied(mocker: MockerFixture, mock_session: AsyncSession): async def test_domain_allowed(mocker: MockerFixture, mock_session: AsyncSession): - domain_allowed_mock = mocker.patch("entities.repos.institutions_repo.is_domain_allowed") + domain_allowed_mock = mocker.patch("regtech_user_fi_management.entities.repos.institutions_repo.is_domain_allowed") domain_allowed_mock.return_value = True - from dependencies import email_domain_denied + from regtech_user_fi_management.dependencies import email_domain_denied allowed_domain = "allowed.domain" diff --git a/tests/entities/conftest.py b/tests/entities/conftest.py index fc0633d..40a7f7b 100644 --- a/tests/entities/conftest.py +++ b/tests/entities/conftest.py @@ -8,7 +8,7 @@ async_scoped_session, async_sessionmaker, ) -from entities.models import Base +from regtech_user_fi_management.entities.models.dao import Base @pytest.fixture(scope="session") diff --git a/tests/entities/repos/test_institutions_repo.py b/tests/entities/repos/test_institutions_repo.py index ce3e13d..cf59e3e 100644 --- a/tests/entities/repos/test_institutions_repo.py +++ b/tests/entities/repos/test_institutions_repo.py @@ -2,22 +2,22 @@ from pytest_mock import MockerFixture from sqlalchemy.ext.asyncio import AsyncSession -from entities.models import ( - FinancialInstitutionDao, +from regtech_user_fi_management.entities.models.dto import ( FinancialInstitutionDto, - FinancialInstitutionDomainDao, FinancialInsitutionDomainCreate, + SblTypeAssociationDto, ) -from entities.models import ( +from regtech_user_fi_management.entities.models.dao import ( + FinancialInstitutionDomainDao, + FinancialInstitutionDao, DeniedDomainDao, AddressStateDao, FederalRegulatorDao, HMDAInstitutionTypeDao, SBLInstitutionTypeDao, SblTypeMappingDao, - SblTypeAssociationDto, ) -from entities.repos import institutions_repo as repo +import regtech_user_fi_management.entities.repos.institutions_repo as repo from regtech_api_commons.models import AuthenticatedUser diff --git a/tests/entities/test_listeners.py b/tests/entities/test_listeners.py index f7d2ece..fb8abe5 100644 --- a/tests/entities/test_listeners.py +++ b/tests/entities/test_listeners.py @@ -6,9 +6,13 @@ from sqlalchemy.orm import Mapper, InstanceState, AttributeState from sqlalchemy.orm.attributes import History -from entities.models.dao import FinancialInstitutionDao, SBLInstitutionTypeDao, SblTypeMappingDao +from regtech_user_fi_management.entities.models.dao import ( + FinancialInstitutionDao, + SBLInstitutionTypeDao, + SblTypeMappingDao, +) -from entities.listeners import _setup_fi_history +from regtech_user_fi_management.entities.listeners import _setup_fi_history class TestListeners: @@ -48,7 +52,7 @@ def setup(self): self.connection.reset_mock() def test_fi_history_listener(self, mocker: MockerFixture): - inspect_mock = mocker.patch("entities.listeners.inspect") + inspect_mock = mocker.patch("regtech_user_fi_management.entities.listeners.inspect") attr_mock1: AttributeState = Mock(AttributeState) attr_mock1.key = "name" attr_mock2: AttributeState = Mock(AttributeState) @@ -80,7 +84,7 @@ def _get_mapping_inspect_mock(self): return mapping_state_mock def test_fi_mapping_changed(self, mocker: MockerFixture): - inspect_mock = mocker.patch("entities.listeners.inspect") + inspect_mock = mocker.patch("regtech_user_fi_management.entities.listeners.inspect") fi_state_mock = self._get_fi_inspect_mock() mapping_state_mock = self._get_mapping_inspect_mock() From 91872255113df4d9a37c4e48afdd131bf7c0dfe6 Mon Sep 17 00:00:00 2001 From: lchen-2101 <73617864+lchen-2101@users.noreply.github.com> Date: Mon, 18 Mar 2024 18:24:17 -0400 Subject: [PATCH 08/12] fix: python version --- .github/workflows/linters.yml | 8 ++++---- .github/workflows/tests.yml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index dec14da..46c5d82 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -7,10 +7,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up Python 3.11 + - name: Set up Python 3.12 uses: actions/setup-python@v4 with: - python-version: 3.11 + python-version: 3.12 - name: Install dependencies run: | python -m pip install --upgrade pip @@ -24,10 +24,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up Python 3.11 + - name: Set up Python 3.12 uses: actions/setup-python@v4 with: - python-version: 3.11 + python-version: 3.12 - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6ebb2cd..b3d3a45 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,10 +19,10 @@ jobs: contents: write steps: - uses: actions/checkout@v3 - - name: Set up Python 3.11 + - name: Set up Python 3.12 uses: actions/setup-python@v4 with: - python-version: 3.11 + python-version: 3.12 - name: Install dependencies run: | python -m pip install --upgrade pip From 9c777df023025daae53851ae702ba0848fb851e1 Mon Sep 17 00:00:00 2001 From: lchen-2101 <73617864+lchen-2101@users.noreply.github.com> Date: Tue, 19 Mar 2024 11:16:52 -0400 Subject: [PATCH 09/12] fix: python update and run app in module --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 97d6840..3dd2533 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11-alpine +FROM python:3.12-alpine WORKDIR /usr/app @@ -12,8 +12,8 @@ RUN poetry install --no-root COPY ./src ./src COPY ./db_revisions ./db_revisions -WORKDIR /usr/app/src/regtech_user_fi_management +WORKDIR /usr/app/src EXPOSE 8888 -CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8888"] \ No newline at end of file +CMD ["uvicorn", "regtech_user_fi_management.main:app", "--host", "0.0.0.0", "--port", "8888"] \ No newline at end of file From 7ff22b72a29dab7e1723936d85b60cfd60e99b1c Mon Sep 17 00:00:00 2001 From: lchen-2101 <73617864+lchen-2101@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:17:18 -0400 Subject: [PATCH 10/12] chore: update imports from commons --- poetry.lock | 4 ++-- pyproject.toml | 4 ---- .../entities/repos/institutions_repo.py | 2 +- src/regtech_user_fi_management/routers/admin.py | 6 +++--- src/regtech_user_fi_management/routers/institutions.py | 2 +- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/poetry.lock b/poetry.lock index 94a611f..a489c2f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1255,7 +1255,7 @@ requests = "^2.31.0" type = "git" url = "https://github.com/cfpb/regtech-api-commons.git" reference = "HEAD" -resolved_reference = "e65414c33af3bc8fa84af68deffdd9d41745d0dc" +resolved_reference = "29356c630d2609cb81087ce35dd6c79512954d49" [[package]] name = "requests" @@ -1507,4 +1507,4 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", [metadata] lock-version = "2.0" python-versions = ">=3.12,<4" -content-hash = "9746ae6b352991413938db37bc3c35e51fcacd6b91650a377e1e5452742a03aa" +content-hash = "80e17382fb2de14a85772e1e65c1c9147e75bbe7033cd6cf8e3be2b90726f0f3" diff --git a/pyproject.toml b/pyproject.toml index 38418d2..8027cf0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,17 +8,13 @@ packages = [{ include = "regtech_user_fi_management", from = "src" }] [tool.poetry.dependencies] python = ">=3.12,<4" -fastapi = "^0.109.1" uvicorn = "^0.22.0" python-dotenv = "^1.0.0" python-keycloak = "^3.0.0" SQLAlchemy = "^2.0.16" psycopg2-binary = "^2.9.6" -python-jose = "^3.3.0" -requests = "^2.31.0" asyncpg = "^0.29.0" alembic = "^1.12.0" -pydantic-settings = "^2.0.3" regtech-api-commons = {git = "https://github.com/cfpb/regtech-api-commons.git"} [tool.poetry.group.dev.dependencies] diff --git a/src/regtech_user_fi_management/entities/repos/institutions_repo.py b/src/regtech_user_fi_management/entities/repos/institutions_repo.py index 263332e..d7210e1 100644 --- a/src/regtech_user_fi_management/entities/repos/institutions_repo.py +++ b/src/regtech_user_fi_management/entities/repos/institutions_repo.py @@ -4,7 +4,7 @@ from sqlalchemy.orm import joinedload from sqlalchemy.ext.asyncio import AsyncSession -from regtech_api_commons.models import AuthenticatedUser +from regtech_api_commons.models.auth import AuthenticatedUser from .repo_utils import get_associated_sbl_types, query_type diff --git a/src/regtech_user_fi_management/routers/admin.py b/src/regtech_user_fi_management/routers/admin.py index 8feb0c1..bc663c5 100644 --- a/src/regtech_user_fi_management/routers/admin.py +++ b/src/regtech_user_fi_management/routers/admin.py @@ -4,11 +4,11 @@ from starlette.authentication import requires from regtech_user_fi_management.dependencies import check_domain -from regtech_api_commons.api import Router +from regtech_api_commons.api.router_wrapper import Router from regtech_user_fi_management.entities.models.dto import UserProfile -from regtech_api_commons.models import RegTechUser -from regtech_api_commons.oauth2 import OAuth2Admin +from regtech_api_commons.models.auth import RegTechUser +from regtech_api_commons.oauth2.oauth2_admin import OAuth2Admin from regtech_user_fi_management.config import kc_settings router = Router() diff --git a/src/regtech_user_fi_management/routers/institutions.py b/src/regtech_user_fi_management/routers/institutions.py index a0db2c3..dd534a6 100644 --- a/src/regtech_user_fi_management/routers/institutions.py +++ b/src/regtech_user_fi_management/routers/institutions.py @@ -2,7 +2,7 @@ from http import HTTPStatus from regtech_api_commons.oauth2.oauth2_admin import OAuth2Admin from regtech_user_fi_management.config import kc_settings -from regtech_api_commons.api import Router +from regtech_api_commons.api.router_wrapper import Router from regtech_user_fi_management.dependencies import ( check_domain, parse_leis, From 79377b57fb80475c9ccf4e58ab603f2898cdc8c2 Mon Sep 17 00:00:00 2001 From: lchen-2101 <73617864+lchen-2101@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:22:14 -0400 Subject: [PATCH 11/12] fix: test mocks --- tests/api/conftest.py | 2 +- tests/api/routers/test_admin_api.py | 6 +++--- tests/app/conftest.py | 2 +- tests/entities/repos/test_institutions_repo.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/api/conftest.py b/tests/api/conftest.py index ca27e49..906093d 100644 --- a/tests/api/conftest.py +++ b/tests/api/conftest.py @@ -4,7 +4,7 @@ from fastapi import FastAPI from pytest_mock import MockerFixture from starlette.authentication import AuthCredentials, UnauthenticatedUser -from regtech_api_commons.models import AuthenticatedUser +from regtech_api_commons.models.auth import AuthenticatedUser from regtech_user_fi_management.entities.models.dao import ( FinancialInstitutionDao, FinancialInstitutionDomainDao, diff --git a/tests/api/routers/test_admin_api.py b/tests/api/routers/test_admin_api.py index 7a549af..8cdbe54 100644 --- a/tests/api/routers/test_admin_api.py +++ b/tests/api/routers/test_admin_api.py @@ -5,7 +5,7 @@ from pytest_mock import MockerFixture from starlette.authentication import AuthCredentials -from regtech_api_commons.models import RegTechUser, AuthenticatedUser +from regtech_api_commons.models.auth import RegTechUser, AuthenticatedUser class TestAdminApi: @@ -15,7 +15,7 @@ def test_get_me_unauthed(self, app_fixture: FastAPI, unauthed_user_mock: Mock): assert res.status_code == 403 def test_get_me_authed(self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock): - get_user_mock = mocker.patch("regtech_api_commons.oauth2.OAuth2Admin.get_user") + get_user_mock = mocker.patch("regtech_api_commons.oauth2.oauth2_admin.OAuth2Admin.get_user") get_user_mock.return_value = authed_user_mock.return_value[1] client = TestClient(app_fixture) res = client.get("/v1/admin/me") @@ -36,7 +36,7 @@ def test_get_me_authed_with_institutions(self, mocker: MockerFixture, app_fixtur AuthCredentials(["authenticated"]), AuthenticatedUser.from_claim(claims), ) - get_user_mock = mocker.patch("regtech_api_commons.oauth2.OAuth2Admin.get_user") + get_user_mock = mocker.patch("regtech_api_commons.oauth2.oauth2_admin.OAuth2Admin.get_user") get_user_mock.return_value = RegTechUser.from_claim(claims) client = TestClient(app_fixture) res = client.get("/v1/admin/me") diff --git a/tests/app/conftest.py b/tests/app/conftest.py index 141329c..3512078 100644 --- a/tests/app/conftest.py +++ b/tests/app/conftest.py @@ -4,7 +4,7 @@ from pytest_mock import MockerFixture from starlette.authentication import AuthCredentials -from regtech_api_commons.models import AuthenticatedUser, RegTechUser +from regtech_api_commons.models.auth import AuthenticatedUser, RegTechUser @pytest.fixture(autouse=True) diff --git a/tests/entities/repos/test_institutions_repo.py b/tests/entities/repos/test_institutions_repo.py index cf59e3e..c54921b 100644 --- a/tests/entities/repos/test_institutions_repo.py +++ b/tests/entities/repos/test_institutions_repo.py @@ -18,7 +18,7 @@ SblTypeMappingDao, ) import regtech_user_fi_management.entities.repos.institutions_repo as repo -from regtech_api_commons.models import AuthenticatedUser +from regtech_api_commons.models.auth import AuthenticatedUser class TestInstitutionsRepo: From e83e1a2f5b63d3eb85e9ec18d8a7aefdde215185 Mon Sep 17 00:00:00 2001 From: lchen-2101 <73617864+lchen-2101@users.noreply.github.com> Date: Tue, 19 Mar 2024 13:14:35 -0400 Subject: [PATCH 12/12] fix: absolute module import --- src/regtech_user_fi_management/entities/listeners.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/regtech_user_fi_management/entities/listeners.py b/src/regtech_user_fi_management/entities/listeners.py index 8083ba6..03dc6a2 100644 --- a/src/regtech_user_fi_management/entities/listeners.py +++ b/src/regtech_user_fi_management/entities/listeners.py @@ -2,8 +2,8 @@ from sqlalchemy import Connection, Table, event, inspect from sqlalchemy.orm import Mapper -from .models.dao import Base, FinancialInstitutionDao, SblTypeMappingDao -from .engine.engine import engine +from regtech_user_fi_management.entities.models.dao import Base, FinancialInstitutionDao, SblTypeMappingDao +from regtech_user_fi_management.entities.engine.engine import engine def inspect_fi(fi: FinancialInstitutionDao):