diff --git a/changelog.md b/changelog.md index a54ae4a..af883b4 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.5.0] + +### Added + +- Humanitarian needs tables and views + ## [0.4.0] ### Added diff --git a/pyproject.toml b/pyproject.toml index 825bd80..d47b989 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ classifiers = [ "Operating System :: Microsoft :: Windows", ] requires-python = ">=3.8" -dependencies = ['sqlalchemy'] +dependencies = ["sqlalchemy"] dynamic = ["version"] [project.readme] diff --git a/requirements.txt b/requirements.txt index dec6b93..301cfb1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,16 +7,18 @@ cfgv==3.4.0 # via pre-commit coverage[toml]==7.3.2 - # via pytest-cov + # via + # coverage + # pytest-cov distlib==0.3.7 # via virtualenv -filelock==3.12.4 +filelock==3.13.1 # via virtualenv -greenlet==3.0.0 +greenlet==3.0.1 # via sqlalchemy hdx-python-database==1.2.9 # via hapi-schema (pyproject.toml) -identify==2.5.30 +identify==2.5.32 # via pre-commit iniconfig==2.0.0 # via pytest @@ -24,13 +26,13 @@ nodeenv==1.8.0 # via pre-commit packaging==23.2 # via pytest -platformdirs==3.11.0 +platformdirs==4.0.0 # via virtualenv pluggy==1.3.0 # via pytest pre-commit==3.5.0 # via hapi-schema (pyproject.toml) -pytest==7.4.2 +pytest==7.4.3 # via # hapi-schema (pyproject.toml) # pytest-cov @@ -38,13 +40,13 @@ pytest-cov==4.1.0 # via hapi-schema (pyproject.toml) pyyaml==6.0.1 # via pre-commit -sqlalchemy==2.0.22 +sqlalchemy==2.0.23 # via # hapi-schema (pyproject.toml) # hdx-python-database typing-extensions==4.8.0 # via sqlalchemy -virtualenv==20.24.5 +virtualenv==20.24.7 # via pre-commit # The following packages are considered to be unsafe in a requirements file: diff --git a/src/hapi_schema/db_gender.py b/src/hapi_schema/db_gender.py index dbb8680..3687a23 100644 --- a/src/hapi_schema/db_gender.py +++ b/src/hapi_schema/db_gender.py @@ -1,6 +1,6 @@ """Gender table and view.""" -from sqlalchemy import CHAR, String, select +from sqlalchemy import String, select from sqlalchemy.orm import Mapped, mapped_column from hapi_schema.utils.base import Base @@ -10,7 +10,7 @@ class DBGender(Base): __tablename__ = "gender" - code: Mapped[str] = mapped_column(CHAR(1), primary_key=True) + code: Mapped[str] = mapped_column(String(1), primary_key=True) description: Mapped[str] = mapped_column(String(256), nullable=False) diff --git a/src/hapi_schema/db_humanitarian_needs.py b/src/hapi_schema/db_humanitarian_needs.py new file mode 100644 index 0000000..0e20e81 --- /dev/null +++ b/src/hapi_schema/db_humanitarian_needs.py @@ -0,0 +1,132 @@ +"""HumanitarianNeeds table and view.""" +from datetime import datetime + +from sqlalchemy import ( + Boolean, + DateTime, + ForeignKey, + Integer, + Text, + select, + text, +) +from sqlalchemy.orm import Mapped, mapped_column, relationship + +from hapi_schema.db_admin1 import DBAdmin1 +from hapi_schema.db_admin2 import DBAdmin2 +from hapi_schema.db_dataset import DBDataset +from hapi_schema.db_location import DBLocation +from hapi_schema.db_resource import DBResource +from hapi_schema.db_sector import DBSector +from hapi_schema.utils.base import Base +from hapi_schema.utils.view_params import ViewParams + + +class DBHumanitarianNeeds(Base): + __tablename__ = "humanitarian_needs" + + id: Mapped[int] = mapped_column(Integer, primary_key=True) + resource_ref: Mapped[int] = mapped_column( + ForeignKey("resource.id", onupdate="CASCADE", ondelete="CASCADE"), + nullable=False, + ) + admin2_ref: Mapped[int] = mapped_column( + ForeignKey("admin2.id", onupdate="CASCADE"), nullable=False + ) + gender_code: Mapped[str] = mapped_column( + ForeignKey("gender.code", onupdate="CASCADE"), nullable=True + ) + age_range_code: Mapped[str] = mapped_column( + ForeignKey("age_range.code", onupdate="CASCADE"), nullable=True + ) + disabled_marker: Mapped[bool] = mapped_column( + Boolean, nullable=True, server_default=text("NULL") + ) + sector_code: Mapped[str] = mapped_column( + ForeignKey("sector.code", onupdate="CASCADE"), nullable=True + ) + population_group_code: Mapped[str] = mapped_column( + ForeignKey("population_group.code", onupdate="CASCADE"), nullable=True + ) + population_status_code: Mapped[str] = mapped_column( + ForeignKey("population_status.code", onupdate="CASCADE"), + nullable=True, + ) + population: Mapped[int] = mapped_column( + Integer, nullable=False, index=True + ) + reference_period_start: Mapped[datetime] = mapped_column( + DateTime, nullable=False, index=True + ) + reference_period_end: Mapped[datetime] = mapped_column( + DateTime, nullable=True, server_default=text("NULL") + ) + source_data: Mapped[str] = mapped_column(Text, nullable=True) + + resource = relationship("DBResource") + admin2 = relationship("DBAdmin2") + gender = relationship("DBGender") + age_range = relationship("DBAgeRange") + sector = relationship("DBSector") + population_group = relationship("DBPopulationGroup") + population_status = relationship("DBPopulationStatus") + + +view_params_humanitarian_needs = ViewParams( + name="humanitarian_needs_view", + metadata=Base.metadata, + selectable=select( + *DBHumanitarianNeeds.__table__.columns, + DBDataset.hdx_id.label("dataset_hdx_id"), + DBDataset.hdx_stub.label("dataset_hdx_stub"), + DBDataset.title.label("dataset_title"), + DBDataset.hdx_provider_stub.label("dataset_hdx_provider_stub"), + DBDataset.hdx_provider_name.label("dataset_hdx_provider_name"), + DBResource.hdx_id.label("resource_hdx_id"), + DBResource.name.label("resource_name"), + DBResource.update_date.label("resource_update_date"), + DBLocation.code.label("location_code"), + DBLocation.name.label("location_name"), + DBAdmin1.code.label("admin1_code"), + DBAdmin1.name.label("admin1_name"), + DBAdmin1.is_unspecified.label("admin1_is_unspecified"), + DBAdmin2.code.label("admin2_code"), + DBAdmin2.name.label("admin2_name"), + DBAdmin2.is_unspecified.label("admin2_is_unspecified"), + DBSector.name.label("sector_name"), + ).select_from( + # Join pop to admin2 to admin1 to loc + DBHumanitarianNeeds.__table__.join( + DBAdmin2.__table__, + DBHumanitarianNeeds.admin2_ref == DBAdmin2.id, + isouter=True, + ) + .join( + DBAdmin1.__table__, + DBAdmin2.admin1_ref == DBAdmin1.id, + isouter=True, + ) + .join( + DBLocation.__table__, + DBAdmin1.location_ref == DBLocation.id, + isouter=True, + ) + # Join needs to resource to dataset + .join( + DBResource.__table__, + DBHumanitarianNeeds.resource_ref == DBResource.id, + isouter=True, + ) + .join( + DBDataset.__table__, + DBResource.dataset_ref == DBDataset.id, + isouter=True, + ) + # Join needs to sector + .join( + DBSector.__table__, + DBHumanitarianNeeds.sector_code == DBSector.code, + isouter=True, + ) + ), +) diff --git a/src/hapi_schema/db_operational_presence.py b/src/hapi_schema/db_operational_presence.py index 336b950..b0dc17d 100644 --- a/src/hapi_schema/db_operational_presence.py +++ b/src/hapi_schema/db_operational_presence.py @@ -31,15 +31,15 @@ class DBOperationalPresence(Base): ForeignKey("resource.id", onupdate="CASCADE", ondelete="CASCADE"), nullable=False, ) - org_ref = mapped_column( + admin2_ref: Mapped[int] = mapped_column( + ForeignKey("admin2.id", onupdate="CASCADE"), nullable=False + ) + org_ref: Mapped[str] = mapped_column( ForeignKey("org.id", onupdate="CASCADE"), nullable=False ) - sector_code = mapped_column( + sector_code: Mapped[str] = mapped_column( ForeignKey("sector.code", onupdate="CASCADE"), nullable=False ) - admin2_ref: Mapped[int] = mapped_column( - ForeignKey("admin2.id", onupdate="CASCADE"), nullable=False - ) reference_period_start: Mapped[datetime] = mapped_column( DateTime, nullable=False, index=True ) @@ -49,9 +49,9 @@ class DBOperationalPresence(Base): source_data: Mapped[str] = mapped_column(Text, nullable=True) resource = relationship("DBResource") + admin2 = relationship("DBAdmin2") org = relationship("DBOrg") sector = relationship("DBSector") - admin2 = relationship("DBAdmin2") view_params_operational_presence = ViewParams( diff --git a/src/hapi_schema/db_population.py b/src/hapi_schema/db_population.py index ce5610e..6279b25 100644 --- a/src/hapi_schema/db_population.py +++ b/src/hapi_schema/db_population.py @@ -13,9 +13,7 @@ from hapi_schema.db_admin1 import DBAdmin1 from hapi_schema.db_admin2 import DBAdmin2 -from hapi_schema.db_age_range import DBAgeRange from hapi_schema.db_dataset import DBDataset -from hapi_schema.db_gender import DBGender from hapi_schema.db_location import DBLocation from hapi_schema.db_resource import DBResource from hapi_schema.utils.base import Base @@ -52,8 +50,8 @@ class DBPopulation(Base): resource = relationship("DBResource") admin2 = relationship("DBAdmin2") - age_range = relationship("DBAgeRange") gender = relationship("DBGender") + age_range = relationship("DBAgeRange") view_params_population = ViewParams( @@ -69,7 +67,6 @@ class DBPopulation(Base): DBResource.hdx_id.label("resource_hdx_id"), DBResource.name.label("resource_name"), DBResource.update_date.label("resource_update_date"), - DBGender.description.label("gender_description"), DBLocation.code.label("location_code"), DBLocation.name.label("location_name"), DBAdmin1.code.label("admin1_code"), @@ -77,7 +74,7 @@ class DBPopulation(Base): DBAdmin1.is_unspecified.label("admin1_is_unspecified"), DBAdmin2.code.label("admin2_code"), DBAdmin2.name.label("admin2_name"), - DBAdmin2.is_unspecified.label("admin2_is_unspecified") + DBAdmin2.is_unspecified.label("admin2_is_unspecified"), ).select_from( # Join pop to admin2 to admin1 to loc DBPopulation.__table__.join( @@ -106,17 +103,5 @@ class DBPopulation(Base): DBResource.dataset_ref == DBDataset.id, isouter=True, ) - # Join pop to gender - .join( - DBGender.__table__, - DBPopulation.gender_code == DBGender.code, - isouter=True, - ) - # Join pop to age range - .join( - DBAgeRange.__table__, - DBPopulation.age_range_code == DBAgeRange.code, - isouter=True, - ) ), ) diff --git a/src/hapi_schema/db_population_group.py b/src/hapi_schema/db_population_group.py new file mode 100644 index 0000000..f336d6a --- /dev/null +++ b/src/hapi_schema/db_population_group.py @@ -0,0 +1,23 @@ +"""Population group table and view.""" + +from sqlalchemy import String, select +from sqlalchemy.orm import Mapped, mapped_column + +from hapi_schema.utils.base import Base +from hapi_schema.utils.view_params import ViewParams + + +class DBPopulationGroup(Base): + __tablename__ = "population_group" + + code: Mapped[str] = mapped_column(String(32), primary_key=True) + description: Mapped[str] = mapped_column( + String(512), nullable=False, index=True + ) + + +view_params_population_group = ViewParams( + name="population_group_view", + metadata=Base.metadata, + selectable=select(*DBPopulationGroup.__table__.columns), +) diff --git a/src/hapi_schema/db_population_status.py b/src/hapi_schema/db_population_status.py new file mode 100644 index 0000000..cb934bc --- /dev/null +++ b/src/hapi_schema/db_population_status.py @@ -0,0 +1,23 @@ +"""Population status table and view.""" + +from sqlalchemy import String, select +from sqlalchemy.orm import Mapped, mapped_column + +from hapi_schema.utils.base import Base +from hapi_schema.utils.view_params import ViewParams + + +class DBPopulationStatus(Base): + __tablename__ = "population_status" + + code: Mapped[str] = mapped_column(String(32), primary_key=True) + description: Mapped[str] = mapped_column( + String(512), nullable=False, index=True + ) + + +view_params_population_status = ViewParams( + name="population_status_view", + metadata=Base.metadata, + selectable=select(*DBPopulationStatus.__table__.columns), +) diff --git a/tests/conftest.py b/tests/conftest.py index fcabd57..38243cf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,6 +8,7 @@ from hapi_schema.db_dataset import DBDataset from hapi_schema.db_food_security import DBFoodSecurity from hapi_schema.db_gender import DBGender +from hapi_schema.db_humanitarian_needs import DBHumanitarianNeeds from hapi_schema.db_ipc_phase import DBIpcPhase from hapi_schema.db_ipc_type import DBIpcType from hapi_schema.db_location import DBLocation @@ -17,6 +18,8 @@ from hapi_schema.db_org import DBOrg from hapi_schema.db_org_type import DBOrgType from hapi_schema.db_population import DBPopulation +from hapi_schema.db_population_group import DBPopulationGroup +from hapi_schema.db_population_status import DBPopulationStatus from hapi_schema.db_resource import DBResource from hapi_schema.db_sector import DBSector from hapi_schema.utils.base import Base @@ -26,6 +29,7 @@ from sample_data.data_dataset import data_dataset from sample_data.data_food_security import data_food_security from sample_data.data_gender import data_gender +from sample_data.data_humanitarian_needs import data_humanitarian_needs from sample_data.data_ipc_phase import data_ipc_phase from sample_data.data_ipc_type import data_ipc_type from sample_data.data_location import data_location @@ -33,6 +37,8 @@ from sample_data.data_org import data_org from sample_data.data_org_type import data_org_type from sample_data.data_population import data_population +from sample_data.data_population_group import data_population_group +from sample_data.data_population_status import data_population_status from sample_data.data_resource import data_resource from sample_data.data_sector import data_sector @@ -46,21 +52,24 @@ def engine(): session = sessionmaker(bind=engine)() # Populate all tables + session.execute(insert(DBResource), data_resource) + session.execute(insert(DBDataset), data_dataset) + session.execute(insert(DBLocation), data_location) session.execute(insert(DBAdmin1), data_admin1) session.execute(insert(DBAdmin2), data_admin2) - session.execute(insert(DBAgeRange), data_age_range) - session.execute(insert(DBDataset), data_dataset) - session.execute(insert(DBFoodSecurity), data_food_security) session.execute(insert(DBGender), data_gender) - session.execute(insert(DBIpcPhase), data_ipc_phase) - session.execute(insert(DBIpcType), data_ipc_type) - session.execute(insert(DBLocation), data_location) - session.execute(insert(DBOperationalPresence), data_operational_presence) + session.execute(insert(DBAgeRange), data_age_range) + session.execute(insert(DBSector), data_sector) session.execute(insert(DBOrg), data_org) session.execute(insert(DBOrgType), data_org_type) + session.execute(insert(DBPopulationGroup), data_population_group) + session.execute(insert(DBPopulationStatus), data_population_status) + session.execute(insert(DBIpcPhase), data_ipc_phase) + session.execute(insert(DBIpcType), data_ipc_type) session.execute(insert(DBPopulation), data_population) - session.execute(insert(DBResource), data_resource) - session.execute(insert(DBSector), data_sector) + session.execute(insert(DBOperationalPresence), data_operational_presence) + session.execute(insert(DBFoodSecurity), data_food_security) + session.execute(insert(DBHumanitarianNeeds), data_humanitarian_needs) session.commit() diff --git a/tests/sample_data/data_humanitarian_needs.py b/tests/sample_data/data_humanitarian_needs.py new file mode 100644 index 0000000..357bd12 --- /dev/null +++ b/tests/sample_data/data_humanitarian_needs.py @@ -0,0 +1,68 @@ +from datetime import datetime + +data_humanitarian_needs = [ + # total national + dict( + id=1, + resource_ref=1, + admin2_ref=1, + gender_code=None, + age_range_code=None, + disabled_marker=None, + sector_code=None, + population_group_code=None, + population_status_code="affected", + population=1_000_000, + reference_period_start=datetime(2023, 1, 1), + reference_period_end=datetime(2023, 6, 30), + source_data="DATA,DATA,DATA", + ), + # national f, all ages, disabled, sector SHL + dict( + id=2, + resource_ref=1, + admin2_ref=1, + gender_code="f", + age_range_code=None, + disabled_marker=True, + sector_code="SHL", + population_group_code="refugees", + population_status_code="inneed", + population=500_000, + reference_period_start=datetime(2023, 1, 1), + reference_period_end=datetime(2023, 6, 30), + source_data="DATA,DATA,DATA", + ), + # admin1 f, age 0-4, not disabled, sector WSH + dict( + id=3, + resource_ref=1, + admin2_ref=2, + gender_code="f", + age_range_code="0-4", + disabled_marker=True, + sector_code="WSH", + population_group_code="idps", + population_status_code="inneed", + population=5_000, + reference_period_start=datetime(2023, 1, 1), + reference_period_end=datetime(2023, 6, 30), + source_data="DATA,DATA,DATA", + ), + # admin2 ages 80+, disabled, sector HEA + dict( + id=4, + resource_ref=1, + admin2_ref=4, + gender_code=None, + age_range_code="80+", + disabled_marker=False, + sector_code="HEA", + population_group_code="idps", + population_status_code="affected", + population=500, + reference_period_start=datetime(2023, 1, 1), + reference_period_end=datetime(2023, 6, 30), + source_data="DATA,DATA,DATA", + ), +] diff --git a/tests/sample_data/data_operational_presence.py b/tests/sample_data/data_operational_presence.py index 3a08205..520aee7 100644 --- a/tests/sample_data/data_operational_presence.py +++ b/tests/sample_data/data_operational_presence.py @@ -4,9 +4,9 @@ dict( id=1, resource_ref=1, + admin2_ref=2, org_ref=1, sector_code="SHL", - admin2_ref=2, reference_period_start=datetime(2023, 1, 1), reference_period_end=None, source_data="DATA,DATA,DATA", @@ -14,9 +14,9 @@ dict( id=2, resource_ref=1, + admin2_ref=4, org_ref=2, sector_code="FSC", - admin2_ref=4, reference_period_start=datetime(2023, 1, 1), reference_period_end=None, source_data="DATA,DATA,DATA", @@ -24,9 +24,9 @@ dict( id=3, resource_ref=1, + admin2_ref=4, org_ref=3, sector_code="WSH", - admin2_ref=4, reference_period_start=datetime(2023, 1, 1), reference_period_end=None, source_data="DATA,DATA,DATA", @@ -34,9 +34,9 @@ dict( id=4, resource_ref=1, + admin2_ref=6, org_ref=3, sector_code="HEA", - admin2_ref=6, reference_period_start=datetime(2023, 1, 1), reference_period_end=None, source_data="DATA,DATA,DATA", @@ -44,9 +44,9 @@ dict( id=5, resource_ref=1, + admin2_ref=1, org_ref=2, sector_code="WSH", - admin2_ref=1, reference_period_start=datetime(2023, 1, 1), reference_period_end=None, source_data="DATA,DATA,DATA", diff --git a/tests/sample_data/data_population_group.py b/tests/sample_data/data_population_group.py new file mode 100644 index 0000000..cf39e44 --- /dev/null +++ b/tests/sample_data/data_population_group.py @@ -0,0 +1,4 @@ +data_population_group = [ + dict(code="refugees", description="refugees"), + dict(code="idps", description="internally displaced persons"), +] diff --git a/tests/sample_data/data_population_status.py b/tests/sample_data/data_population_status.py new file mode 100644 index 0000000..f358089 --- /dev/null +++ b/tests/sample_data/data_population_status.py @@ -0,0 +1,4 @@ +data_population_status = [ + dict(code="affected", description="number of people affected"), + dict(code="inneed", description="number of people in need"), +] diff --git a/tests/test_admin1_view.py b/tests/test_admin1_view.py new file mode 100644 index 0000000..dc8c3a7 --- /dev/null +++ b/tests/test_admin1_view.py @@ -0,0 +1,15 @@ +from hdx.database.views import build_view + +from hapi_schema.db_admin1 import view_params_admin1 + + +def test_admin1_view(run_view_test): + """Check that admin1 view references location.""" + view_admin1 = build_view(view_params_admin1.__dict__) + run_view_test( + view=view_admin1, + whereclause=( + view_admin1.c.id == 1, + view_admin1.c.location_code == "FOO", + ), + ) diff --git a/tests/test_admin2_view.py b/tests/test_admin2_view.py new file mode 100644 index 0000000..9d4f09d --- /dev/null +++ b/tests/test_admin2_view.py @@ -0,0 +1,16 @@ +from hdx.database.views import build_view + +from hapi_schema.db_admin2 import view_params_admin2 + + +def test_admin2_view(run_view_test): + """Check that admin2 view references admin1 and location.""" + view_admin2 = build_view(view_params_admin2.__dict__) + run_view_test( + view=view_admin2, + whereclause=( + view_admin2.c.id == 1, + view_admin2.c.admin1_code == "FOO-XXX", + view_admin2.c.location_code == "FOO", + ), + ) diff --git a/tests/test_age_range_view.py b/tests/test_age_range_view.py new file mode 100644 index 0000000..aabbe11 --- /dev/null +++ b/tests/test_age_range_view.py @@ -0,0 +1,16 @@ +from hdx.database.views import build_view + +from hapi_schema.db_age_range import view_params_age_range + + +def test_age_range_view(run_view_test): + """Check that age range shows code and numbers.""" + view_age_range = build_view(view_params_age_range.__dict__) + run_view_test( + view=view_age_range, + whereclause=( + view_age_range.c.code == "0-4", + view_age_range.c.age_min == 0, + view_age_range.c.age_max == 4, + ), + ) diff --git a/tests/test_dataset_view.py b/tests/test_dataset_view.py new file mode 100644 index 0000000..b278e6e --- /dev/null +++ b/tests/test_dataset_view.py @@ -0,0 +1,18 @@ +from hdx.database.views import build_view + +from hapi_schema.db_dataset import view_params_dataset + + +def test_dataset_view(run_view_test): + """Check that dataset view has most columns.""" + view_dataset = build_view(view_params_dataset.__dict__) + run_view_test( + view=view_dataset, + whereclause=( + view_dataset.c.id == 1, + view_dataset.c.hdx_stub == "dataset01", + view_dataset.c.title == "Dataset #1", + view_dataset.c.hdx_provider_stub == "provider01", + view_dataset.c.hdx_provider_name == "Provider #1", + ), + ) diff --git a/tests/test_food_security_view.py b/tests/test_food_security_view.py new file mode 100644 index 0000000..67f1a5a --- /dev/null +++ b/tests/test_food_security_view.py @@ -0,0 +1,22 @@ +from hdx.database.views import build_view + +from hapi_schema.db_food_security import view_params_food_security + + +def test_food_security_view(run_view_test): + """Check that food security view references other tables.""" + view_food_security = build_view(view_params_food_security.__dict__) + run_view_test( + view=view_food_security, + whereclause=( + view_food_security.c.id == 3, + view_food_security.c.dataset_hdx_id + == "7cf3cec8-dbbc-4c96-9762-1464cd0bff75", + view_food_security.c.resource_hdx_id + == "62ad6e55-5f5d-4494-854c-4110687e9e25", + view_food_security.c.ipc_phase_name == "Phase 3: Crisis", + view_food_security.c.admin2_code == "FOO-001-A", + view_food_security.c.admin1_code == "FOO-001", + view_food_security.c.location_code == "FOO", + ), + ) diff --git a/tests/test_gender_view.py b/tests/test_gender_view.py new file mode 100644 index 0000000..1499ef7 --- /dev/null +++ b/tests/test_gender_view.py @@ -0,0 +1,15 @@ +from hdx.database.views import build_view + +from hapi_schema.db_gender import view_params_gender + + +def test_gender_view(run_view_test): + """Check gender view has all columns.""" + view_gender = build_view(view_params_gender.__dict__) + run_view_test( + view=view_gender, + whereclause=( + view_gender.c.code == "f", + view_gender.c.description == "female", + ), + ) diff --git a/tests/test_humanitarian_needs_view.py b/tests/test_humanitarian_needs_view.py new file mode 100644 index 0000000..d24136c --- /dev/null +++ b/tests/test_humanitarian_needs_view.py @@ -0,0 +1,29 @@ +from hdx.database.views import build_view + +from hapi_schema.db_humanitarian_needs import view_params_humanitarian_needs + + +def test_humanitarian_needs_view(run_view_test): + """Check that humanitarian needs references other tables.""" + view_humanitarian_needs = build_view( + view_params_humanitarian_needs.__dict__ + ) + run_view_test( + view=view_humanitarian_needs, + whereclause=( + view_humanitarian_needs.c.id == 3, + view_humanitarian_needs.c.dataset_hdx_id + == "c3f001fa-b45b-464c-9460-1ca79fd39b40", + view_humanitarian_needs.c.resource_hdx_id + == "90deb235-1bf5-4bae-b231-3393222c2d01", + view_humanitarian_needs.c.admin2_code == "FOO-001-XXX", + view_humanitarian_needs.c.admin1_code == "FOO-001", + view_humanitarian_needs.c.location_code == "FOO", + view_humanitarian_needs.c.gender_code == "f", + view_humanitarian_needs.c.disabled_marker == True, # noqa: E712 + view_humanitarian_needs.c.sector_name + == "Water Sanitation Hygiene", + view_humanitarian_needs.c.population_group_code == "idps", + view_humanitarian_needs.c.population_status_code == "inneed", + ), + ) diff --git a/tests/test_ipc_phase_view.py b/tests/test_ipc_phase_view.py new file mode 100644 index 0000000..4a6334e --- /dev/null +++ b/tests/test_ipc_phase_view.py @@ -0,0 +1,21 @@ +from hdx.database.views import build_view + +from hapi_schema.db_ipc_phase import view_params_ipc_phase + + +def test_ipc_phase_view(run_view_test): + """Check IPC phase view has all columns.""" + phase1_description = ( + "Households are able to meet essential food and non-food " + "needs without engaging in atypical and unsustainable " + "strategies to access food and income." + ) + view_ipc_phase = build_view(view_params_ipc_phase.__dict__) + run_view_test( + view=view_ipc_phase, + whereclause=( + view_ipc_phase.c.code == "1", + view_ipc_phase.c.name == "Phase 1: None/Minimal", + view_ipc_phase.c.description == phase1_description, + ), + ) diff --git a/tests/test_ipc_type_view.py b/tests/test_ipc_type_view.py new file mode 100644 index 0000000..90a75bf --- /dev/null +++ b/tests/test_ipc_type_view.py @@ -0,0 +1,17 @@ +from hdx.database.views import build_view + +from hapi_schema.db_ipc_type import view_params_ipc_type + + +def test_ipc_type_view(run_view_test): + """Check IPC type view has all columns.""" + + view_ipc_type = build_view(view_params_ipc_type.__dict__) + run_view_test( + view=view_ipc_type, + whereclause=( + view_ipc_type.c.code == "current", + view_ipc_type.c.description == "Food insecurity that is " + "occurring in the current analysis period.", + ), + ) diff --git a/tests/test_location_view.py b/tests/test_location_view.py new file mode 100644 index 0000000..6953546 --- /dev/null +++ b/tests/test_location_view.py @@ -0,0 +1,16 @@ +from hdx.database.views import build_view + +from hapi_schema.db_location import view_params_location + + +def test_location_view(run_view_test): + """Check that location view has some columns.""" + view_location = build_view(view_params_location.__dict__) + run_view_test( + view=view_location, + whereclause=( + view_location.c.id == 1, + view_location.c.code == "FOO", + view_location.c.name == "Foolandia", + ), + ) diff --git a/tests/test_operational_presence_view.py b/tests/test_operational_presence_view.py new file mode 100644 index 0000000..180c475 --- /dev/null +++ b/tests/test_operational_presence_view.py @@ -0,0 +1,30 @@ +from hdx.database.views import build_view + +from hapi_schema.db_operational_presence import ( + view_params_operational_presence, +) + + +def test_operational_presence_view(run_view_test): + """Check that OP view has all references.""" + view_operational_presence = build_view( + view_params_operational_presence.__dict__ + ) + run_view_test( + view=view_operational_presence, + whereclause=( + view_operational_presence.c.id == 5, + view_operational_presence.c.dataset_hdx_id + == "c3f001fa-b45b-464c-9460-1ca79fd39b40", + view_operational_presence.c.resource_hdx_id + == "90deb235-1bf5-4bae-b231-3393222c2d01", + view_operational_presence.c.admin2_code == "FOO-XXX-XXX", + view_operational_presence.c.admin1_code == "FOO-XXX", + view_operational_presence.c.location_code == "FOO", + view_operational_presence.c.org_type_description + == "International NGO", + view_operational_presence.c.org_acronym == "ORG02", + view_operational_presence.c.sector_name + == "Water Sanitation Hygiene", + ), + ) diff --git a/tests/test_org_type_view.py b/tests/test_org_type_view.py new file mode 100644 index 0000000..bab3541 --- /dev/null +++ b/tests/test_org_type_view.py @@ -0,0 +1,16 @@ +from hdx.database.views import build_view + +from hapi_schema.db_org_type import view_params_org_type + + +def test_org_type_view(run_view_test): + """Check that org type has all fields.""" + dict(code="433", description="Donor"), + view_org_type = build_view(view_params_org_type.__dict__) + run_view_test( + view=view_org_type, + whereclause=( + view_org_type.c.code == "433", + view_org_type.c.description == "Donor", + ), + ) diff --git a/tests/test_org_view.py b/tests/test_org_view.py new file mode 100644 index 0000000..7ca167c --- /dev/null +++ b/tests/test_org_view.py @@ -0,0 +1,16 @@ +from hdx.database.views import build_view + +from hapi_schema.db_org import view_params_org + + +def test_org_view(run_view_test): + """Check that org view references org type.""" + view_org = build_view(view_params_org.__dict__) + run_view_test( + view=view_org, + whereclause=( + view_org.c.id == 1, + view_org.c.org_type_code == "433", + view_org.c.org_type_description == "Donor", + ), + ) diff --git a/tests/test_population_group_view.py b/tests/test_population_group_view.py new file mode 100644 index 0000000..bef114b --- /dev/null +++ b/tests/test_population_group_view.py @@ -0,0 +1,16 @@ +from hdx.database.views import build_view + +from hapi_schema.db_population_group import view_params_population_group + + +def test_population_group_view(run_view_test): + """Check gender view has all columns.""" + view_population_group = build_view(view_params_population_group.__dict__) + run_view_test( + view=view_population_group, + whereclause=( + view_population_group.c.code == "idps", + view_population_group.c.description + == "internally displaced persons", + ), + ) diff --git a/tests/test_population_status_view.py b/tests/test_population_status_view.py new file mode 100644 index 0000000..d610745 --- /dev/null +++ b/tests/test_population_status_view.py @@ -0,0 +1,15 @@ +from hdx.database.views import build_view + +from hapi_schema.db_population_status import view_params_population_status + + +def test_population_status_view(run_view_test): + """Check gender view has all columns.""" + view_population_status = build_view(view_params_population_status.__dict__) + run_view_test( + view=view_population_status, + whereclause=( + view_population_status.c.code == "inneed", + view_population_status.c.description == "number of people in need", + ), + ) diff --git a/tests/test_population_view.py b/tests/test_population_view.py new file mode 100644 index 0000000..e494673 --- /dev/null +++ b/tests/test_population_view.py @@ -0,0 +1,22 @@ +from hdx.database.views import build_view + +from hapi_schema.db_population import view_params_population + + +def test_population_view(run_view_test): + """Check that population references other tables.""" + view_population = build_view(view_params_population.__dict__) + run_view_test( + view=view_population, + whereclause=( + view_population.c.id == 3, + view_population.c.dataset_hdx_id + == "c3f001fa-b45b-464c-9460-1ca79fd39b40", + view_population.c.resource_hdx_id + == "90deb235-1bf5-4bae-b231-3393222c2d01", + view_population.c.admin2_code == "FOO-001-XXX", + view_population.c.admin1_code == "FOO-001", + view_population.c.location_code == "FOO", + view_population.c.gender_code == "f", + ), + ) diff --git a/tests/test_resource_view.py b/tests/test_resource_view.py new file mode 100644 index 0000000..6a557ae --- /dev/null +++ b/tests/test_resource_view.py @@ -0,0 +1,16 @@ +from hdx.database.views import build_view + +from hapi_schema.db_resource import view_params_resource + + +def test_resource_view(run_view_test): + """Check that resource references dataset.""" + view_resource = build_view(view_params_resource.__dict__) + run_view_test( + view=view_resource, + whereclause=( + view_resource.c.id == 1, + view_resource.c.dataset_hdx_id + == "c3f001fa-b45b-464c-9460-1ca79fd39b40", + ), + ) diff --git a/tests/test_sector_view.py b/tests/test_sector_view.py new file mode 100644 index 0000000..3fb977e --- /dev/null +++ b/tests/test_sector_view.py @@ -0,0 +1,15 @@ +from hdx.database.views import build_view + +from hapi_schema.db_sector import view_params_sector + + +def test_sector_view(run_view_test): + """Check that sector view shows some columns.""" + view_sector = build_view(view_params_sector.__dict__) + run_view_test( + view=view_sector, + whereclause=( + view_sector.c.code == "SHL", + view_sector.c.name == "Emergency Shelter and NFI", + ), + ) diff --git a/tests/test_views.py b/tests/test_views.py deleted file mode 100644 index 419c811..0000000 --- a/tests/test_views.py +++ /dev/null @@ -1,241 +0,0 @@ -from hdx.database.views import build_view - -from hapi_schema.db_admin1 import view_params_admin1 -from hapi_schema.db_admin2 import view_params_admin2 -from hapi_schema.db_age_range import view_params_age_range -from hapi_schema.db_dataset import view_params_dataset -from hapi_schema.db_food_security import view_params_food_security -from hapi_schema.db_gender import view_params_gender -from hapi_schema.db_ipc_phase import view_params_ipc_phase -from hapi_schema.db_ipc_type import view_params_ipc_type -from hapi_schema.db_location import view_params_location -from hapi_schema.db_operational_presence import ( - view_params_operational_presence, -) -from hapi_schema.db_org import view_params_org -from hapi_schema.db_org_type import view_params_org_type -from hapi_schema.db_population import view_params_population -from hapi_schema.db_resource import view_params_resource -from hapi_schema.db_sector import view_params_sector - - -def test_admin1_view(run_view_test): - """Check that admin1 view references location.""" - view_admin1 = build_view(view_params_admin1.__dict__) - run_view_test( - view=view_admin1, - whereclause=( - view_admin1.c.id == 1, - view_admin1.c.location_code == "FOO", - ), - ) - - -def test_admin2_view(run_view_test): - """Check that admin2 view references admin1 and location.""" - view_admin2 = build_view(view_params_admin2.__dict__) - run_view_test( - view=view_admin2, - whereclause=( - view_admin2.c.id == 1, - view_admin2.c.admin1_code == "FOO-XXX", - view_admin2.c.location_code == "FOO", - ), - ) - - -def test_age_range_view(run_view_test): - """Check that age range shows code and numbers.""" - view_age_range = build_view(view_params_age_range.__dict__) - run_view_test( - view=view_age_range, - whereclause=( - view_age_range.c.code == "0-4", - view_age_range.c.age_min == 0, - view_age_range.c.age_max == 4, - ), - ) - - -def test_dataset_view(run_view_test): - """Check that dataset view has most columns.""" - view_dataset = build_view(view_params_dataset.__dict__) - run_view_test( - view=view_dataset, - whereclause=( - view_dataset.c.id == 1, - view_dataset.c.hdx_stub == "dataset01", - view_dataset.c.title == "Dataset #1", - view_dataset.c.hdx_provider_stub == "provider01", - view_dataset.c.hdx_provider_name == "Provider #1", - ), - ) - - -def test_food_security_view(run_view_test): - """Check that food security view references other tables.""" - view_food_security = build_view(view_params_food_security.__dict__) - run_view_test( - view=view_food_security, - whereclause=( - view_food_security.c.id == 3, - view_food_security.c.dataset_hdx_id - == "7cf3cec8-dbbc-4c96-9762-1464cd0bff75", - view_food_security.c.resource_hdx_id - == "62ad6e55-5f5d-4494-854c-4110687e9e25", - view_food_security.c.ipc_phase_name == "Phase 3: Crisis", - view_food_security.c.admin2_code == "FOO-001-A", - view_food_security.c.admin1_code == "FOO-001", - view_food_security.c.location_code == "FOO", - ), - ) - - -def test_gender_view(run_view_test): - """Check gender view has all columns.""" - view_gender = build_view(view_params_gender.__dict__) - run_view_test( - view=view_gender, - whereclause=( - view_gender.c.code == "f", - view_gender.c.description == "female", - ), - ) - - -def test_ipc_phase_view(run_view_test): - """Check IPC phase view has all columns.""" - phase1_description = ( - "Households are able to meet essential food and non-food " - "needs without engaging in atypical and unsustainable " - "strategies to access food and income." - ) - view_ipc_phase = build_view(view_params_ipc_phase.__dict__) - run_view_test( - view=view_ipc_phase, - whereclause=( - view_ipc_phase.c.code == "1", - view_ipc_phase.c.name == "Phase 1: None/Minimal", - view_ipc_phase.c.description == phase1_description, - ), - ) - - -def test_ipc_type_view(run_view_test): - """Check IPC type view has all columns.""" - - view_ipc_type = build_view(view_params_ipc_type.__dict__) - run_view_test( - view=view_ipc_type, - whereclause=( - view_ipc_type.c.code == "current", - view_ipc_type.c.description == "Food insecurity that is " - "occurring in the current analysis period.", - ), - ) - - -def test_location_view(run_view_test): - """Check that location view has some columns.""" - view_location = build_view(view_params_location.__dict__) - run_view_test( - view=view_location, - whereclause=( - view_location.c.id == 1, - view_location.c.code == "FOO", - view_location.c.name == "Foolandia", - ), - ) - - -def test_operational_presence_view(run_view_test): - """Check that OP view has all references.""" - view_operational_presence = build_view( - view_params_operational_presence.__dict__ - ) - run_view_test( - view=view_operational_presence, - whereclause=( - view_operational_presence.c.id == 5, - view_operational_presence.c.dataset_hdx_id - == "c3f001fa-b45b-464c-9460-1ca79fd39b40", - view_operational_presence.c.resource_hdx_id - == "90deb235-1bf5-4bae-b231-3393222c2d01", - view_operational_presence.c.admin2_code == "FOO-XXX-XXX", - view_operational_presence.c.admin1_code == "FOO-XXX", - view_operational_presence.c.location_code == "FOO", - view_operational_presence.c.org_type_description - == "International NGO", - view_operational_presence.c.org_acronym == "ORG02", - ), - ) - - -def test_org_view(run_view_test): - """Check that org view references org type.""" - view_org = build_view(view_params_org.__dict__) - run_view_test( - view=view_org, - whereclause=( - view_org.c.id == 1, - view_org.c.org_type_code == "433", - view_org.c.org_type_description == "Donor", - ), - ) - - -def test_org_type_view(run_view_test): - """Check that org type has all fields.""" - dict(code="433", description="Donor"), - view_org_type = build_view(view_params_org_type.__dict__) - run_view_test( - view=view_org_type, - whereclause=( - view_org_type.c.code == "433", - view_org_type.c.description == "Donor", - ), - ) - - -def test_population_view(run_view_test): - """Check that population references other tables.""" - view_population = build_view(view_params_population.__dict__) - run_view_test( - view=view_population, - whereclause=( - view_population.c.id == 3, - view_population.c.dataset_hdx_id - == "c3f001fa-b45b-464c-9460-1ca79fd39b40", - view_population.c.resource_hdx_id - == "90deb235-1bf5-4bae-b231-3393222c2d01", - view_population.c.gender_description == "female", - view_population.c.admin2_code == "FOO-001-XXX", - view_population.c.admin1_code == "FOO-001", - view_population.c.location_code == "FOO", - ), - ) - - -def test_resource_view(run_view_test): - """Check that resource references dataset.""" - view_resource = build_view(view_params_resource.__dict__) - run_view_test( - view=view_resource, - whereclause=( - view_resource.c.id == 1, - view_resource.c.dataset_hdx_id - == "c3f001fa-b45b-464c-9460-1ca79fd39b40", - ), - ) - - -def test_sector_view(run_view_test): - """Check that sector view shows some columns.""" - view_sector = build_view(view_params_sector.__dict__) - run_view_test( - view=view_sector, - whereclause=( - view_sector.c.code == "SHL", - view_sector.c.name == "Emergency Shelter and NFI", - ), - )