Skip to content

Commit

Permalink
Merge pull request #323 from SignalOceanSdk/develop
Browse files Browse the repository at this point in the history
Release20240903
  • Loading branch information
IsidorosTsalapatis authored Sep 3, 2024
2 parents 8f1fe78 + 84977ea commit 47f10dc
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 19 deletions.
11 changes: 11 additions & 0 deletions docs/releases/Version 12.0.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# v12.0.0
Download here: [![PyPI version shields.io](https://img.shields.io/pypi/v/signal-ocean.svg)](https://pypi.python.org/pypi/signal-ocean/)

## Vessels API

- Added missing fields `BowChainStopperDetailsAsStr, BowChainStoppersFitted,NumberOfBowChainStoppers, NumberOfCranes, NumberOfGrabs, NumberOfHatches`
- Fix mapping of fields `IMOType1, IMOType2, IMOType3` so they can load data
- Rename `te_u14` to `teu14` (Breaking Change)

## Installation and Upgrade Notes
Update your package with: `pip install signal-ocean -U`
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ nav:
- Historical Tonnage List (deprecated):
- 'historical_tonnage_list.md'
- Release notes:
- 'releases/Version 12.0.0.md'
- 'releases/Version 11.1.0.md'
- 'releases/Version 11.0.0.md'
- 'releases/Version 10.7.0.md'
Expand Down
37 changes: 31 additions & 6 deletions signal_ocean/vessels/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ class Vessel:
teu: Numeric, measured in TEU (Twenty-Foot Equivalent Unit), denotes a
volumetric measure of a container's cargo carrying capacity. Used
for Containers, that is vessels with VesselType=4.
te_u14: Numeric, denotes the capacity of the vessel measured in twenty-
teu14: Numeric, denotes the capacity of the vessel measured in twenty-
foot equivalent units (TEU) loaded at 14 tons.
reefers: Numeric, denotes the capacity of the vessel measured in
refrigerated twenty-foot equivalent units (TEU), i.e., the maximum
Expand Down Expand Up @@ -205,6 +205,17 @@ class Vessel:
vessel's classification certificate. Default value: Not set.
number_of_holds: Numeric, the number of separate enclosed spaces within
a ship designed for storing cargo.
number_of_hatches: Numeric, the number of cargo hatches on the vessel
that cover the opening to the cargo hold to protect the cargo. Most
cargo holds have a cargo hatch.
number_of_grabs: Numeric, the number of separate grabs a vessel is
equipped with for handling and lifting the cargo.
number_of_cranes: Numeric, the number of separate cranes a vessel is
equipped with for handling and lifting the cargo.
number_of_bow_chain_stoppers: Numeric denotes the
number of bow chain stoppers the vessel is equipped
with. Ships likely to trade to Single Point
Moorings should be equipped with bow chain stoppers.
grain_capacity: This is the space available for a liquid-type cargo,
like bulk grain, which can flow into every corner.
bale_capacity: This is the space available for solid cargo. Bale space
Expand Down Expand Up @@ -245,9 +256,6 @@ class Vessel:
with a heating coils system. Tanker vessels may be fitted with
heating coils in order to maintain the required temperature of
the cargo for pumping.
crane_details_as_str: String, SWL (Safe Working Load) in mt for
each crane, collected in one single string with the format
commonly used across market reports. Example: "4 x 30 MT".
cranes_max_outreach: Numeric, in meters (m). The maximum outreach
range across all the cranes that the vessel has. This range
is measured as the distance from the boom tip to the crane hook.
Expand All @@ -267,6 +275,13 @@ class Vessel:
mt of each single grab, collected in one single string with
the format commonly used across market reports.
Example: "4 x 12 CBM".
crane_details_as_str: String, SWL (Safe Working Load) in mt for
each crane, collected in one single string with the format
commonly used across market reports. Example: "4 x 30 MT".
bow_chain_stopper_details_as_str: String, number of Bow
Chain Stoppers with their maximum load capacity for
each type of bow chain stopper in a string format.
Example: `""2 x 200 MT, 1 x 100 MT""`.
box_shaped_holds: Boolean, denotes whether the vessel has any hold
with box shape.
neo_panama_locks: Boolean, denotes whether the vessel is fitted to
Expand Down Expand Up @@ -381,6 +396,10 @@ class Vessel:
manifold is the point on the ship where cargo hoses
or arms are connected for the loading or unloading
of liquid cargoes.
bow_chain_stoppers_fitted: Boolean, indicates whether
the vessel is equipped with bow chain stoppers.
Ships likely to trade to Single Point Moorings
should be equipped with bow chain stoppers.
"""

imo: int
Expand Down Expand Up @@ -420,7 +439,7 @@ class Vessel:
shipyard_built_name: Optional[str] = None
ice_class: Optional[str] = None
teu: Optional[int] = None
te_u14: Optional[int] = None
teu14: Optional[int] = None
reefers: Optional[int] = None
panama_canal_net_tonnage: Optional[int] = None
cubic_size: Optional[int] = None
Expand All @@ -431,6 +450,10 @@ class Vessel:
delivery_date: Optional[datetime] = None
classification_register: Optional[str] = None
number_of_holds: Optional[int] = None
number_of_hatches: Optional[int] = None
number_of_grabs: Optional[int] = None
number_of_cranes: Optional[int] = None
number_of_bow_chain_stoppers: Optional[int] = None
grain_capacity: Optional[int] = None
bale_capacity: Optional[int] = None
main_engine_kw: Optional[int] = None
Expand All @@ -454,12 +477,13 @@ class Vessel:
beneficial_owner: Optional[str] = None
parallel_body_length: Optional[float] = None
heating_coils_fitted: Optional[bool] = None
crane_details_as_str: Optional[str] = None
cranes_max_outreach: Optional[float] = None
cranes_max_lifting_capacity: Optional[float] = None
hold_details_as_str: Optional[str] = None
hatch_details_as_str: Optional[str] = None
grab_details_as_str: Optional[str] = None
crane_details_as_str: Optional[str] = None
bow_chain_stopper_details_as_str: Optional[str] = None
box_shaped_holds: Optional[bool] = None
neo_panama_locks: Optional[bool] = None
australian_hold_ladder: Optional[bool] = None
Expand Down Expand Up @@ -491,6 +515,7 @@ class Vessel:
water_line_to_manifold: Optional[float] = None
deck_to_center_manifold: Optional[float] = None
rail_to_center_manifold: Optional[float] = None
bow_chain_stoppers_fitted: Optional[bool] = None


@dataclass(frozen=True)
Expand Down
23 changes: 11 additions & 12 deletions signal_ocean/vessels/vessels_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ class VesselsAPI:
relative_url = "vessels-api/v2/"
default_pit = str(date.today())

rename_keys = {"STSTCoating": "stst_coating",
"BWTS": "bwts",
"GHG": "ghg",
"VCM": "vcm",
"IMOType1": "imo_type_1",
"IMOType2": "imo_type_2",
"IMOType3": "imo_type_3"}

def __init__(self, connection: Optional[Connection] = None):
"""Initializes VesselsAPI.
Expand Down Expand Up @@ -56,10 +64,7 @@ def get_vessel(self, imo: int) -> Optional[Vessel]:
"""
url = urljoin(VesselsAPI.relative_url, f"vessels/{imo}")
return get_single(self.__connection, url, Vessel,
rename_keys={"STSTCoating": "stst_coating",
"BWTS": "bwts",
"GHG": "ghg",
"VCM": "vcm"})
rename_keys=VesselsAPI.rename_keys)

def get_vessels(self, name: Optional[str] = None) -> Tuple[Vessel, ...]:
"""Retrieves all available vessels.
Expand All @@ -77,10 +82,7 @@ def get_vessels(self, name: Optional[str] = None) -> Tuple[Vessel, ...]:
)
url = urljoin(VesselsAPI.relative_url, endpoint)
return get_multiple(self.__connection, url, Vessel,
rename_keys={"STSTCoating": "stst_coating",
"BWTS": "bwts",
"GHG": "ghg",
"VCM": "vcm"})
rename_keys=VesselsAPI.rename_keys)

