Пример #1
0
    def get_tracking(self,
                     request: Serializable[List[str]]) -> Deserializable[str]:
        """
        get_tracking make parallel request for each pin
        """
        _throttle = 0.0

        def track(tracking_pin: str) -> str:
            nonlocal _throttle
            time.sleep(_throttle)
            _throttle += 0.025

            return http(
                url=
                f"{self.settings.server_url}/vis/track/pin/{tracking_pin}/detail",
                headers={
                    "Accept": "application/vnd.cpc.track-v2+xml",
                    "Authorization": f"Basic {self.settings.authorization}",
                    "Accept-language": f"{self.settings.language}-CA",
                },
                method="GET",
            )

        response: List[str] = exec_async(track, request.serialize())

        return Deserializable(XP.bundle_xml(xml_strings=response), XP.to_xml)
Пример #2
0
    def create_shipment(
            self, request: Serializable[Pipeline]) -> Deserializable[str]:
        def process(job: Job):
            if job.data is None:
                return job.fallback

            return self._send_request(
                request=job.data,
                path=dict(
                    create="/EWS/V2/Shipping/ShippingService.asmx",
                    validate="/EWS/V2/Shipping/ShippingService.asmx",
                    document=
                    "/EWS/V1/ShippingDocuments/ShippingDocumentsService.asmx",
                )[job.id],
                soapaction=dict(
                    create="http://purolator.com/pws/service/v2/CreateShipment",
                    validate=
                    "http://purolator.com/pws/service/v2/ValidateShipment",
                    document="http://purolator.com/pws/service/v1/GetDocuments",
                )[job.id],
            )

        pipeline: Pipeline = request.serialize()
        _, *response = pipeline.apply(process)
        return Deserializable(XP.bundle_xml(response), XP.to_xml)
Пример #3
0
def _get_pickup(update_response: str, payload: PickupUpdateRequest,
                settings: Settings) -> Job:
    errors = parse_error_response(XP.to_xml(XP.bundle_xml([update_response])),
                                  settings)
    data = None if any(
        errors
    ) else f"/enab/{settings.customer_number}/pickuprequest/{payload.confirmation_number}/details"

    return Job(id="get_pickup",
               data=Serializable(data),
               fallback="" if data is None else "")
Пример #4
0
    def modify_pickup(self, request: Serializable[Pipeline]) -> Deserializable[str]:
        def process(job: Job):
            if job.data is None:
                return job.fallback

            return self._send_request("/pickup", job.data)

        pipeline: Pipeline = request.serialize()
        response = pipeline.apply(process)

        return Deserializable(XP.bundle_xml(response), XP.to_xml)
Пример #5
0
    def get_rates(self,
                  request: Serializable[Envelope]) -> Deserializable[str]:
        product, data = request.serialize()
        responses = [
            f'<product>{product}</product>',
            self._send_request(
                soapaction="http://www.icscourier.ca/GetEstimatedCharges",
                request=Serializable(data),
            )
        ]

        return Deserializable(XP.bundle_xml(responses), XP.to_xml)
Пример #6
0
    def get_tracking(
            self,
            request: Serializable[List[Envelope]]) -> Deserializable[str]:
        """
        get_tracking make parallel request for each TrackRequest
        """
        def get_tracking(track_request: str):
            return self._send_request("/Track", Serializable(track_request))

        response: List[str] = exec_parrallel(get_tracking, request.serialize())

        return Deserializable(XP.bundle_xml(xml_strings=response), XP.to_xml)
Пример #7
0
    def create_shipment(self, request: Serializable) -> Deserializable[str]:
        def process(job: Job):
            if job.data is None:
                return job.fallback

            return self._send_request(
                request=job.data,
                path=dict(
                    create="/expressconnect/shipping/ship",
                    get_label="/expresslabel/documentation/getlabel")[job.id],
            )

        pipeline: Pipeline = request.serialize()
        response = pipeline.apply(process)

        return Deserializable(XP.bundle_xml(response), XP.to_xml)
