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 86ba5e47..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.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"], + extras_require={"testing": ["pytest", "shapely", "flake8"]}, ) diff --git a/tests/test_sdk.py b/tests/test_sdk.py index c305162b..d2bbdb79 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" @@ -132,8 +132,8 @@ def setUp(self): self.historical = WattTimeHistorical() def test_get_historical_jsons_3_months(self): - start = "2022-01-01 00:00Z" - end = "2022-12-31 00:00Z" + start = "2024-01-01 00:00Z" + end = "2024-03-31 00:00Z" jsons = self.historical.get_historical_jsons(start, end, REGION) self.assertIsInstance(jsons, list) @@ -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()