UncountablePythonSDK 0.0.52__py3-none-any.whl → 0.0.54__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 UncountablePythonSDK might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: UncountablePythonSDK
3
- Version: 0.0.52
3
+ Version: 0.0.54
4
4
  Summary: Uncountable SDK
5
5
  Project-URL: Homepage, https://github.com/uncountableinc/uncountable-python-sdk
6
6
  Project-URL: Repository, https://github.com/uncountableinc/uncountable-python-sdk.git
@@ -28,7 +28,7 @@ pkgs/argument_parser/case_convert.py,sha256=NuJLJUJRbyVb6_Slen4uqaStEHbcOS1d-hBB
28
28
  pkgs/filesystem_utils/__init__.py,sha256=NSsQrUCoGISBCqCCyq6_583sYHTVEQeDjDO8hvZn3ag,1261
29
29
  pkgs/filesystem_utils/_gdrive_session.py,sha256=OZudNoP2HikolnpurVJhJdh5fgzqbaZQvn53ReGGXx4,11015
30
30
  pkgs/filesystem_utils/_local_session.py,sha256=xFEYhAvNqrOYqwt4jrEYOuYkjJn0zclZhTelW_Q1-rw,2325
31
- pkgs/filesystem_utils/_s3_session.py,sha256=q4q0MTWXWu5RNRVZ5ibv4M4UXXxWl_J6xCnitvngIMM,3957
31
+ pkgs/filesystem_utils/_s3_session.py,sha256=UbVTUM5olc2Kq_1TX7e5rI3UD5w49ko7CWjsMnSJVmg,3946
32
32
  pkgs/filesystem_utils/_sftp_session.py,sha256=gNoUD_b4MuVqWj31nU-FpfpXZlyWkwdEHtX1S8W6gpQ,4727
33
33
  pkgs/filesystem_utils/file_type_utils.py,sha256=Xd-mg35mAENUgNJVz5uK8nEfrUp-NQld_gnXFEq3K-8,1487
34
34
  pkgs/filesystem_utils/filesystem_session.py,sha256=BQ2Go8Mu9-GcnaWh2Pm4x7ugLVsres6XrOQ8RoiEpcE,1045
@@ -92,8 +92,8 @@ uncountable/integration/executors/executors.py,sha256=v5ClGVUlvrZcMdmGQa8Ll668G_
92
92
  uncountable/integration/executors/generic_upload_executor.py,sha256=wafNY_gpbUiQhvkFPDw-GGiJLmDVtTRgH_5jwMLy2Z4,10283
93
93
  uncountable/integration/executors/script_executor.py,sha256=OmSBOtU48G3mqza9c2lCm84pGGyaDk-ZBJCx3RsdJXc,846
94
94
  uncountable/integration/secret_retrieval/__init__.py,sha256=3QXVj35w8rRMxVvmmsViFYDi3lcb3g70incfalOEm6o,87
95
- uncountable/integration/secret_retrieval/retrieve_secret.py,sha256=iDqLbYKKLv8Wl5hNSKl7b4hKJnDshFe6tgdAJmQgQyA,2205
96
- uncountable/types/__init__.py,sha256=95iOd3WXWoI_4a461IS2ieWRic3zRyNaCYzfTpX764o,8162
95
+ uncountable/integration/secret_retrieval/retrieve_secret.py,sha256=BS1dXVaChgpgBDKWkcLrl9hBDQIASRQMr3l41ytfbEc,3036
96
+ uncountable/types/__init__.py,sha256=UuLBpo8Uxv9k-UZS8DINg3y-LPrs2dC7Qg83BB8p2_k,8222
97
97
  uncountable/types/async_batch.py,sha256=ihCv5XWSTTPmuO-GMPn1EACGI2CBUIJTATZ3aPgsNBA,523
98
98
  uncountable/types/async_batch_processor.py,sha256=R--exgi4Gw0HWCnh8M-3_2PqG2ByTBtdyuSQ2eYtYn8,8671
99
99
  uncountable/types/async_batch_t.py,sha256=9jp9rOyetRdD5aQVyijzQggTyYU4021PBVGXk0ooBCQ,1911
@@ -130,6 +130,8 @@ uncountable/types/job_definition.py,sha256=Cgwop6iNcWEsEpfjMl1EtkRES_3-SVzpMe-w7
130
130
  uncountable/types/job_definition_t.py,sha256=pL-0YVyR0oz6-5wWXJsX1UyYo4R_FPwhOYFj9iMKgvo,7170
131
131
  uncountable/types/outputs.py,sha256=sUZx_X-TKCZtLm1YCEH8OISX9DdPlv9ZuUfM3-askCc,281
132
132
  uncountable/types/outputs_t.py,sha256=2aORUOr0ls1ZYo-ddkWax3D1ZndmQsWtHfJxpYozlhg,656
133
+ uncountable/types/overrides.py,sha256=Mv-smwK1B3pvbt48fNOiqkeQn9wMgYlBFJKUBOJqceE,431
134
+ uncountable/types/overrides_t.py,sha256=-DMuW3Iqxlf7pb3HmPN8cswYrhG9UrRstRUzM9wDVHo,960
133
135
  uncountable/types/permissions.py,sha256=1mRnSsmRgjuLgp6pylTwwACD_YRIcmlqxHkufwZtMns,297
134
136
  uncountable/types/permissions_t.py,sha256=i0vFwVvmmnInrA5qW8uuo0_tM6KYn3VYZ75d9084Vko,1625
135
137
  uncountable/types/phases.py,sha256=YCsU77DdjRJJWdLTwLuOZNG4e9ML82NIBI1xTWr3ggA,266
@@ -155,7 +157,7 @@ uncountable/types/recipes_t.py,sha256=04dh2wn_lIWB3KF36sxcdJxb_JDclkHp5g3AHbfoc-
155
157
  uncountable/types/response.py,sha256=WOlSgQYKK_fnnXk1i-h3Bwx2ZiYqpLj-lnt-hXhmbWs,274
156
158
  uncountable/types/response_t.py,sha256=jjTyB0bM-xEz7WjqPb6GUIkMgUvqXvM9trMdKdIcAZw,622
157
159
  uncountable/types/secret_retrieval.py,sha256=Jt_-sjYBKBwJytS4QgF1KnUVEEu9YAsCYI3NtYlbqa4,592
158
- uncountable/types/secret_retrieval_t.py,sha256=UQjkNUKMDMRG-44vXE28MxcD5HjHWQD9LTRMmMVx1EI,1864
160
+ uncountable/types/secret_retrieval_t.py,sha256=i9Aq1HoNvARYVgKmSjTjECUYp1AZtW4052hYJi9Jngo,1930
159
161
  uncountable/types/units.py,sha256=R_TBhxWCIWSSXK9J3S0Omtj3t5BZNK9C80MyqFjMO7k,275
160
162
  uncountable/types/units_t.py,sha256=w_k7SQ_J_-XTGY-BMcWC5sQi2z3uInqtrRUPHgniuew,559
161
163
  uncountable/types/users.py,sha256=YEk8v0vDOBFvmOQMQw7MAOicSGzMui8Hb9hdFX2Vw3E,275
@@ -240,7 +242,7 @@ uncountable/types/api/triggers/__init__.py,sha256=gCgbynxG3jA8FQHzercKtrHKHkiIKr
240
242
  uncountable/types/api/triggers/run_trigger.py,sha256=_Rpha9nxXI3Xr17CrGDtofg4HZ81x2lt0rMZ6As0qfE,893
241
243
  uncountable/types/api/uploader/__init__.py,sha256=gCgbynxG3jA8FQHzercKtrHKHkiIKr8APdZYUniAor8,55
242
244
  uncountable/types/api/uploader/invoke_uploader.py,sha256=4zOcB_38uT73Jm3-XqkG40fBM1R5vpvPpGAg-U4lzxY,1059
243
- UncountablePythonSDK-0.0.52.dist-info/METADATA,sha256=OUWoU--wdBpw37DliJoAfdWz3iXECZumjR4eK3nxzec,1934
244
- UncountablePythonSDK-0.0.52.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
245
- UncountablePythonSDK-0.0.52.dist-info/top_level.txt,sha256=1UVGjAU-6hJY9qw2iJ7nCBeEwZ793AEN5ZfKX9A1uj4,31
246
- UncountablePythonSDK-0.0.52.dist-info/RECORD,,
245
+ UncountablePythonSDK-0.0.54.dist-info/METADATA,sha256=PzDsbl724f6w2EAH-tAuiai1I0Mn-SDqVt1ux1xSur0,1934
246
+ UncountablePythonSDK-0.0.54.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
247
+ UncountablePythonSDK-0.0.54.dist-info/top_level.txt,sha256=1UVGjAU-6hJY9qw2iJ7nCBeEwZ793AEN5ZfKX9A1uj4,31
248
+ UncountablePythonSDK-0.0.54.dist-info/RECORD,,
@@ -53,16 +53,16 @@ class S3Session(FileSystemSession):
53
53
  recursive: bool = False,
54
54
  valid_extensions: list[str] | None = None,
55
55
  ) -> list[FileSystemObject]:
56
- if recursive:
57
- raise NotImplementedError("recursive file listings not implemented for s3")
58
-
59
56
  if not isinstance(dir_path, FileSystemFileReference):
60
57
  raise IncompatibleFileReference()
61
58
 
62
59
  assert self.bucket is not None, "call to list_files on uninitialized s3 session"
63
60
 
64
61
  filesystem_references: list[FileSystemObject] = []
65
- for obj in self.bucket.objects.filter(Prefix=dir_path.filepath):
62
+ prefix = _add_slash(dir_path.filepath)
63
+ for obj in self.bucket.objects.filter(Prefix=prefix):
64
+ if not recursive and (obj.key == prefix or "/" in obj.key[len(prefix) :]):
65
+ continue
66
66
  if valid_extensions is None or any(
67
67
  obj.key.endswith(valid_extension) for valid_extension in valid_extensions
68
68
  ):
@@ -85,7 +85,7 @@ class S3Session(FileSystemSession):
85
85
  or file_object.filename is None
86
86
  ):
87
87
  raise IncompatibleFileReference()
88
- s3_file_obj = self.bucket.Object(_add_slash(file_object.filepath))
88
+ s3_file_obj = self.bucket.Object(file_object.filepath)
89
89
  response = s3_file_obj.get()
90
90
  file_obj_bytes = response["Body"].read()
91
91
  downloaded_files.append(
@@ -107,10 +107,10 @@ class S3Session(FileSystemSession):
107
107
  dest_file, FileSystemFileReference
108
108
  ):
109
109
  raise IncompatibleFileReference()
