lange-python 0.3.26__tar.gz → 0.3.28__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 (31) hide show
  1. {lange_python-0.3.26 → lange_python-0.3.28}/PKG-INFO +1 -1
  2. {lange_python-0.3.26 → lange_python-0.3.28}/lange/distribution/_client.py +50 -2
  3. {lange_python-0.3.26 → lange_python-0.3.28}/pyproject.toml +1 -1
  4. {lange_python-0.3.26 → lange_python-0.3.28}/README.md +0 -0
  5. {lange_python-0.3.26 → lange_python-0.3.28}/lange/__init__.py +0 -0
  6. {lange_python-0.3.26 → lange_python-0.3.28}/lange/__main__.py +0 -0
  7. {lange_python-0.3.26 → lange_python-0.3.28}/lange/_util/__init__.py +0 -0
  8. {lange_python-0.3.26 → lange_python-0.3.28}/lange/_util/_base_client.py +0 -0
  9. {lange_python-0.3.26 → lange_python-0.3.28}/lange/_util/_key_handling.py +0 -0
  10. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/__init__.py +0 -0
  11. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/build/__init__.py +0 -0
  12. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/build/_command.py +0 -0
  13. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/build/_discovery.py +0 -0
  14. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/build/_docker.py +0 -0
  15. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/build/_poetry.py +0 -0
  16. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/build/_types.py +0 -0
  17. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/code/__init__.py +0 -0
  18. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/code/_stats.py +0 -0
  19. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/code/audit/__init__.py +0 -0
  20. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/code/audit/_command.py +0 -0
  21. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/code/audit/_discovery.py +0 -0
  22. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/code/audit/_runner.py +0 -0
  23. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/code/audit/_types.py +0 -0
  24. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/distribution/__init__.py +0 -0
  25. {lange_python-0.3.26 → lange_python-0.3.28}/lange/cli/distribution/_command.py +0 -0
  26. {lange_python-0.3.26 → lange_python-0.3.28}/lange/distribution/__init__.py +0 -0
  27. {lange_python-0.3.26 → lange_python-0.3.28}/lange/distribution/_update_macos.py +0 -0
  28. {lange_python-0.3.26 → lange_python-0.3.28}/lange/distribution/_util.py +0 -0
  29. {lange_python-0.3.26 → lange_python-0.3.28}/lange/tunnel/__init__.py +0 -0
  30. {lange_python-0.3.26 → lange_python-0.3.28}/lange/tunnel/_client.py +0 -0
  31. {lange_python-0.3.26 → lange_python-0.3.28}/lange/tunnel/_util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lange-python
3
- Version: 0.3.26
3
+ Version: 0.3.28
4
4
  Summary: A bundeld set of tools, clients for the lange-suite of tools and more.
5
5
  Author: contact@robertlange.me
6
6
  Requires-Python: >=3.10
@@ -6,6 +6,8 @@ import mimetypes
6
6
  import shutil
7
7
  from pathlib import Path
8
8
  from typing import Any
9
+ from urllib.parse import quote
10
+ from uuid import UUID
9
11
 
10
12
  import httpx
11
13
 
@@ -64,6 +66,9 @@ class DistributionClient(BaseLangeLabsClient):
64
66
  raise ValueError("check your distribution name again. spaces are not allowed by design")
65
67
 
66
68
  self.distribution_name = normalized_distribution_name
69
+ self.distribution_id: UUID | None = None
70
+ if self.api_key is not None:
71
+ self.distribution_id = self._resolve_distribution_id()
67
72
  self._refresh_capabilities()
68
73
 
69
74
  @property
@@ -109,6 +114,9 @@ class DistributionClient(BaseLangeLabsClient):
109
114
  """
110
115
  super().reload(api_key=api_key)
111
116
  self._last_error = None
117
+ self.distribution_id = (
118
+ self._resolve_distribution_id() if self.api_key is not None else None
119
+ )
112
120
 
113
121
  if self.api_key is None:
114
122
  self._last_update_result = None
@@ -210,13 +218,52 @@ class DistributionClient(BaseLangeLabsClient):
210
218
  f"/versions/{version}/artifacts/{os_name}/download"
211
219
  )
212
220
 
221
+ def _build_distribution_name_url(self) -> str:
222
+ """
223
+ Build the authenticated distribution lookup endpoint URL.
224
+
225
+ :returns: Fully qualified distribution name lookup URL.
226
+ """
227
+ encoded_name = quote(self.distribution_name, safe="")
228
+ return f"{self.host}/api/v1/distributions/names/{encoded_name}"
229
+
213
230
  def _build_versions_url(self) -> str:
214
231
  """
215
232
  Build the authenticated distribution versions endpoint URL.
216
233
 
217
234
  :returns: Fully qualified versions collection URL.
235
+ :raises ValueError: If the authenticated distribution has not been resolved.
218
236
  """
219
- return f"{self.host}/api/v1/distributions/{self.distribution_name}/versions"
237
+ if self.distribution_id is None:
238
+ raise ValueError("Distribution id is required for this operation.")
239
+
240
+ return f"{self.host}/api/v1/distributions/{self.distribution_id}/versions"
241
+
242
+ def _resolve_distribution_id(self) -> UUID:
243
+ """
244
+ Resolve the configured distribution name into its authenticated distribution id.
245
+
246
+ :returns: Distribution UUID returned by the API service.
247
+ :raises httpx.HTTPError: If the lookup request fails.
248
+ :raises ValueError: If the response does not include a valid distribution id.
249
+ """
250
+ client = httpx.Client(timeout=self.timeout)
251
+
252
+ try:
253
+ response = client.get(
254
+ self._build_distribution_name_url(),
255
+ headers=self._build_connection_headers(),
256
+ )
257
+ response.raise_for_status()
258
+ payload = response.json()
259
+ finally:
260
+ client.close()
261
+
262
+ distribution_id = str(payload.get("id", "")).strip()
263
+ if not distribution_id:
264
+ raise ValueError("Distribution lookup response did not include an id.")
265
+
266
+ return UUID(distribution_id)
220
267
 
221
268
  def _get_newest_version_artifact(self, os_name: str) -> tuple[str, dict[str, Any]] | None:
222
269
  """
@@ -499,6 +546,7 @@ class DistributionClient(BaseLangeLabsClient):
499
546
  if not artifact_path.is_file():
500
547
  raise ValueError("Artifact path must point to a file.")
501
548
 
549
+ headers = self._build_connection_headers()
502
550
  content_type = mimetypes.guess_type(artifact_path.name)[0] or "application/octet-stream"
503
551
  file_field_name = f"{normalized_os_name}File"
504
552
 
@@ -508,7 +556,7 @@ class DistributionClient(BaseLangeLabsClient):
508
556
  with artifact_path.open("rb") as artifact_file:
509
557
  response = client.post(
510
558
  self._build_versions_url(),
511
- headers=self._build_connection_headers(),
559
+ headers=headers,
512
560
  data={"version": normalized_version_name},
513
561
  files={
514
562
  file_field_name: (
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lange-python"
3
- version = "0.3.26"
3
+ version = "0.3.28"
4
4
  description = "A bundeld set of tools, clients for the lange-suite of tools and more."
5
5
  authors = [
6
6
  {name = "contact@robertlange.me"}
File without changes