def get_vessels_by_vessel_class(
self, vesselClass: int
Expand All @@ -96,10 +98,7 @@ def get_vessels_by_vessel_class(
endpoint = f"vessels?vesselClass={vesselClass}"
url = urljoin(VesselsAPI.relative_url, endpoint)
response = get_single(self.__connection, url, VesselPagedResponse,
rename_keys={"STSTCoating": "stst_coating",
"BWTS": "bwts",
"GHG": "ghg",
"VCM": "vcm"})
rename_keys=VesselsAPI.rename_keys)
return response if response is None else response.items

def get_vessels_name_history(
Expand Down
128 changes: 128 additions & 0 deletions tests/vessels/test_vessels_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Tuple
from unittest.mock import MagicMock
from urllib.parse import urljoin
from signal_ocean.util.parsing_helpers import _to_snake_case

import requests

Expand Down Expand Up @@ -257,3 +258,130 @@ def test_requests_search_vessels():
mocked_make_request.assert_called_with(
urljoin(VesselsAPI.relative_url, 'vessels/searchByName/signal'),
query_string=None)

def test_vessel_field_names():
api_fields = [
"IMO",
"VesselName",
"CallSign",
"VesselTypeID",
"VesselType",
"BuiltForTradeID",
"BuiltForTrade",
"TradeID",
"Trade",
"CleanDirtyWilling",
"VesselClassID",
"VesselClass",
"FlagCode",
"Flag",
"CommercialOperatorID",
"CommercialOperator",
"Deadweight",
"BreadthExtreme",
"GrossRatedTonnage",
"ReducedGrossTonnage",
"NetRatedTonnage",
"Draught",
"LengthOverall",
"MouldedDepth",
"BowToCenterManifold",
"WaterLineToManifold",
"DeckToCenterManifold",
"RailToCenterManifold",
"YearBuilt",
"BuiltCountryCode",
"BuiltCountryName",
"ScrappedDate",
"ShipyardBuiltID",
"YardNumber",
"DesignModel",
"ShipyardBuiltName",
"IceClass",
"TEU",
"TEU14",
"Reefers",
"Geared",
"PanamaCanalNetTonnage",
"CubicSize",
"ScrubbersDate",
"SummerTPC",
"LightshipTonnes",
"MainEngineManufacturer",
"MainEngineManufacturerID",
"DeliveryDate",
"ClassificationRegisterID",
"ClassificationRegister",
"NumberOfHolds",
"NumberOfCranes",
"NumberOfGrabs",
"NumberOfHatches",
"GrainCapacity",
"BaleCapacity",
"MainEngineKW",
"MainEngineRPM",
"AirDraught",
"DeckTeu",
"UnderDeckTeu",
"SuezCanalNetTonnage",
"ClassRenewalDate",
"MewisDuct",
"InertGasSystem",
"IMOType1",
"IMOType2",
"IMOType3",
"STSTCoating",
"EpoxyCoating",
"ZincCoating",
"MarinelineCoating",
"InterlineCoating",
"CrudeOilWashing",
"NumberOfBowChainStoppers",
"BowChainStoppersFitted",
"BowChainStopperDetailsAsStr",
"BeneficialOwnerID",
"BeneficialOwner",
"ParallelBodyLength",
"BallastParallelBodyLength",
"EmptyParallelBodyLength",
"HeatingCoilsFitted",
"CraneDetailsAsStr",
"CranesMaxOutreach",
"CranesMaxLiftingCapacity",
"HoldDetailsAsStr",
"HatchDetailsAsStr",
"GrabDetailsAsStr",
"BoxShapedHolds",
"NeoPanamaLocks",
"AustralianHoldLadder",
"CO2Fitted",
"A60Bulkhead",
"LogFitted",
"SternLine",
"OpenHatch",
"BWTS",
"GrabsFitted",
"GHG",
"OrderBookStatusID",
"OrderBookStatus",
"OrderDate",
"ConstructionStartDate",
"LaunchDate",
"ScheduledDeliveryDate",
"CancelledDate",
"MinimumTemperature",
"MaximumPressure",
"Ammonia",
"VCM",
"Ethylene",
"UpdatedDate",
]

for k, r, in VesselsAPI.rename_keys.items():
api_fields[api_fields.index(k)] = r

snake_case_api_fields = list(map(_to_snake_case, api_fields))
vessels_model_fields = list(Vessel.__dataclass_fields__)
snake_case_api_fields.sort()
vessels_model_fields.sort()
assert snake_case_api_fields == vessels_model_fields
2 changes: 1 addition & 1 deletion version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
11.1.0
12.0.0

0 comments on commit 47f10dc

Please sign in to comment.