waveium 0.2.2__tar.gz → 0.2.5__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 (64) hide show
  1. {waveium-0.2.2 → waveium-0.2.5}/PKG-INFO +1 -1
  2. {waveium-0.2.2 → waveium-0.2.5}/pyproject.toml +1 -1
  3. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/antenna_patterns.py +43 -0
  4. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/executions.py +1 -1
  5. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/scenes.py +23 -13
  6. {waveium-0.2.2 → waveium-0.2.5}/.gitignore +0 -0
  7. {waveium-0.2.2 → waveium-0.2.5}/.python-version +0 -0
  8. {waveium-0.2.2 → waveium-0.2.5}/LICENSE +0 -0
  9. {waveium-0.2.2 → waveium-0.2.5}/README.md +0 -0
  10. {waveium-0.2.2 → waveium-0.2.5}/examples/.env.example +0 -0
  11. {waveium-0.2.2 → waveium-0.2.5}/examples/async_streaming_usage.py +0 -0
  12. {waveium-0.2.2 → waveium-0.2.5}/examples/async_usage.py +0 -0
  13. {waveium-0.2.2 → waveium-0.2.5}/examples/basic_usage.py +0 -0
  14. {waveium-0.2.2 → waveium-0.2.5}/examples/load_and_plot.py +0 -0
  15. {waveium-0.2.2 → waveium-0.2.5}/examples/openapi.json +0 -0
  16. {waveium-0.2.2 → waveium-0.2.5}/examples/streaming_usage.py +0 -0
  17. {waveium-0.2.2 → waveium-0.2.5}/examples/underground_workflow.py +0 -0
  18. {waveium-0.2.2 → waveium-0.2.5}/examples/underground_workflow_sse.py +0 -0
  19. {waveium-0.2.2 → waveium-0.2.5}/examples/upload_download.py +0 -0
  20. {waveium-0.2.2 → waveium-0.2.5}/examples/verify_sdk.py +0 -0
  21. {waveium-0.2.2 → waveium-0.2.5}/setup.cfg +0 -0
  22. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/__init__.py +0 -0
  23. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/_config.py +0 -0
  24. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/_http.py +0 -0
  25. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/_sse.py +0 -0
  26. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/async_client.py +0 -0
  27. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/client.py +0 -0
  28. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/exceptions.py +0 -0
  29. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/__init__.py +0 -0
  30. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/auth.py +0 -0
  31. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/common.py +0 -0
  32. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/environments.py +0 -0
  33. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/events.py +0 -0
  34. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/executions.py +0 -0
  35. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/files.py +0 -0
  36. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/organizations.py +0 -0
  37. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/post_processing.py +0 -0
  38. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/projects.py +0 -0
  39. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/roles.py +0 -0
  40. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/scenes.py +0 -0
  41. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/shares.py +0 -0
  42. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/teams.py +0 -0
  43. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/models/users.py +0 -0
  44. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/__init__.py +0 -0
  45. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/_base.py +0 -0
  46. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/_file_ops.py +0 -0
  47. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/_share_ops.py +0 -0
  48. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/_stream_ops.py +0 -0
  49. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/_upload_ops.py +0 -0
  50. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/antenna_patterns.py +0 -0
  51. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/auth.py +0 -0
  52. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/environments.py +0 -0
  53. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/organizations.py +0 -0
  54. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/projects.py +0 -0
  55. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/roles.py +0 -0
  56. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/teams.py +0 -0
  57. {waveium-0.2.2 → waveium-0.2.5}/src/waveium/resources/users.py +0 -0
  58. {waveium-0.2.2 → waveium-0.2.5}/tests/__init__.py +0 -0
  59. {waveium-0.2.2 → waveium-0.2.5}/tests/test_events.py +0 -0
  60. {waveium-0.2.2 → waveium-0.2.5}/tests/test_exceptions.py +0 -0
  61. {waveium-0.2.2 → waveium-0.2.5}/tests/test_parse_stations.py +0 -0
  62. {waveium-0.2.2 → waveium-0.2.5}/tests/test_repr.py +0 -0
  63. {waveium-0.2.2 → waveium-0.2.5}/tests/test_sse_connection.py +0 -0
  64. {waveium-0.2.2 → waveium-0.2.5}/tests/test_sse_parser.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: waveium
3
- Version: 0.2.2
3
+ Version: 0.2.5
4
4
  Summary: Official Python SDK for the Waveium API
5
5
  Project-URL: Homepage, https://waveium.io
6
6
  Project-URL: Documentation, https://docs.waveium.io
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "waveium"
7
- version = "0.2.2"
7
+ version = "0.2.5"
8
8
  description = "Official Python SDK for the Waveium API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -5,6 +5,9 @@ from typing import List, Optional
5
5
 
6
6
  from pydantic import BaseModel, Field
7
7
 
8
+ from .common import _tabulate
9
+ from .files import _fmt_size
10
+
8
11
 
9
12
  class CreateAntennaPatternRequest(BaseModel):
10
13
  """Request to upload a new antenna pattern."""
@@ -50,6 +53,16 @@ class AntennaPatternResponse(BaseModel):
50
53
  )
51
54
  created_at: datetime = Field(description="Creation timestamp")
52
55
 
56
+ def __repr__(self) -> str:
57
+ size = _fmt_size(self.file_size_bytes)
58
+ return (
59
+ f"AntennaPatternResponse("
60
+ f"{self.pattern_id}, "
61
+ f"name={self.name!r}, "
62
+ f"source={self.source!r}, "
63
+ f"size={size})"
64
+ )
65
+
53
66
 
54
67
  class AntennaPatternUploadResponse(BaseModel):