Пример #8
0
    def create_shipment(
            self, request: Serializable[Envelope]) -> Deserializable[str]:
        response = self._send_request(
            soapaction="http://www.icscourier.ca/CreateShipment",
            request=request,
        )

        labelURL = XP.find(XP.to_xml(response), "PackageIDAndLink", first=True)
        if labelURL is not None:
            label = http(
                labelURL,
                decoder=lambda b: base64.encodebytes(b).decode("utf-8"))
            responses = [f'<label>{label}</label>', response]

            return Deserializable(XP.bundle_xml(responses), XP.to_xml)

        return Deserializable(response, XP.to_xml)
Пример #9
0
    def schedule_pickup(
            self, request: Serializable[Pipeline]) -> Deserializable[str]:
        def _availability(job: Job) -> str:
            return http(
                url=
                f"{self.settings.server_url}/ad/pickup/pickupavailability/{job.data}",
                headers={
                    "Accept": "application/vnd.cpc.pickup+xml",
                    "Authorization": f"Basic {self.settings.authorization}",
                    "Accept-language": f"{self.settings.language}-CA",
                },
                method="GET",
            )

        def _create_pickup(job: Job) -> str:
            return http(
                url=
                f"{self.settings.server_url}/enab/{self.settings.customer_number}/pickuprequest",
                data=bytearray(job.data.serialize(), "utf-8"),
                headers={
                    "Accept": "application/vnd.cpc.pickuprequest+xml",
                    "Content-Type": "application/vnd.cpc.pickuprequest+xml",
                    "Authorization": f"Basic {self.settings.authorization}",
                    "Accept-language": f"{self.settings.language}-CA",
                },
                method="POST",
            )

        def process(job: Job):
            if job.data is None:
                return job.fallback

            subprocess = {
                "create_pickup": _create_pickup,
                "availability": _availability,
            }
            if job.id not in subprocess:
                raise PurplShipError(
                    f"Unknown pickup request job id: {job.id}")

            return subprocess[job.id](job)

        pipeline: Pipeline = request.serialize()
        response = pipeline.apply(process)

        return Deserializable(XP.bundle_xml(response), XP.to_xml)
Пример #10
0
    def modify_pickup(self,
                      request: Serializable[dict]) -> Deserializable[str]:
        def _get_pickup(job: Job) -> str:
            return http(
                url=f"{self.settings.server_url}{job.data.serialize()}",
                headers={
                    "Accept": "application/vnd.cpc.pickup+xml",
                    "Authorization": f"Basic {self.settings.authorization}",
                    "Accept-language": f"{self.settings.language}-CA",
                },
                method="GET",
            )

        def _update_pickup(job: Job) -> str:
            payload = job.data.serialize()
            return http(
                url=
                f"{self.settings.server_url}/enab/{self.settings.customer_number}/pickuprequest/{payload['pickuprequest']}",
                data=bytearray(payload["data"], "utf-8"),
                headers={
                    "Accept": "application/vnd.cpc.pickuprequest+xml",
                    "Authorization": f"Basic {self.settings.authorization}",
                    "Accept-language": f"{self.settings.language}-CA",
                },
                method="PUT",
            )

        def process(job: Job):
            if job.data is None:
                return job.fallback

            subprocess = {
                "update_pickup": _update_pickup,
                "get_pickup": _get_pickup,
            }
            if job.id not in subprocess:
                raise PurplShipError(
                    f"Unknown pickup request job id: {job.id}")

            return subprocess[job.id](job)

        pipeline: Pipeline = request.serialize()
        response = pipeline.apply(process)

        return Deserializable(XP.bundle_xml(response), XP.to_xml)
Пример #11
0
    def get_tracking(self,
                     request: Serializable[List[str]]) -> Deserializable[str]:
        """
        get_tracking make parallel request for each pin
        """
        def track(tracking_pin: str) -> str:
            return http(
                url=
                f"{self.settings.server_url}/vis/track/pin/{tracking_pin}/summary",
                headers={
                    "Accept": "application/vnd.cpc.track+xml",
                    "Authorization": f"Basic {self.settings.authorization}",
                    "Accept-language": f"{self.settings.language}-CA",
                },
                method="GET",
            )

        response: List[str] = exec_parrallel(track, request.serialize())

        return Deserializable(XP.bundle_xml(xml_strings=response), XP.to_xml)