110
- self.bucket.Object(_add_slash(dest_file.filepath)).copy_from(
110
+ self.bucket.Object(dest_file.filepath).copy_from(
111
111
  CopySource={
112
112
  "Bucket": self.bucket.name,
113
- "Key": _add_slash(src_file.filepath),
113
+ "Key": src_file.filepath,
114
114
  }
115
115
  )
116
- self.bucket.Object(_add_slash(src_file.filepath)).delete()
116
+ self.bucket.Object(src_file.filepath).delete()
@@ -5,6 +5,8 @@ import os
5
5
 
6
6
  import boto3
7
7
 
8
+ from pkgs.argument_parser import CachedParser
9
+ from uncountable.types import overrides_t
8
10
  from uncountable.types.job_definition_t import ProfileMetadata
9
11
  from uncountable.types.secret_retrieval_t import (
10
12
  SecretRetrieval,
@@ -46,9 +48,31 @@ def _get_aws_secret(*, secret_name: str, region_name: str, sub_key: str | None)
46
48
  return str(value)
47
49
 
48
50
 
51
+ @functools.cache
52
+ def _load_secret_overrides(profile_name: str) -> dict[SecretRetrieval, str]:
53
+ overrides_parser = CachedParser(overrides_t.Overrides)
54
+ profiles_module = os.environ["UNC_PROFILES_MODULE"]
55
+ try:
56
+ overrides = overrides_parser.parse_yaml_resource(
57
+ package=".".join([profiles_module, profile_name]),
58
+ resource="local_overrides.yaml",
59
+ )
60
+ return {
61
+ override.secret_retrieval: override.value for override in overrides.secrets
62
+ }
63
+ except FileNotFoundError:
64
+ return {}
65
+
66
+
49
67
  def retrieve_secret(
50
68
  secret_retrieval: SecretRetrieval, profile_metadata: ProfileMetadata
51
69
  ) -> str:
70
+ value_from_override = _load_secret_overrides(profile_metadata.name).get(
71
+ secret_retrieval
72
+ )
73
+ if value_from_override is not None:
74
+ return value_from_override
75
+
52
76
  match secret_retrieval:
53
77
  case SecretRetrievalEnv():
54
78
  env_name = (
@@ -58,6 +58,7 @@ from .api.entity import lock_entity as lock_entity_t
58
58
  from .api.recipes import lock_recipes as lock_recipes_t
59
59
  from .api.id_source import match_id_source as match_id_source_t
60
60
  from . import outputs_t as outputs_t
61
+ from . import overrides_t as overrides_t
61
62
  from . import permissions_t as permissions_t
62
63
  from . import phases_t as phases_t
63
64
  from . import post_base_t as post_base_t
@@ -154,6 +155,7 @@ __all__: list[str] = [
154
155
  "lock_recipes_t",
155
156
  "match_id_source_t",
156
157
  "outputs_t",
158
+ "overrides_t",
157
159
  "permissions_t",
158
160
  "phases_t",
159
161
  "post_base_t",
@@ -0,0 +1,10 @@
1
+ # flake8: noqa: F821
2
+ # ruff: noqa: E402 Q003
3
+ # fmt: off
4
+ # isort: skip_file
5
+ # DO NOT MODIFY -- This file is generated by type_spec
6
+ # Kept only for SDK backwards compatibility
7
+ from .overrides_t import SecretRetrievalOverride as SecretRetrievalOverride
8
+ from .overrides_t import SecretRetrievalOverrides as SecretRetrievalOverrides
9
+ from .overrides_t import Overrides as Overrides
10
+ # DO NOT MODIFY -- This file is generated by type_spec
@@ -0,0 +1,36 @@
1
+ # DO NOT MODIFY -- This file is generated by type_spec
2
+ # flake8: noqa: F821
3
+ # ruff: noqa: E402 Q003
4
+ # fmt: off
5
+ # isort: skip_file
6
+ from __future__ import annotations
7
+ import typing # noqa: F401
8
+ import datetime # noqa: F401
9
+ from decimal import Decimal # noqa: F401
10
+ import dataclasses
11
+ from . import secret_retrieval_t
12
+
13
+ __all__: list[str] = [
14
+ "Overrides",
15
+ "SecretRetrievalOverride",
16
+ "SecretRetrievalOverrides",
17
+ ]
18
+
19
+
20
+ # DO NOT MODIFY -- This file is generated by type_spec
21
+ @dataclasses.dataclass(kw_only=True)
22
+ class SecretRetrievalOverride:
23
+ profile_name: str
24
+ secret_retrieval: secret_retrieval_t.SecretRetrieval
25
+ value: str
26
+
27
+
28
+ # DO NOT MODIFY -- This file is generated by type_spec
29
+ SecretRetrievalOverrides = list[SecretRetrievalOverride]
30
+
31
+
32
+ # DO NOT MODIFY -- This file is generated by type_spec
33
+ @dataclasses.dataclass(kw_only=True)
34
+ class Overrides:
35
+ secrets: SecretRetrievalOverrides
36
+ # DO NOT MODIFY -- This file is generated by type_spec
@@ -22,7 +22,7 @@ __all__: list[str] = [
22
22
 
23
23
 
24
24
  # DO NOT MODIFY -- This file is generated by type_spec
25
- @dataclasses.dataclass(kw_only=True)
25
+ @dataclasses.dataclass(kw_only=True, frozen=True, eq=True)
26
26
  class SecretRetrievalBase:
27
27
  type: SecretRetrievalType
28
28
 
@@ -37,7 +37,7 @@ class SecretRetrievalType(StrEnum):
37
37
  @serial_class(
38
38
  parse_require={"type"},
39
39
  )
40
- @dataclasses.dataclass(kw_only=True)
40
+ @dataclasses.dataclass(kw_only=True, frozen=True, eq=True)
41
41
  class SecretRetrievalEnv(SecretRetrievalBase):
42
42
  type: typing.Literal[SecretRetrievalType.ENV] = SecretRetrievalType.ENV
43
43
  env_key: str
@@ -47,7 +47,7 @@ class SecretRetrievalEnv(SecretRetrievalBase):
47
47
  @serial_class(
48
48
  parse_require={"type"},
49
49
  )
50
- @dataclasses.dataclass(kw_only=True)
50
+ @dataclasses.dataclass(kw_only=True, frozen=True, eq=True)
51
51
  class SecretRetrievalAWS(SecretRetrievalBase):
52
52
  type: typing.Literal[SecretRetrievalType.AWS] = SecretRetrievalType.AWS
53
53
  secret_name: str