Skip to content

Commit

Permalink
(initialize) Sendle carrier extension
Browse files Browse the repository at this point in the history
  • Loading branch information
danh91 committed Dec 14, 2023
1 parent 157bff6 commit 42fe7a7
Show file tree
Hide file tree
Showing 47 changed files with 1,913 additions and 1,189 deletions.
3 changes: 2 additions & 1 deletion modules/connectors/sendle/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# karrio.sendle

This package is a Sendle extension of the [karrio](https://pypi.org/project/karrio) multi carrier shipping SDK.
Expand All @@ -20,7 +21,7 @@ from karrio.mappers.sendle.settings import Settings


# Initialize a carrier gateway
canadapost = karrio.gateway["sendle"].create(
sendle = karrio.gateway["sendle"].create(
Settings(
...
)
Expand Down
12 changes: 7 additions & 5 deletions modules/connectors/sendle/generate
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ quicktype () {
echo "Generating $1..."
docker run -it -v $PWD:/app -e SCHEMAS=/app/schemas -e LIB_MODULES=/app/karrio/schemas/sendle \
karrio/tools /quicktype/script/quicktype --no-uuids --no-date-times --no-enums --src-lang json --lang jstruct \
--all-properties-optional $@
--no-nice-property-names --all-properties-optional --type-as-suffix $@
}

quicktype --src="${SCHEMAS}/order_cancel_response.json" --out="${LIB_MODULES}/order_cancel_response.py"
quicktype --src="${SCHEMAS}/cancel_request.json" --out="${LIB_MODULES}/cancel_request.py"
quicktype --src="${SCHEMAS}/cancel_response.json" --out="${LIB_MODULES}/cancel_response.py"
quicktype --src="${SCHEMAS}/error_responses.json" --out="${LIB_MODULES}/error_responses.py"
quicktype --src="${SCHEMAS}/order_request.json" --out="${LIB_MODULES}/order_request.py"
quicktype --src="${SCHEMAS}/order_response.json" --out="${LIB_MODULES}/order_response.py"
quicktype --src="${SCHEMAS}/products_response.json" --out="${LIB_MODULES}/products_response.py"
quicktype --src="${SCHEMAS}/rating.json" --out="${LIB_MODULES}/rating.py"
quicktype --src="${SCHEMAS}/product_request.json" --out="${LIB_MODULES}/product_request.py"
quicktype --src="${SCHEMAS}/product_response.json" --out="${LIB_MODULES}/product_response.py"
quicktype --src="${SCHEMAS}/tracking_request.json" --out="${LIB_MODULES}/tracking_request.py"
quicktype --src="${SCHEMAS}/tracking_response.json" --out="${LIB_MODULES}/tracking_response.py"
quicktype --src="${SCHEMAS}/validation_error.json" --out="${LIB_MODULES}/validation_error.py"
10 changes: 3 additions & 7 deletions modules/connectors/sendle/karrio/mappers/sendle/__init__.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@

from karrio.core.metadata import Metadata

from karrio.mappers.sendle.mapper import Mapper
from karrio.mappers.sendle.proxy import Proxy
from karrio.mappers.sendle.settings import Settings
# import karrio.providers.sendle.units as units
import karrio.providers.sendle.units as units


METADATA = Metadata(
id="sendle",
label="Sendle",

# Integrations
Mapper=Mapper,
Proxy=Proxy,
Settings=Settings,

# Data Units
# options=units.OptionCode,
# package_presets=units.PackagePresets,
# packaging_types=units.PackagingType,
# services=units.Serives,
is_hub=False
)
168 changes: 53 additions & 115 deletions modules/connectors/sendle/karrio/mappers/sendle/mapper.py
Original file line number Diff line number Diff line change
@@ -1,117 +1,55 @@
from typing import List, Tuple
from karrio.core.utils.serializable import Serializable, Deserializable
from karrio.api.mapper import Mapper as BaseMapper
from karrio.core.models import (
# AddressValidationRequest,
# ShipmentCancelRequest,
# PickupUpdateRequest,
# PickupCancelRequest,
# ShipmentRequest,
TrackingRequest,
# PickupRequest,
# RateRequest,
# AddressValidationDetails,
# ConfirmationDetails,
TrackingDetails,
# ShipmentDetails,
# PickupDetails,
# RateDetails,
Message,
)
from karrio.providers.sendle import (
# parse_address_validation_response,
# parse_shipment_cancel_response,
# parse_pickup_update_response,
# parse_pickup_cancel_response,
# parse_shipment_response,
parse_tracking_response,
# parse_pickup_response,
# parse_rate_response,
# address_validation_request,
# shipment_cancel_request,
# pickup_update_request,
# pickup_cancel_request,
tracking_request,
# shipment_request,
# pickup_request,
# rate_request,
)
from karrio.mappers.sendle.settings import Settings


class Mapper(BaseMapper):
settings: Settings

# def create_address_validation_request(self, payload: AddressValidationRequest) -> Serializable:
# return address_validation_request(payload, self.settings)
#
# def create_pickup_request(
# self, payload: PickupRequest
# ) -> Serializable:
# return pickup_request(payload, self.settings)
#
# def create_pickup_update_request(
# self, payload: PickupUpdateRequest
# ) -> Serializable:
# return pickup_update_request(payload, self.settings)
#
# def create_cancel_pickup_request(
# self, payload: PickupCancelRequest
# ) -> Serializable:
# return pickup_cancel_request(payload, self.settings)

# def create_rate_request(
# self, payload: RateRequest
# ) -> Serializable:
# return rate_request(payload, self.settings)

# def create_shipment_request(
# self, payload: ShipmentRequest
# ) -> Serializable:
# return shipment_request(payload, self.settings)
#
# def create_cancel_shipment_request(self, payload: ShipmentCancelRequest) -> Serializable:
# return shipment_cancel_request(payload, self.settings)

def create_tracking_request(self, payload: TrackingRequest) -> Serializable:
return tracking_request(payload, self.settings)

# def parse_address_validation_response(
# self, response: Deserializable
# ) -> Tuple[AddressValidationDetails, List[Message]]:
# return parse_address_validation_response(response, self.settings)
#
# def parse_cancel_pickup_response(
# self, response: Deserializable
# ) -> Tuple[ConfirmationDetails, List[Message]]:
# return parse_pickup_cancel_response(response, self.settings)
#
# def parse_pickup_response(
# self, response: Deserializable
# ) -> Tuple[PickupDetails, List[Message]]:
# return parse_pickup_response(response, self.settings)
#
# def parse_pickup_update_response(
# self, response: Deserializable
# ) -> Tuple[PickupDetails, List[Message]]:
# return parse_pickup_update_response(response, self.settings)

# def parse_rate_response(
# self, response: Deserializable
# ) -> Tuple[List[RateDetails], List[Message]]:
# return parse_rate_response(response, self.settings)

# def parse_shipment_response(
# self, response: Deserializable
# ) -> Tuple[ShipmentDetails, List[Message]]:
# return parse_shipment_response(response, self.settings)
#
# def parse_cancel_shipment_response(
# self, response: Deserializable
# ) -> Tuple[ConfirmationDetails, List[Message]]:
# return parse_shipment_cancel_response(response, self.settings)

"""Karrio Sendle client mapper."""

import typing
import karrio.lib as lib
import karrio.api.mapper as mapper
import karrio.core.models as models
import karrio.providers.sendle as provider
import karrio.mappers.sendle.settings as provider_settings


class Mapper(mapper.Mapper):
settings: provider_settings.Settings

def create_rate_request(
self, payload: models.RateRequest
) -> lib.Serializable:
return provider.rate_request(payload, self.settings)

def create_tracking_request(
self, payload: models.TrackingRequest
) -> lib.Serializable:
return provider.tracking_request(payload, self.settings)

def create_shipment_request(
self, payload: models.ShipmentRequest
) -> lib.Serializable:
return provider.shipment_request(payload, self.settings)

def create_cancel_shipment_request(
self, payload: models.ShipmentCancelRequest
) -> lib.Serializable[str]:
return provider.shipment_cancel_request(payload, self.settings)


def parse_cancel_shipment_response(
self, response: lib.Deserializable[str]
) -> typing.Tuple[models.ConfirmationDetails, typing.List[models.Message]]:
return provider.parse_shipment_cancel_response(response, self.settings)

def parse_rate_response(
self, response: lib.Deserializable[str]
) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
return provider.parse_rate_response(response, self.settings)

def parse_shipment_response(
self, response: lib.Deserializable[str]
) -> typing.Tuple[models.ShipmentDetails, typing.List[models.Message]]:
return provider.parse_shipment_response(response, self.settings)

def parse_tracking_response(
self, response: Deserializable
) -> Tuple[List[TrackingDetails], List[Message]]:
return parse_tracking_response(response, self.settings)
self, response: lib.Deserializable[str]
) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
return provider.parse_tracking_response(response, self.settings)

115 changes: 76 additions & 39 deletions modules/connectors/sendle/karrio/mappers/sendle/proxy.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,78 @@
from typing import List, Tuple
from karrio.core.utils import (
DP,
request as http,
Serializable,
Deserializable,
exec_async,
)
from karrio.api.proxy import Proxy as BaseProxy
from karrio.mappers.sendle.settings import Settings


class Proxy(BaseProxy):
settings: Settings

""" Proxy Methods """

def get_tracking(
self, request: Serializable
) -> Deserializable[List[Tuple[str, dict]]]:
def _get_tracking(ref: str):
response = http(
url=f"{self.settings.server_url}/api/tracking/{ref}",
trace=self.trace_as("json"),
method="GET",
headers={
"Accept": "application/json",
"Authorization": f"Basic {self.settings.authorization}",
},
)
return ref, response

responses: List[Tuple[str, str]] = exec_async(
_get_tracking, request.serialize()
"""Karrio Sendle client proxy."""

import karrio.lib as lib
import karrio.api.proxy as proxy
import karrio.mappers.sendle.settings as provider_settings


class Proxy(proxy.Proxy):
settings: provider_settings.Settings

def get_rates(self, request: lib.Serializable) -> lib.Deserializable[str]:
response = lib.request(
url=f"{self.settings.server_url}/api/products",
data=request.serialize(),
trace=self.trace_as("json"),
method="POST",
headers={
"Accept": "application/json",
"Content-type": "application/json",
"Authorization": f"Basic {self.settings.authorization}",
},
)

return lib.Deserializable(response, lib.to_dict)

def create_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]:
response = lib.request(
url=f"{self.settings.server_url}/api/orders",
data=request.serialize(),
trace=self.trace_as("json"),
method="POST",
headers={
"Accept": "application/json",
"Content-type": "application/json",
"Authorization": f"Basic {self.settings.authorization}",
},
)
return Deserializable(
responses,
lambda res: [
(num, DP.to_dict(track)) for num, track in res if any(track.strip())
],

return lib.Deserializable(response, lib.to_dict)

def cancel_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]:
payload = request.serialize()
response = lib.request(
url=f"{self.settings.server_url}/api/orders/{payload['id']}",
data=request.serialize(),
trace=self.trace_as("json"),
method="DELETE",
headers={
"Accept": "application/json",
"Content-type": "application/json",
"Authorization": f"Basic {self.settings.authorization}",
},
)

return lib.Deserializable(response, lib.to_dict)

def get_tracking(self, request: lib.Serializable) -> lib.Deserializable[str]:
response = lib.run_asynchronously(
lambda payload: (
payload["ref"],
lib.request(
url=f"{self.settings.server_url}/api/tracking/{payload['ref']}",
trace=self.trace_as("json"),
method="POST",
headers={
"Accept": "application/json",
"Content-type": "application/json",
"Authorization": f"Basic {self.settings.authorization}",
},
),
),
request.serialize(),
)

return lib.Deserializable(
response,
lambda __: [(no, lib.to_dict(_)) for no, _ in __],
)
14 changes: 7 additions & 7 deletions modules/connectors/sendle/karrio/mappers/sendle/settings.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
"""Karrio Sendle settings."""
"""Karrio Sendle client settings."""

import attr
from karrio.providers.sendle.utils import Settings as BaseSettings
import karrio.providers.sendle.utils as provider_utils


@attr.s(auto_attribs=True)
class Settings(BaseSettings):
class Settings(provider_utils.Settings):
"""Sendle connection settings."""

# Carrier specific properties
# required carrier specific properties
sendle_id: str
api_key: str
sendle_api_key: str

# Base properties
# generic properties
id: str = None
test_mode: bool = False
carrier_id: str = "sendle"
account_country_code: str = "AU"
account_country_code: str = None
metadata: dict = {}
config: dict = {}
Loading

0 comments on commit 42fe7a7

Please sign in to comment.