hestia-earth-models 0.59.5__py3-none-any.whl → 0.59.7__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/cache_sites.py +6 -8
- hestia_earth/models/cycle/animal/milkYield.py +86 -0
- hestia_earth/models/cycle/endDate.py +50 -0
- hestia_earth/models/cycle/inorganicFertiliser.py +3 -2
- hestia_earth/models/cycle/milkYield.py +8 -3
- hestia_earth/models/cycle/pre_checks/__init__.py +1 -2
- hestia_earth/models/cycle/siteDuration.py +1 -1
- hestia_earth/models/cycle/startDate.py +42 -0
- hestia_earth/models/emepEea2019/nh3ToAirInorganicFertiliser.py +9 -6
- hestia_earth/models/faostat2018/liveweightPerHead.py +77 -41
- hestia_earth/models/faostat2018/product/price.py +43 -57
- hestia_earth/models/faostat2018/utils.py +10 -2
- hestia_earth/models/geospatialDatabase/utils.py +0 -1
- hestia_earth/models/haversineFormula/transport/distance.py +6 -3
- hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2019/co2ToAirLimeHydrolysis.py +1 -1
- hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py +2 -7
- hestia_earth/models/ipcc2019/organicCarbonPerHa.py +26 -6
- hestia_earth/models/ipcc2019/pastureGrass.py +2 -1
- hestia_earth/models/linkedImpactAssessment/__init__.py +3 -3
- hestia_earth/models/mocking/search-results.json +244 -232
- hestia_earth/models/schmidt2007/h2SToAirWasteTreatment.py +58 -0
- hestia_earth/models/site/management.py +3 -1
- hestia_earth/models/site/pre_checks/cache_geospatialDatabase.py +2 -2
- hestia_earth/models/utils/__init__.py +4 -1
- hestia_earth/models/utils/animalProduct.py +6 -4
- hestia_earth/models/utils/blank_node.py +3 -2
- hestia_earth/models/utils/product.py +9 -1
- hestia_earth/models/utils/property.py +2 -1
- hestia_earth/models/utils/site.py +7 -4
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.59.5.dist-info → hestia_earth_models-0.59.7.dist-info}/METADATA +1 -1
- {hestia_earth_models-0.59.5.dist-info → hestia_earth_models-0.59.7.dist-info}/RECORD +44 -38
- tests/models/cycle/animal/test_milkYield.py +43 -0
- tests/models/cycle/test_endDate.py +24 -0
- tests/models/cycle/test_startDate.py +22 -0
- tests/models/faostat2018/product/test_price.py +40 -48
- tests/models/faostat2018/test_liveweightPerHead.py +106 -42
- tests/models/ipcc2019/test_organicCarbonPerHa.py +102 -39
- tests/models/schmidt2007/test_h2SToAirWasteTreatment.py +45 -0
- tests/models/utils/test_blank_node.py +71 -3
- hestia_earth/models/cycle/pre_checks/startDate.py +0 -52
- tests/models/cycle/pre_checks/test_startDate.py +0 -44
- {hestia_earth_models-0.59.5.dist-info → hestia_earth_models-0.59.7.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.59.5.dist-info → hestia_earth_models-0.59.7.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.59.5.dist-info → hestia_earth_models-0.59.7.dist-info}/top_level.txt +0 -0
|
@@ -2,22 +2,12 @@ import json
|
|
|
2
2
|
from unittest.mock import patch
|
|
3
3
|
from tests.utils import fixtures_path
|
|
4
4
|
|
|
5
|
-
from hestia_earth.models.faostat2018.product.price import MODEL, MODEL_KEY, run,
|
|
5
|
+
from hestia_earth.models.faostat2018.product.price import MODEL, MODEL_KEY, run, _lookup_data
|
|
6
6
|
|
|
7
7
|
class_path = f"hestia_earth.models.{MODEL}.product.{MODEL_KEY}"
|
|
8
8
|
fixtures_folder = f"{fixtures_path}/{MODEL}/product/{MODEL_KEY}"
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def test_should_run():
|
|
12
|
-
cycle = {'endDate': '2020-01'}
|
|
13
|
-
should_run, *_ = _should_run(cycle)
|
|
14
|
-
assert not should_run
|
|
15
|
-
|
|
16
|
-
cycle['site'] = {'country': {'@id': 'GADM-GBR'}}
|
|
17
|
-
should_run, *_ = _should_run(cycle)
|
|
18
|
-
assert should_run is True
|
|
19
|
-
|
|
20
|
-
|
|
21
11
|
def test_lookup_data():
|
|
22
12
|
assert _lookup_data('cocoaSeedDehulled', 'Cocoa beans', 'GADM-GHA', 2000, term_type='crop') == 412.9
|
|
23
13
|
# average price per tonne as year value is missing
|
|
@@ -37,11 +27,23 @@ def test_run_crop(*args):
|
|
|
37
27
|
|
|
38
28
|
|
|
39
29
|
@patch(f"{class_path}.download_hestia", return_value={})
|
|
40
|
-
def
|
|
41
|
-
with open(f"{fixtures_folder}/animalProduct/cycle.jsonld", encoding='utf-8') as f:
|
|
30
|
+
def test_run_animalProduct_kg(*args):
|
|
31
|
+
with open(f"{fixtures_folder}/animalProduct/kg/cycle.jsonld", encoding='utf-8') as f:
|
|
32
|
+
cycle = json.load(f)
|
|
33
|
+
|
|
34
|
+
with open(f"{fixtures_folder}/animalProduct/kg/result.jsonld", encoding='utf-8') as f:
|
|
35
|
+
expected = json.load(f)
|
|
36
|
+
|
|
37
|
+
value = run(cycle)
|
|
38
|
+
assert value == expected
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@patch(f"{class_path}.download_hestia", return_value={})
|
|
42
|
+
def test_run_animalProduct_number(*args):
|
|
43
|
+
with open(f"{fixtures_folder}/animalProduct/number/cycle.jsonld", encoding='utf-8') as f:
|
|
42
44
|
cycle = json.load(f)
|
|
43
45
|
|
|
44
|
-
with open(f"{fixtures_folder}/animalProduct/result.jsonld", encoding='utf-8') as f:
|
|
46
|
+
with open(f"{fixtures_folder}/animalProduct/number/result.jsonld", encoding='utf-8') as f:
|
|
45
47
|
expected = json.load(f)
|
|
46
48
|
|
|
47
49
|
value = run(cycle)
|
|
@@ -57,24 +59,10 @@ def test_run_liveAnimal_chicken(mock_download_hestia):
|
|
|
57
59
|
expected = json.load(f)
|
|
58
60
|
|
|
59
61
|
mock_download_hestia.return_value = {
|
|
60
|
-
"@id": "
|
|
62
|
+
"@id": "meatChickenLiveweight",
|
|
61
63
|
"@type": "Term",
|
|
62
|
-
"units": "kg
|
|
63
|
-
"termType": "animalProduct"
|
|
64
|
-
"defaultProperties": [
|
|
65
|
-
{
|
|
66
|
-
"term": {
|
|
67
|
-
"@type": "Term",
|
|
68
|
-
"name": "Processing conversion, cold carcass weight to ready-to-cook weight",
|
|
69
|
-
"termType": "property",
|
|
70
|
-
"@id": "processingConversionColdCarcassWeightToReadyToCookWeight",
|
|
71
|
-
"units": "%"
|
|
72
|
-
},
|
|
73
|
-
"value": 72.45065789473684,
|
|
74
|
-
"sd": 3.605314180391945,
|
|
75
|
-
"@type": "Property"
|
|
76
|
-
}
|
|
77
|
-
]
|
|
64
|
+
"units": "kg liveweight",
|
|
65
|
+
"termType": "animalProduct"
|
|
78
66
|
}
|
|
79
67
|
value = run(cycle)
|
|
80
68
|
assert value == expected
|
|
@@ -89,24 +77,28 @@ def test_run_liveAnimal_pig(mock_download_hestia):
|
|
|
89
77
|
expected = json.load(f)
|
|
90
78
|
|
|
91
79
|
mock_download_hestia.return_value = {
|
|
92
|
-
"@id": "
|
|
80
|
+
"@id": "meatPigLiveweight",
|
|
81
|
+
"@type": "Term",
|
|
82
|
+
"units": "kg liveweight",
|
|
83
|
+
"termType": "animalProduct"
|
|
84
|
+
}
|
|
85
|
+
value = run(cycle)
|
|
86
|
+
assert value == expected
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@patch(f"{class_path}.download_hestia")
|
|
90
|
+
def test_run_liveAnimal_sheepLamb(mock_download_hestia):
|
|
91
|
+
with open(f"{fixtures_folder}/liveAnimal/sheepLamb/cycle.jsonld", encoding='utf-8') as f:
|
|
92
|
+
cycle = json.load(f)
|
|
93
|
+
|
|
94
|
+
with open(f"{fixtures_folder}/liveAnimal/sheepLamb/result.jsonld", encoding='utf-8') as f:
|
|
95
|
+
expected = json.load(f)
|
|
96
|
+
|
|
97
|
+
mock_download_hestia.return_value = {
|
|
98
|
+
"@id": "meatSheepLiveweight",
|
|
93
99
|
"@type": "Term",
|
|
94
|
-
"units": "kg
|
|
95
|
-
"termType": "animalProduct"
|
|
96
|
-
"defaultProperties": [
|
|
97
|
-
{
|
|
98
|
-
"term": {
|
|
99
|
-
"@type": "Term",
|
|
100
|
-
"name": "Processing conversion, liveweight to cold carcass weight",
|
|
101
|
-
"termType": "property",
|
|
102
|
-
"@id": "processingConversionLiveweightToColdCarcassWeight",
|
|
103
|
-
"units": "%"
|
|
104
|
-
},
|
|
105
|
-
"value": 75.22666597366735,
|
|
106
|
-
"sd": 2.9377280394802323,
|
|
107
|
-
"@type": "Property"
|
|
108
|
-
}
|
|
109
|
-
]
|
|
100
|
+
"units": "kg liveweight",
|
|
101
|
+
"termType": "animalProduct"
|
|
110
102
|
}
|
|
111
103
|
value = run(cycle)
|
|
112
104
|
assert value == expected
|
|
@@ -1,61 +1,125 @@
|
|
|
1
1
|
from unittest.mock import patch
|
|
2
2
|
import json
|
|
3
3
|
|
|
4
|
-
from hestia_earth.schema import TermTermType
|
|
5
4
|
from tests.utils import fixtures_path, fake_new_property
|
|
6
5
|
|
|
7
|
-
from hestia_earth.models.faostat2018.liveweightPerHead import MODEL, TERM_ID,
|
|
6
|
+
from hestia_earth.models.faostat2018.liveweightPerHead import MODEL, TERM_ID, run
|
|
8
7
|
|
|
9
8
|
class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
|
|
10
9
|
fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
'
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@patch(f"{class_path}._new_property", side_effect=fake_new_property)
|
|
13
|
+
def test_run_animalProduct(*args):
|
|
14
|
+
with open(f"{fixtures_folder}/animalProduct/cycle.jsonld", encoding='utf-8') as f:
|
|
15
|
+
cycle = json.load(f)
|
|
16
|
+
|
|
17
|
+
with open(f"{fixtures_folder}/animalProduct/result.jsonld", encoding='utf-8') as f:
|
|
18
|
+
expected = json.load(f)
|
|
19
|
+
|
|
20
|
+
value = run(cycle)
|
|
21
|
+
assert value == expected
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@patch(f"{class_path}._new_property", side_effect=fake_new_property)
|
|
25
|
+
@patch(f"{class_path}.download_hestia")
|
|
26
|
+
def test_run_liveAnimal_chicken(mock_download_hestia, *args):
|
|
27
|
+
with open(f"{fixtures_folder}/liveAnimal/chicken/cycle.jsonld", encoding='utf-8') as f:
|
|
28
|
+
cycle = json.load(f)
|
|
29
|
+
|
|
30
|
+
with open(f"{fixtures_folder}/liveAnimal/chicken/result.jsonld", encoding='utf-8') as f:
|
|
31
|
+
expected = json.load(f)
|
|
32
|
+
|
|
33
|
+
mock_download_hestia.return_value = {
|
|
34
|
+
"@id": "meatChickenReadyToCookWeight",
|
|
35
|
+
"@type": "Term",
|
|
36
|
+
"units": "kg ready-to-cook weight",
|
|
37
|
+
"defaultProperties": [
|
|
38
|
+
{
|
|
39
|
+
"term": {
|
|
40
|
+
"@type": "Term",
|
|
41
|
+
"name": "Processing conversion, liveweight to cold carcass weight",
|
|
42
|
+
"termType": "property",
|
|
43
|
+
"@id": "processingConversionLiveweightToColdCarcassWeight",
|
|
44
|
+
"units": "%"
|
|
45
|
+
},
|
|
46
|
+
"value": 72.30401869158878,
|
|
47
|
+
"@type": "Property"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"term": {
|
|
51
|
+
"@type": "Term",
|
|
52
|
+
"name": "Processing conversion, cold carcass weight to ready-to-cook weight",
|
|
53
|
+
"termType": "property",
|
|
54
|
+
"@id": "processingConversionColdCarcassWeightToReadyToCookWeight",
|
|
55
|
+
"units": "%"
|
|
56
|
+
},
|
|
57
|
+
"value": 72.45065789473684,
|
|
58
|
+
"@type": "Property"
|
|
38
59
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
assert
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
value = run(cycle)
|
|
63
|
+
assert value == expected
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@patch(f"{class_path}._new_property", side_effect=fake_new_property)
|
|
67
|
+
@patch(f"{class_path}.download_hestia")
|
|
68
|
+
def test_run_liveAnimal_pig(mock_download_hestia, *args):
|
|
69
|
+
with open(f"{fixtures_folder}/liveAnimal/pig/cycle.jsonld", encoding='utf-8') as f:
|
|
70
|
+
cycle = json.load(f)
|
|
43
71
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
72
|
+
with open(f"{fixtures_folder}/liveAnimal/pig/result.jsonld", encoding='utf-8') as f:
|
|
73
|
+
expected = json.load(f)
|
|
74
|
+
|
|
75
|
+
mock_download_hestia.return_value = {
|
|
76
|
+
"@id": "meatPigColdDressedCarcassWeight",
|
|
77
|
+
"@type": "Term",
|
|
78
|
+
"units": "kg cold dressed carcass weight",
|
|
79
|
+
"defaultProperties": [
|
|
80
|
+
{
|
|
81
|
+
"term": {
|
|
82
|
+
"@type": "Term",
|
|
83
|
+
"name": "Processing conversion, liveweight to cold carcass weight",
|
|
84
|
+
"termType": "property",
|
|
85
|
+
"@id": "processingConversionLiveweightToColdCarcassWeight",
|
|
86
|
+
"units": "%"
|
|
87
|
+
},
|
|
88
|
+
"value": 75.22666597366735,
|
|
89
|
+
"@type": "Property"
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
value = run(cycle)
|
|
94
|
+
assert value == expected
|
|
49
95
|
|
|
50
96
|
|
|
51
|
-
@patch(f"hestia_earth.models.{MODEL}.utils.download_hestia", return_value=FAO_TERM)
|
|
52
97
|
@patch(f"{class_path}._new_property", side_effect=fake_new_property)
|
|
53
|
-
|
|
54
|
-
|
|
98
|
+
@patch(f"{class_path}.download_hestia")
|
|
99
|
+
def test_run_liveAnimal_sheepLamb(mock_download_hestia, *args):
|
|
100
|
+
with open(f"{fixtures_folder}/liveAnimal/sheepLamb/cycle.jsonld", encoding='utf-8') as f:
|
|
55
101
|
cycle = json.load(f)
|
|
56
102
|
|
|
57
|
-
with open(f"{fixtures_folder}/result.jsonld", encoding='utf-8') as f:
|
|
103
|
+
with open(f"{fixtures_folder}/liveAnimal/sheepLamb/result.jsonld", encoding='utf-8') as f:
|
|
58
104
|
expected = json.load(f)
|
|
59
105
|
|
|
106
|
+
mock_download_hestia.return_value = {
|
|
107
|
+
"@id": "meatSheepColdDressedCarcassWeight",
|
|
108
|
+
"@type": "Term",
|
|
109
|
+
"units": "kg cold dressed carcass weight",
|
|
110
|
+
"defaultProperties": [
|
|
111
|
+
{
|
|
112
|
+
"term": {
|
|
113
|
+
"@type": "Term",
|
|
114
|
+
"name": "Processing conversion, liveweight to cold carcass weight",
|
|
115
|
+
"termType": "property",
|
|
116
|
+
"@id": "processingConversionLiveweightToColdCarcassWeight",
|
|
117
|
+
"units": "%"
|
|
118
|
+
},
|
|
119
|
+
"value": 47.301833667687326,
|
|
120
|
+
"@type": "Property"
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
}
|
|
60
124
|
value = run(cycle)
|
|
61
125
|
assert value == expected
|
|
@@ -20,6 +20,7 @@ from hestia_earth.models.ipcc2019.organicCarbonPerHa import (
|
|
|
20
20
|
_check_cropland_medium_category,
|
|
21
21
|
_get_carbon_input_kwargs,
|
|
22
22
|
_iterate_soc_equilibriums,
|
|
23
|
+
_should_run,
|
|
23
24
|
IpccCarbonInputCategory,
|
|
24
25
|
IpccLandUseCategory,
|
|
25
26
|
IpccManagementCategory,
|
|
@@ -103,36 +104,38 @@ def find_term_property_side_effect(term: dict, property: str, *_):
|
|
|
103
104
|
# --- TIER 1 & TIER 2 TESTS ---
|
|
104
105
|
|
|
105
106
|
|
|
106
|
-
# subfolder, load_cycles
|
|
107
|
-
|
|
108
|
-
("tier-1-and-2/cropland", True),
|
|
109
|
-
("tier-2/with-
|
|
110
|
-
("tier-2/with-
|
|
111
|
-
("tier-2/with-
|
|
112
|
-
("tier-2/with-
|
|
113
|
-
("tier-2/with-multi-year-cycles
|
|
114
|
-
("tier-2/
|
|
115
|
-
("tier-2/without-
|
|
116
|
-
("tier-2/
|
|
117
|
-
("tier-2/with-irrigation
|
|
118
|
-
("tier-2/with-
|
|
119
|
-
("tier-2/with-
|
|
120
|
-
("tier-2/with-
|
|
121
|
-
("tier-
|
|
122
|
-
("tier-1/cropland-
|
|
123
|
-
("tier-1/cropland-
|
|
124
|
-
("tier-1/
|
|
125
|
-
("tier-1/
|
|
126
|
-
("tier-1/
|
|
127
|
-
("tier-1/
|
|
128
|
-
("tier-1/
|
|
107
|
+
# subfolder, load_cycles, should_run
|
|
108
|
+
SHOULD_RUN_SUBFOLDERS = [
|
|
109
|
+
("tier-1-and-2/cropland", True, True),
|
|
110
|
+
("tier-1-and-2/with-zero-carbon-input", True, True), # Closes issue 777
|
|
111
|
+
("tier-2/with-generalised-monthly-measurements", True, False), # Closes issue 600
|
|
112
|
+
("tier-2/with-incomplete-climate-data", True, False), # Closes issue 599
|
|
113
|
+
("tier-2/with-initial-soc", True, True),
|
|
114
|
+
("tier-2/with-multi-year-cycles", True, True),
|
|
115
|
+
("tier-2/with-multi-year-cycles-and-missing-properties", True, True), # Closes issue 734
|
|
116
|
+
("tier-2/without-any-measurements", True, False), # Closes issue 594
|
|
117
|
+
("tier-2/without-initial-soc", True, True),
|
|
118
|
+
("tier-2/with-irrigation", True, True),
|
|
119
|
+
("tier-2/with-irrigation-dates", True, True),
|
|
120
|
+
("tier-2/with-paddy-rice", True, False),
|
|
121
|
+
("tier-2/with-sand-without-date", True, True), # Closes issue 739
|
|
122
|
+
("tier-2/with-irrigated-upland-rice", True, False),
|
|
123
|
+
("tier-1/cropland-depth-as-float", False, True),
|
|
124
|
+
("tier-1/cropland-with-measured-soc", False, True),
|
|
125
|
+
("tier-1/cropland-without-measured-soc", False, True),
|
|
126
|
+
("tier-1/permanent-pasture", False, True),
|
|
127
|
+
("tier-1/should-not-run", False, False),
|
|
128
|
+
("tier-1/without-management-with-measured-soc", False, False),
|
|
129
|
+
("tier-1/land-use-change", False, True), # Closes issue 755
|
|
130
|
+
("tier-1/run-with-site-type", False, True), # Closes issue 755
|
|
131
|
+
("tier-1/cropland-polar", False, False) # Closes issue 794
|
|
129
132
|
]
|
|
130
133
|
|
|
131
134
|
|
|
132
135
|
@mark.parametrize(
|
|
133
|
-
"subfolder, load_cycles",
|
|
134
|
-
|
|
135
|
-
ids=[params[0] for params in
|
|
136
|
+
"subfolder, load_cycles, should_run",
|
|
137
|
+
SHOULD_RUN_SUBFOLDERS,
|
|
138
|
+
ids=[params[0] for params in SHOULD_RUN_SUBFOLDERS]
|
|
136
139
|
)
|
|
137
140
|
@patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
|
|
138
141
|
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
@@ -142,8 +145,8 @@ RUN_SUBFOLDERS = [
|
|
|
142
145
|
@patch(f"{class_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
143
146
|
@patch(f"{class_path}.get_upland_rice_crop_terms", return_value=UPLAND_RICE_CROP_TERM_IDS)
|
|
144
147
|
@patch(f"{class_path}.related_cycles")
|
|
145
|
-
@patch("hestia_earth.models.utils.property.find_term_property")
|
|
146
|
-
def
|
|
148
|
+
@patch("hestia_earth.models.utils.property.find_term_property", side_effect=find_term_property_side_effect)
|
|
149
|
+
def test_should_run(
|
|
147
150
|
mock_find_term_property,
|
|
148
151
|
mock_related_cycles,
|
|
149
152
|
_mock_get_upland_rice_crop_terms,
|
|
@@ -154,7 +157,8 @@ def test_run(
|
|
|
154
157
|
_mock_get_cover_crop_property_terms,
|
|
155
158
|
_mock_new_measurement,
|
|
156
159
|
subfolder,
|
|
157
|
-
load_cycles
|
|
160
|
+
load_cycles,
|
|
161
|
+
should_run
|
|
158
162
|
):
|
|
159
163
|
folder = f"{fixtures_folder}/{subfolder}"
|
|
160
164
|
|
|
@@ -162,20 +166,17 @@ def test_run(
|
|
|
162
166
|
with open(f"{folder}/cycles.jsonld", encoding='utf-8') as f:
|
|
163
167
|
return json.load(f)
|
|
164
168
|
|
|
165
|
-
mock_find_term_property.side_effect = find_term_property_side_effect
|
|
166
169
|
mock_related_cycles.return_value = load_cycles_from_file() if load_cycles else []
|
|
167
170
|
|
|
168
171
|
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
169
172
|
site = json.load(f)
|
|
170
173
|
|
|
171
|
-
|
|
172
|
-
|
|
174
|
+
should_run_tier_1, should_run_tier_2, *_ = _should_run(site)
|
|
175
|
+
should_run_ = should_run_tier_1 or should_run_tier_2
|
|
173
176
|
|
|
174
|
-
|
|
175
|
-
assert result == expected
|
|
177
|
+
assert should_run_ == should_run
|
|
176
178
|
|
|
177
179
|
|
|
178
|
-
@patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
|
|
179
180
|
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
180
181
|
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
181
182
|
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
@@ -183,11 +184,66 @@ def test_run(
|
|
|
183
184
|
@patch(f"{class_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
184
185
|
@patch(f"{class_path}.get_upland_rice_crop_terms", return_value=UPLAND_RICE_CROP_TERM_IDS)
|
|
185
186
|
@patch(f"{class_path}.related_cycles", return_value=[])
|
|
186
|
-
|
|
187
|
+
@patch("hestia_earth.models.utils.property.find_term_property", side_effect=find_term_property_side_effect)
|
|
188
|
+
def test_should_run_no_data(*args):
|
|
187
189
|
SITE = {}
|
|
188
|
-
EXPECTED =
|
|
189
|
-
|
|
190
|
-
|
|
190
|
+
EXPECTED = False
|
|
191
|
+
|
|
192
|
+
should_run_tier_1, should_run_tier_2, *_ = _should_run(SITE)
|
|
193
|
+
should_run = should_run_tier_1 or should_run_tier_2
|
|
194
|
+
|
|
195
|
+
assert should_run == EXPECTED
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
RUN_SUBFOLDERS = [
|
|
199
|
+
(subfolder, load_cycles) for subfolder, load_cycles, should_run in SHOULD_RUN_SUBFOLDERS
|
|
200
|
+
if should_run
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@mark.parametrize(
|
|
205
|
+
"subfolder, load_cycles",
|
|
206
|
+
RUN_SUBFOLDERS,
|
|
207
|
+
ids=[params[0] for params in RUN_SUBFOLDERS]
|
|
208
|
+
)
|
|
209
|
+
@patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
|
|
210
|
+
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
211
|
+
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
212
|
+
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
213
|
+
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
214
|
+
@patch(f"{class_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
215
|
+
@patch(f"{class_path}.get_upland_rice_crop_terms", return_value=UPLAND_RICE_CROP_TERM_IDS)
|
|
216
|
+
@patch(f"{class_path}.related_cycles")
|
|
217
|
+
@patch("hestia_earth.models.utils.property.find_term_property", side_effect=find_term_property_side_effect)
|
|
218
|
+
def test_run(
|
|
219
|
+
mock_find_term_property,
|
|
220
|
+
mock_related_cycles,
|
|
221
|
+
_mock_get_upland_rice_crop_terms,
|
|
222
|
+
_mock_get_upland_rice_land_cover_terms,
|
|
223
|
+
_mock_get_residue_removed_or_burnt_terms,
|
|
224
|
+
_mock_get_irrigated_terms,
|
|
225
|
+
_mock_get_crop_residue_incorporated_or_left_on_field_terms,
|
|
226
|
+
_mock_get_cover_crop_property_terms,
|
|
227
|
+
_mock_new_measurement,
|
|
228
|
+
subfolder,
|
|
229
|
+
load_cycles
|
|
230
|
+
):
|
|
231
|
+
folder = f"{fixtures_folder}/{subfolder}"
|
|
232
|
+
|
|
233
|
+
def load_cycles_from_file():
|
|
234
|
+
with open(f"{folder}/cycles.jsonld", encoding='utf-8') as f:
|
|
235
|
+
return json.load(f)
|
|
236
|
+
|
|
237
|
+
mock_related_cycles.return_value = load_cycles_from_file() if load_cycles else []
|
|
238
|
+
|
|
239
|
+
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
240
|
+
site = json.load(f)
|
|
241
|
+
|
|
242
|
+
with open(f"{folder}/result.jsonld", encoding='utf-8') as f:
|
|
243
|
+
expected = json.load(f)
|
|
244
|
+
|
|
245
|
+
result = run(site)
|
|
246
|
+
assert result == expected
|
|
191
247
|
|
|
192
248
|
|
|
193
249
|
# --- TIER 2 TESTS: SUB-MODELS ---
|
|
@@ -227,6 +283,13 @@ def test_calc_water_factor():
|
|
|
227
283
|
assert _calc_water_factor(1, 1) == _calc_water_factor(1000, 1000)
|
|
228
284
|
|
|
229
285
|
|
|
286
|
+
def test_calc_water_factor_zero():
|
|
287
|
+
"""
|
|
288
|
+
Closes issue 771. Function should not raise 0 error and should return the maximum water factor.
|
|
289
|
+
"""
|
|
290
|
+
assert _calc_water_factor(0, 0) == 1.49961875
|
|
291
|
+
|
|
292
|
+
|
|
230
293
|
# --- IPCC SOIL CATEGORY TESTS ---
|
|
231
294
|
|
|
232
295
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from unittest.mock import patch
|
|
2
|
+
import json
|
|
3
|
+
from tests.utils import fixtures_path, fake_new_emission
|
|
4
|
+
|
|
5
|
+
from hestia_earth.models.schmidt2007.h2SToAirWasteTreatment import MODEL, TERM_ID, run, _should_run
|
|
6
|
+
|
|
7
|
+
class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
|
|
8
|
+
fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@patch(f"{class_path}.get_waste_values")
|
|
12
|
+
def test_should_run(mock_get_waste_values):
|
|
13
|
+
# no fuel values => no run
|
|
14
|
+
mock_get_waste_values.return_value = []
|
|
15
|
+
should_run, *args = _should_run({})
|
|
16
|
+
assert not should_run
|
|
17
|
+
|
|
18
|
+
# with fuel values => run
|
|
19
|
+
mock_get_waste_values.return_value = [0]
|
|
20
|
+
should_run, *args = _should_run({})
|
|
21
|
+
assert should_run is True
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
|
|
25
|
+
def test_run(*args):
|
|
26
|
+
with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
|
|
27
|
+
cycle = json.load(f)
|
|
28
|
+
|
|
29
|
+
with open(f"{fixtures_folder}/result.jsonld", encoding='utf-8') as f:
|
|
30
|
+
expected = json.load(f)
|
|
31
|
+
|
|
32
|
+
value = run(cycle)
|
|
33
|
+
assert value == expected
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
|
|
37
|
+
def test_run_data_complete(*args):
|
|
38
|
+
with open(f"{fixtures_folder}/no-input-data-complete/cycle.jsonld", encoding='utf-8') as f:
|
|
39
|
+
cycle = json.load(f)
|
|
40
|
+
|
|
41
|
+
with open(f"{fixtures_folder}/no-input-data-complete/result.jsonld", encoding='utf-8') as f:
|
|
42
|
+
expected = json.load(f)
|
|
43
|
+
|
|
44
|
+
value = run(cycle)
|
|
45
|
+
assert value == expected
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
import pytest
|
|
3
|
+
from pytest import mark
|
|
3
4
|
from unittest.mock import patch
|
|
4
5
|
|
|
5
6
|
from hestia_earth.schema import SiteSiteType
|
|
7
|
+
from hestia_earth.utils.tools import parse
|
|
6
8
|
|
|
7
9
|
from hestia_earth.models.utils.blank_node import (
|
|
8
10
|
_calc_datetime_range_intersection_duration,
|
|
@@ -552,13 +554,31 @@ GROUP_NODES_BY_YEAR_SCENARIO_A_CYCLES = [
|
|
|
552
554
|
]
|
|
553
555
|
|
|
554
556
|
|
|
555
|
-
|
|
557
|
+
@mark.parametrize(
|
|
558
|
+
"system_datetime",
|
|
559
|
+
[
|
|
560
|
+
datetime(2024, 5, 1), # Closes issue 772
|
|
561
|
+
datetime(2024, 1, 1), # Jan 1st
|
|
562
|
+
datetime(2024, 2, 29), # Leap year
|
|
563
|
+
datetime(2024, 12, 31), # Dec 31st
|
|
564
|
+
# 3 random dates...
|
|
565
|
+
datetime(2030, 5, 4),
|
|
566
|
+
datetime(2035, 7, 22),
|
|
567
|
+
datetime(2047, 8, 14)
|
|
568
|
+
],
|
|
569
|
+
ids=lambda system_datetime: f"system_datetime = {datetime.strftime(system_datetime, r'%Y-%m-%d')}"
|
|
570
|
+
)
|
|
571
|
+
@patch("hestia_earth.utils.tools.parse")
|
|
572
|
+
def test_group_nodes_by_year_scenario_a(mock_parse, system_datetime):
|
|
556
573
|
"""
|
|
557
574
|
Datestr in format `YYYY`. Some nodes missing `startDate` field. One multi-year cycle.
|
|
558
575
|
|
|
559
576
|
Incomplete datestrs are gapfilled by default; with `endDate` datestrs snapping to the end
|
|
560
577
|
of the calendar year, and `startDate` datestrs snapping to the beginning of the calendar
|
|
561
578
|
year.
|
|
579
|
+
|
|
580
|
+
A bug used to occur in this function when it was run on the first day of a calendar month (e.g., 2024-04-01). To
|
|
581
|
+
verify that the bug is fixed we have simulated running the function on a variety of different dates.
|
|
562
582
|
"""
|
|
563
583
|
|
|
564
584
|
EXPECTED = {
|
|
@@ -597,6 +617,9 @@ def test_group_nodes_by_year_scenario_a():
|
|
|
597
617
|
}]
|
|
598
618
|
}
|
|
599
619
|
|
|
620
|
+
# As we can't mock builtin method datetime.now(), we have to pass our test system_datetime into the parse function.
|
|
621
|
+
mock_parse.side_effect = lambda *args, **kwargs: parse(*args, default=system_datetime, **kwargs)
|
|
622
|
+
|
|
600
623
|
result = group_nodes_by_year(GROUP_NODES_BY_YEAR_SCENARIO_A_CYCLES)
|
|
601
624
|
assert result == EXPECTED
|
|
602
625
|
|
|
@@ -965,7 +988,26 @@ def test_group_nodes_by_year_missing_dates():
|
|
|
965
988
|
assert result == EXPECTED
|
|
966
989
|
|
|
967
990
|
|
|
968
|
-
|
|
991
|
+
@mark.parametrize(
|
|
992
|
+
"system_datetime",
|
|
993
|
+
[
|
|
994
|
+
datetime(2024, 5, 1), # Closes issue 772
|
|
995
|
+
datetime(2024, 1, 1), # Jan 1st
|
|
996
|
+
datetime(2024, 2, 29), # Leap year
|
|
997
|
+
datetime(2024, 12, 31), # Dec 31st
|
|
998
|
+
# 3 random dates...
|
|
999
|
+
datetime(2026, 5, 14),
|
|
1000
|
+
datetime(2032, 10, 10),
|
|
1001
|
+
datetime(2043, 8, 22)
|
|
1002
|
+
],
|
|
1003
|
+
ids=lambda system_datetime: f"system_datetime = {datetime.strftime(system_datetime, r'%Y-%m-%d')}"
|
|
1004
|
+
)
|
|
1005
|
+
@patch("hestia_earth.utils.tools.parse")
|
|
1006
|
+
def test_group_nodes_by_year_multiple_values_and_dates(mock_parse, system_datetime):
|
|
1007
|
+
"""
|
|
1008
|
+
A bug used to occur in this function when it was run on the first day of a calendar month (e.g., 2024-04-01). To
|
|
1009
|
+
verify that the bug is fixed we have simulated running the function on a variety of different dates.
|
|
1010
|
+
"""
|
|
969
1011
|
|
|
970
1012
|
NODES = [{
|
|
971
1013
|
"value": [1, 2, 3, 4, 5],
|
|
@@ -1005,11 +1047,34 @@ def test_group_nodes_by_year_multiple_values_and_dates():
|
|
|
1005
1047
|
}]
|
|
1006
1048
|
}
|
|
1007
1049
|
|
|
1050
|
+
# As we can't mock builtin method datetime.now(), we have to pass our test system_datetime into the parse function.
|
|
1051
|
+
mock_parse.side_effect = lambda *args, **kwargs: parse(*args, default=system_datetime, **kwargs)
|
|
1052
|
+
|
|
1008
1053
|
result = group_nodes_by_year(NODES, mode=GroupNodesByYearMode.DATES)
|
|
1009
1054
|
assert result == EXPECTED
|
|
1010
1055
|
|
|
1011
1056
|
|
|
1012
|
-
|
|
1057
|
+
@mark.parametrize(
|
|
1058
|
+
"system_datetime",
|
|
1059
|
+
[
|
|
1060
|
+
datetime(2024, 5, 1), # Closes issue 772
|
|
1061
|
+
datetime(2024, 1, 1), # Jan 1st
|
|
1062
|
+
datetime(2024, 2, 29), # Leap year
|
|
1063
|
+
datetime(2024, 12, 31), # Dec 31st
|
|
1064
|
+
# 3 random dates...
|
|
1065
|
+
datetime(2026, 4, 6),
|
|
1066
|
+
datetime(2034, 7, 24),
|
|
1067
|
+
datetime(2049, 10, 10)
|
|
1068
|
+
],
|
|
1069
|
+
ids=lambda system_datetime: f"system_datetime = {datetime.strftime(system_datetime, r'%Y-%m-%d')}"
|
|
1070
|
+
)
|
|
1071
|
+
@patch("hestia_earth.utils.tools.parse")
|
|
1072
|
+
def test_group_nodes_by_year_and_month(mock_parse, system_datetime):
|
|
1073
|
+
"""
|
|
1074
|
+
A bug used to occur in this function when it was run on the first day of a calendar month (e.g., 2024-04-01). To
|
|
1075
|
+
verify that the bug is fixed we have simulated running the function on a variety of different dates.
|
|
1076
|
+
"""
|
|
1077
|
+
|
|
1013
1078
|
MANAGEMENT = [
|
|
1014
1079
|
{
|
|
1015
1080
|
"term.@id": "fullTillage",
|
|
@@ -1064,5 +1129,8 @@ def test_group_nodes_by_year_and_month():
|
|
|
1064
1129
|
}
|
|
1065
1130
|
}
|
|
1066
1131
|
|
|
1132
|
+
# As we can't mock builtin method datetime.now(), we have to pass our test system date into the parse function.
|
|
1133
|
+
mock_parse.side_effect = lambda *args, **kwargs: parse(*args, default=system_datetime, **kwargs)
|
|
1134
|
+
|
|
1067
1135
|
result = group_nodes_by_year_and_month(MANAGEMENT)
|
|
1068
1136
|
assert result == EXPECTED
|