55
68
  """Response after requesting an antenna pattern upload."""
@@ -72,3 +85,33 @@ class PaginatedAntennaPatternResponse(BaseModel):
72
85
  total: int = Field(description="Total number of patterns")
73
86
  limit: int = Field(description="Maximum results per page")
74
87
  offset: int = Field(description="Number of results skipped")
88
+
89
+ def __repr__(self) -> str:
90
+ page = (self.offset // self.limit) + 1 if self.limit else 1
91
+ total_pages = (
92
+ (self.total + self.limit - 1) // self.limit if self.limit else 1
93
+ )
94
+ header = (
95
+ f"PaginatedAntennaPatternResponse: "
96
+ f"{self.total} patterns"
97
+ f" (page {page}/{total_pages})"
98
+ )
99
+ if not self.patterns:
100
+ return header
101
+
102
+ rows = []
103
+ for p in self.patterns:
104
+ rows.append(
105
+ (
106
+ p.pattern_id,
107
+ p.source,
108
+ p.name,
109
+ _fmt_size(p.file_size_bytes),
110
+ )
111
+ )
112
+
113
+ table = _tabulate(
114
+ ("ID", "Source", "Name", "Size"),
115
+ rows,
116
+ )
117
+ return f"{header}\n{table}"
@@ -49,7 +49,7 @@ if TYPE_CHECKING:
49
49
  from .._http import AsyncHTTPClient, HTTPClient
50
50
 
51
51
  _BASE = "/v0/executions"
52
- _SSE_PATH = "/v0/executions/{resource_id}"
52
+ _SSE_PATH = "/v0/events/executions/{resource_id}"
53
53
 
54
54
 
55
55
  def _unpack_binary_columns(df: Any) -> Any:
@@ -64,7 +64,7 @@ if TYPE_CHECKING:
64
64
 
65
65
  _BASE = "/v0/scenes"
66
66
  _SSE_PATH = "/v0/events/scenes/{resource_id}"
67
- _EXEC_SSE_PATH = "/v0/executions/{resource_id}"
67
+ _EXEC_SSE_PATH = "/v0/events/executions/{resource_id}"
68
68
 
69
69
 
70
70
  class ScenesResource(BaseResource):
@@ -211,18 +211,16 @@ class ScenesResource(BaseResource):
211
211
  project_id: Optional project ID.
212
212
  stations_file: Optional path to a stations CSV
213
213
  file. When provided, the CSV is parsed locally
214
- and the station positions are sent inline in
215
- the JSON payload (no file upload needed).
214
+ and the station positions are PATCHed into the
215
+ scene after creation (no file upload needed).
216
216
  The CSV must have ``name``, ``x``, ``y``, ``z``
217
217
  columns; ``yaw`` and ``pitch`` are optional.
218
218
 
219
219
  Returns:
220
- Created scene response.
220
+ Created (and optionally patched) scene response.
221
221
  """
222
222
  if isinstance(parameters, dict):
223
223
  parameters = SceneParameters(**parameters)
224
- if stations_file is not None:
225
- parameters.stations = parse_stations_csv(stations_file)
226
224
  request = CreateSceneRequest(
227
225
  environment_id=environment_id,
228
226
  name=name,
@@ -230,12 +228,19 @@ class ScenesResource(BaseResource):
230
228
  description=description,
231
229
  project_id=project_id,
232
230
  )
233
- return self._http.request(
231
+ scene: SceneResponse = self._http.request(
234
232
  "POST",
235
233
  _BASE,
236
234
  json_data=request.model_dump(exclude_none=True),
237
235
  response_model=SceneResponse,
238
236
  )
237
+ if stations_file is not None:
238
+ stations = parse_stations_csv(stations_file)
239
+ scene = self.patch(
240
+ scene.scene_id,
241
+ parameters=SceneParameters(stations=stations),
242
+ )
243
+ return scene
239
244
 
240
245
  def list(
241
246
  self,
@@ -860,18 +865,16 @@ class AsyncScenesResource(AsyncBaseResource):
860
865
  project_id: Optional project ID.
861
866
  stations_file: Optional path to a stations CSV
862
867
  file. When provided, the CSV is parsed locally
863
- and the station positions are sent inline in
864
- the JSON payload (no file upload needed).
868
+ and the station positions are PATCHed into the
869
+ scene after creation (no file upload needed).
865
870
  The CSV must have ``name``, ``x``, ``y``, ``z``
866
871
  columns; ``yaw`` and ``pitch`` are optional.
867
872
 
868
873
  Returns:
869
- Created scene response.
874
+ Created (and optionally patched) scene response.
870
875
  """
871
876
  if isinstance(parameters, dict):
872
877
  parameters = SceneParameters(**parameters)
873
- if stations_file is not None:
874
- parameters.stations = parse_stations_csv(stations_file)
875
878
  request = CreateSceneRequest(
876
879
  environment_id=environment_id,
877
880
  name=name,
@@ -879,12 +882,19 @@ class AsyncScenesResource(AsyncBaseResource):
879
882
  description=description,
880
883
  project_id=project_id,
881
884
  )
882
- return await self._http.request(
885
+ scene: SceneResponse = await self._http.request(
883
886
  "POST",
884
887
  _BASE,
885
888
  json_data=request.model_dump(exclude_none=True),
886
889
  response_model=SceneResponse,
887
890
  )
891
+ if stations_file is not None:
892
+ stations = parse_stations_csv(stations_file)
893
+ scene = await self.patch(
894
+ scene.scene_id,
895
+ parameters=SceneParameters(stations=stations),
896
+ )
897
+ return scene
888
898
 
889
899
  async def list(
890
900
  self,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes