hestia-earth-models 0.59.4__py3-none-any.whl → 0.59.6__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.

Files changed (55) hide show
  1. hestia_earth/models/cycle/animal/milkYield.py +86 -0
  2. hestia_earth/models/cycle/endDate.py +50 -0
  3. hestia_earth/models/cycle/inorganicFertiliser.py +3 -2
  4. hestia_earth/models/cycle/liveAnimal.py +3 -0
  5. hestia_earth/models/cycle/milkYield.py +8 -3
  6. hestia_earth/models/cycle/pre_checks/__init__.py +1 -2
  7. hestia_earth/models/cycle/startDate.py +42 -0
  8. hestia_earth/models/cycle/utils.py +1 -1
  9. hestia_earth/models/faostat2018/liveweightPerHead.py +77 -41
  10. hestia_earth/models/faostat2018/product/price.py +30 -55
  11. hestia_earth/models/faostat2018/utils.py +10 -2
  12. hestia_earth/models/geospatialDatabase/potentialEvapotranspirationLongTermAnnualMean.py +2 -2
  13. hestia_earth/models/geospatialDatabase/potentialEvapotranspirationMonthly.py +9 -8
  14. hestia_earth/models/geospatialDatabase/precipitationMonthly.py +10 -8
  15. hestia_earth/models/geospatialDatabase/temperatureAnnual.py +2 -5
  16. hestia_earth/models/geospatialDatabase/temperatureLongTermAnnualMean.py +2 -3
  17. hestia_earth/models/geospatialDatabase/temperatureMonthly.py +8 -8
  18. hestia_earth/models/geospatialDatabase/utils.py +6 -1
  19. hestia_earth/models/haversineFormula/transport/distance.py +6 -3
  20. hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserIndirect.py +1 -1
  21. hestia_earth/models/ipcc2019/organicCarbonPerHa.py +89 -114
  22. hestia_earth/models/ipcc2019/pastureGrass.py +2 -1
  23. hestia_earth/models/linkedImpactAssessment/__init__.py +78 -43
  24. hestia_earth/models/mocking/search-results.json +244 -271
  25. hestia_earth/models/schmidt2007/h2SToAirWasteTreatment.py +58 -0
  26. hestia_earth/models/schmidt2007/n2OToAirWasteTreatmentDirect.py +58 -0
  27. hestia_earth/models/schmidt2007/nh3ToAirWasteTreatment.py +58 -0
  28. hestia_earth/models/site/management.py +107 -12
  29. hestia_earth/models/site/soilMeasurement.py +9 -9
  30. hestia_earth/models/utils/__init__.py +4 -1
  31. hestia_earth/models/utils/animalProduct.py +6 -4
  32. hestia_earth/models/utils/blank_node.py +6 -5
  33. hestia_earth/models/utils/product.py +9 -1
  34. hestia_earth/models/utils/term.py +0 -23
  35. hestia_earth/models/version.py +1 -1
  36. {hestia_earth_models-0.59.4.dist-info → hestia_earth_models-0.59.6.dist-info}/METADATA +1 -1
  37. {hestia_earth_models-0.59.4.dist-info → hestia_earth_models-0.59.6.dist-info}/RECORD +53 -43
  38. tests/models/cycle/animal/test_milkYield.py +43 -0
  39. tests/models/cycle/test_endDate.py +24 -0
  40. tests/models/cycle/test_startDate.py +22 -0
  41. tests/models/faostat2018/product/test_price.py +25 -45
  42. tests/models/faostat2018/test_liveweightPerHead.py +106 -42
  43. tests/models/ipcc2019/test_organicCarbonPerHa.py +12 -18
  44. tests/models/schmidt2007/test_h2SToAirWasteTreatment.py +45 -0
  45. tests/models/schmidt2007/test_n2OToAirWasteTreatmentDirect.py +45 -0
  46. tests/models/schmidt2007/test_nh3ToAirWasteTreatment.py +45 -0
  47. tests/models/site/test_management.py +24 -3
  48. tests/models/site/test_soilMeasurement.py +40 -21
  49. tests/models/utils/test_blank_node.py +71 -3
  50. tests/models/utils/test_term.py +1 -8
  51. hestia_earth/models/cycle/pre_checks/startDate.py +0 -52
  52. tests/models/cycle/pre_checks/test_startDate.py +0 -44
  53. {hestia_earth_models-0.59.4.dist-info → hestia_earth_models-0.59.6.dist-info}/LICENSE +0 -0
  54. {hestia_earth_models-0.59.4.dist-info → hestia_earth_models-0.59.6.dist-info}/WHEEL +0 -0
  55. {hestia_earth_models-0.59.4.dist-info → hestia_earth_models-0.59.6.dist-info}/top_level.txt +0 -0
