click_and_drop_api 3.0.3__tar.gz → 3.0.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. {click_and_drop_api-3.0.3/click_and_drop_api.egg-info → click_and_drop_api-3.0.4}/PKG-INFO +1 -1
  2. click_and_drop_api-3.0.4/click_and_drop_api/examples/mock-label.pdf +0 -0
  3. click_and_drop_api-3.0.4/click_and_drop_api/examples/mock-manifest.pdf +0 -0
  4. click_and_drop_api-3.0.4/click_and_drop_api/examples/oba_full_workflow.py +138 -0
  5. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/api.py +10 -0
  6. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/base.py +185 -2
  7. click_and_drop_api-3.0.4/click_and_drop_api/simple/compatibility.py +8 -0
  8. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/mock.py +48 -2
  9. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/types.py +13 -0
  10. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4/click_and_drop_api.egg-info}/PKG-INFO +1 -1
  11. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api.egg-info/SOURCES.txt +6 -0
  12. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/pyproject.toml +4 -1
  13. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_mock_api.py +15 -0
  14. click_and_drop_api-3.0.4/test/test_mock_api_manifest.py +51 -0
  15. click_and_drop_api-3.0.4/test/test_mock_api_update_orders.py +207 -0
  16. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/LICENSE +0 -0
  17. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/MANIFEST.in +0 -0
  18. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/README.md +0 -0
  19. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/__init__.py +0 -0
  20. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api/__init__.py +0 -0
  21. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api/labels_api.py +0 -0
  22. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api/manifests_api.py +0 -0
  23. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api/orders_api.py +0 -0
  24. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api/version_api.py +0 -0
  25. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api_client.py +0 -0
  26. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/api_response.py +0 -0
  27. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/configuration.py +0 -0
  28. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/__init__.py +0 -0
  29. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/__main__.py +0 -0
  30. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/check_oba.py +0 -0
  31. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/create_order.py +0 -0
  32. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/generate_label.py +0 -0
  33. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/package_size_and_cost.py +0 -0
  34. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/shipping_countries.py +0 -0
  35. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/view_order.py +0 -0
  36. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/view_specific_orders.py +0 -0
  37. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/examples/view_version.py +0 -0
  38. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/exceptions.py +0 -0
  39. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/__init__.py +0 -0
  40. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/address_request.py +0 -0
  41. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/billing_details_request.py +0 -0
  42. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_order_error_response.py +0 -0
  43. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_order_label_error_response.py +0 -0
  44. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_order_request.py +0 -0
  45. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_order_response.py +0 -0
  46. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_orders_request.py +0 -0
  47. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_orders_response.py +0 -0
  48. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/create_packages_response.py +0 -0
  49. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/delete_orders_resource.py +0 -0
  50. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/deleted_order_info.py +0 -0
  51. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/dimensions_request.py +0 -0
  52. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/error_response.py +0 -0
  53. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/failed_order_response.py +0 -0
  54. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_order_details_resource.py +0 -0
  55. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_order_info_resource.py +0 -0
  56. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_order_line_result.py +0 -0
  57. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_orders_details_response.py +0 -0
  58. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_orders_response.py +0 -0
  59. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_postal_details_result.py +0 -0
  60. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_shipping_details_result.py +0 -0
  61. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_tag_details_result.py +0 -0
  62. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/get_version_resource.py +0 -0
  63. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/importer.py +0 -0
  64. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/label_generation_request.py +0 -0
  65. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/manifest_details_response.py +0 -0
  66. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/manifest_eligible_orders_request.py +0 -0
  67. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/manifest_errors_error_details_response.py +0 -0
  68. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/manifest_errors_response.py +0 -0
  69. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/manifest_orders_response.py +0 -0
  70. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/order_error_info.py +0 -0
  71. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/order_error_response.py +0 -0
  72. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/order_field_response.py +0 -0
  73. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/order_update_error.py +0 -0
  74. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/postage_details_request.py +0 -0
  75. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/product_item_request.py +0 -0
  76. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/recipient_details_request.py +0 -0
  77. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/sender_details_request.py +0 -0
  78. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/shipment_package_request.py +0 -0
  79. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/tag_request.py +0 -0
  80. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/update_order_status_request.py +0 -0
  81. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/update_order_status_response.py +0 -0
  82. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/update_orders_status_request.py +0 -0
  83. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/models/updated_order_info.py +0 -0
  84. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/py.typed +0 -0
  85. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/rest.py +0 -0
  86. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/__init__.py +0 -0
  87. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/addresses.py +0 -0
  88. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/errors.py +0 -0
  89. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/__init__.py +0 -0
  90. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/db.py +0 -0
  91. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/documents.py +0 -0
  92. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/format_dimensions.py +0 -0
  93. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/large_letter.py +0 -0
  94. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/large_parcel.py +0 -0
  95. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/letter.py +0 -0
  96. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/medium_parcel.py +0 -0
  97. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/large_letter-DE.txt +0 -0
  98. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/large_letter-GB.txt +0 -0
  99. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/large_parcel-DE.txt +0 -0
  100. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/large_parcel-GB.txt +0 -0
  101. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/letter-DE.txt +0 -0
  102. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/letter-GB.txt +0 -0
  103. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/medium_parcel-DE.txt +0 -0
  104. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/medium_parcel-GB.txt +0 -0
  105. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/small_parcel-DE.txt +0 -0
  106. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/non-oba codes/small_parcel-GB.txt +0 -0
  107. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/documents-DE.txt +0 -0
  108. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/large_letter-DE.txt +0 -0
  109. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/large_letter-GB.txt +0 -0
  110. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/letter-DE.txt +0 -0
  111. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/letter-GB.txt +0 -0
  112. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/parcel-DE.txt +0 -0
  113. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba-codes/parcel-GB.txt +0 -0
  114. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/oba_parser.py +0 -0
  115. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/package_shipping_option.py +0 -0
  116. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/parcel.py +0 -0
  117. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/parser.py +0 -0
  118. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping/small_parcel.py +0 -0
  119. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api/simple/shipping_test_result.py +0 -0
  120. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api.egg-info/dependency_links.txt +0 -0
  121. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api.egg-info/requires.txt +0 -0
  122. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/click_and_drop_api.egg-info/top_level.txt +0 -0
  123. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/setup.cfg +0 -0
  124. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/setup.py +0 -0
  125. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_address_request.py +0 -0
  126. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_billing_details_request.py +0 -0
  127. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_choose_size_by_weight.py +0 -0
  128. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_order_error_response.py +0 -0
  129. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_order_label_error_response.py +0 -0
  130. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_order_request.py +0 -0
  131. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_order_response.py +0 -0
  132. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_orders_request.py +0 -0
  133. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_orders_response.py +0 -0
  134. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_create_packages_response.py +0 -0
  135. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_delete_orders_resource.py +0 -0
  136. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_deleted_order_info.py +0 -0
  137. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_dimensions_request.py +0 -0
  138. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_error_response.py +0 -0
  139. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_failed_order_response.py +0 -0
  140. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_order_details_resource.py +0 -0
  141. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_order_info_resource.py +0 -0
  142. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_order_line_result.py +0 -0
  143. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_orders_details_response.py +0 -0
  144. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_orders_response.py +0 -0
  145. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_postal_details_result.py +0 -0
  146. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_shipping_details_result.py +0 -0
  147. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_tag_details_result.py +0 -0
  148. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_get_version_resource.py +0 -0
  149. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_importer.py +0 -0
  150. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_label_generation_request.py +0 -0
  151. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_labels_api.py +0 -0
  152. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_manifest_details_response.py +0 -0
  153. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_manifest_eligible_orders_request.py +0 -0
  154. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_manifest_errors_error_details_response.py +0 -0
  155. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_manifest_errors_response.py +0 -0
  156. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_manifest_orders_response.py +0 -0
  157. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_manifests_api.py +0 -0
  158. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_oba_parser.py +0 -0
  159. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_order_error_info.py +0 -0
  160. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_order_error_response.py +0 -0
  161. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_order_field_response.py +0 -0
  162. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_order_update_error.py +0 -0
  163. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_orders_api.py +0 -0
  164. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_parcel_constraints.py +0 -0
  165. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_parcel_weights.py +0 -0
  166. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_postage_details_request.py +0 -0
  167. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_product_item_request.py +0 -0
  168. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_recipient_details_request.py +0 -0
  169. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_sender_details_request.py +0 -0
  170. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_shipment_package_request.py +0 -0
  171. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_shipping_option_model.py +0 -0
  172. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_shipping_options.py +0 -0
  173. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_simple_create_api.py +0 -0
  174. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_tag_request.py +0 -0
  175. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_update_order_status_request.py +0 -0
  176. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_update_order_status_response.py +0 -0
  177. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_update_orders_status_request.py +0 -0
  178. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_updated_order_info.py +0 -0
  179. {click_and_drop_api-3.0.3 → click_and_drop_api-3.0.4}/test/test_version_api.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: click_and_drop_api
