hestia-earth-models 0.64.14__py3-none-any.whl → 0.65.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of hestia-earth-models might be problematic. Click here for more details.
- hestia_earth/models/agribalyse2016/fuelElectricity.py +1 -1
- hestia_earth/models/cache_sites.py +15 -24
- hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsLandTransformation.py +6 -9
- hestia_earth/models/cycle/input/hestiaAggregatedData.py +46 -22
- hestia_earth/models/cycle/pre_checks/cache_sources.py +3 -25
- hestia_earth/models/cycle/product/economicValueShare.py +2 -2
- hestia_earth/models/ecoinventV3/__init__.py +3 -2
- hestia_earth/models/ecoinventV3/utils.py +1 -2
- hestia_earth/models/ecoinventV3AndEmberClimate/__init__.py +3 -2
- hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandTransformation.py +17 -37
- hestia_earth/models/faostat2018/landTransformation100YearAverageDuringCycle.py +34 -0
- hestia_earth/models/faostat2018/landTransformation20YearAverageDuringCycle.py +34 -0
- hestia_earth/models/faostat2018/utils.py +47 -3
- hestia_earth/models/hestia/landCover.py +5 -5
- hestia_earth/models/hestia/seed_emissions.py +284 -0
- hestia_earth/models/ipcc2019/aboveGroundBiomass.py +2 -2
- hestia_earth/models/ipcc2019/belowGroundBiomass.py +8 -2
- hestia_earth/models/ipcc2019/biomass_utils.py +11 -4
- hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +19 -10
- hestia_earth/models/ipcc2019/co2ToAirAboveGroundBiomassStockChange.py +2 -1
- hestia_earth/models/ipcc2019/co2ToAirBelowGroundBiomassStockChange.py +2 -1
- hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +8 -7
- hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChange.py +2 -1
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1_utils.py +28 -34
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2_utils.py +8 -12
- hestia_earth/models/ipcc2019/organicCarbonPerHa_utils.py +13 -30
- hestia_earth/models/linkedImpactAssessment/freshwaterWithdrawalsInputsProduction.py +4 -1
- hestia_earth/models/linkedImpactAssessment/landOccupationInputsProduction.py +16 -1
- hestia_earth/models/linkedImpactAssessment/{landTransformationFromForest100YearAverageInputsProduction.py → landTransformation100YearAverageInputsProduction.py} +8 -3
- hestia_earth/models/linkedImpactAssessment/{landTransformationFromCropland100YearAverageInputsProduction.py → landTransformation20YearAverageInputsProduction.py} +8 -3
- hestia_earth/models/linkedImpactAssessment/utils.py +80 -16
- hestia_earth/models/mocking/search-results.json +448 -448
- hestia_earth/models/pooreNemecek2018/excretaKgN.py +45 -41
- hestia_earth/models/pooreNemecek2018/excretaKgVs.py +89 -63
- hestia_earth/models/pooreNemecek2018/saplingsDepreciatedAmountPerCycle.py +8 -8
- hestia_earth/models/pooreNemecek2018/utils.py +60 -19
- hestia_earth/models/schererPfister2015/nErosionSoilFlux.py +4 -3
- hestia_earth/models/schererPfister2015/pErosionSoilFlux.py +4 -3
- hestia_earth/models/schererPfister2015/utils.py +12 -9
- hestia_earth/models/site/management.py +70 -55
- hestia_earth/models/site/pre_checks/cache_sources.py +2 -20
- hestia_earth/models/utils/__init__.py +12 -1
- hestia_earth/models/utils/aggregated.py +1 -1
- hestia_earth/models/utils/blank_node.py +20 -12
- hestia_earth/models/utils/cache_sources.py +15 -0
- hestia_earth/models/utils/crop.py +5 -0
- hestia_earth/models/utils/indicator.py +3 -1
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.64.14.dist-info → hestia_earth_models-0.65.1.dist-info}/LICENSE +1 -1
- {hestia_earth_models-0.64.14.dist-info → hestia_earth_models-0.65.1.dist-info}/METADATA +3 -3
- {hestia_earth_models-0.64.14.dist-info → hestia_earth_models-0.65.1.dist-info}/RECORD +80 -109
- tests/models/cml2001Baseline/test_abioticResourceDepletionMineralsAndMetals.py +1 -1
- tests/models/cycle/input/test_hestiaAggregatedData.py +5 -2
- tests/models/environmentalFootprintV3/test_soilQualityIndexLandTransformation.py +39 -28
- tests/models/{hyde32/test_landTransformationFromForest20YearAverageDuringCycle.py → faostat2018/test_landTransformation100YearAverageDuringCycle.py} +5 -5
- tests/models/{hyde32/test_landTransformationFromForest100YearAverageDuringCycle.py → faostat2018/test_landTransformation20YearAverageDuringCycle.py} +5 -5
- tests/models/faostat2018/test_utils.py +28 -0
- tests/models/hestia/test_landCover.py +2 -1
- tests/models/hestia/test_seed_emissions.py +27 -0
- tests/models/ipcc2019/test_aboveGroundBiomass.py +40 -4
- tests/models/ipcc2019/test_belowGroundBiomass.py +40 -4
- tests/models/ipcc2019/test_co2ToAirAboveGroundBiomassStockChange.py +52 -15
- tests/models/ipcc2019/test_co2ToAirBelowGroundBiomassStockChange.py +50 -14
- tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChange.py +53 -32
- tests/models/ipcc2019/test_organicCarbonPerHa.py +91 -108
- tests/models/ipcc2019/test_organicCarbonPerHa_tier_1_utils.py +33 -50
- tests/models/ipcc2019/test_organicCarbonPerHa_tier_2_utils.py +0 -52
- tests/models/linkedImpactAssessment/test_freshwaterWithdrawalsInputsProduction.py +6 -4
- tests/models/linkedImpactAssessment/test_landOccupationInputsProduction.py +6 -4
- tests/models/linkedImpactAssessment/{test_landTransformationFromForest100YearAverageInputsProduction.py → test_landTransformation100YearAverageInputsProduction.py} +7 -5
- tests/models/linkedImpactAssessment/{test_landTransformationFromForest20YearAverageInputsProduction.py → test_landTransformation20YearAverageInputsProduction.py} +7 -5
- tests/models/pooreNemecek2018/test_excretaKgN.py +2 -2
- tests/models/pooreNemecek2018/test_excretaKgVs.py +1 -1
- tests/models/pooreNemecek2018/test_utils.py +26 -0
- tests/models/site/test_management.py +10 -27
- tests/models/test_cache_sites.py +40 -12
- tests/models/utils/test_blank_node.py +0 -8
- tests/models/utils/test_cache_sources.py +21 -0
- hestia_earth/models/blonkConsultants2016/landTransformationFromForest20YearAverageDuringCycle.py +0 -90
- hestia_earth/models/faostat2018/landTransformationFromCropland100YearAverage.py +0 -74
- hestia_earth/models/faostat2018/landTransformationFromCropland20YearAverage.py +0 -74
- hestia_earth/models/hyde32/__init__.py +0 -13
- hestia_earth/models/hyde32/landTransformationFromCropland100YearAverageDuringCycle.py +0 -60
- hestia_earth/models/hyde32/landTransformationFromCropland20YearAverageDuringCycle.py +0 -60
- hestia_earth/models/hyde32/landTransformationFromForest100YearAverageDuringCycle.py +0 -60
- hestia_earth/models/hyde32/landTransformationFromForest20YearAverageDuringCycle.py +0 -60
- hestia_earth/models/hyde32/landTransformationFromOtherNaturalVegetation100YearAverageDuringCycle.py +0 -61
- hestia_earth/models/hyde32/landTransformationFromOtherNaturalVegetation20YearAverageDuringCycle.py +0 -61
- hestia_earth/models/hyde32/landTransformationFromPermanentPasture100YearAverageDuringCycle.py +0 -61
- hestia_earth/models/hyde32/landTransformationFromPermanentPasture20YearAverageDuringCycle.py +0 -61
- hestia_earth/models/hyde32/utils.py +0 -72
- hestia_earth/models/linkedImpactAssessment/landTransformationFromCropland20YearAverageInputsProduction.py +0 -36
- hestia_earth/models/linkedImpactAssessment/landTransformationFromForest20YearAverageInputsProduction.py +0 -36
- hestia_earth/models/linkedImpactAssessment/landTransformationFromOtherNaturalVegetation100YearAverageInputsProduction.py +0 -36
- hestia_earth/models/linkedImpactAssessment/landTransformationFromOtherNaturalVegetation20YearAverageInputsProduction.py +0 -36
- hestia_earth/models/linkedImpactAssessment/landTransformationFromPermanentPasture100YearAverageInputsProduction.py +0 -36
- hestia_earth/models/linkedImpactAssessment/landTransformationFromPermanentPasture20YearAverageInputsProduction.py +0 -36
- tests/models/blonkConsultants2016/test_landTransformationFromForest20YearAverageDuringCycle.py +0 -36
- tests/models/cycle/pre_checks/test_cache_sources.py +0 -25
- tests/models/faostat2018/test_landTransformationFromCropland100YearAverage.py +0 -40
- tests/models/faostat2018/test_landTransformationFromCropland20YearAverage.py +0 -40
- tests/models/hyde32/__init__.py +0 -0
- tests/models/hyde32/test_landTransformationFromCropland100YearAverageDuringCycle.py +0 -21
- tests/models/hyde32/test_landTransformationFromCropland20YearAverageDuringCycle.py +0 -21
- tests/models/hyde32/test_landTransformationFromOtherNaturalVegetation100YearAverageDuringCycle.py +0 -23
- tests/models/hyde32/test_landTransformationFromOtherNaturalVegetation20YearAverageDuringCycle.py +0 -21
- tests/models/hyde32/test_landTransformationFromPermanentPasture100YearAverageDuringCycle.py +0 -21
- tests/models/hyde32/test_landTransformationFromPermanentPasture20YearAverageDuringCycle.py +0 -21
- tests/models/linkedImpactAssessment/test_landTransformationFromCropland100YearAverageInputsProduction.py +0 -23
- tests/models/linkedImpactAssessment/test_landTransformationFromCropland20YearAverageInputsProduction.py +0 -23
- tests/models/linkedImpactAssessment/test_landTransformationFromOtherNaturalVegetation100YearAverageInputsProduction.py +0 -23
- tests/models/linkedImpactAssessment/test_landTransformationFromOtherNaturalVegetation20YearAverageInputsProduction.py +0 -23
- tests/models/linkedImpactAssessment/test_landTransformationFromPermanentPasture100YearAverageInputsProduction.py +0 -24
- tests/models/linkedImpactAssessment/test_landTransformationFromPermanentPasture20YearAverageInputsProduction.py +0 -24
- tests/models/site/pre_checks/test_cache_sources.py +0 -21
- {hestia_earth_models-0.64.14.dist-info → hestia_earth_models-0.65.1.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.64.14.dist-info → hestia_earth_models-0.65.1.dist-info}/top_level.txt +0 -0
|
@@ -2,7 +2,7 @@ from functools import reduce
|
|
|
2
2
|
import json
|
|
3
3
|
from os.path import isfile
|
|
4
4
|
from pytest import mark
|
|
5
|
-
from unittest.mock import patch
|
|
5
|
+
from unittest.mock import MagicMock, patch
|
|
6
6
|
|
|
7
7
|
from hestia_earth.models.ipcc2019.co2ToAirBelowGroundBiomassStockChange import MODEL, run
|
|
8
8
|
|
|
@@ -10,8 +10,26 @@ from tests.utils import fake_new_emission, fixtures_path, order_list
|
|
|
10
10
|
|
|
11
11
|
class_path = f"hestia_earth.models.{MODEL}.co2ToAirBelowGroundBiomassStockChange"
|
|
12
12
|
utils_path = f"hestia_earth.models.{MODEL}.co2ToAirCarbonStockChange_utils"
|
|
13
|
+
biomass_utils_path = f"hestia_earth.models.{MODEL}.biomass_utils"
|
|
14
|
+
term_path = "hestia_earth.models.utils.term"
|
|
13
15
|
fixtures_folder = f"{fixtures_path}/{MODEL}/co2ToAirBelowGroundBiomassStockChange"
|
|
14
16
|
|
|
17
|
+
COVER_CROP_PROPERTY_TERM_IDS = [
|
|
18
|
+
"catchCrop",
|
|
19
|
+
"coverCrop",
|
|
20
|
+
"groundCover",
|
|
21
|
+
"longFallowCrop",
|
|
22
|
+
"shortFallowCrop"
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _load_fixture(path: str, default=None):
|
|
27
|
+
if isfile(path):
|
|
28
|
+
with open(path, encoding="utf-8") as f:
|
|
29
|
+
return json.load(f)
|
|
30
|
+
return default
|
|
31
|
+
|
|
32
|
+
|
|
15
33
|
RUN_SCENARIOS = [
|
|
16
34
|
("no-overlapping-cycles", 3),
|
|
17
35
|
("overlapping-cycles", 4),
|
|
@@ -21,18 +39,11 @@ RUN_SCENARIOS = [
|
|
|
21
39
|
("non-consecutive-biomass-measurements", 1), # Closes issue #827
|
|
22
40
|
("multiple-method-classifications", 5), # Closes issue #764
|
|
23
41
|
("non-soil-based-gohac-system", 3), # Closes issue #848
|
|
24
|
-
("with-gapfilled-start-date-end-date", 1)
|
|
42
|
+
("with-gapfilled-start-date-end-date", 1), # Closes issue #972
|
|
43
|
+
("forest-to-orchard-with-ground-cover", 3) # Closes issue #989
|
|
25
44
|
]
|
|
26
45
|
"""List of (subfolder: str, num_cycles: int)."""
|
|
27
46
|
|
|
28
|
-
|
|
29
|
-
def _load_fixture(path: str, default=None):
|
|
30
|
-
if isfile(path):
|
|
31
|
-
with open(path, encoding="utf-8") as f:
|
|
32
|
-
return json.load(f)
|
|
33
|
-
return default
|
|
34
|
-
|
|
35
|
-
|
|
36
47
|
RUN_PARAMS = reduce(
|
|
37
48
|
lambda params, scenario: params + [(scenario[0], scenario[1], i) for i in range(scenario[1])],
|
|
38
49
|
RUN_SCENARIOS,
|
|
@@ -47,7 +58,18 @@ RUN_IDS = [f"{param[0]}, cycle{param[2]}" for param in RUN_PARAMS]
|
|
|
47
58
|
@patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
|
|
48
59
|
@patch(f"{utils_path}.related_cycles")
|
|
49
60
|
@patch(f"{utils_path}._get_site")
|
|
50
|
-
|
|
61
|
+
@patch(f"{biomass_utils_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
62
|
+
@patch(f"{term_path}.search")
|
|
63
|
+
def test_run(
|
|
64
|
+
search_mock: MagicMock,
|
|
65
|
+
get_cover_crop_property_terms_mock: MagicMock,
|
|
66
|
+
get_site_mock: MagicMock,
|
|
67
|
+
related_cycles_mock: MagicMock,
|
|
68
|
+
_new_emission_mock: MagicMock,
|
|
69
|
+
subfolder: str,
|
|
70
|
+
num_cycles: int,
|
|
71
|
+
cycle_index: int
|
|
72
|
+
):
|
|
51
73
|
"""
|
|
52
74
|
Test `run` function for each cycle in each scenario.
|
|
53
75
|
"""
|
|
@@ -59,25 +81,39 @@ def test_run(_get_site_mock, related_cycles_mock, _new_emission_mock, subfolder,
|
|
|
59
81
|
_load_fixture(f"{fixtures_folder}/{subfolder}/cycle{i}.jsonld") for i in range(num_cycles)
|
|
60
82
|
]
|
|
61
83
|
|
|
62
|
-
|
|
84
|
+
get_site_mock.return_value = site
|
|
63
85
|
related_cycles_mock.return_value = cycles
|
|
64
86
|
|
|
65
87
|
result = run(cycle)
|
|
66
88
|
assert order_list(result) == order_list(expected)
|
|
67
89
|
|
|
90
|
+
assert get_cover_crop_property_terms_mock.call_count <= 1 # assert the API call is only requested once
|
|
91
|
+
search_mock.assert_not_called() # assert the API call is properly mocked
|
|
92
|
+
|
|
68
93
|
|
|
69
94
|
@patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
|
|
70
95
|
@patch(f"{utils_path}.related_cycles")
|
|
71
96
|
@patch(f"{utils_path}._get_site")
|
|
72
|
-
|
|
97
|
+
@patch(f"{biomass_utils_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
98
|
+
@patch(f"{term_path}.search")
|
|
99
|
+
def test_run_empty(
|
|
100
|
+
search_mock: MagicMock,
|
|
101
|
+
get_cover_crop_property_terms_mock: MagicMock,
|
|
102
|
+
get_site_mock: MagicMock,
|
|
103
|
+
related_cycles_mock: MagicMock,
|
|
104
|
+
_new_emission_mock: MagicMock
|
|
105
|
+
):
|
|
73
106
|
"""
|
|
74
107
|
Test `run` function for each cycle in each scenario.
|
|
75
108
|
"""
|
|
76
109
|
CYCLE = {}
|
|
77
110
|
EXPECTED = []
|
|
78
111
|
|
|
79
|
-
|
|
112
|
+
get_site_mock.return_value = {}
|
|
80
113
|
related_cycles_mock.return_value = [CYCLE]
|
|
81
114
|
|
|
82
115
|
result = run(CYCLE)
|
|
83
116
|
assert result == EXPECTED
|
|
117
|
+
|
|
118
|
+
assert get_cover_crop_property_terms_mock.call_count <= 1 # assert the API call is only requested once
|
|
119
|
+
search_mock.assert_not_called() # assert the API call is properly mocked
|
|
@@ -2,7 +2,7 @@ from functools import reduce
|
|
|
2
2
|
import json
|
|
3
3
|
from os.path import isfile
|
|
4
4
|
from pytest import mark
|
|
5
|
-
from unittest.mock import patch
|
|
5
|
+
from unittest.mock import MagicMock, patch
|
|
6
6
|
|
|
7
7
|
from hestia_earth.models.ipcc2019.co2ToAirSoilOrganicCarbonStockChange import MODEL, run
|
|
8
8
|
|
|
@@ -11,9 +11,17 @@ from tests.utils import fake_new_emission, fixtures_path, order_list
|
|
|
11
11
|
class_path = f"hestia_earth.models.{MODEL}.co2ToAirSoilOrganicCarbonStockChange"
|
|
12
12
|
utils_path = f"hestia_earth.models.{MODEL}.co2ToAirCarbonStockChange_utils"
|
|
13
13
|
soc_utils_path = f"hestia_earth.models.{MODEL}.organicCarbonPerHa_utils"
|
|
14
|
-
|
|
14
|
+
soc_tier_1_utils_path = f"hestia_earth.models.{MODEL}.organicCarbonPerHa_tier_1_utils"
|
|
15
|
+
term_path = "hestia_earth.models.utils.term"
|
|
15
16
|
fixtures_folder = f"{fixtures_path}/{MODEL}/co2ToAirSoilOrganicCarbonStockChange"
|
|
16
17
|
|
|
18
|
+
COVER_CROP_PROPERTY_TERM_IDS = [
|
|
19
|
+
"catchCrop",
|
|
20
|
+
"coverCrop",
|
|
21
|
+
"groundCover",
|
|
22
|
+
"longFallowCrop",
|
|
23
|
+
"shortFallowCrop"
|
|
24
|
+
]
|
|
17
25
|
|
|
18
26
|
IRRIGATED_TERM_IDS = [
|
|
19
27
|
"rainfedDeepWater",
|
|
@@ -38,6 +46,14 @@ UPLAND_RICE_LAND_COVER_TERM_IDS = [
|
|
|
38
46
|
"ricePlantUpland"
|
|
39
47
|
]
|
|
40
48
|
|
|
49
|
+
|
|
50
|
+
def _load_fixture(path: str, default=None):
|
|
51
|
+
if isfile(path):
|
|
52
|
+
with open(path, encoding="utf-8") as f:
|
|
53
|
+
return json.load(f)
|
|
54
|
+
return default
|
|
55
|
+
|
|
56
|
+
|
|
41
57
|
RUN_SCENARIOS = [
|
|
42
58
|
("no-overlapping-cycles", 3),
|
|
43
59
|
("overlapping-cycles", 4),
|
|
@@ -47,18 +63,11 @@ RUN_SCENARIOS = [
|
|
|
47
63
|
("non-consecutive-organic-carbon-measurements", 1), # Closes issue #827
|
|
48
64
|
("multiple-method-classifications", 5), # Closes issue #764
|
|
49
65
|
("non-soil-based-gohac-system", 3), # Closes issue #848
|
|
50
|
-
("with-gapfilled-start-date-end-date", 1)
|
|
66
|
+
("with-gapfilled-start-date-end-date", 1), # Closes issue #972
|
|
67
|
+
("forest-to-orchard-with-ground-cover", 3) # Closes issue #989
|
|
51
68
|
]
|
|
52
69
|
"""List of (subfolder: str, num_cycles: int)."""
|
|
53
70
|
|
|
54
|
-
|
|
55
|
-
def _load_fixture(path: str, default=None):
|
|
56
|
-
if isfile(path):
|
|
57
|
-
with open(path, encoding="utf-8") as f:
|
|
58
|
-
return json.load(f)
|
|
59
|
-
return default
|
|
60
|
-
|
|
61
|
-
|
|
62
71
|
RUN_PARAMS = reduce(
|
|
63
72
|
lambda params, scenario: params + [(scenario[0], scenario[1], i) for i in range(scenario[1])],
|
|
64
73
|
RUN_SCENARIOS,
|
|
@@ -73,19 +82,21 @@ RUN_IDS = [f"{param[0]}, cycle{param[2]}" for param in RUN_PARAMS]
|
|
|
73
82
|
@patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
|
|
74
83
|
@patch(f"{utils_path}.related_cycles")
|
|
75
84
|
@patch(f"{utils_path}._get_site")
|
|
76
|
-
@patch(f"{
|
|
85
|
+
@patch(f"{soc_tier_1_utils_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
77
86
|
@patch(f"{soc_utils_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
78
|
-
@patch(f"{
|
|
87
|
+
@patch(f"{soc_utils_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
88
|
+
@patch(f"{term_path}.search")
|
|
79
89
|
def test_run(
|
|
80
|
-
search_mock,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
search_mock: MagicMock,
|
|
91
|
+
_get_cover_crop_property_terms_mock: MagicMock,
|
|
92
|
+
_get_irrigated_terms_mock: MagicMock,
|
|
93
|
+
_get_upland_rice_land_cover_terms_mock: MagicMock,
|
|
94
|
+
get_site_mock: MagicMock,
|
|
95
|
+
related_cycles_mock: MagicMock,
|
|
96
|
+
_new_emission_mock: MagicMock,
|
|
97
|
+
subfolder: str,
|
|
98
|
+
num_cycles: int,
|
|
99
|
+
cycle_index: int
|
|
89
100
|
):
|
|
90
101
|
"""
|
|
91
102
|
Test `run` function for each cycle in each scenario.
|
|
@@ -98,33 +109,43 @@ def test_run(
|
|
|
98
109
|
_load_fixture(f"{fixtures_folder}/{subfolder}/cycle{i}.jsonld") for i in range(num_cycles)
|
|
99
110
|
]
|
|
100
111
|
|
|
101
|
-
|
|
112
|
+
get_site_mock.return_value = site
|
|
102
113
|
related_cycles_mock.return_value = cycles
|
|
103
114
|
|
|
104
115
|
result = run(cycle)
|
|
116
|
+
assert order_list(result) == order_list(expected)
|
|
105
117
|
|
|
106
|
-
#
|
|
107
|
-
get_irrigated_terms_mock.call_count <= 1
|
|
108
|
-
get_upland_rice_land_cover_terms_mock.call_count <= 1
|
|
109
|
-
|
|
110
|
-
# Ensure that the property and term utils are properly mocked.
|
|
118
|
+
# assert the API calls are properly mocked
|
|
111
119
|
search_mock.assert_not_called()
|
|
112
120
|
|
|
113
|
-
assert order_list(result) == order_list(expected)
|
|
114
|
-
|
|
115
121
|
|
|
116
122
|
@patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
|
|
117
123
|
@patch(f"{utils_path}.related_cycles")
|
|
118
124
|
@patch(f"{utils_path}._get_site")
|
|
119
|
-
|
|
125
|
+
@patch(f"{soc_tier_1_utils_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
126
|
+
@patch(f"{soc_utils_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
127
|
+
@patch(f"{soc_utils_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
128
|
+
@patch(f"{term_path}.search")
|
|
129
|
+
def test_run_empty(
|
|
130
|
+
search_mock: MagicMock,
|
|
131
|
+
_get_cover_crop_property_terms_mock: MagicMock,
|
|
132
|
+
_get_irrigated_terms_mock: MagicMock,
|
|
133
|
+
_get_upland_rice_land_cover_terms_mock: MagicMock,
|
|
134
|
+
get_site_mock: MagicMock,
|
|
135
|
+
related_cycles_mock: MagicMock,
|
|
136
|
+
_new_emission_mock: MagicMock
|
|
137
|
+
):
|
|
120
138
|
"""
|
|
121
139
|
Test `run` function for each cycle in each scenario.
|
|
122
140
|
"""
|
|
123
141
|
CYCLE = {}
|
|
124
142
|
EXPECTED = []
|
|
125
143
|
|
|
126
|
-
|
|
144
|
+
get_site_mock.return_value = {}
|
|
127
145
|
related_cycles_mock.return_value = [CYCLE]
|
|
128
146
|
|
|
129
147
|
result = run(CYCLE)
|
|
130
148
|
assert result == EXPECTED
|
|
149
|
+
|
|
150
|
+
# assert the API calls are properly mocked
|
|
151
|
+
search_mock.assert_not_called()
|
|
@@ -10,8 +10,8 @@ from hestia_earth.models.ipcc2019.organicCarbonPerHa_utils import sample_constan
|
|
|
10
10
|
from tests.utils import fake_new_measurement, fixtures_path
|
|
11
11
|
|
|
12
12
|
class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
tier_1_utils_path = f"hestia_earth.models.{MODEL}.{TERM_ID}_tier_1_utils"
|
|
14
|
+
tier_2_utils_path = f"hestia_earth.models.{MODEL}.{TERM_ID}_tier_2_utils"
|
|
15
15
|
utils_path = f"hestia_earth.models.{MODEL}.{TERM_ID}_utils"
|
|
16
16
|
term_path = "hestia_earth.models.utils.term"
|
|
17
17
|
property_path = "hestia_earth.models.utils.property"
|
|
@@ -109,6 +109,8 @@ PARAMS_SHOULD_RUN = [
|
|
|
109
109
|
("tier-1/cropland-polar", False), # Closes issue 794
|
|
110
110
|
("tier-1/cropland-with-system-increasing-c-input", True), # Closes issue 851
|
|
111
111
|
("tier-1/with-gapfilled-start-date-end-date", False), # Closes issue 972
|
|
112
|
+
("tier-1/forest-to-orchard-with-ground-cover", True), # Closes 989
|
|
113
|
+
("tier-1/forest-to-other-with-ground-cover", True), # Closes 989
|
|
112
114
|
("tier-2/with-generalised-monthly-measurements", False), # Closes issue 600
|
|
113
115
|
("tier-2/with-incomplete-climate-data", False), # Closes issue 599
|
|
114
116
|
("tier-2/with-initial-soc", True),
|
|
@@ -125,27 +127,28 @@ PARAMS_SHOULD_RUN = [
|
|
|
125
127
|
IDS_SHOULD_RUN = [p[0] for p in PARAMS_SHOULD_RUN]
|
|
126
128
|
|
|
127
129
|
|
|
128
|
-
# TODO: update mocks
|
|
129
130
|
@mark.parametrize("subfolder, should_run", PARAMS_SHOULD_RUN, ids=IDS_SHOULD_RUN)
|
|
130
|
-
@patch(f"{
|
|
131
|
-
@patch(f"{
|
|
132
|
-
@patch(f"{
|
|
133
|
-
@patch(f"{
|
|
134
|
-
@patch(f"{
|
|
135
|
-
@patch(f"{utils_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
131
|
+
@patch(f"{tier_2_utils_path}.related_cycles")
|
|
132
|
+
@patch(f"{tier_2_utils_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
133
|
+
@patch(f"{tier_2_utils_path}.get_upland_rice_crop_terms", return_value=UPLAND_RICE_CROP_TERM_IDS)
|
|
134
|
+
@patch(f"{tier_1_utils_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
135
|
+
@patch(f"{tier_1_utils_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
136
136
|
@patch(f"{utils_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
137
137
|
@patch(f"{utils_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
138
|
-
@patch(f"{
|
|
138
|
+
@patch(f"{term_path}.search")
|
|
139
|
+
@patch(f"{property_path}.find_term_property", side_effect=fake_find_term_property)
|
|
140
|
+
@patch(f"{property_path}.download_hestia")
|
|
139
141
|
def test_should_run(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
142
|
+
download_hestia_mock: MagicMock,
|
|
143
|
+
_find_term_property_mock: MagicMock,
|
|
144
|
+
search_mock: MagicMock,
|
|
145
|
+
_get_cover_crop_property_terms_mock: MagicMock,
|
|
146
|
+
_get_irrigated_terms_mock: MagicMock,
|
|
147
|
+
_get_residue_removed_or_burnt_terms_mock: MagicMock,
|
|
148
|
+
_get_upland_rice_land_cover_terms_mock_t1: MagicMock,
|
|
149
|
+
_get_upland_rice_crop_terms_mock: MagicMock,
|
|
150
|
+
_get_upland_rice_land_cover_terms_mock_t2: MagicMock,
|
|
151
|
+
related_cycles_mock: MagicMock,
|
|
149
152
|
subfolder: str,
|
|
150
153
|
should_run: bool
|
|
151
154
|
):
|
|
@@ -155,7 +158,7 @@ def test_should_run(
|
|
|
155
158
|
with open(f"{folder}/cycles.jsonld", encoding='utf-8') as f:
|
|
156
159
|
return json.load(f)
|
|
157
160
|
|
|
158
|
-
|
|
161
|
+
related_cycles_mock.return_value = (
|
|
159
162
|
load_cycles_from_file() if isfile(f"{folder}/cycles.jsonld") else []
|
|
160
163
|
)
|
|
161
164
|
|
|
@@ -163,75 +166,68 @@ def test_should_run(
|
|
|
163
166
|
site = json.load(f)
|
|
164
167
|
|
|
165
168
|
result, _ = _should_run(site)
|
|
166
|
-
|
|
167
|
-
# Ensure that API calls to retrieve term IDs are properly cached.
|
|
168
|
-
mock_get_cover_crop_property_terms.call_count <= 1
|
|
169
|
-
mock_get_irrigated_terms.call_count <= 1
|
|
170
|
-
mock_get_residue_removed_or_burnt_terms.call_count <= 1
|
|
171
|
-
mock_get_upland_rice_crop_terms.call_count <= 1
|
|
172
|
-
mock_get_upland_rice_land_cover_terms.call_count <= 1
|
|
169
|
+
assert result == should_run
|
|
173
170
|
|
|
174
171
|
# Ensure that the property and term utils are properly mocked.
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
assert result == should_run
|
|
172
|
+
download_hestia_mock.assert_not_called()
|
|
173
|
+
search_mock.assert_not_called()
|
|
179
174
|
|
|
180
175
|
|
|
176
|
+
@patch(f"{tier_2_utils_path}.related_cycles", return_value=[])
|
|
181
177
|
@patch(f"{term_path}.search")
|
|
182
178
|
@patch(f"{property_path}.download_hestia")
|
|
183
|
-
@patch(f"{tier_2_path}.related_cycles", return_value=[])
|
|
184
179
|
def test_should_run_no_data(
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
180
|
+
download_hestia_mock: MagicMock,
|
|
181
|
+
search_mock: MagicMock,
|
|
182
|
+
_related_cycles_mock: MagicMock
|
|
188
183
|
):
|
|
189
184
|
SITE = {}
|
|
190
185
|
EXPECTED = []
|
|
191
186
|
|
|
192
187
|
result = run(SITE)
|
|
193
188
|
|
|
194
|
-
|
|
195
|
-
|
|
189
|
+
download_hestia_mock.assert_not_called()
|
|
190
|
+
search_mock.assert_not_called()
|
|
196
191
|
assert result == EXPECTED
|
|
197
192
|
|
|
198
193
|
|
|
199
194
|
PARAMS_RUN = [subfolder for subfolder, should_run in PARAMS_SHOULD_RUN if should_run]
|
|
200
195
|
|
|
201
196
|
|
|
202
|
-
# TODO: update mocks
|
|
203
197
|
@mark.parametrize("subfolder", PARAMS_RUN)
|
|
204
|
-
@patch(f"{
|
|
205
|
-
@patch(f"{
|
|
206
|
-
@patch(f"{
|
|
207
|
-
@patch(f"{
|
|
208
|
-
@patch(f"{
|
|
209
|
-
@patch(f"{
|
|
198
|
+
@patch(f"{tier_2_utils_path}.related_cycles")
|
|
199
|
+
@patch(f"{tier_2_utils_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
200
|
+
@patch(f"{tier_2_utils_path}.get_upland_rice_crop_terms", return_value=UPLAND_RICE_CROP_TERM_IDS)
|
|
201
|
+
@patch(f"{tier_2_utils_path}.calc_descriptive_stats", side_effect=fake_calc_descriptive_stats)
|
|
202
|
+
@patch(f"{tier_2_utils_path}._new_measurement", side_effect=fake_new_measurement)
|
|
203
|
+
@patch(f"{tier_2_utils_path}._get_sample_func", return_value=sample_constant)
|
|
204
|
+
@patch(f"{tier_1_utils_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
205
|
+
@patch(f"{tier_1_utils_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
206
|
+
@patch(f"{tier_1_utils_path}.calc_descriptive_stats", side_effect=fake_calc_descriptive_stats)
|
|
207
|
+
@patch(f"{tier_1_utils_path}._new_measurement", side_effect=fake_new_measurement)
|
|
208
|
+
@patch(f"{tier_1_utils_path}._get_sample_func", return_value=sample_constant)
|
|
210
209
|
@patch(f"{utils_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
211
210
|
@patch(f"{utils_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
212
|
-
@patch(f"{
|
|
213
|
-
@patch(f"{
|
|
214
|
-
@patch(f"{
|
|
215
|
-
@patch(f"{tier_2_path}._get_sample_func", return_value=sample_constant)
|
|
216
|
-
@patch(f"{tier_1_path}.calc_descriptive_stats", side_effect=fake_calc_descriptive_stats)
|
|
217
|
-
@patch(f"{tier_1_path}._new_measurement", side_effect=fake_new_measurement)
|
|
218
|
-
@patch(f"{tier_1_path}._get_sample_func", return_value=sample_constant)
|
|
211
|
+
@patch(f"{term_path}.search")
|
|
212
|
+
@patch(f"{property_path}.find_term_property", side_effect=fake_find_term_property)
|
|
213
|
+
@patch(f"{property_path}.download_hestia")
|
|
219
214
|
def test_run(
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
215
|
+
download_hestia_mock: MagicMock,
|
|
216
|
+
_find_term_property_mock: MagicMock,
|
|
217
|
+
search_mock: MagicMock,
|
|
218
|
+
_get_cover_crop_property_terms_mock: MagicMock,
|
|
219
|
+
_get_irrigated_terms_mock: MagicMock,
|
|
220
|
+
_get_sample_func_mock_t1: MagicMock,
|
|
221
|
+
_new_measurement_mock_t1: MagicMock,
|
|
222
|
+
_calc_descriptive_stats_mock_t1: MagicMock,
|
|
223
|
+
_get_residue_removed_or_burnt_terms_mock: MagicMock,
|
|
224
|
+
_get_upland_rice_land_cover_terms_mock_t1: MagicMock,
|
|
225
|
+
_get_sample_func_mock_t2: MagicMock,
|
|
226
|
+
_new_measurement_mock_t2: MagicMock,
|
|
225
227
|
_mock_calc_descriptive_stats_t2: MagicMock,
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
mock_get_residue_removed_or_burnt_terms: MagicMock,
|
|
230
|
-
mock_get_upland_rice_crop_terms: MagicMock,
|
|
231
|
-
mock_get_upland_rice_land_cover_terms: MagicMock,
|
|
232
|
-
_mock_find_term_property: MagicMock,
|
|
233
|
-
mock_download_hestia: MagicMock,
|
|
234
|
-
mock_search: MagicMock,
|
|
228
|
+
_get_upland_rice_crop_terms_mock: MagicMock,
|
|
229
|
+
_get_upland_rice_land_cover_terms_mock_t2: MagicMock,
|
|
230
|
+
related_cycles_mock: MagicMock,
|
|
235
231
|
subfolder: str
|
|
236
232
|
):
|
|
237
233
|
folder = f"{fixtures_folder}/{subfolder}"
|
|
@@ -240,7 +236,7 @@ def test_run(
|
|
|
240
236
|
with open(f"{folder}/cycles.jsonld", encoding='utf-8') as f:
|
|
241
237
|
return json.load(f)
|
|
242
238
|
|
|
243
|
-
|
|
239
|
+
related_cycles_mock.return_value = (
|
|
244
240
|
load_cycles_from_file() if isfile(f"{folder}/cycles.jsonld") else []
|
|
245
241
|
)
|
|
246
242
|
|
|
@@ -253,18 +249,11 @@ def test_run(
|
|
|
253
249
|
with patch(f"{class_path}.ITERATIONS", ITERATIONS):
|
|
254
250
|
result = run(site)
|
|
255
251
|
|
|
256
|
-
|
|
257
|
-
mock_get_cover_crop_property_terms.call_count <= 1
|
|
258
|
-
mock_get_irrigated_terms.call_count <= 1
|
|
259
|
-
mock_get_residue_removed_or_burnt_terms.call_count <= 1
|
|
260
|
-
mock_get_upland_rice_crop_terms.call_count <= 1
|
|
261
|
-
mock_get_upland_rice_land_cover_terms.call_count <= 1
|
|
252
|
+
assert order_list(result) == order_list(expected)
|
|
262
253
|
|
|
263
254
|
# Ensure that the property and term utils are properly mocked.
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
assert order_list(result) == order_list(expected)
|
|
255
|
+
download_hestia_mock.assert_not_called()
|
|
256
|
+
search_mock.assert_not_called()
|
|
268
257
|
|
|
269
258
|
|
|
270
259
|
PARAMS_RUN_WITH_STATS = [
|
|
@@ -276,31 +265,32 @@ PARAMS_RUN_WITH_STATS = [
|
|
|
276
265
|
]
|
|
277
266
|
|
|
278
267
|
|
|
279
|
-
# TODO: update mocks
|
|
280
268
|
@mark.parametrize("subfolder", PARAMS_RUN_WITH_STATS)
|
|
281
|
-
@patch(f"{
|
|
282
|
-
@patch(f"{
|
|
283
|
-
@patch(f"{
|
|
284
|
-
@patch(f"{
|
|
285
|
-
@patch(f"{
|
|
286
|
-
@patch(f"{
|
|
269
|
+
@patch(f"{tier_2_utils_path}.related_cycles")
|
|
270
|
+
@patch(f"{tier_2_utils_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
271
|
+
@patch(f"{tier_2_utils_path}.get_upland_rice_crop_terms", return_value=UPLAND_RICE_CROP_TERM_IDS)
|
|
272
|
+
@patch(f"{tier_2_utils_path}._new_measurement", side_effect=fake_new_measurement)
|
|
273
|
+
@patch(f"{tier_1_utils_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
274
|
+
@patch(f"{tier_1_utils_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
275
|
+
@patch(f"{tier_1_utils_path}._new_measurement", side_effect=fake_new_measurement)
|
|
287
276
|
@patch(f"{utils_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
288
277
|
@patch(f"{utils_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
289
|
-
@patch(f"{
|
|
290
|
-
@patch(f"{
|
|
291
|
-
@patch(f"{
|
|
278
|
+
@patch(f"{term_path}.search")
|
|
279
|
+
@patch(f"{property_path}.find_term_property", side_effect=fake_find_term_property)
|
|
280
|
+
@patch(f"{property_path}.download_hestia")
|
|
292
281
|
def test_run_with_stats(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
282
|
+
download_hestia_mock: MagicMock,
|
|
283
|
+
_find_term_property_mock: MagicMock,
|
|
284
|
+
search_mock: MagicMock,
|
|
285
|
+
_get_cover_crop_property_terms_mock: MagicMock,
|
|
286
|
+
_get_irrigated_terms_mock: MagicMock,
|
|
287
|
+
_new_measurement_mock_t1: MagicMock,
|
|
288
|
+
_get_residue_removed_or_burnt_terms_mock: MagicMock,
|
|
289
|
+
_get_upland_rice_land_cover_terms_mock_t1: MagicMock,
|
|
290
|
+
_new_measurement_mock_t2: MagicMock,
|
|
291
|
+
_get_upland_rice_crop_terms_mock: MagicMock,
|
|
292
|
+
_get_upland_rice_land_cover_terms_mock_t2: MagicMock,
|
|
293
|
+
related_cycles_mock: MagicMock,
|
|
304
294
|
subfolder: str
|
|
305
295
|
):
|
|
306
296
|
folder = f"{fixtures_folder}/{subfolder}"
|
|
@@ -309,7 +299,7 @@ def test_run_with_stats(
|
|
|
309
299
|
with open(f"{folder}/cycles.jsonld", encoding='utf-8') as f:
|
|
310
300
|
return json.load(f)
|
|
311
301
|
|
|
312
|
-
|
|
302
|
+
related_cycles_mock.return_value = (
|
|
313
303
|
load_cycles_from_file() if isfile(f"{folder}/cycles.jsonld") else []
|
|
314
304
|
)
|
|
315
305
|
|
|
@@ -322,15 +312,8 @@ def test_run_with_stats(
|
|
|
322
312
|
with patch(f"{class_path}.ITERATIONS", ITERATIONS):
|
|
323
313
|
result = run(site)
|
|
324
314
|
|
|
325
|
-
|
|
326
|
-
mock_get_cover_crop_property_terms.call_count <= 1
|
|
327
|
-
mock_get_irrigated_terms.call_count <= 1
|
|
328
|
-
mock_get_residue_removed_or_burnt_terms.call_count <= 1
|
|
329
|
-
mock_get_upland_rice_crop_terms.call_count <= 1
|
|
330
|
-
mock_get_upland_rice_land_cover_terms.call_count <= 1
|
|
315
|
+
assert order_list(result) == order_list(expected)
|
|
331
316
|
|
|
332
317
|
# Ensure that the property and term utils are properly mocked.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
assert order_list(result) == order_list(expected)
|
|
318
|
+
download_hestia_mock.assert_not_called()
|
|
319
|
+
search_mock.assert_not_called()
|