kleinkram 0.51.0.dev20251003120233__py3-none-any.whl → 0.51.0.dev20251010055743__py3-none-any.whl

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.

Potentially problematic release.


This version of kleinkram might be problematic. Click here for more details.

kleinkram/api/deser.py CHANGED
@@ -4,17 +4,18 @@ from datetime import datetime
4
4
  from enum import Enum
5
5
  from typing import Any
6
6
  from typing import Dict
7
+ from typing import List
7
8
  from typing import Literal
8
9
  from typing import NewType
9
10
  from typing import Tuple
10
- from typing import List
11
11
  from uuid import UUID
12
12
 
13
13
  import dateutil.parser
14
14
 
15
15
  from kleinkram.errors import ParsingError
16
- from kleinkram.models import File, MetadataValue
16
+ from kleinkram.models import File
17
17
  from kleinkram.models import FileState
18
+ from kleinkram.models import MetadataValue
18
19
  from kleinkram.models import Mission
19
20
  from kleinkram.models import Project
20
21
 
@@ -85,16 +86,22 @@ def _parse_file_state(state: str) -> FileState:
85
86
  except ValueError as e:
86
87
  raise ParsingError(f"error parsing file state: {state}") from e
87
88
 
89
+
88
90
  def _parse_metadata(tags: List[Dict]) -> Dict[str, MetadataValue]:
89
91
  result = {}
90
92
  try:
91
93
  for tag in tags:
92
- entry = {tag.get("name"): MetadataValue(tag.get("valueAsString"), tag.get("datatype"))}
94
+ entry = {
95
+ tag.get("name"): MetadataValue(
96
+ tag.get("valueAsString"), tag.get("datatype")
97
+ )
98
+ }
93
99
  result.update(entry)
94
100
  return result
95
101
  except ValueError as e:
96
102
  raise ParsingError(f"error parsing metadata: {e}") from e
97
103
 
104
+
98
105
  def _parse_required_tags(tags: List[Dict]) -> list[str]:
99
106
  return list(_parse_metadata(tags).keys())
100
107
 
@@ -106,7 +113,9 @@ def _parse_project(project_object: ProjectObject) -> Project:
106
113
  description = project_object[ProjectObjectKeys.DESCRIPTION]
107
114
  created_at = _parse_datetime(project_object[ProjectObjectKeys.CREATED_AT])
108
115
  updated_at = _parse_datetime(project_object[ProjectObjectKeys.UPDATED_AT])
109
- required_tags = _parse_required_tags(project_object[ProjectObjectKeys.REQUIRED_TAGS])
116
+ required_tags = _parse_required_tags(
117
+ project_object[ProjectObjectKeys.REQUIRED_TAGS]
118
+ )
110
119
  except Exception as e:
111
120
  raise ParsingError(f"error parsing project: {project_object}") from e