3
- Version: 3.0.3
3
+ Version: 3.0.4
4
4
  Summary: ChannelShipper & Royal Mail Public API
5
5
  Home-page:
6
6
  Author: OpenAPI Generator community
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env python
2
+ """Full OBA workflow: create a cheap domestic order, generate a label,
3
+ apply postage via manifest, and mark the order as despatched.
4
+
5
+ Steps performed:
6
+ 1. Verify the account is OBA (required for label generation and OBA services)
7
+ 2. Pick the cheapest domestic OBA service
8
+ 3. Create the order (with label generation requested at creation time)
9
+ 4. Save the label PDF to disk
10
+ 5. Manifest eligible orders (applies postage)
11
+ 6. Set the order status to "despatched"
12
+
13
+ Note: Label generation is only available for OBA customers.
14
+ """
15
+
16
+ import os
17
+ import sys
18
+ from datetime import datetime, UTC
19
+ from pathlib import Path
20
+
21
+ from click_and_drop_api.simple import (
22
+ ClickAndDrop,
23
+ CreateOrder,
24
+ LabelGeneration,
25
+ RecipientDetails,
26
+ Address,
27
+ db,
28
+ )
29
+
30
+ # ---------------------------------------------------------------------------
31
+ # Configuration
32
+ # ---------------------------------------------------------------------------
33
+
34
+ API_KEY = os.environ["API_KEY"]
35
+ REFERENCE = "oba-workflow-{now}".format(now=datetime.now(UTC).strftime("%Y%m%d%H%M%S"))
36
+ WEIGHT_GRAMS = 100
37
+
38
+ api = ClickAndDrop(API_KEY)
39
+
40
+ # ---------------------------------------------------------------------------
41
+ # Step 1: verify OBA
42
+ # ---------------------------------------------------------------------------
43
+
44
+ print("Checking account type…")
45
+ if not api.is_oba():
46
+ print("ERROR: This account is not OBA. Label generation requires an OBA account.")
47
+ sys.exit(1)
48
+ print("Account is OBA.")
49
+
50
+ # ---------------------------------------------------------------------------
51
+ # Step 2: pick cheapest domestic OBA service
52
+ # ---------------------------------------------------------------------------
53
+
54
+ cheapest = db.filter(is_oba=True, international=False).any_or_none
55
+ if cheapest is None:
56
+ print("ERROR: No domestic OBA service found in the shipping database.")
57
+ sys.exit(1)
58
+
59
+ print(
60
+ f"Using service: {cheapest.brand} {cheapest.service_code}"
61
+ f" ({cheapest.delivery_speed}) — £{cheapest.gross}"
62
+ )
63
+
64
+ # ---------------------------------------------------------------------------
65
+ # Step 3: create the order, requesting a label in the response
66
+ # ---------------------------------------------------------------------------
67
+
68
+ order = CreateOrder(
69
+ order_reference=REFERENCE,
70
+ recipient=RecipientDetails(
71
+ address=Address(
72
+ full_name="Nicco Kunzmann",
73
+ address_line1="1 Test Street",
74
+ city="London",
75
+ postcode="SW1A 1AA",
76
+ country_code="GB",
77
+ )
78
+ ),
79
+ order_date=datetime.now(UTC),
80
+ subtotal=1.00,
81
+ shipping_cost_charged=float(cheapest.gross),
82
+ total=1.00 + float(cheapest.gross),
83
+ currency_code="GBP",
84
+ postage_details=cheapest.as_postage_details(),
85
+ packages=[cheapest.as_package_request(weight_in_grams=WEIGHT_GRAMS)],
86
+ label=LabelGeneration(
87
+ include_label_in_response=True,
88
+ include_cn=False,
89
+ include_returns_label=False,
90
+ ),
91
+ )
92
+
93
+ print(f"Creating order {REFERENCE!r}…")
94
+ response = api.create_order(order)
95
+
96
+ if response.errors_count or not response.created_orders:
97
+ print(f"ERROR: Order creation failed: {response.failed_orders}")
98
+ sys.exit(1)
99
+
100
+ created = response.created_orders[0]
101
+ order_id = created.order_identifier
102
+ print(f"Order created: id={order_id}, reference={created.order_reference}")
103
+
104
+ # ---------------------------------------------------------------------------
105
+ # Step 4: save label PDF
106
+ # ---------------------------------------------------------------------------
107
+
108
+ print("Fetching label…")
109
+ label_pdf = api.get_label(order_id, "postageLabel", include_returns_label=False)
110
+ label_path = Path(__file__).parent / "label.pdf"
111
+ label_path.write_bytes(label_pdf)
112
+ print(f"Label saved to {label_path}")
113
+
114
+ # ---------------------------------------------------------------------------
115
+ # Step 5: manifest (applies postage)
116
+ # ---------------------------------------------------------------------------
117
+
118
+ print("Manifesting eligible orders…")
119
+ manifest = api.manifest_orders()
120
+ print(f"Manifest number: {manifest.manifest_number}")
121
+ if manifest.pdf is not None:
122
+ manifest_path = Path(__file__).parent / "manifest.pdf"
123
+ manifest_path.write_bytes(manifest.pdf)
124
+ print(f"Manifest PDF saved to {manifest_path}")
125
+
126
+ # ---------------------------------------------------------------------------
127
+ # Step 6: mark as despatched
128
+ # ---------------------------------------------------------------------------
129
+
130
+ print(f"Setting order {order_id} to 'despatched'…")
131
+ update = api.update_orders([order_id], status="despatched")
132
+
133
+ if update.errors:
134
+ print(f"WARNING: status update errors: {update.errors}")
135
+ else:
136
+ print("Order marked as despatched.")
137
+
138
+ print("Done.")
@@ -170,5 +170,15 @@ class ClickAndDrop(AbstractClickAndDrop):
170
170
  include_cn=include_cn,