Пример #12
0
    def modify_pickup(self,
                      request: Serializable[Pipeline]) -> Deserializable[str]:
        def process(job: Job):
            if job.data is None:
                return job.fallback

            return self._send_request(
                path="/EWS/V1/PickUp/PickUpService.asmx",
                request=job.data,
                soapaction=dict(
                    validate=
                    "http://purolator.com/pws/service/v1/ValidatePickUp",
                    modify="http://purolator.com/pws/service/v1/ModifyPickUp",
                )[job.id],
            )

        pipeline: Pipeline = request.serialize()
        response = pipeline.apply(process)

        return Deserializable(XP.bundle_xml(response), XP.to_xml)
Пример #13
0
    def cancel_shipment(self, request: Serializable) -> Deserializable:
        def _request(method: str, shipment_id: str, path: str = '', **kwargs):
            return http(
                url=
                f"{self.settings.server_url}/rs/{self.settings.customer_number}/{self.settings.customer_number}/shipment/{shipment_id}{path}",
                headers={
                    "Content-Type": "application/vnd.cpc.shipment-v8+xml",
                    "Accept": "application/vnd.cpc.shipment-v8+xml",
                    "Authorization": f"Basic {self.settings.authorization}",
                    "Accept-language": f"{self.settings.language}-CA",
                },
                method=method,
                **kwargs)

        def process(job: Job):
            if job.data is None:
                return job.fallback

            subprocess = {
                "info":
                lambda _: _request('GET', job.data.serialize()),
                "refund":
                lambda _: _request(
                    'POST',
                    job.data['id'],
                    '/refund',
                    data=bytearray(job.data['payload'].serialize(), "utf-8")),
                "cancel":
                lambda _: _request('DELETE', job.data.serialize()),
            }
            if job.id not in subprocess:
                raise PurplShipError(
                    f"Unknown shipment cancel request job id: {job.id}")

            return subprocess[job.id](job)

        pipeline: Pipeline = request.serialize()
        response = pipeline.apply(process)
        return Deserializable(XP.bundle_xml(response), XP.to_xml)
Пример #14
0
    def create_shipment(
            self, request: Serializable[Pipeline]) -> Deserializable[str]:
        def _contract_shipment(job: Job):
            return http(
                url=
                f"{self.settings.server_url}/rs/{self.settings.customer_number}/{self.settings.customer_number}/shipment",
                data=bytearray(job.data.serialize(), "utf-8"),
                headers={
                    "Content-Type": "application/vnd.cpc.shipment-v8+xml",
                    "Accept": "application/vnd.cpc.shipment-v8+xml",
                    "Authorization": f"Basic {self.settings.authorization}",
                    "Accept-language": f"{self.settings.language}-CA",
                },
                method="POST",
            )

        def _non_contract_shipment(job: Job):
            return http(
                url=
                f"{self.settings.server_url}/rs/{self.settings.customer_number}/ncshipment",
                data=bytearray(job.data.serialize(), "utf-8"),
                headers={
                    "Accept": "application/vnd.cpc.ncshipment-v4+xml",
                    "Content-Type": "application/vnd.cpc.ncshipment-v4+xml",
                    "Authorization": f"Basic {self.settings.authorization}",
                    "Accept-language": f"{self.settings.language}-CA",
                },
                method="POST",
            )

        def _get_label(job: Job):
            label_string = http(
                decoder=lambda b: base64.encodebytes(b).decode("utf-8"),
                url=job.data["href"],
                headers={
                    "Accept": job.data["media"],
                    "Authorization": f"Basic {self.settings.authorization}",
                },
                method="GET",
            )
            return f"<label>{label_string}</label>"

        def process(job: Job):
            if job.data is None:
                return job.fallback

            subprocess = {
                "contract_shipment": _contract_shipment,
                "non_contract_shipment": _non_contract_shipment,
                "shipment_label": _get_label,
            }
            if job.id not in subprocess:
                raise PurplShipError(
                    f"Unknown shipment request job id: {job.id}")

            return subprocess[job.id](job)

        pipeline: Pipeline = request.serialize()
        response = pipeline.apply(process)

        return Deserializable(XP.bundle_xml(response), XP.to_xml)