112
121
  return Project(
@@ -17,6 +17,7 @@ DataPage = Dict[str, Any]
17
17
  PAGE_SIZE = 128
18
18
  SKIP = "skip"
19
19
  TAKE = "take"
20
+ EXACT_MATCH = "exactMatch"
20
21
 
21
22
 
22
23
  def paginated_request(
@@ -25,6 +26,7 @@ def paginated_request(
25
26
  params: Optional[Mapping[str, Any]] = None,
26
27
  max_entries: Optional[int] = None,
27
28
  page_size: int = PAGE_SIZE,
29
+ exact_match: bool = False,
28
30
  ) -> Generator[DataPage, None, None]:
29
31
  total_entries_count = 0
30
32
 
@@ -32,6 +34,7 @@ def paginated_request(
32
34
 
33
35
  params[TAKE] = page_size
34
36
  params[SKIP] = 0
37
+ params[EXACT_MATCH] = str(exact_match).lower() # pass string rather than bool
35
38
 
36
39
  while True:
37
40
  resp = client.get(endpoint, params=params)
kleinkram/api/routes.py CHANGED
@@ -40,13 +40,14 @@ from kleinkram.errors import InvalidMissionQuery
40
40
  from kleinkram.errors import InvalidProjectQuery
41
41
  from kleinkram.errors import MissionExists
42
42
  from kleinkram.errors import MissionNotFound
43
+ from kleinkram.errors import MissionValidationError
43
44
  from kleinkram.errors import ProjectExists
44
45
  from kleinkram.errors import ProjectNotFound
45
- from kleinkram.errors import MissionValidationError
46
46
  from kleinkram.models import File
47
47
  from kleinkram.models import Mission
48
48
  from kleinkram.models import Project
49
- from kleinkram.utils import is_valid_uuid4, split_args
49
+ from kleinkram.utils import is_valid_uuid4
50
+ from kleinkram.utils import split_args
50
51
 
51
52
  __all__ = [
52
53
  "_get_api_version",
@@ -162,15 +163,22 @@ def get_projects(
162
163
  client: AuthenticatedClient,
163
164
  project_query: ProjectQuery,
164
165
  max_entries: Optional[int] = None,
166
+ exact_match: bool = False,
165
167
  ) -> Generator[Project, None, None]:
166
168
  params = _project_query_to_params(project_query)
167
169
  response_stream = paginated_request(
168
- client, PROJECT_ENDPOINT, params=params, max_entries=max_entries
170
+ client,
171
+ PROJECT_ENDPOINT,
172
+ params=params,
173
+ max_entries=max_entries,
174
+ exact_match=exact_match,
169
175
  )
170
176
  yield from map(lambda p: _parse_project(ProjectObject(p)), response_stream)
171
177
 
172
178
 
173
- def get_project(client: AuthenticatedClient, query: ProjectQuery) -> Project:
179
+ def get_project(
180
+ client: AuthenticatedClient, query: ProjectQuery, exact_match: bool = False
181
+ ) -> Project:
174
182
  """\
175
183
  get a unique project by specifying a project spec
176
184
  """
@@ -179,7 +187,7 @@ def get_project(client: AuthenticatedClient, query: ProjectQuery) -> Project:
179
187
  f"Project query does not uniquely determine project: {query}"
180
188
  )
181
189
  try:
182
- return next(get_projects(client, query))
190
+ return next(get_projects(client, query, exact_match=exact_match))
183
191
  except StopIteration:
184
192
  raise ProjectNotFound(f"Project not found: {query}")
185
193
 
@@ -224,7 +232,7 @@ def _mission_name_is_available(
224
232
 
225
233
 
226
234
  def _validate_mission_name(
227
- client: AuthenticatedClient, project_id: UUID, mission_name: str
235
+ client: AuthenticatedClient, project_id: UUID, mission_name: str
228
236
  ) -> None:
229
237
  if not _mission_name_is_available(client, mission_name, project_id):
230
238
  raise MissionExists(
@@ -241,7 +249,7 @@ def _validate_mission_name(
241
249
  if mission_name.endswith(" "):
242
250
  raise ValueError(
243
251
  "A mission name cannot end with a whitespace. "
244
- f"The given mission name was \'{mission_name}\'"
252
+ f"The given mission name was '{mission_name}'"
245
253
  )
246
254
 
247
255
 
@@ -253,7 +261,10 @@ def _project_name_is_available(client: AuthenticatedClient, project_name: str) -
253
261
  return True
254
262
  return False
255
263
 
256
- def _validate_mission_created(client: AuthenticatedClient, project_id: str, mission_name: str) -> None:
264
+
265
+ def _validate_mission_created(
266
+ client: AuthenticatedClient, project_id: str, mission_name: str
267
+ ) -> None:
257
268
  """
258
269
  validate that a mission is successfully created
259
270
  """
@@ -350,20 +361,20 @@ def _create_project(
350
361
  return UUID(resp.json()["uuid"], version=4)
351
362
 
352
363
 
353
- def _validate_tag_value(
354
- tag_value, tag_datatype
355
- ) -> None:
364
+ def _validate_tag_value(tag_value, tag_datatype) -> None:
356
365
  if tag_datatype == "NUMBER":
357
366
  try:
358
367
  float(tag_value)
359
- except:
368
+ except ValueError:
360
369
  raise InvalidMissionMetadata(f"Value '{tag_value}' is not a valid NUMBER")
361
370
  elif tag_datatype == "BOOLEAN":
362
371
  if tag_value.lower() not in {"true", "false"}:
363
- raise InvalidMissionMetadata(f"Value '{tag_value}' is not a valid BOOLEAN (expected 'true' or 'false')")
372
+ raise InvalidMissionMetadata(
373
+ f"Value '{tag_value}' is not a valid BOOLEAN (expected 'true' or 'false')"
374
+ )
364
375
  else:
365
- pass # any string is fine
366
- #TODO: add check for LOCATION tag datatype
376
+ pass # any string is fine
377
+ # TODO: add check for LOCATION tag datatype
367
378
 
368
379
 
369
380
  def _get_metadata_type_id_by_name(
@@ -376,7 +387,7 @@ def _get_metadata_type_id_by_name(
376
387
 
377
388
  resp.raise_for_status()
378
389
  try:
379
- data = resp.json()['data'][0]
390
+ data = resp.json()["data"][0]
380
391
  except IndexError:
381
392
  return None, None
382
393
 
kleinkram/cli/_project.py CHANGED
@@ -90,7 +90,7 @@ def delete(
90
90
  project_query = ProjectQuery(ids=project_ids, patterns=project_patterns)
91
91
 
92
92
  client = AuthenticatedClient()
93
- project_id = get_project(client=client, query=project_query).id
93
+ project_id = get_project(client=client, query=project_query, exact_match=True).id
94
94
  kleinkram.core.delete_project(client=client, project_id=project_id)
95
95
 
96
96
 
kleinkram/core.py CHANGED
@@ -107,9 +107,7 @@ def upload(
107
107
 
108
108
  if create and mission is None:
109
109
  # check if project exists and get its id at the same time
110
- project = kleinkram.api.routes.get_project(
111
- client, query=query.project_query
112
- )
110
+ project = kleinkram.api.routes.get_project(client, query=query.project_query)
113
111
  project_id = project.id
114
112
  project_required_tags = project.required_tags
115
113
  mission_name = check_mission_query_is_creatable(query)
@@ -284,7 +282,9 @@ def delete_mission(*, client: AuthenticatedClient, mission_id: UUID) -> None:
284
282
 
285
283
  def delete_project(*, client: AuthenticatedClient, project_id: UUID) -> None:
286
284
  pquery = ProjectQuery(ids=[project_id])
287
- _ = kleinkram.api.routes.get_project(client, pquery) # check if project exists
285
+ _ = kleinkram.api.routes.get_project(
286
+ client, pquery, exact_match=True
287
+ ) # check if project exists
288
288
 
289
289
  # delete all missions and files
290
290
  missions = list(
kleinkram/errors.py CHANGED
@@ -45,6 +45,7 @@ class FileNameNotSupported(Exception): ...
45
45
 
46
46
  class InvalidMissionMetadata(Exception): ...
47
47
 
48
+
48
49
  class MissionValidationError(Exception): ...
49
50
 
50
51
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kleinkram
3
- Version: 0.51.0.dev20251003120233
3
+ Version: 0.51.0.dev20251010055743
4
4
  Summary: give me your bags
5
5
  Author: Cyrill Püntener, Dominique Garmier, Johann Schwabe
6
6
  Author-email: pucyril@ethz.ch, dgarmier@ethz.ch, jschwab@ethz.ch
@@ -3,8 +3,8 @@ kleinkram/__main__.py,sha256=B9RiZxfO4jpCmWPUHyKJ7_EoZlEG4sPpH-nz7T_YhhQ,125
3
3
  kleinkram/_version.py,sha256=QYJyRTcqFcJj4qWYpqs7WcoOP6jxDMqyvxLY-cD6KcE,129
4
4
  kleinkram/auth.py,sha256=PdSYZZO8AauNLZbn9PBgPM3o-O_nwoOKTj94EGnPRE8,3003
5
5
  kleinkram/config.py,sha256=nx6uSM5nLP4SKe8b9VAx4KDtCCwtyshXmzbEJcUwpsY,7411
6
- kleinkram/core.py,sha256=rAMHiH9uwaNcAbVo5NVMl40ArC0Jdp3M9aN2aEBMOCg,9750
7
- kleinkram/errors.py,sha256=270MC1V-2DDPpER3Dq2F6_aVGDrv4yaYX-oxsqyE1K0,1011
6
+ kleinkram/core.py,sha256=N91W_IRw7yH9pR-_wAmaVjcGgiz0xF7QwG20863oOiY,9760
7
+ kleinkram/errors.py,sha256=WrEOpSwOUr-_waaQ237E6Gm1P5A2OrI55g6Q6iGgkNk,1012
8
8
  kleinkram/main.py,sha256=BTE0mZN__xd46wBhFi6iBlK9eGGQvJ1LdUMsbnysLi0,172
9
9
  kleinkram/models.py,sha256=0C_TharLDHA4RCe6Plas9N_uO_teN1Z4iP70WljOAfs,1899
10
10
  kleinkram/printing.py,sha256=9o4UQq9MYkGwMIlTchbdMLjUROdJWB100Lq1b3OFfko,12280
@@ -14,18 +14,18 @@ kleinkram/utils.py,sha256=AtaTvEQ0TrGaQtZylwniE9l1u7_IRYigLT2bc_jc-lQ,6790
14
14
  kleinkram/wrappers.py,sha256=ZScoEov5Q6D2rvaJJ8E-4f58P_NGWrGc9mRPYxSqOC0,13127
15
15
  kleinkram/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  kleinkram/api/client.py,sha256=VwuT97_WdbDpcVGwMXB0fRnUoQnUSf7BOP5eXUFokfI,5932
17
- kleinkram/api/deser.py,sha256=ypAxYi6pTxp6PSNsm9i3oaT1kdri9XxEN0_SnSPzbVw,5517
17
+ kleinkram/api/deser.py,sha256=6ar6_WbgvTIkx1rNRzvVP9YNa5BrFD4181q1fml1KwU,5637
18
18
  kleinkram/api/file_transfer.py,sha256=Ija34JXaszZR7_hvb08aVzq-DB2KG3ze-qqb7zjrchQ,19985
19
- kleinkram/api/pagination.py,sha256=P_zPsBKlMWkmAv-YfUNHaGW-XLB_4U8BDMrKyiDFIXk,1370
19
+ kleinkram/api/pagination.py,sha256=VqjIPMzcD2FY3yeBmP76S7vprUGnuFfTLOzbskqnl0U,1511
20
20
  kleinkram/api/query.py,sha256=9Exi4hJR7Ml38_zjAcOvSEoIAxZLlpM6QwwzO9fs5Gk,3293
21
- kleinkram/api/routes.py,sha256=VKxwaESg-HdUP5urqUYMr52VLpPD9EuhHEWK7CR-skw,15052
21
+ kleinkram/api/routes.py,sha256=buWu4BKdAF1Tk3fmT-MiuG_otJ2Sv4lIcEVE9cZ8isg,15264
22
22
  kleinkram/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  kleinkram/cli/_download.py,sha256=e0fDyp_CFOdbKIUGKmtITvAVINa6STYJk5w5QlElXSs,2394
24
24
  kleinkram/cli/_endpoint.py,sha256=oY0p4bnuHLEDJCXtTmir4AHswcKAygZ8I4IWC3RFcKc,1796
25
25
  kleinkram/cli/_file.py,sha256=Q2fLDdUyfHFmdGC6wIxMqgEl0F76qszhzWJrRV5rTBM,2973
26
26
  kleinkram/cli/_list.py,sha256=5gI3aIUeKC0_eWPQqdFXSBBFvpkTTJSm31TamHa197c,3090
27
27
  kleinkram/cli/_mission.py,sha256=3ZMPRlPZIvJwmFQqeXu6N8DcmYtSVGj4xWHuAdKAlsc,5845
28
- kleinkram/cli/_project.py,sha256=N0C96NC_onCEwTteYp2wgkkwkdJt-1q43LFdqNXfjC8,3398
28
+ kleinkram/cli/_project.py,sha256=tvVwcNaBYKZhIh6KjPcdyyTmaep6y-GvG_sV7O49Ov0,3416
29
29
  kleinkram/cli/_upload.py,sha256=8gKg_QIFUJh4Sz06EEX3gQoa3Rl41KTdZWqtsntypJU,3531
30
30
  kleinkram/cli/_verify.py,sha256=n9QThY0JnqaIqw6udYXdRQGcpUl2lIbFXGQIgpTnDPE,2112
31
31
  kleinkram/cli/app.py,sha256=Yetkt2jd6cggor7mPpV9Lcp6aLd45rACdF1nBW0uy9k,7546
@@ -43,8 +43,8 @@ tests/test_printing.py,sha256=kPzpIQOtQJ9yQ32mM8cMGDVOGsbrZZLQhfsXN1Pe68Q,2231
43
43
  tests/test_query.py,sha256=fExmCKXLA7-9j2S2sF_sbvRX_2s6Cp3a7OTcqE25q9g,3864
44
44
  tests/test_utils.py,sha256=eUBYrn3xrcgcaxm1X4fqZaX4tRvkbI6rh6BUbNbu9T0,4784
45
45
  tests/test_wrappers.py,sha256=TbcTyO2L7fslbzgfDdcVZkencxNQ8cGPZm_iB6c9d6Q,2673
46
- kleinkram-0.51.0.dev20251003120233.dist-info/METADATA,sha256=wl07qC6n8Kv_fKqgQ-15o6dI40ydyUOYRK23ZIYRgcc,2846
47
- kleinkram-0.51.0.dev20251003120233.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
48
- kleinkram-0.51.0.dev20251003120233.dist-info/entry_points.txt,sha256=SaB2l5aqhSr8gmaMw2kvQU90a8Bnl7PedU8cWYxkfYo,46
49
- kleinkram-0.51.0.dev20251003120233.dist-info/top_level.txt,sha256=N3-sJagEHu1Tk1X6Dx1X1q0pLDNbDZpLzRxVftvepds,24
50
- kleinkram-0.51.0.dev20251003120233.dist-info/RECORD,,
46
+ kleinkram-0.51.0.dev20251010055743.dist-info/METADATA,sha256=09mxfAwJAQrgmlf7ZKFUMMHvxOrvOL-AzWg5CblTCFE,2846
47
+ kleinkram-0.51.0.dev20251010055743.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
48
+ kleinkram-0.51.0.dev20251010055743.dist-info/entry_points.txt,sha256=SaB2l5aqhSr8gmaMw2kvQU90a8Bnl7PedU8cWYxkfYo,46
49
+ kleinkram-0.51.0.dev20251010055743.dist-info/top_level.txt,sha256=N3-sJagEHu1Tk1X6Dx1X1q0pLDNbDZpLzRxVftvepds,24
50
+ kleinkram-0.51.0.dev20251010055743.dist-info/RECORD,,