|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
3 | 3 | from datetime import date, datetime |
4 | | -from typing import Any, Dict, List, Optional, Sequence, Union |
| 4 | +from typing import Any, Dict, List, Optional, Sequence, Union, cast |
5 | 5 |
|
6 | 6 | from . import _fuel_surcharge_common as fs |
7 | 7 | from ._subscriptions_common import ( |
|
54 | 54 | ) |
55 | 55 | from .resources import _calculated_metrics as metrics_ops |
56 | 56 | from .resources._futures_slug import normalize_futures_slug |
| 57 | +from .resources._removed import removed_endpoint |
| 58 | +from .resources._route_args import ( |
| 59 | + bunker_grade_prefix, |
| 60 | + bunker_port_code, |
| 61 | + bunker_spread_params, |
| 62 | + filter_bunker_history, |
| 63 | + storage_history_code, |
| 64 | + storage_history_period, |
| 65 | +) |
57 | 66 | from .resources.ei._envelopes import ei_data, unwrap_ei_collection, unwrap_ei_object |
58 | 67 | from .resources.ei.well_permits import unwrap_well_permit_search_response |
59 | 68 | from .resources.subscriptions import SubscriptionEventsPage |
@@ -442,10 +451,16 @@ async def intraday(self, contract: str) -> List[Dict[str, Any]]: |
442 | 451 | return response |
443 | 452 |
|
444 | 453 | async def spreads(self, contract1: str, contract2: str) -> Dict[str, Any]: |
445 | | - response = await self.client.request( |
446 | | - method="GET", path="/v1/futures/spreads", |
447 | | - params={"contract1": contract1, "contract2": contract2} |
| 454 | + """Deprecated: no API route (#153). Use ``calendar_spreads(contract)``.""" |
| 455 | + removed_endpoint( |
| 456 | + "client.futures.spreads()", |
| 457 | + "client.futures.calendar_spreads(contract)", |
448 | 458 | ) |
| 459 | + |
| 460 | + async def calendar_spreads(self, contract: str) -> Dict[str, Any]: |
| 461 | + """Calendar spreads for one contract family (``/v1/futures/{slug}/spreads``).""" |
| 462 | + slug = normalize_futures_slug(contract) |
| 463 | + response = await self.client.request(method="GET", path=f"/v1/futures/{slug}/spreads") |
449 | 464 | if "data" in response: |
450 | 465 | return response["data"] |
451 | 466 | return response |
@@ -512,25 +527,17 @@ async def regional(self, region: Optional[str] = None) -> Dict[str, Any]: |
512 | 527 | return response["data"] |
513 | 528 | return response |
514 | 529 |
|
515 | | - async def history( |
516 | | - self, |
517 | | - code: str, |
518 | | - start_date: Optional[Union[str, date, datetime]] = None, |
519 | | - end_date: Optional[Union[str, date, datetime]] = None |
520 | | - ) -> List[Dict[str, Any]]: |
521 | | - params = {} |
522 | | - if start_date is not None: |
523 | | - params["start_date"] = format_date(start_date) |
524 | | - if end_date is not None: |
525 | | - params["end_date"] = format_date(end_date) |
| 530 | + async def history(self, code: str, period: str = "90d") -> Dict[str, Any]: |
| 531 | + """Storage history (``/v1/storage/history/{code}``). See the sync docstring.""" |
526 | 532 | response = await self.client.request( |
527 | | - method="GET", path=f"/v1/storage/{code}/history", params=params |
| 533 | + method="GET", |
| 534 | + path=f"/v1/storage/history/{storage_history_code(code)}", |
| 535 | + params={"period": storage_history_period(period)}, |
528 | 536 | ) |
529 | 537 | if "data" in response: |
530 | 538 | return response["data"] |
531 | 539 | return response |
532 | 540 |
|
533 | | - |
534 | 541 | class AsyncRigCountsResource: |
535 | 542 | def __init__(self, client): |
536 | 543 | self.client = client |
@@ -604,30 +611,41 @@ async def compare(self, ports: List[str]) -> Dict[str, Any]: |
604 | 611 | return response["data"] |
605 | 612 | return response |
606 | 613 |
|
607 | | - async def spreads(self) -> Dict[str, Any]: |
608 | | - response = await self.client.request(method="GET", path="/v1/bunker-fuels/spreads") |
| 614 | + async def spreads(self, from_port: str, to_port: str, grade: Optional[str] = None) -> Dict[str, Any]: |
| 615 | + """Port-to-port spread (``/v1/bunker-fuels/spreads/ports``).""" |
| 616 | + response = await self.client.request( |
| 617 | + method="GET", |
| 618 | + path="/v1/bunker-fuels/spreads/ports", |
| 619 | + params=bunker_spread_params(from_port, to_port, grade), |
| 620 | + ) |
609 | 621 | if "data" in response: |
610 | 622 | return response["data"] |
611 | 623 | return response |
612 | 624 |
|
613 | 625 | async def historical( |
614 | 626 | self, |
615 | 627 | port: str, |
616 | | - fuel_type: str, |
| 628 | + fuel_type: Optional[str] = None, |
617 | 629 | start_date: Optional[Union[str, date, datetime]] = None, |
618 | | - end_date: Optional[Union[str, date, datetime]] = None |
619 | | - ) -> List[Dict[str, Any]]: |
620 | | - params: Dict[str, Any] = {"port": port, "fuel_type": fuel_type} |
| 630 | + end_date: Optional[Union[str, date, datetime]] = None, |
| 631 | + interval: Optional[str] = None, |
| 632 | + ) -> Dict[str, Any]: |
| 633 | + """Port history (``/v1/bunker-fuels/historical/{port}``). See the sync docstring.""" |
| 634 | + prefix = bunker_grade_prefix(fuel_type) |
| 635 | + params: Dict[str, Any] = {} |
621 | 636 | if start_date is not None: |
622 | | - params["start_date"] = format_date(start_date) |
| 637 | + params["from"] = format_date(start_date) |
623 | 638 | if end_date is not None: |
624 | | - params["end_date"] = format_date(end_date) |
| 639 | + params["to"] = format_date(end_date) |
| 640 | + if interval is not None: |
| 641 | + params["interval"] = interval |
625 | 642 | response = await self.client.request( |
626 | | - method="GET", path="/v1/bunker-fuels/historical", params=params |
| 643 | + method="GET", |
| 644 | + path=f"/v1/bunker-fuels/historical/{bunker_port_code(port)}", |
| 645 | + params=params, |
627 | 646 | ) |
628 | | - if "data" in response: |
629 | | - return response["data"] |
630 | | - return response |
| 647 | + data = response["data"] if "data" in response else response |
| 648 | + return filter_bunker_history(data, prefix) |
631 | 649 |
|
632 | 650 | async def export(self, format: str = "json") -> Any: |
633 | 651 | response = await self.client.request( |
@@ -718,21 +736,23 @@ async def monthly(self, commodity: Optional[str] = None) -> Dict[str, Any]: |
718 | 736 | return response |
719 | 737 |
|
720 | 738 | async def accuracy(self) -> Dict[str, Any]: |
721 | | - response = await self.client.request(method="GET", path="/v1/forecasts/accuracy") |
| 739 | + """Forecast accuracy (``/v1/forecasts/monthly/accuracy``).""" |
| 740 | + response = await self.client.request(method="GET", path="/v1/forecasts/monthly/accuracy") |
722 | 741 | if "data" in response: |
723 | | - return response["data"] |
724 | | - return response |
| 742 | + return cast(Dict[str, Any], response["data"]) |
| 743 | + return cast(Dict[str, Any], response) |
725 | 744 |
|
726 | 745 | async def archive(self, year: Optional[int] = None) -> List[Dict[str, Any]]: |
727 | | - params = {} |
| 746 | + """Archived forecasts (``/v1/forecasts/monthly/archive``).""" |
| 747 | + params: Dict[str, Any] = {} |
728 | 748 | if year: |
729 | 749 | params["year"] = year |
730 | 750 | response = await self.client.request( |
731 | | - method="GET", path="/v1/forecasts/archive", params=params |
| 751 | + method="GET", path="/v1/forecasts/monthly/archive", params=params |
732 | 752 | ) |
733 | 753 | if "data" in response: |
734 | | - return response["data"] |
735 | | - return response |
| 754 | + return cast(List[Dict[str, Any]], response["data"]) |
| 755 | + return cast(List[Dict[str, Any]], response) |
736 | 756 |
|
737 | 757 | async def get(self, period: str, commodity: Optional[str] = None) -> Dict[str, Any]: |
738 | 758 | params = {} |
@@ -793,13 +813,9 @@ async def summary(self) -> Dict[str, Any]: |
793 | 813 | return response["data"] |
794 | 814 | return response |
795 | 815 |
|
796 | | - async def trends(self, **params) -> List[Dict[str, Any]]: |
797 | | - response = await self.client.request( |
798 | | - method="GET", path="/v1/drilling-intelligence/trends", params=params |
799 | | - ) |
800 | | - if "data" in response: |
801 | | - return response["data"] |
802 | | - return response |
| 816 | + async def trends(self, **params: Any) -> List[Dict[str, Any]]: |
| 817 | + """Deprecated: no API route (#153). Use ``client.rig_counts.trends()``.""" |
| 818 | + removed_endpoint("client.drilling.trends()", "client.rig_counts.trends()") |
803 | 819 |
|
804 | 820 | async def frac_spreads(self, **params) -> List[Dict[str, Any]]: |
805 | 821 | response = await self.client.request( |
@@ -842,13 +858,11 @@ async def wells_drilled(self, **params) -> List[Dict[str, Any]]: |
842 | 858 | return response |
843 | 859 |
|
844 | 860 | async def basin(self, name: str) -> Dict[str, Any]: |
845 | | - response = await self.client.request( |
846 | | - method="GET", path=f"/v1/drilling-intelligence/basin/{name}" |
| 861 | + """Deprecated: no API route (#153). Use ``client.ei.drilling_productivity.by_basin()``.""" |
| 862 | + removed_endpoint( |
| 863 | + "client.drilling.basin()", |
| 864 | + "client.ei.drilling_productivity.by_basin()", |
847 | 865 | ) |
848 | | - if "data" in response: |
849 | | - return response["data"] |
850 | | - return response |
851 | | - |
852 | 866 |
|
853 | 867 | class AsyncWellProductionResource: |
854 | 868 | """Async resource for US well production data (beta). |
|
0 commit comments