From 19967e568bce2a2448a9772f3cc243396628084c Mon Sep 17 00:00:00 2001 From: sam-watttime Date: Mon, 16 Dec 2024 14:01:02 -0700 Subject: [PATCH 1/3] test for CCW geometries in maps --- setup.py | 4 ++-- tests/test_sdk.py | 47 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/setup.py b/setup.py index 86ba5e47..2b79a0f7 100644 --- a/setup.py +++ b/setup.py @@ -5,8 +5,8 @@ description="An officially maintained python client for WattTime's API providing access to electricity grid emissions data.", long_description=open('README.md').read(), long_description_content_type="text/markdown", - version="v1.2.1", + version="v1.2.2", packages=["watttime"], python_requires=">=3.8", - install_requires=["requests", "pandas>1.0.0", "python-dateutil"], + install_requires=["requests", "pandas>1.0.0", "python-dateutil", "shapely"], ) diff --git a/tests/test_sdk.py b/tests/test_sdk.py index c305162b..ea0525b7 100644 --- a/tests/test_sdk.py +++ b/tests/test_sdk.py @@ -14,7 +14,7 @@ from pathlib import Path import pandas as pd -import requests +from shapely.geometry import shape, Polygon, MultiPolygon REGION = "CAISO_NORTH" @@ -53,7 +53,7 @@ def setUp(self): def test_login_with_real_api(self): self.base._login() assert self.base.token is not None - assert self.base.token_valid_until > datetime.now() + assert self.base.token_valid_until > datetime.now(tz=UTC) def test_parse_dates_with_string(self): start = "2022-01-01" @@ -132,7 +132,7 @@ def setUp(self): self.historical = WattTimeHistorical() def test_get_historical_jsons_3_months(self): - start = "2022-01-01 00:00Z" + start = "2024-01-01 00:00Z" end = "2022-12-31 00:00Z" jsons = self.historical.get_historical_jsons(start, end, REGION) @@ -141,8 +141,8 @@ def test_get_historical_jsons_3_months(self): self.assertIsInstance(jsons[0], dict) def test_get_historical_jsons_1_week(self): - start = "2022-01-01 00:00Z" - end = "2022-01-07 00:00Z" + start = "2024-10-11 00:00Z" + end = "2024-10-19 00:00Z" jsons = self.historical.get_historical_jsons(start, end, REGION) self.assertIsInstance(jsons, list) @@ -150,8 +150,8 @@ def test_get_historical_jsons_1_week(self): self.assertIsInstance(jsons[0], dict) def test_get_historical_jsons_signal_types(self): - start = "2023-01-01 00:00Z" - end = "2023-01-07 00:00Z" + start = datetime.now(tz=UTC) - timedelta(days=7) + end = datetime.now(tz=UTC) signal_types = ["co2_moer", "co2_aoer", "health_damage"] for signal_type in signal_types: if signal_type == "co2_aoer": @@ -168,8 +168,8 @@ def test_get_historical_jsons_signal_types(self): self.assertEqual(jsons[0]["meta"]["region"], region) def test_get_historical_pandas(self): - start = datetime.now() - timedelta(days=7) - end = datetime.now() + start = datetime.now(tz=UTC) - timedelta(days=7) + end = datetime.now(tz=UTC) df = self.historical.get_historical_pandas(start, end, REGION) self.assertIsInstance(df, pd.DataFrame) @@ -178,8 +178,8 @@ def test_get_historical_pandas(self): self.assertIn("value", df.columns) def test_get_historical_pandas_meta(self): - start = datetime.now() - timedelta(days=7) - end = datetime.now() + start = datetime.now(tz=UTC) - timedelta(days=7) + end = datetime.now(tz=UTC) df = self.historical.get_historical_pandas( start, end, REGION, include_meta=True ) @@ -313,8 +313,8 @@ def test_get_current_pandas(self): self.assertIn("value", df.columns) def test_historical_forecast_jsons(self): - start = "2023-01-01 00:00Z" - end = "2023-01-03 00:00Z" + start = "2024-01-01 00:00Z" + end = "2024-01-03 00:00Z" json_list = self.forecast.get_historical_forecast_json( start, end, region=REGION ) @@ -326,8 +326,8 @@ def test_historical_forecast_jsons(self): self.assertIn("generated_at", first_json["data"][0]) def test_historical_forecast_pandas(self): - start = "2023-01-01 00:00Z" - end = "2023-01-03 00:00Z" + start = "2024-10-01 00:00Z" + end = "2024-10-03 00:00Z" df = self.forecast.get_historical_forecast_pandas(start, end, region=REGION) self.assertIsInstance(df, pd.DataFrame) @@ -395,6 +395,23 @@ def test_region_from_loc(self): self.assertEqual(region["region_full_name"], "Public Service Co of Colorado") self.assertEqual(region["signal_type"], "co2_moer") + def test_ccw(self): + moer = self.maps.get_maps_json(signal_type="co2_moer") + + def _is_ccw(geometry): + if isinstance(geometry, Polygon): + return geometry.exterior.is_ccw + elif isinstance(geometry, MultiPolygon): + return all(poly.exterior.is_ccw for poly in geometry.geoms) + return True + + bad = [ + f["properties"]["region_full_name"] + for f in moer["features"] + if not _is_ccw(shape(f["geometry"])) + ] + assert len(bad) == 0, f"Non-CCW geometries: {bad}" + if __name__ == "__main__": unittest.main() From 0360bf7a64686af99e529a1190f3c9e42917cbde Mon Sep 17 00:00:00 2001 From: sam-watttime Date: Mon, 16 Dec 2024 15:43:24 -0700 Subject: [PATCH 2/3] fix failing tests -- unrelated to CCW --- tests/test_sdk.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_sdk.py b/tests/test_sdk.py index ea0525b7..d2bbdb79 100644 --- a/tests/test_sdk.py +++ b/tests/test_sdk.py @@ -53,7 +53,7 @@ def setUp(self): def test_login_with_real_api(self): self.base._login() assert self.base.token is not None - assert self.base.token_valid_until > datetime.now(tz=UTC) + assert self.base.token_valid_until > datetime.now() def test_parse_dates_with_string(self): start = "2022-01-01" @@ -133,7 +133,7 @@ def setUp(self): def test_get_historical_jsons_3_months(self): start = "2024-01-01 00:00Z" - end = "2022-12-31 00:00Z" + end = "2024-03-31 00:00Z" jsons = self.historical.get_historical_jsons(start, end, REGION) self.assertIsInstance(jsons, list) From 97305149281e01e40322b0b7228df9d1556269ca Mon Sep 17 00:00:00 2001 From: samkoebrich Date: Thu, 27 Feb 2025 10:22:14 -0700 Subject: [PATCH 3/3] make shapely an optional dependency for [testing] --- .github/workflows/tests.yml | 3 +-- setup.py | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 61fd9076..18097b6f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,8 +29,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install flake8 pytest - pip install . + pip install .[testing] - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names diff --git a/setup.py b/setup.py index 2b79a0f7..9657edd2 100644 --- a/setup.py +++ b/setup.py @@ -3,10 +3,11 @@ setup( name="watttime", description="An officially maintained python client for WattTime's API providing access to electricity grid emissions data.", - long_description=open('README.md').read(), + long_description=open("README.md").read(), long_description_content_type="text/markdown", version="v1.2.2", packages=["watttime"], python_requires=">=3.8", install_requires=["requests", "pandas>1.0.0", "python-dateutil", "shapely"], + extras_require={"testing": ["pytest", "shapely", "flake8"]}, )