Skip to content
Open
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
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ pip install -e '.[tests]'

To run the live tests, you'll need to have the `VORTEXA_API_KEY` environment variable set - `export VORTEXA_API_KEY=xyz`

run tests
run all tests

```bash
python setup.py test
pytest
```

If you're just looking to run tests in a single module (`test_vessels` in this case), you can do like this:
Expand Down
14 changes: 14 additions & 0 deletions docs/autogen.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@ def copy_examples(examples_dir: str, destination_dir: str) -> None:
f_out.write("```")


def copy_css(source_dir: str, destination_dir: str) -> None:
"""Copy CSS files to the documentation build directory."""
pathlib.Path(destination_dir).mkdir(parents=True, exist_ok=True)
for file in os.listdir(source_dir):
if file.endswith(".css"):
source_path = os.path.join(source_dir, file)
dest_path = os.path.join(destination_dir, file)
with open(source_path, "r", encoding="utf-8") as f_in:
content = f_in.read()
with open(dest_path, "w", encoding="utf-8") as f_out:
f_out.write(content)


if __name__ == "__main__":
print(os.getcwd())
copy_examples("./docs/examples", "./_build/pydocmd/examples")
copy_css("./docs/css", "./_build/pydocmd/css")
5 changes: 5 additions & 0 deletions docs/css/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* Fix long module names overflowing */
h1, h2, h3, h4, h5, h6 {
word-wrap: break-word;
overflow-wrap: break-word;
}
2 changes: 2 additions & 0 deletions docs/scripts/serve_docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ set -e
. venv/bin/activate
rm -rf ./_build
mkdir -p ./_build/pydocmd/examples
mkdir -p ./_build/pydocmd/css
cp -r docs/css/* ./_build/pydocmd/css/
python docs/autogen.py
Comment thread
Jack-Burge55 marked this conversation as resolved.
pydocmd serve
12 changes: 12 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ pages:
Products: endpoints/products.md
Vessels: endpoints/vessels.md
Fixtures: endpoints/fixtures.md
Anywhere Freight Pricing:
Latest Update: endpoints/anywhere_freight_pricing_latest_update_timestamp.md
Time-series: endpoints/anywhere_freight_pricing_price_timeseries.md
Price:
Get Prices: endpoints/anywhere_freight_pricing_get_price_details.md
Post Prices: endpoints/anywhere_freight_pricing_post_price_details.md
Top Ports:
Origin: endpoints/anywhere_freight_pricing_top_ports_origin.md
Destination: endpoints/anywhere_freight_pricing_top_ports_destination.md
Vessel Classes: endpoints/anywhere_freight_pricing_vessel_classes_details.md
Vessel Availability:
Search: endpoints/vessel_availability_search.md
Time Series: endpoints/vessel_availability_timeseries.md
Expand Down Expand Up @@ -75,3 +85,5 @@ theme:
custom_dir: custom_theme/
name: readthedocs
search_index_only: false
extra_css:
- css/custom.css
Comment thread
Jack-Burge55 marked this conversation as resolved.
18 changes: 17 additions & 1 deletion pydocmd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,24 @@ generate:
- endpoints/voyages_routes_breakdown.md: vortexasdk.endpoints.voyages_routes_breakdown++
- endpoints/voyages_top_hits.md: vortexasdk.endpoints.voyages_top_hits++
- endpoints/voyages_congestion_breakdown.md: vortexasdk.endpoints.voyages_congestion_breakdown++
- endpoints/refineries.md:
- endpoints/refineries.md:
- vortexasdk.endpoints.refineries++
- endpoints/anywhere_freight_pricing_latest_update_timestamp.md:
- vortexasdk.endpoints.anywhere_freight_pricing_latest_update_timestamp++
- endpoints/anywhere_freight_pricing_result.md:
- vortexasdk.endpoints.anywhere_freight_pricing_result++
- endpoints/anywhere_freight_pricing_price_timeseries.md:
- vortexasdk.endpoints.anywhere_freight_pricing_price_timeseries++
- endpoints/anywhere_freight_pricing_get_price_details.md:
- vortexasdk.endpoints.anywhere_freight_pricing_get_price_details++
- endpoints/anywhere_freight_pricing_post_price_details.md:
- vortexasdk.endpoints.anywhere_freight_pricing_post_price_details++
- endpoints/anywhere_freight_pricing_top_ports_origin.md:
- vortexasdk.endpoints.anywhere_freight_pricing_top_ports_origin++
- endpoints/anywhere_freight_pricing_top_ports_destination.md:
- vortexasdk.endpoints.anywhere_freight_pricing_top_ports_destination++
- endpoints/anywhere_freight_pricing_vessel_classes_details.md:
- vortexasdk.endpoints.anywhere_freight_pricing_vessel_classes_details++
pages:
- Home: index.md << README.md
- Endpoints:
Expand Down
71 changes: 71 additions & 0 deletions scripts/Untitled.ipynb

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions tests/endpoints/test_anywhere_freight_pricing_get_price_details.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from datetime import datetime

from tests.testcases import TestCaseUsingRealAPI
from vortexasdk import AnywhereFreightPricingGetPriceDetails


class TestAnywhereFreightPricingGetPriceDetails(TestCaseUsingRealAPI):
def test_search_returns_data(self):
result = AnywhereFreightPricingGetPriceDetails().search(
time_min=datetime(2024, 1, 1),
time_max=datetime(2024, 1, 31),
origin_port="7f314ba0a498c36359b1c88781e94a73e19dcc9bbb030ec6b82f944a73d4da2f",
destination_port="68faf65af1345067f11dc6723b8da32f00e304a6f33c000118fccd81947deb4e",
vessel_class="oil_aframax_lr2",
product="crude",
unit="usd_per_tonne",
)

result_list = result.to_list()
assert len(result_list) > 0
assert "origin_port" in result_list[0]
assert "destination_port" in result_list[0]
assert "vessel_class" in result_list[0]
assert "rates" in result_list[0]

def test_search_to_df(self):
result = AnywhereFreightPricingGetPriceDetails().search(
time_min=datetime(2024, 1, 1),
time_max=datetime(2024, 1, 31),
origin_port="7f314ba0a498c36359b1c88781e94a73e19dcc9bbb030ec6b82f944a73d4da2f",
destination_port="68faf65af1345067f11dc6723b8da32f00e304a6f33c000118fccd81947deb4e",
vessel_class="oil_aframax_lr2",
product="crude",
unit="usd_per_tonne",
)

df = result.to_df()
assert len(df) > 0
# pd.json_normalize uses dot notation for nested keys
assert "origin_port.id" in df.columns
assert "destination_port.id" in df.columns
assert "vessel_class" in df.columns

def test_search_with_avoid_zone(self):
result = AnywhereFreightPricingGetPriceDetails().search(
time_min=datetime(2024, 1, 1),
time_max=datetime(2024, 1, 31),
origin_port="7f314ba0a498c36359b1c88781e94a73e19dcc9bbb030ec6b82f944a73d4da2f",
destination_port="68faf65af1345067f11dc6723b8da32f00e304a6f33c000118fccd81947deb4e",
vessel_class="oil_aframax_lr2",
product="crude",
unit="usd_per_tonne",
avoid_zone=["Suez Canal"],
)

result_list = result.to_list()
assert len(result_list) > 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from tests.testcases import TestCaseUsingRealAPI
from vortexasdk import AnywhereFreightPricingLatestUpdateTimestamp

Comment thread
Jack-Burge55 marked this conversation as resolved.

class TestAnywhereFreightPricingLatestUpdateTimestamp(TestCaseUsingRealAPI):
def test_search_returns_timestamp(self):
result = AnywhereFreightPricingLatestUpdateTimestamp().search()
assert "timestamp" in result
101 changes: 101 additions & 0 deletions tests/endpoints/test_anywhere_freight_pricing_post_price_details.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from datetime import datetime

from tests.testcases import TestCaseUsingRealAPI
from vortexasdk import AnywhereFreightPricingPostPriceDetails


class TestAnywhereFreightPricingPostPriceDetails(TestCaseUsingRealAPI):
def test_search_returns_data(self):
routes = [
{
"origin_port": "7f314ba0a498c36359b1c88781e94a73e19dcc9bbb030ec6b82f944a73d4da2f",
"destination_port": "68faf65af1345067f11dc6723b8da32f00e304a6f33c000118fccd81947deb4e",
"product": "crude",
"vessel_class": "oil_aframax_lr2",
}
]

result = AnywhereFreightPricingPostPriceDetails().search(
routes=routes,
time_min=datetime(2024, 1, 1),
time_max=datetime(2024, 1, 31),
unit="usd_per_tonne",
)

result_list = result.to_list()
assert len(result_list) > 0
assert "origin_port" in result_list[0]
assert "destination_port" in result_list[0]
assert "vessel_class" in result_list[0]
assert "rates" in result_list[0]

def test_search_to_df(self):
routes = [
{
"origin_port": "7f314ba0a498c36359b1c88781e94a73e19dcc9bbb030ec6b82f944a73d4da2f",
"destination_port": "68faf65af1345067f11dc6723b8da32f00e304a6f33c000118fccd81947deb4e",
"product": "crude",
"vessel_class": "oil_aframax_lr2",
}
]

result = AnywhereFreightPricingPostPriceDetails().search(
routes=routes,
time_min=datetime(2024, 1, 1),
time_max=datetime(2024, 1, 31),
unit="usd_per_tonne",
)

df = result.to_df()
assert len(df) > 0
# pd.json_normalize uses dot notation for nested keys
assert "origin_port.id" in df.columns
assert "destination_port.id" in df.columns
assert "vessel_class" in df.columns

def test_search_multiple_routes(self):
routes = [
{
"origin_port": "7f314ba0a498c36359b1c88781e94a73e19dcc9bbb030ec6b82f944a73d4da2f",
"destination_port": "68faf65af1345067f11dc6723b8da32f00e304a6f33c000118fccd81947deb4e",
"product": "crude",
"vessel_class": "oil_aframax_lr2",
},
{
"origin_port": "68faf65af1345067f11dc6723b8da32f00e304a6f33c000118fccd81947deb4e",
"destination_port": "ea4921c8ad4fddb5fe3e7a4f834c1aa5863e43283c73da5f02d93bbc5dba72eb",
"product": "clean",
"vessel_class": "oil_handymax_mr2",
},
]

result = AnywhereFreightPricingPostPriceDetails().search(
routes=routes,
time_min=datetime(2024, 1, 1),
time_max=datetime(2024, 1, 31),
unit="usd_per_tonne",
)

result_list = result.to_list()
assert len(result_list) >= 2

def test_search_with_avoid_zone(self):
routes = [
{
"origin_port": "7f314ba0a498c36359b1c88781e94a73e19dcc9bbb030ec6b82f944a73d4da2f",
"destination_port": "68faf65af1345067f11dc6723b8da32f00e304a6f33c000118fccd81947deb4e",
"product": "crude",
"vessel_class": "oil_aframax_lr2",
"avoid_zone": ["Suez Canal"],
}
]

result = AnywhereFreightPricingPostPriceDetails().search(
routes=routes,
time_min=datetime(2024, 1, 1),
time_max=datetime(2024, 1, 31),
unit="usd_per_tonne",
)

result_list = result.to_list()
assert len(result_list) > 0
55 changes: 55 additions & 0 deletions tests/endpoints/test_anywhere_freight_pricing_price_timeseries.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from datetime import datetime

from tests.testcases import TestCaseUsingRealAPI
from vortexasdk import AnywhereFreightPricingPriceTimeseries


class TestAnywhereFreightPricingPriceTimeseries(TestCaseUsingRealAPI):
def test_search_returns_data(self):
routes = [
{
"origin_port": "68faf65af1345067f11dc6723b8da32f00e304a6f33c000118fccd81947deb4e",
"destination_port": "ea4921c8ad4fddb5fe3e7a4f834c1aa5863e43283c73da5f02d93bbc5dba72eb",
"product": "clean",
"vessel_class": "oil_handymax_mr2",
}
]

result = AnywhereFreightPricingPriceTimeseries().search(
routes=routes,
time_min=datetime(2026, 2, 20),
time_max=datetime(2026, 5, 20),
frequency="month",
unit="usd_per_tonne",
)

result_list = result.to_list()
assert len(result_list) > 0
assert "origin_port" in result_list[0]
assert "destination_port" in result_list[0]
assert "prices" in result_list[0]

def test_search_to_df(self):
routes = [
{
"origin_port": "68faf65af1345067f11dc6723b8da32f00e304a6f33c000118fccd81947deb4e",
"destination_port": "ea4921c8ad4fddb5fe3e7a4f834c1aa5863e43283c73da5f02d93bbc5dba72eb",
"product": "clean",
"vessel_class": "oil_handymax_mr2",
}
]

result = AnywhereFreightPricingPriceTimeseries().search(
routes=routes,
time_min=datetime(2026, 2, 20),
time_max=datetime(2026, 5, 20),
frequency="month",
unit="usd_per_tonne",
)

df = result.to_df()
assert len(df) > 0
# Top-level keys preserved, nested arrays like prices stay as lists
assert "origin_port" in df.columns
assert "destination_port" in df.columns
assert "vessel_class" in df.columns
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from tests.testcases import TestCaseUsingRealAPI
from vortexasdk import AnywhereFreightPricingTopPortsDestination


class TestAnywhereFreightPricingTopPortsDestination(TestCaseUsingRealAPI):
def test_search_returns_data(self):
result = AnywhereFreightPricingTopPortsDestination().search(
origin_id="7f314ba0a498c36359b1c88781e94a73e19dcc9bbb030ec6b82f944a73d4da2f",
vessel_class="oil_handymax_mr2",
product="clean",
unit="usd_per_tonne",
)

result_list = result.to_list()
assert len(result_list) > 0
assert "geography" in result_list[0]
assert "price_details" in result_list[0]
assert "id" in result_list[0]["geography"]
assert "name" in result_list[0]["geography"]

def test_search_to_df(self):
result = AnywhereFreightPricingTopPortsDestination().search(
origin_id="7f314ba0a498c36359b1c88781e94a73e19dcc9bbb030ec6b82f944a73d4da2f",
vessel_class="oil_handymax_mr2",
product="clean",
unit="usd_per_tonne",
)

df = result.to_df()
assert len(df) > 0
# pd.json_normalize uses dot notation for nested keys
assert "geography.id" in df.columns
assert "geography.name" in df.columns

def test_search_with_avoid_zone(self):
result = AnywhereFreightPricingTopPortsDestination().search(
origin_id="7f314ba0a498c36359b1c88781e94a73e19dcc9bbb030ec6b82f944a73d4da2f",
vessel_class="oil_handymax_mr2",
product="clean",
unit="usd_per_tonne",
avoid_zone=["Suez Canal"],
)

result_list = result.to_list()
assert len(result_list) > 0
Loading
Loading