171
171
  )
172
172
 
173
+ def _set_order_status(
174
+ self, request: click_and_drop_api.UpdateOrdersStatusRequest
175
+ ) -> click_and_drop_api.UpdateOrderStatusResponse:
176
+ return self._orders_api.update_orders_status_async(request)
177
+
178
+ def _manifest_orders(
179
+ self, request: click_and_drop_api.ManifestEligibleOrdersRequest
180
+ ) -> click_and_drop_api.ManifestOrdersResponse:
181
+ return self._manifests_api.manifest_eligible_async(request)
182
+
173
183
 
174
184
  __all__ = ["ClickAndDrop"]
@@ -3,7 +3,9 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from abc import ABC, abstractmethod
6
+ import os
6
7
  from typing import Literal, Optional, Union
8
+ from click_and_drop_api.simple.compatibility import Self
7
9
 
8
10
  import click_and_drop_api
9
11
 
@@ -12,7 +14,17 @@ from datetime import datetime, timezone
12
14
 
13
15
  from click_and_drop_api.exceptions import ApiException
14
16
  from click_and_drop_api.models.create_order_response import CreateOrderResponse
17
+ from click_and_drop_api.models.manifest_eligible_orders_request import (
18
+ ManifestEligibleOrdersRequest,
19
+ )
20
+ from click_and_drop_api.models.manifest_orders_response import ManifestOrdersResponse
15
21
  from click_and_drop_api.models.order_field_response import OrderFieldResponse
