mycommerce-platform 0.1.0__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.
@@ -0,0 +1,94 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+
15
+ # Editor directories and files
16
+ .vscode/*
17
+ !.vscode/extensions.json
18
+ !.vscode/settings.json
19
+ .idea
20
+ .DS_Store
21
+ *.suo
22
+ *.ntvs*
23
+ *.njsproj
24
+ *.sln
25
+ *.sw?
26
+
27
+ .thumbs.db
28
+
29
+ # Quasar core related directories
30
+ .quasar
31
+ /quasar.config.*.temporary.compiled*
32
+
33
+ # Cordova related directories and files
34
+ /src-cordova/node_modules
35
+ /src-cordova/platforms
36
+ /src-cordova/plugins
37
+ /src-cordova/www
38
+
39
+ # Capacitor related directories and files
40
+ /src-capacitor/www
41
+ /src-capacitor/node_modules
42
+
43
+ # BEX related directories and files
44
+ /src-bex/www
45
+ /src-bex/js/core
46
+
47
+ # Nuxt dev/build outputs
48
+ .output
49
+ .data
50
+ .nuxt
51
+ .nitro
52
+ .cache
53
+
54
+ # Local env files
55
+ .env
56
+ .env.*
57
+ .env.local*
58
+ !.env.example
59
+
60
+ # Misc files
61
+ .fleet
62
+ .tmp
63
+ *.tmp*
64
+ *.sublime-project
65
+ *.sublime-workspace
66
+ UserInterfaceState.xcuserstate
67
+ $RECYCLE.BIN/
68
+ log.txt
69
+ .coverage
70
+ *.sqlite*
71
+
72
+ # IDE and build directories
73
+ /.ionic
74
+ /.sass-cache
75
+ /.sourcemaps
76
+ /.versions
77
+ /.vscode/*
78
+ !/.vscode/extensions.json
79
+ !/.vscode/settings.json
80
+ /coverage
81
+ /platforms
82
+ /plugins
83
+ /www
84
+
85
+ # Python
86
+ __pycache__/
87
+
88
+ # Tests
89
+ */coverage/
90
+ __snapshots__/
91
+
92
+ *~
93
+ Thumbs.db
94
+ .pytest_cache
@@ -0,0 +1,64 @@
1
+ Metadata-Version: 2.5
2
+ Name: mycommerce-platform
3
+ Version: 0.1.0
4
+ Summary: Small, dependency-free Python client for the MyCommerce API gateway
5
+ Project-URL: Homepage, https://github.com/bayzed123/mycommerce
6
+ Project-URL: Repository, https://github.com/bayzed123/mycommerce
7
+ Project-URL: Issues, https://github.com/bayzed123/mycommerce/issues
8
+ Author: MyCommerce Contributors
9
+ License: MIT
10
+ Keywords: api,cart,ecommerce,mycommerce,payments,shop
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+
25
+ # mycommerce-platform
26
+
27
+ `mycommerce-platform` is the small, dependency-free Python client for the MyCommerce Cloudflare Worker gateway. It gives Python applications one stable base URL while the gateway routes requests to the Shop API, Cart API, and Go Purchase service.
28
+
29
+ ## Install
30
+
31
+ ```bash
32
+ pip install mycommerce-platform
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ ```python
38
+ from mycommerce import MyCommerceClient
39
+
40
+ client = MyCommerceClient(
41
+ "https://mycommerce-api-gateway.<your-subdomain>.workers.dev",
42
+ token="optional-jwt-token",
43
+ )
44
+
45
+ print(client.health())
46
+ products = client.shop("api/v1/shop/")
47
+ cart = client.cart("cart/v1/")
48
+ payment = client.purchase("create", method="POST", payload={"sessionId": "session-123"})
49
+ ```
50
+
51
+ The package only uses Python's standard library. It does not contain Stripe, database, Django, or Cloudflare credentials. Authentication is supplied through the optional bearer token and service authorization remains a gateway/backend responsibility.
52
+
53
+ ## Development
54
+
55
+ ```bash
56
+ cd packages/mycommerce-platform
57
+ python -m venv .venv
58
+ . .venv/bin/activate
59
+ python -m pip install -U pip pytest
60
+ pytest
61
+ python -m build
62
+ ```
63
+
64
+ The package is published from GitHub Actions when a `mycommerce-platform-v*` tag is pushed. Configure a PyPI Trusted Publisher for this GitHub repository before creating the first release.
@@ -0,0 +1,40 @@
1
+ # mycommerce-platform
2
+
3
+ `mycommerce-platform` is the small, dependency-free Python client for the MyCommerce Cloudflare Worker gateway. It gives Python applications one stable base URL while the gateway routes requests to the Shop API, Cart API, and Go Purchase service.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install mycommerce-platform
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```python
14
+ from mycommerce import MyCommerceClient
15
+
16
+ client = MyCommerceClient(
17
+ "https://mycommerce-api-gateway.<your-subdomain>.workers.dev",
18
+ token="optional-jwt-token",
19
+ )
20
+
21
+ print(client.health())
22
+ products = client.shop("api/v1/shop/")
23
+ cart = client.cart("cart/v1/")
24
+ payment = client.purchase("create", method="POST", payload={"sessionId": "session-123"})
25
+ ```
26
+
27
+ The package only uses Python's standard library. It does not contain Stripe, database, Django, or Cloudflare credentials. Authentication is supplied through the optional bearer token and service authorization remains a gateway/backend responsibility.
28
+
29
+ ## Development
30
+
31
+ ```bash
32
+ cd packages/mycommerce-platform
33
+ python -m venv .venv
34
+ . .venv/bin/activate
35
+ python -m pip install -U pip pytest
36
+ pytest
37
+ python -m build
38
+ ```
39
+
40
+ The package is published from GitHub Actions when a `mycommerce-platform-v*` tag is pushed. Configure a PyPI Trusted Publisher for this GitHub repository before creating the first release.
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "mycommerce-platform"
7
+ version = "0.1.0"
8
+ description = "Small, dependency-free Python client for the MyCommerce API gateway"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "MyCommerce Contributors" }]
13
+ keywords = ["mycommerce", "ecommerce", "api", "shop", "cart", "payments"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3 :: Only",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
25
+ "Typing :: Typed",
26
+ ]
27
+
28
+ [project.urls]
29
+ Homepage = "https://github.com/bayzed123/mycommerce"
30
+ Repository = "https://github.com/bayzed123/mycommerce"
31
+ Issues = "https://github.com/bayzed123/mycommerce/issues"
32
+
33
+ [tool.hatch.build.targets.wheel]
34
+ packages = ["src/mycommerce"]
35
+
36
+ [tool.pytest.ini_options]
37
+ testpaths = ["tests"]
38
+ addopts = "-q"
39
+
40
+ [tool.hatch.version]
41
+ path = "src/mycommerce/__init__.py"
@@ -0,0 +1,6 @@
1
+ """Public API for the mycommerce-platform package."""
2
+
3
+ from .client import ApiError, MyCommerceClient
4
+
5
+ __all__ = ["ApiError", "MyCommerceClient"]
6
+ __version__ = "0.1.0"
@@ -0,0 +1,83 @@
1
+ """Small standard-library-only client for the MyCommerce API gateway."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from dataclasses import dataclass
7
+ from typing import Any, Mapping
8
+ from urllib.error import HTTPError, URLError
9
+ from urllib.parse import urljoin
10
+ from urllib.request import Request, urlopen
11
+
12
+
13
+ class ApiError(RuntimeError):
14
+ """Raised when the gateway cannot return a successful JSON response."""
15
+
16
+ def __init__(self, status: int, message: str, payload: Any = None) -> None:
17
+ super().__init__(f"MyCommerce API error {status}: {message}")
18
+ self.status = status
19
+ self.payload = payload
20
+
21
+
22
+ @dataclass
23
+ class MyCommerceClient:
24
+ """Client for the Worker gateway and its three backend routes.
25
+
26
+ The gateway is expected to expose `/shop/*`, `/cart/*`, and `/purchase/*`.
27
+ The client does not contain service credentials; authentication is supplied
28
+ through the optional bearer token at request time or construction time.
29
+ """
30
+
31
+ base_url: str
32
+ token: str | None = None
33
+ timeout: float = 15.0
34
+
35
+ def _request(
36
+ self,
37
+ method: str,
38
+ route: str,
39
+ payload: Mapping[str, Any] | list[Any] | None = None,
40
+ *,
41
+ token: str | None = None,
42
+ ) -> Any:
43
+ url = urljoin(self.base_url.rstrip("/") + "/", route.lstrip("/"))
44
+ headers = {"Accept": "application/json"}
45
+ auth_token = token or self.token
46
+ if auth_token:
47
+ headers["Authorization"] = f"Bearer {auth_token}"
48
+ body = None
49
+ if payload is not None:
50
+ headers["Content-Type"] = "application/json"
51
+ body = json.dumps(payload).encode("utf-8")
52
+ request = Request(url, data=body, headers=headers, method=method.upper())
53
+ try:
54
+ with urlopen(request, timeout=self.timeout) as response:
55
+ raw = response.read()
56
+ if not raw:
57
+ return None
58
+ return json.loads(raw.decode("utf-8"))
59
+ except HTTPError as error:
60
+ raw = error.read().decode("utf-8", errors="replace")
61
+ try:
62
+ payload_data = json.loads(raw) if raw else None
63
+ except json.JSONDecodeError:
64
+ payload_data = raw
65
+ raise ApiError(error.code, error.reason, payload_data) from error
66
+ except URLError as error:
67
+ raise ApiError(0, str(error.reason)) from error
68
+
69
+ def health(self) -> Any:
70
+ """Return the gateway health response."""
71
+ return self._request("GET", "/health")
72
+
73
+ def shop(self, path: str = "", *, method: str = "GET", payload: Any = None) -> Any:
74
+ """Call a path proxied to the Shop API."""
75
+ return self._request(method, f"/shop/{path.lstrip('/')}", payload)
76
+
77
+ def cart(self, path: str = "", *, method: str = "GET", payload: Any = None) -> Any:
78
+ """Call a path proxied to the Cart API."""
79
+ return self._request(method, f"/cart/{path.lstrip('/')}", payload)
80
+
81
+ def purchase(self, path: str = "", *, method: str = "GET", payload: Any = None) -> Any:
82
+ """Call a path proxied to the Go Purchase service."""
83
+ return self._request(method, f"/purchase/{path.lstrip('/')}", payload)
@@ -0,0 +1,22 @@
1
+ from unittest.mock import patch
2
+
3
+ from mycommerce import ApiError, MyCommerceClient
4
+
5
+
6
+ def test_route_prefixes_are_forwarded_to_the_gateway():
7
+ client = MyCommerceClient("https://api.example.test")
8
+ with patch.object(client, "_request", return_value={"ok": True}) as request:
9
+ assert client.shop("api/v1/products") == {"ok": True}
10
+ assert client.cart("cart/v1/items", method="POST", payload={"id": 1}) == {"ok": True}
11
+ assert client.purchase("create", method="POST", payload={"total": 10}) == {"ok": True}
12
+
13
+ assert request.call_count == 3
14
+ assert request.call_args_list[0].args == ("GET", "/shop/api/v1/products", None)
15
+ assert request.call_args_list[1].args == ("POST", "/cart/cart/v1/items", {"id": 1})
16
+ assert request.call_args_list[2].args == ("POST", "/purchase/create", {"total": 10})
17
+
18
+
19
+ def test_api_error_exposes_status_and_payload():
20
+ error = ApiError(401, "Unauthorized", {"detail": "invalid token"})
21
+ assert error.status == 401
22
+ assert error.payload["detail"] == "invalid token"