@@ -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
- def test_group_nodes_by_year_scenario_a():
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
- def test_group_nodes_by_year_multiple_values_and_dates():
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
- def test_group_nodes_by_year_and_month():
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
@@ -4,7 +4,7 @@ from hestia_earth.models.utils.term import (
4
4
  get_liquid_fuel_terms, get_irrigation_terms, get_urea_terms, get_excreta_N_terms, get_excreta_VS_terms,
5
5
  get_generic_crop, get_rice_paddy_terms, get_tillage_terms, get_crop_residue_terms, get_cover_crop_property_terms,
6
6
  get_crop_residue_incorporated_or_left_on_field_terms, get_irrigated_terms, get_residue_removed_or_burnt_terms,
7
- get_upland_rice_land_cover_terms, get_upland_rice_crop_terms, get_long_fallow_land_cover_terms
7
+ get_upland_rice_land_cover_terms, get_upland_rice_crop_terms
8
8
  )
9
9
 
10
10
  class_path = 'hestia_earth.models.utils.term'
@@ -113,10 +113,3 @@ def test_get_upland_rice_crop_terms(mock_find_node):
113
113
  id = 'term-id'
114
114
  mock_find_node.return_value = [{'@id': id}]
115
115
  assert get_upland_rice_crop_terms() == [id]
116
-
117
-
118
- @patch(f"{class_path}.search")
119
- def test_get_long_fallow_land_cover_terms(mock_find_node):
120
- id = 'term-id'
121
- mock_find_node.return_value = [{'@id': id}]
122
- assert get_long_fallow_land_cover_terms() == [id]
@@ -1,52 +0,0 @@
1
- """
2
- Pre Checks Start Date
3
-
4
- This model calculates the
5
- [startDate](https://hestia.earth/schema/Cycle#startDate) from the
6
- [endDate](https://hestia.earth/schema/Cycle#endDate) and
7
- [cycleDuration](https://hestia.earth/schema/Cycle#cycleDuration).
8
- """
9
- from dateutil.relativedelta import relativedelta
10
- from hestia_earth.utils.date import is_in_days
11
- from hestia_earth.utils.tools import safe_parse_date
12
-
13
- from hestia_earth.models.log import logRequirements, logShouldRun
14
- from .. import MODEL
15
-
16
- REQUIREMENTS = {
17
- "Cycle": {
18
- "endDate": "",
19
- "cycleDuration": ""
20
- }
21
- }
22
- RETURNS = {
23
- "Cycle": {
24
- "startDate": ""
25
- }
26
- }
27
- MODEL_KEY = 'startDate'
28
-
29
-
30
- def _run(cycle: dict):
31
- days = -float(cycle.get('cycleDuration'))
32
- return (safe_parse_date(cycle.get('endDate')) + relativedelta(days=days)).strftime('%Y-%m-%d')
33
-
34
-
35
- def _should_run(cycle: dict):
36
- has_full_date = is_in_days(cycle.get('endDate'))
37
- cycleDuration = cycle.get('cycleDuration')
38
-
39
- logRequirements(cycle, model=MODEL, key=MODEL_KEY,
40
- has_full_date=has_full_date,
41
- cycleDuration=cycleDuration)
42
-
43
- should_run = all([
44
- has_full_date,
45
- cycleDuration is not None,
46
- cycle.get(MODEL_KEY) is None
47
- ])
48
- logShouldRun(cycle, MODEL, None, should_run, key=MODEL_KEY)
49
- return should_run
50
-
51
-
52
- def run(cycle: dict): return {**cycle, MODEL_KEY: _run(cycle)} if _should_run(cycle) else cycle
@@ -1,44 +0,0 @@
1
- import json
2
- from tests.utils import fixtures_path
3
-
4
- from hestia_earth.models.cycle.pre_checks.startDate import run, _should_run
5
-
6
- fixtures_folder = f"{fixtures_path}/cycle/pre_checks/startDate"
7
-
8
-
9
- def test_should_run():
10
- cycle = {}
11
-
12
- # no endDate => no run
13
- cycle['endDate'] = None
14
- assert not _should_run(cycle)
15
-
16
- cycle['endDate'] = '2010'
17
- # no cycleDuration => no run
18
- cycle['cycleDuration'] = None
19
- assert not _should_run(cycle)
20
-
21
- cycle['cycleDuration'] = 120
22
- # with a startDate => no run
23
- cycle['startDate'] = '2010'
24
- assert not _should_run(cycle)
25
-
26
- cycle['startDate'] = None
27
- # endDate not precise enough => no run
28
- cycle['endDate'] = '2020-01'
29
- assert not _should_run(cycle)
30
-
31
- # endDate is precise enough => run
32
- cycle['endDate'] = '2020-01-01'
33
- assert _should_run(cycle) is True
34
-
35
-
36
- def test_run():
37
- with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
38
- cycle = json.load(f)
39
-
40
- with open(f"{fixtures_folder}/result.jsonld", encoding='utf-8') as f:
41
- expected = json.load(f)
42
-
43
- value = run(cycle)
44
- assert value == expected