22
+ from click_and_drop_api.models.update_order_status_response import (
23
+ UpdateOrderStatusResponse,
24
+ )
25
+ from click_and_drop_api.models.update_orders_status_request import (
26
+ UpdateOrdersStatusRequest,
27
+ )
16
28
  from click_and_drop_api.simple import (
17
29
  Address,
18
30
  CreateOrder,
@@ -22,11 +34,17 @@ from click_and_drop_api.simple import (
22
34
  )
23
35
  from click_and_drop_api.simple.shipping_test_result import ShippingTestResult
24
36
  from click_and_drop_api.simple.addresses import get_address, get_all_country_codes
37
+ from .types import ManifestedOrders, UpdateOrderStatus
25
38
 
26
39
 
27
40
  class AbstractClickAndDrop(ABC):
28
41
  """Common interface shared by ClickAndDrop and MockClickAndDrop."""
29
42
 
43
+ @classmethod
44
+ def from_env(cls, api_env_var: str = "API_KEY") -> Self:
45
+ api_key = os.environ[api_env_var]
46
+ return cls(api_key)
47
+
30
48
  max_order_count: int = 100
31
49
 
32
50
  @property
@@ -52,7 +70,7 @@ class AbstractClickAndDrop(ABC):
52
70
  Parameters:
53
71
  orders: One or more :class:`~click_and_drop_api.simple.types.CreateOrder` instances.
54
72
  Returns:
55
- A :class:`~click_and_drop_api.CreateOrdersResponse` instance containing created and failed orders.
73
+ A :class:`~click_and_drop_api.models.create_orders_response.CreateOrdersResponse` instance containing created and failed orders.
56
74
 
57
75
  https://api.parcel.royalmail.com/#tag/Orders/operation/CreateOrdersAsync
58
76
  """
@@ -223,7 +241,7 @@ class AbstractClickAndDrop(ABC):
223
241
  address for every country.
224
242
 
225
243
  Returns:
226
- :class:`ShippingTestResult` with ``success=True/False`` and a message.
244
+ :class:`~click_and_drop_api.simple.shipping_test_result.ShippingTestResult` with ``success=True/False`` and a message.
227
245
 
228
246
  Note:
229
247
  This method only seems to work for OBA accounts
@@ -316,6 +334,171 @@ class AbstractClickAndDrop(ABC):
316
334
  postage_details=PostageDetails(service_code=service_code),
317
335
  )
318
336
 
337
+ def update_order_status(
338
+ self, updates: list[UpdateOrderStatus]
339
+ ) -> UpdateOrderStatusResponse:
340
+ """Set the status of an order.
341
+
342
+ Parameters:
343
+ requests: A list of UpdateOrdersStatusRequest instances.
344
+
345
+ Returns:
346
+ A :class:`~click_and_drop_api.models.set_order_status_resource.SetOrderStatusResource` instance containing the updated order information.
347
+ """
348
+ result = UpdateOrderStatusResponse(updated_orders=[], errors=[])
349
+ for i in range(0, len(updates), self.max_order_count):
350
+ request = UpdateOrdersStatusRequest(
351
+ items=updates[i : i + self.max_order_count]
352
+ )
353
+ response = self._set_order_status(request)
354
+ result.updated_orders.extend(response.updated_orders)
355
+ result.errors.extend(response.errors)
356
+ return result
357
+
358
+ def update_orders(
359
+ self,
360
+ order_identifiers: list[Union[str, int]] | str | int,
361
+ status: Literal["new", "despatchedByOtherCourier", "despatched"] | None = None,
362
+ tracking_number: str | None = None,
363
+ despatch_date: datetime | None = None,
364
+ shipping_carrier: str | None = None,
365
+ shipping_service: str | None = None,
366
+ ):
367
+ """Update the status of multiple orders."""
368
+ return self.update_order_status(
369
+ self._get_orders_update_request(
370
+ order_identifiers,
371
+ status=status,
372
+ tracking_number=tracking_number,
373
+ despatch_date=despatch_date,
374
+ shipping_carrier=shipping_carrier,
375
+ shipping_service=shipping_service,
376
+ )
377
+ )
378
+
379
+ def set_order_status(
380
+ self,
381
+ order_identifiers: list[Union[str, int]] | str | int,
382
+ status: Literal["new", "despatchedByOtherCourier", "despatched"],
383
+ ) -> UpdateOrderStatusResponse:
384
+ """Set the status of orders."""
385
+ return self.update_order_status(
386
+ self._get_orders_update_request(order_identifiers, status=status)
387
+ )
388
+
389
+ def set_order_tracking_number(
390
+ self, order_identifiers: list[Union[str, int]] | str | int, tracking_number: str
391
+ ) -> UpdateOrderStatusResponse:
392
+ """Set the tracking number of a orders."""
393
+ return self.update_order_status(
394
+ self._get_orders_update_request(
395
+ order_identifiers, tracking_number=tracking_number
396
+ )
397
+ )
398
+
399
+ def set_order_despatch_date(
400
+ self,
401
+ order_identifiers: list[Union[str, int]] | str | int,
402
+ despatch_date: datetime,
403
+ ) -> UpdateOrderStatusResponse:
404
+ """Set the despatch date of a orders."""
405
+ return self.update_order_status(
406
+ self._get_orders_update_request(
407
+ order_identifiers, despatch_date=despatch_date
408
+ )
409
+ )
410
+
411
+ def set_order_shipping_carrier(
412
+ self,
413
+ order_identifiers: list[Union[str, int]] | str | int,
414
+ shipping_carrier: str,
415
+ ) -> UpdateOrderStatusResponse:
416
+ """Set the shipping carrier of a orders."""
417
+ return self.update_order_status(
418
+ self._get_orders_update_request(
419
+ order_identifiers, shipping_carrier=shipping_carrier
420
+ )
421
+ )
422
+
423
+ def set_order_shipping_service(
424
+ self,
425
+ order_identifiers: list[Union[str, int]] | str | int,
426
+ shipping_service: str,
427
+ ) -> UpdateOrderStatusResponse:
428
+ """Set the shipping service of a orders."""
429
+ return self.update_order_status(
430
+ self._get_orders_update_request(
431
+ order_identifiers, shipping_service=shipping_service
432
+ )
433
+ )
434
+
435
+ def _get_orders_update_request(
436
+ self,
437
+ order_identifiers: list[Union[str, int]] | str | int,
438
+ status: str | None = None,
439
+ tracking_number: str | None = None,
440
+ despatch_date: datetime | None = None,
441
+ shipping_carrier: str | None = None,
442
+ shipping_service: str | None = None,
443
+ ) -> list[UpdateOrderStatus]:
444
+ """Get a list of UpdateOrderStatus for the given order identifiers and attributes."""
445
+ if not isinstance(order_identifiers, list):
446
+ order_identifiers = [order_identifiers]
447
+ result = []
448
+ for identifier in order_identifiers:
449
+ order_id = identifier if isinstance(identifier, int) else None
450
+ order_ref = identifier if isinstance(identifier, str) else None
451
+ result.append(
452
+ UpdateOrderStatus(
453
+ order_identifier=order_id,
454
+ order_reference=order_ref,
455
+ status=status,
456
+ tracking_number=tracking_number,
457
+ despatch_date=despatch_date,
458
+ shipping_carrier=shipping_carrier,
459
+ shipping_service=shipping_service,
460
+ )
461
+ )
462
+ return result
463
+
464
+ @abstractmethod
465
+ def _set_order_status(
466
+ self, request: UpdateOrdersStatusRequest
467
+ ) -> UpdateOrderStatusResponse:
468
+ """Set the status of an order."""
469
+
470
+ @abstractmethod
471
+ def _manifest_orders(
472
+ self, request: ManifestEligibleOrdersRequest
473
+ ) -> ManifestOrdersResponse:
474
+ """Manifest eligible orders."""
475
+
476
+ def manifest_orders(self, carrier_name: str | None = None) -> ManifestedOrders:
477
+ """Manifest all eligible orders, applying postage.
478
+
479
+ Manifests all orders in ``Label Generated`` and ``Despatched`` statuses
480
+ and returns manifest paperwork where possible.
481
+
482
+ Parameters:
483
+ carrier_name:
484
+ Required when the account has multiple carriers or postage
485
+ location numbers. Must match the carrier name configured in the
486
+ account settings. Pass ``None`` for single-carrier accounts.
487
+
488
+ Returns:
489
+ A :class:`~click_and_drop_api.models.manifest_orders_response.ManifestOrdersResponse`
490
+ containing the manifest number and an optional base64-encoded PDF.
491
+
492
+ https://api.parcel.royalmail.com/#tag/Manifests/operation/ManifestEligibleAsync
493
+ """
494
+ response = self._manifest_orders(
495
+ ManifestEligibleOrdersRequest(carrier_name=carrier_name)
496
+ )
497
+ return ManifestedOrders(
498
+ manifest_number=response.manifest_number,
499
+ document_pdf=response.document_pdf,
500
+ )
501
+
319
502
 
320
503
  __all__ = [
321
504
  "AbstractClickAndDrop",
@@ -0,0 +1,8 @@
1
+ import sys
2
+
3
+ if sys.version_info < (3, 11):
4
+ from typing_extensions import Self
5
+ else:
6
+ from typing import Self
7
+
8
+ __all__ = ["Self"]
@@ -2,6 +2,8 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import base64
6
+ from importlib.resources import files
5
7
  from datetime import datetime, timezone
6
8
  from typing import Literal, Optional, Union
7
9
 
@@ -26,7 +28,7 @@ class MockClickAndDrop(AbstractClickAndDrop):
26
28
  assert response.success_count == 1
27
29
  """
28
30
 
29
- def __init__(self, key: str = _MOCK_KEY):
31
+ def __init__(self, key: str = _MOCK_KEY, is_oba: bool = True):
30
32
  if not isinstance(key, str):
31
33
  raise TypeError(f"Expected str, got {key}.")
32
34
  key = key.strip()
@@ -35,8 +37,13 @@ class MockClickAndDrop(AbstractClickAndDrop):
35
37
  if "".join(key.split()) != key:
36
38
  raise ValueError(f"Expected no whitespace in {key!r}.")
37
39
  self._key = key
40
+ self._is_oba = is_oba
38
41
  self._orders: dict[int, click_and_drop_api.GetOrderInfoResource] = {}
39
42
  self._next_id = 1
43
+ self._next_manifest_id = 1
44
+
45
+ def is_oba(self) -> bool:
46
+ return self._is_oba
40
47
 
41
48
  @property
42
49
  def key(self) -> str:
@@ -135,7 +142,46 @@ class MockClickAndDrop(AbstractClickAndDrop):
135
142
  include_returns_label: Optional[bool] = None,
136
143
  include_cn: Optional[bool] = None,
137
144
  ) -> bytearray:
