Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
231 changes: 0 additions & 231 deletions WEBSITE_FIXES_DEPLOYED.md

This file was deleted.

13 changes: 7 additions & 6 deletions examples/visualization_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from oilpriceapi import OilPriceAPI
from oilpriceapi.visualization import HAS_MATPLOTLIB

# Configuration
API_KEY = os.getenv("OILPRICEAPI_KEY")
Expand All @@ -30,8 +31,8 @@ def demo_price_series():

client = OilPriceAPI(api_key=API_KEY, base_url=BASE_URL)

if not client.viz:
print("⚠️ Matplotlib not installed. Install with: pip install matplotlib")
if not HAS_MATPLOTLIB:
print("⚠️ Matplotlib not installed. Install with: pip install 'oilpriceapi[viz]'")
return

# Create visualization
Expand Down Expand Up @@ -76,7 +77,7 @@ def demo_spread_analysis():

client = OilPriceAPI(api_key=API_KEY, base_url=BASE_URL)

if not client.viz:
if not HAS_MATPLOTLIB:
print("⚠️ Visualization not available")
return

Expand Down Expand Up @@ -112,7 +113,7 @@ def demo_sparklines():

client = OilPriceAPI(api_key=API_KEY, base_url=BASE_URL)

if not client.viz:
if not HAS_MATPLOTLIB:
print("⚠️ Visualization not available")
return

Expand Down Expand Up @@ -146,7 +147,7 @@ def demo_small_multiples():

client = OilPriceAPI(api_key=API_KEY, base_url=BASE_URL)

if not client.viz:
if not HAS_MATPLOTLIB:
print("⚠️ Visualization not available")
return

Expand Down Expand Up @@ -191,7 +192,7 @@ def main():
print(f"\n✅ Matplotlib version: {matplotlib.__version__}")
except ImportError:
print("\n⚠️ Matplotlib not installed!")
print(" Install with: pip install matplotlib")
print(" Install with: pip install 'oilpriceapi[viz]'")
return

# Run demos
Expand Down
25 changes: 17 additions & 8 deletions oilpriceapi/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,20 +221,29 @@ def __init__(
# LTL + parcel carrier fuel surcharges (#101).
self.fuel_surcharge = FuelSurchargeResource(self)

# Initialize visualization (optional)
self.viz: Optional["PriceVisualizer"]
try:
from .visualization import PriceVisualizer

self.viz = PriceVisualizer(self)
except ImportError:
self.viz = None
# Visualization is optional and built on first use of ``viz`` (#151):
# constructing a client must not import matplotlib or warn about it.
self._viz: Optional["PriceVisualizer"] = None

# Initialize telemetry (opt-in, disabled by default)
from .telemetry import Telemetry

self._telemetry = Telemetry(enabled=enable_telemetry)

@property
def viz(self) -> "PriceVisualizer":
"""Tufte-style charts, built on first access.

Building the visualizer imports nothing optional and never warns. If
matplotlib is missing, each plotting method raises ``ImportError``
naming the extra: ``pip install 'oilpriceapi[viz]'``.
"""
if self._viz is None:
from .visualization import PriceVisualizer

self._viz = PriceVisualizer(self)
return self._viz

def request(
self,
method: str,
Expand Down
24 changes: 13 additions & 11 deletions oilpriceapi/visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
except ImportError:
HAS_MATPLOTLIB = False

# Raised by every plotting method when matplotlib is not installed. It names
# the extra so the fix is one copy-paste away.
MATPLOTLIB_REQUIRED = (
"matplotlib is required for visualization. "
"Install it with: pip install 'oilpriceapi[viz]'"
)

try:
import pandas as pd
HAS_PANDAS = True
Expand Down Expand Up @@ -88,13 +95,8 @@ class PriceVisualizer:
def __init__(self, client):
"""Initialize visualizer with OilPriceAPI client."""
self.client = client

if not HAS_MATPLOTLIB:
warnings.warn(
"matplotlib is required for visualization. "
"Install with: pip install matplotlib",
ImportWarning
)
# No warning here (#151): every plotting method raises ImportError
# with install guidance when matplotlib is missing.

def plot_price_series(
self,
Expand All @@ -119,7 +121,7 @@ def plot_price_series(
matplotlib Figure object
"""
if not HAS_MATPLOTLIB:
raise ImportError("matplotlib required for visualization")
raise ImportError(MATPLOTLIB_REQUIRED)

# Fetch data
history = self.client.historical.get(
Expand Down Expand Up @@ -238,7 +240,7 @@ def plot_spread(
Following Tufte's principle of showing data relationships clearly.
"""
if not HAS_MATPLOTLIB:
raise ImportError("matplotlib required for visualization")
raise ImportError(MATPLOTLIB_REQUIRED)

# Fetch data for both commodities
hist1 = self.client.historical.get(
Expand Down Expand Up @@ -381,7 +383,7 @@ def create_sparkline(
Perfect for embedding in reports or dashboards.
"""
if not HAS_MATPLOTLIB:
raise ImportError("matplotlib required for visualization")
raise ImportError(MATPLOTLIB_REQUIRED)

# Fetch recent data
end_date = datetime.now()
Expand Down Expand Up @@ -442,7 +444,7 @@ def create_small_multiples(
Allows easy comparison across multiple commodities.
"""
if not HAS_MATPLOTLIB:
raise ImportError("matplotlib required for visualization")
raise ImportError(MATPLOTLIB_REQUIRED)

n = len(commodities)
rows = (n + cols - 1) // cols
Expand Down
Loading
Loading