Skip to content

Commit ffa73b4

Browse files
committed
Use upsert strategy
- Add field admindiv.gaul - Do not use TRUNCATE CASCADE - Use UPSERT strategy for admindivs - Maintain contacts and recommandations relations using GAUL - Add class docstring
1 parent f7ed482 commit ffa73b4

File tree

6 files changed

+431
-51
lines changed

6 files changed

+431
-51
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""Add field admindiv.gaul
2+
3+
Revision ID: 50e54a034fa5
4+
Revises: cdcea4ae97ed
5+
Create Date: 2025-12-19 12:21:52.532645
6+
7+
"""
8+
9+
# revision identifiers, used by Alembic.
10+
revision = '50e54a034fa5'
11+
down_revision = 'cdcea4ae97ed'
12+
branch_labels = None
13+
depends_on = None
14+
15+
from alembic import op
16+
import sqlalchemy as sa
17+
18+
19+
def upgrade(engine_name):
20+
op.add_column(
21+
'administrativedivision',
22+
sa.Column('gaul', sa.Integer(), nullable=True),
23+
schema='datamart',
24+
)
25+
op.create_index(
26+
op.f('ix_datamart_administrativedivision_gaul'),
27+
'administrativedivision',
28+
['gaul'],
29+
# unique=True,
30+
schema='datamart',
31+
)
32+
33+
def downgrade(engine_name):
34+
op.drop_index(
35+
op.f('ix_datamart_administrativedivision_gaul'),
36+
table_name='administrativedivision',
37+
schema='datamart',
38+
)
39+
op.drop_column('administrativedivision', 'gaul', schema='datamart')

tests/data/ADM2.geojson

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"type": "FeatureCollection",
3-
"name": "TH_ADM2_sample",
3+
"name": "ADM2",
44
"crs": {
55
"type": "name",
66
"properties": {

tests/data/URB.geojson

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"type": "FeatureCollection",
3-
"name": "TH_URB_sample",
3+
"name": "URB",
44
"crs": {
55
"type": "name",
66
"properties": {

tests/processing/test_import_geopackage.py

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,14 @@
2222
import geopandas as gpd
2323
from mock import patch
2424

25-
from thinkhazard.models import AdministrativeDivision
25+
from thinkhazard.models import (
26+
AdministrativeDivision,
27+
ClimateChangeRecommendation,
28+
ClimateChangeRecAdministrativeDivisionAssociation,
29+
Contact,
30+
ContactAdministrativeDivisionHazardTypeAssociation,
31+
HazardType,
32+
)
2633
from thinkhazard.processing.import_geopackage import GeopackageImporter
2734

2835
from .. import DBSession, engine, settings, DATA_FOLDER
@@ -39,9 +46,9 @@
3946

4047
def mock_read_file(path, layer=None, **kwargs):
4148
if layer == "ADM2":
42-
return _real_read_file(ADM2_PATH, engine="pyogrio")
49+
return _real_read_file(ADM2_PATH, layer=layer, engine="pyogrio")
4350
if layer == "URB":
44-
return _real_read_file(URBAN_PATH, engine="pyogrio")
51+
return _real_read_file(URBAN_PATH, layer=layer, engine="pyogrio")
4552
else:
4653
raise ValueError(f"Unknown layer: {layer}")
4754

@@ -76,3 +83,72 @@ def test_dry_run(self, mock_read):
7683
assert DBSession.query(AdministrativeDivision).count() == 3
7784
self.importer().execute(geopackage_path=ADM2_PATH, verbose=True, dry_run=True)
7885
assert DBSession.query(AdministrativeDivision).count() == 3
86+
87+
@patch(
88+
"thinkhazard.processing.import_geopackage.gpd.read_file",
89+
side_effect=mock_read_file,
90+
)
91+
def test_contact_gaul(self, mock_read):
92+
"""Test that contacts are correctly mapped using GAUL."""
93+
94+
administrativedivision = AdministrativeDivision(
95+
code="999999", # GAUL
96+
leveltype_id=1,
97+
name="test",
98+
)
99+
DBSession.add(administrativedivision)
100+
101+
contact = Contact(
102+
name="test",
103+
)
104+
DBSession.add(contact)
105+
106+
hazardtype = DBSession.query(HazardType).first()
107+
108+
rel = ContactAdministrativeDivisionHazardTypeAssociation(
109+
contact=contact,
110+
administrativedivision=administrativedivision,
111+
hazardtype=hazardtype,
112+
)
113+
DBSession.add(rel)
114+
DBSession.flush()
115+
116+
self.importer().execute(geopackage_path=ADM2_PATH, verbose=True)
117+
118+
DBSession.expire_all()
119+
assert rel.administrativedivision.code == "TST"
120+
121+
@patch(
122+
"thinkhazard.processing.import_geopackage.gpd.read_file",
123+
side_effect=mock_read_file,
124+
)
125+
def test_climatechangerecommendation_gaul(self, mock_read):
126+
"""Test that climatechangerecommandations are correctly mapped using GAUL."""
127+
128+
administrativedivision = AdministrativeDivision(
129+
code="999999", # GAUL
130+
leveltype_id=1,
131+
name="test",
132+
)
133+
DBSession.add(administrativedivision)
134+
135+
hazardtype = DBSession.query(HazardType).first()
136+
137+
climatechangerecommendation = ClimateChangeRecommendation(
138+
text="test",
139+
hazardtype=hazardtype,
140+
)
141+
DBSession.add(climatechangerecommendation)
142+
143+
rel = ClimateChangeRecAdministrativeDivisionAssociation(
144+
climatechangerecommendation=climatechangerecommendation,
145+
administrativedivision=administrativedivision,
146+
hazardtype=hazardtype,
147+
)
148+
DBSession.add(rel)
149+
DBSession.flush()
150+
151+
self.importer().execute(geopackage_path=ADM2_PATH, verbose=True)
152+
153+
DBSession.expire_all()
154+
assert rel.administrativedivision.code == "TST"

thinkhazard/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ class AdministrativeDivision(Base):
282282

283283
id = Column(Integer, primary_key=True)
284284
code = Column(String, index=True, unique=True, nullable=False)
285+
gaul = Column(Integer, index=True)
285286
leveltype_id = Column(
286287
Integer, ForeignKey(AdminLevelType.id), nullable=False, index=True
287288
)

0 commit comments

Comments
 (0)