From c696b10755a7416db4df8b82a0b2b0dafa15f753 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sat, 31 May 2025 21:26:35 -0400 Subject: [PATCH] Update Makefile aliases and handle distutils --- Makefile | 8 ++++---- scripts/refresh_data.py | 44 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 545c474..750b4d7 100644 --- a/Makefile +++ b/Makefile @@ -2,20 +2,20 @@ # Install dependencies & fetch data install: - ./startup.sh + ./startup.sh lagged_oil_unrate # Download FRED data (if needed) data: - ./startup.sh scripts/refresh_data.py + ./startup.sh refresh_data # Default 18-month lag plot plot: - ./startup.sh + ./startup.sh lagged_oil_unrate # Custom plot of arbitrary series # Usage: make plot-custom ARGS="--series UNRATE CPIAUCSL --start 2000-01-01" plot-custom: - ./startup.sh python scripts/custom_chart.py $(ARGS) + ./startup.sh custom_chart $(ARGS) # Run tests test: diff --git a/scripts/refresh_data.py b/scripts/refresh_data.py index f0e46f9..772e77d 100644 --- a/scripts/refresh_data.py +++ b/scripts/refresh_data.py @@ -20,6 +20,50 @@ import logging logger = logging.getLogger(__name__) +# pandas_datareader < 0.11 requires distutils, which was removed in Python 3.12 +try: # pragma: no cover - prefer stdlib when available + from distutils.version import LooseVersion # type: ignore +except ModuleNotFoundError: # pragma: no cover - Python >=3.12 + from packaging.version import Version + import types, sys + + class LooseVersion: + def __init__(self, v: str | int) -> None: + self.vstring = str(v) + self.version = Version(self.vstring) + + def __repr__(self) -> str: # pragma: no cover - debug helper + return f"LooseVersion('{self.vstring}')" + + def __lt__(self, other: "LooseVersion") -> bool: + return self.version < other.version + + def __le__(self, other: "LooseVersion") -> bool: + return self.version <= other.version + + def __eq__(self, other: object) -> bool: + if not isinstance(other, LooseVersion): + return NotImplemented + return self.version == other.version + + def __ne__(self, other: object) -> bool: # pragma: no cover - unused + if not isinstance(other, LooseVersion): + return NotImplemented + return self.version != other.version + + def __gt__(self, other: "LooseVersion") -> bool: + return self.version > other.version + + def __ge__(self, other: "LooseVersion") -> bool: + return self.version >= other.version + + version_module = types.ModuleType("version") + version_module.LooseVersion = LooseVersion + distutils_module = types.ModuleType("distutils") + distutils_module.version = version_module + sys.modules.setdefault("distutils", distutils_module) + sys.modules.setdefault("distutils.version", version_module) + from pandas_datareader.data import DataReader import pandas as pd