138
- return bytearray(b"%PDF-1.4 mock label\n")
145
+ data = (
146
+ files("click_and_drop_api.examples").joinpath("mock-label.pdf").read_bytes()
147
+ )
148
+ return bytearray(data)
149
+
150
+ def _manifest_orders(
151
+ self, request: click_and_drop_api.ManifestEligibleOrdersRequest
152
+ ) -> click_and_drop_api.ManifestOrdersResponse:
153
+ manifest_id = self._next_manifest_id
154
+ self._next_manifest_id += 1
155
+ data = (
156
+ files("click_and_drop_api.examples")
157
+ .joinpath("mock-manifest.pdf")
158
+ .read_bytes()
159
+ )
160
+ return click_and_drop_api.ManifestOrdersResponse(
161
+ manifest_number=manifest_id,
162
+ document_pdf=base64.b64encode(data).decode(),
163
+ )
164
+
165
+ def _set_order_status(
166
+ self, request: click_and_drop_api.UpdateOrdersStatusRequest
167
+ ) -> click_and_drop_api.UpdateOrderStatusResponse:
168
+ # For simplicity, this mock does not actually update the orders.
169
+ # It just returns a successful response for all items in the request.
170
+ created = []
171
+ errors = []
172
+ for item in request.items or []:
173
+ created.append(
174
+ click_and_drop_api.UpdatedOrderInfo(
175
+ order_identifier=item.order_identifier,
176
+ order_reference=item.order_reference,
177
+ status=item.status,
178
+ )
179
+ )
180
+
181
+ return click_and_drop_api.UpdateOrderStatusResponse(
182
+ updated_orders=created,
183
+ errors=errors,
184
+ )
139
185
 
140
186
 
141
187
  __all__ = ["MockClickAndDrop"]
@@ -1,5 +1,7 @@
1
1
  """Renamed types for nicer reading"""
2
2
 
3
+ import base64
4
+
3
5
  from click_and_drop_api.models.address_request import AddressRequest as Address
4
6
  from click_and_drop_api.models.billing_details_request import (
5
7
  BillingDetailsRequest as BillingDetails,
@@ -20,6 +22,7 @@ from click_and_drop_api.models.manifest_details_response import (
20
22
  from click_and_drop_api.models.manifest_eligible_orders_request import (
21
23
  ManifestEligibleOrdersRequest as ManifestEligibleOrders,
22
24
  )
25
+ from click_and_drop_api.models.manifest_orders_response import ManifestOrdersResponse
23
26
  from click_and_drop_api.models.postage_details_request import (
24
27
  PostageDetailsRequest as PostageDetails,
25
28
  )
@@ -47,9 +50,19 @@ from click_and_drop_api.models.update_orders_status_request import (
47
50
  )
48
51
 
49
52
 
53
+ class ManifestedOrders(ManifestOrdersResponse):
54
+ @property
55
+ def pdf(self) -> bytearray | None:
56
+ """Return the PDF content of the manifest as a bytearray, or None if unavailable."""
57
+ if self.document_pdf is None:
58
+ return None
59
+ return bytearray(base64.b64decode(self.document_pdf))
60
+
61
+
50
62
  __all__ = [
51
63
  "CreateOrder",
52
64
  "RecipientDetails",
65
+ "ManifestedOrders",
53
66
  "Address",
54
67
  "PostageDetails",
55
68
  "ShipmentPackage",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: click_and_drop_api
3
- Version: 3.0.3
3
+ Version: 3.0.4
4
4
  Summary: ChannelShipper & Royal Mail Public API
5
5
  Home-page:
6
6
  Author: OpenAPI Generator community
@@ -26,6 +26,9 @@ click_and_drop_api/examples/__main__.py
26
26
  click_and_drop_api/examples/check_oba.py
27
27
  click_and_drop_api/examples/create_order.py
28
28
  click_and_drop_api/examples/generate_label.py
29
+ click_and_drop_api/examples/mock-label.pdf
30
+ click_and_drop_api/examples/mock-manifest.pdf
31
+ click_and_drop_api/examples/oba_full_workflow.py
29
32
  click_and_drop_api/examples/package_size_and_cost.py
30
33
  click_and_drop_api/examples/shipping_countries.py
31
34
  click_and_drop_api/examples/view_order.py
@@ -80,6 +83,7 @@ click_and_drop_api/simple/__init__.py
80
83
  click_and_drop_api/simple/addresses.py
81
84
  click_and_drop_api/simple/api.py
82
85
  click_and_drop_api/simple/base.py
86
+ click_and_drop_api/simple/compatibility.py
83
87
  click_and_drop_api/simple/errors.py
84
88
  click_and_drop_api/simple/mock.py
85
89
  click_and_drop_api/simple/shipping_test_result.py
@@ -148,6 +152,8 @@ test/test_manifest_errors_response.py
148
152
  test/test_manifest_orders_response.py
149
153
  test/test_manifests_api.py
150
154
  test/test_mock_api.py
155
+ test/test_mock_api_manifest.py
156
+ test/test_mock_api_update_orders.py
151
157
  test/test_oba_parser.py
152
158
  test/test_order_error_info.py
153
159
  test/test_order_error_response.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "click_and_drop_api"
3
- version = "3.0.3"
3
+ version = "3.0.4"
4
4
  description = "ChannelShipper & Royal Mail Public API"
5
5
  authors = [
6
6
  {name = "Nicco Kunzmann", email = "niccokunzmann@rambler.ru"},
@@ -73,6 +73,9 @@ cli = [
73
73
  "tox",
74
74
  ]
75
75
 
76
+ [tool.setuptools.package-data]
77
+ "click_and_drop_api.examples" = ["*.pdf"]
78
+
76
79
  [build-system]
77
80
  requires = ["setuptools"]
78
81
  build-backend = "setuptools.build_meta"
@@ -260,6 +260,21 @@ def test_test_shipping_multiple_calls_stay_clean(api):
260
260
  assert len(api._orders) == 0
261
261
 
262
262
 
263
+ # --- is_oba ---
264
+
265
+
266
+ def test_is_oba_default_is_true():
267
+ assert MockClickAndDrop().is_oba() is True
268
+
269
+
270
+ def test_is_oba_true():
271
+ assert MockClickAndDrop(is_oba=True).is_oba() is True
272
+
273
+
274
+ def test_is_oba_false():
275
+ assert MockClickAndDrop(is_oba=False).is_oba() is False
276
+
277
+
263
278
  # --- format_fields_for_error_message ---
264
279
 
265
280
 
@@ -0,0 +1,51 @@
1
+ """Tests for manifest_orders."""
2
+
3
+ import pytest
4
+
5
+ from click_and_drop_api.models.manifest_orders_response import ManifestOrdersResponse
6
+ from click_and_drop_api.simple.mock import MockClickAndDrop
7
+ from click_and_drop_api.simple.types import ManifestedOrders
8
+
9
+
10
+ @pytest.fixture
11
+ def api() -> MockClickAndDrop:
12
+ return MockClickAndDrop()
13
+
14
+
15
+ def test_manifest_orders_returns_response(api: MockClickAndDrop) -> None:
16
+ result = api.manifest_orders()
17
+ assert isinstance(result, ManifestOrdersResponse)
18
+
19
+
20
+ def test_manifest_orders_has_manifest_number(api: MockClickAndDrop) -> None:
21
+ result = api.manifest_orders()
22
+ assert result.manifest_number is not None
23
+
24
+
25
+ def test_manifest_orders_with_carrier_name(api: MockClickAndDrop) -> None:
26
+ result = api.manifest_orders(carrier_name="Royal Mail")
27
+ assert isinstance(result, ManifestOrdersResponse)
28
+
29
+
30
+ def test_manifest_orders_increments_manifest_number(api: MockClickAndDrop) -> None:
31
+ r1 = api.manifest_orders()
32
+ r2 = api.manifest_orders()
33
+ assert r2.manifest_number != r1.manifest_number
34
+
35
+
36
+ # --- .pdf property ---
37
+
38
+
39
+ def test_manifest_orders_pdf_returns_bytearray(api: MockClickAndDrop) -> None:
40
+ result: ManifestedOrders = api.manifest_orders()
41
+ assert isinstance(result.pdf, bytearray)
42
+
43
+
44
+ def test_manifest_orders_pdf_starts_with_pdf_header(api: MockClickAndDrop) -> None:
45
+ result: ManifestedOrders = api.manifest_orders()
46
+ assert result.pdf[:4] == bytearray(b"%PDF")
47
+
48
+
49
+ def test_manifest_orders_pdf_none_when_no_document() -> None:
50
+ result = ManifestedOrders(manifest_number=1, document_pdf=None)
51
+ assert result.pdf is None