UncountablePythonSDK 0.0.79__py3-none-any.whl → 0.0.81__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.
- {UncountablePythonSDK-0.0.79.dist-info → UncountablePythonSDK-0.0.81.dist-info}/METADATA +1 -1
- {UncountablePythonSDK-0.0.79.dist-info → UncountablePythonSDK-0.0.81.dist-info}/RECORD +14 -13
- examples/integration-server/jobs/materials_auto/example_wh.py +15 -0
- examples/integration-server/jobs/materials_auto/profile.yaml +25 -1
- pkgs/serialization/serial_class.py +4 -0
- pkgs/type_spec/parts/base.py.prepart +2 -2
- uncountable/integration/executors/executors.py +82 -1
- uncountable/integration/queue_runner/job_scheduler.py +41 -9
- uncountable/integration/queue_runner/worker.py +3 -0
- uncountable/types/base_t.py +2 -2
- uncountable/types/entity_t.py +4 -0
- uncountable/types/job_definition_t.py +2 -2
- {UncountablePythonSDK-0.0.79.dist-info → UncountablePythonSDK-0.0.81.dist-info}/WHEEL +0 -0
- {UncountablePythonSDK-0.0.79.dist-info → UncountablePythonSDK-0.0.81.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: UncountablePythonSDK
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.81
|
|
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
|
|
@@ -23,7 +23,8 @@ examples/set_recipe_output_file_sdk.py,sha256=Lz1amqppnWTX83z-C090wCJ4hcKmCD3kb-
|
|
|
23
23
|
examples/upload_files.py,sha256=tUfKFqiqwnw08OL5Y8_e4j5pSRhp94cFex8XTuVa_ig,487
|
|
24
24
|
examples/integration-server/pyproject.toml,sha256=mB0uj-_Wo8WRmhdMwOwcdOB5lAhiW_8Kf-epMFrOq34,9133
|
|
25
25
|
examples/integration-server/jobs/materials_auto/example_cron.py,sha256=7VVQ-UJsq3DbGpN3XPnorRVZYo-vCwbfSU3VVDluIzA,699
|
|
26
|
-
examples/integration-server/jobs/materials_auto/
|
|
26
|
+
examples/integration-server/jobs/materials_auto/example_wh.py,sha256=Hx5nonavOh2L3JykDpI5bPqPu8L1wwhwekTUfTRgq9g,479
|
|
27
|
+
examples/integration-server/jobs/materials_auto/profile.yaml,sha256=XlOXSRplMJ13T6900pv1wDKxeE9V1hZZTMuvup1MiBM,896
|
|
27
28
|
pkgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
29
|
pkgs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
30
|
pkgs/argument_parser/__init__.py,sha256=JRfZkC0-q6axr8F5_TKrjSprJ7d7chfcPvf-iMQqFg0,447
|
|
@@ -41,7 +42,7 @@ pkgs/filesystem_utils/filesystem_session.py,sha256=BQ2Go8Mu9-GcnaWh2Pm4x7ugLVsre
|
|
|
41
42
|
pkgs/serialization/__init__.py,sha256=LifasRW0a50A3qRFmo2bf3FQ6TXhZWOTz2-CVTgPjcQ,753
|
|
42
43
|
pkgs/serialization/missing_sentry.py,sha256=aM_9KxbCk9dVvXvcOKgkIQBqFWvLhv8QlIUCiuFEXMo,806
|
|
43
44
|
pkgs/serialization/opaque_key.py,sha256=FIfXEE0DA1U8R_taFbQ1RCoTSgehrPjP06-qvo-GeNQ,177
|
|
44
|
-
pkgs/serialization/serial_class.py,sha256=
|
|
45
|
+
pkgs/serialization/serial_class.py,sha256=anGUNEArLXjiEX3GoMNk7tn15LQWANXjxNrb5DqNK18,6252
|
|
45
46
|
pkgs/serialization/serial_union.py,sha256=xpdeqCrRd0sNCaUwBQRzje6V40ndCbJpZrLX2K0d5xo,2741
|
|
46
47
|
pkgs/serialization/yaml.py,sha256=yoJtu7_ixnJV6uTxA_U1PpK5F_ixT08AKVh5ocyYwXM,1466
|
|
47
48
|
pkgs/serialization_util/__init__.py,sha256=MVKqHTUl2YnWZAFG9xCxu1SgmkQ5xPofrAGlYg6h7rI,330
|
|
@@ -67,7 +68,7 @@ pkgs/type_spec/util.py,sha256=79SLJsSPVnBe2_3CTF6J-7-QD9nRr6o8MKvfjyx53eI,4864
|
|
|
67
68
|
pkgs/type_spec/actions_registry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
68
69
|
pkgs/type_spec/actions_registry/__main__.py,sha256=JGwKxcAmrQdbpVR2vwknoimN1Q-r5h4SADw1cYLYzgk,4331
|
|
69
70
|
pkgs/type_spec/actions_registry/emit_typescript.py,sha256=Z1ZM4zOw26tvLspvW6Emg79-jxjhNBse-8yaionbmeo,6066
|
|
70
|
-
pkgs/type_spec/parts/base.py.prepart,sha256=
|
|
71
|
+
pkgs/type_spec/parts/base.py.prepart,sha256=St6P21VP8Um_nagZFuSyNzYiKDSrsK3TNOuGY_1O8cg,2186
|
|
71
72
|
pkgs/type_spec/parts/base.ts.prepart,sha256=2FJJvpg2olCcavxj0nbYWdwKl6KeScour2JjSvN42l8,1001
|
|
72
73
|
pkgs/type_spec/type_info/__main__.py,sha256=pmVjVqXyVh8vKTNCTFgz80Sg74C5BKToP3E6GS-X_So,857
|
|
73
74
|
pkgs/type_spec/type_info/emit_type_info.py,sha256=EzX0ONjrLtQFlN5cEAaw2RPVyadmgmZazOfqHUbL_PI,13362
|
|
@@ -98,14 +99,14 @@ uncountable/integration/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
|
98
99
|
uncountable/integration/db/connect.py,sha256=mE3bdV0huclH2iT_dXCQdRL4LkjIuf_myAR64RTWXEs,498
|
|
99
100
|
uncountable/integration/db/session.py,sha256=96cGQXpe6IugBTdSsjdP0S5yhJ6toSmbVB6qhc3FJzE,693
|
|
100
101
|
uncountable/integration/executors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
101
|
-
uncountable/integration/executors/executors.py,sha256=
|
|
102
|
+
uncountable/integration/executors/executors.py,sha256=2OXFUJiG6hlkIB2NUZldobiBk9xSWuk7evvr5wlesG4,5119
|
|
102
103
|
uncountable/integration/executors/generic_upload_executor.py,sha256=0vs9NVk1UL2FBhiMCH6o8p4KtVXNFNvv861QCOD3UU4,10375
|
|
103
104
|
uncountable/integration/executors/script_executor.py,sha256=BBQ9f0l7uH2hgKf60jtm-pONzwk-EeOhM2qBAbv_URo,846
|
|
104
105
|
uncountable/integration/queue_runner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
105
|
-
uncountable/integration/queue_runner/job_scheduler.py,sha256=
|
|
106
|
+
uncountable/integration/queue_runner/job_scheduler.py,sha256=lhvcl11jyk_wg9BSc1Xyh5u8iEtsdqQFW83FPLupjQI,6189
|
|
106
107
|
uncountable/integration/queue_runner/queue_runner.py,sha256=0BmYu5zHdothTevGsB-nXg6MBd1UD-WkP3h1WCKMdQg,710
|
|
107
108
|
uncountable/integration/queue_runner/types.py,sha256=8qTq29BTSa5rmW6CBlBntP0pNIiDcwu1wHa78pjroS0,219
|
|
108
|
-
uncountable/integration/queue_runner/worker.py,sha256=
|
|
109
|
+
uncountable/integration/queue_runner/worker.py,sha256=EMDtdObowaq0aHndH1bBmlSIOih0jF3Gcn7Yl6NNeOM,4265
|
|
109
110
|
uncountable/integration/queue_runner/command_server/__init__.py,sha256=gQPVILGpWzCr2i5GJyoqna7AOSFvtn4tav69gB78mTQ,571
|
|
110
111
|
uncountable/integration/queue_runner/command_server/command_client.py,sha256=DJb0TUVFkiiLBEQzHSN94sTRnuEbutNEgdN39XmnOXI,2046
|
|
111
112
|
uncountable/integration/queue_runner/command_server/command_server.py,sha256=yyXryhiEC2eGS0yFElLGsVzSKwOuYvj-zp22jQorkv0,2138
|
|
@@ -131,7 +132,7 @@ uncountable/types/async_jobs_t.py,sha256=sEh1Ev46ff4n1v8mMV3rEbH3MGmaXnLuvYf0UhD
|
|
|
131
132
|
uncountable/types/auth_retrieval.py,sha256=FY8Vr_BWD4O8PsauPNt_7_08YZSHFaUlTT72L5XJ-4o,570
|
|
132
133
|
uncountable/types/auth_retrieval_t.py,sha256=D2ptCIsuCecJa_P8K2qrNk2-zz1WuBpOrsZ65BRP-Dw,2221
|
|
133
134
|
uncountable/types/base.py,sha256=xVSjWvA_fUUnkCg83EjoYEFvAfmskinKFMeYFOxNc9E,359
|
|
134
|
-
uncountable/types/base_t.py,sha256=
|
|
135
|
+
uncountable/types/base_t.py,sha256=ThxlCKyUBEj7sCRmfvWm2w4b6IDVvUkbAIISNxWTFxE,2726
|
|
135
136
|
uncountable/types/calculations.py,sha256=FFO_D3BbKoGDZnqWvTKpW4KF359i2vrKjpdFCLYzJC0,284
|
|
136
137
|
uncountable/types/calculations_t.py,sha256=157qD0VqijD5kNDF5BRsfGli3WaPGnNjoo2o2CPX-Ik,669
|
|
137
138
|
uncountable/types/chemical_structure.py,sha256=E-LnikTFDoVQ1b2zKaVUIO_PAKm-7aZZYJi8I8SDSic,302
|
|
@@ -142,7 +143,7 @@ uncountable/types/client_config_t.py,sha256=6dStfR0IEHiPW8f9_aF3DD_tHmXXw2rEVrgp
|
|
|
142
143
|
uncountable/types/curves.py,sha256=W6uMpG5SyW1MS82szNpxkFEn1MnxNpBFyFbQb2Ysfng,366
|
|
143
144
|
uncountable/types/curves_t.py,sha256=lKhRM-2cZ_sFaW7pa_I_Ipz_pJhm3_yTFehRXI79pKk,1416
|
|
144
145
|
uncountable/types/entity.py,sha256=ECvhswTj9xp4gUEKTZoZYyxHvx1oyvE5FNiGNfSyUgk,528
|
|
145
|
-
uncountable/types/entity_t.py,sha256=
|
|
146
|
+
uncountable/types/entity_t.py,sha256=_a7maOh51nJPigkfdDipJ0XB9h8G4N6-VAWIQHNbh3o,16491
|
|
146
147
|
uncountable/types/experiment_groups.py,sha256=_0OXcPzSAbkE-rfKt5tPx178YJ4pcEKZvrCxUHgDnvw,309
|
|
147
148
|
uncountable/types/experiment_groups_t.py,sha256=qEs8YW0eJOJ_sCOObT5v9QRx9wsjLYpJqJhCJXa-vNA,721
|
|
148
149
|
uncountable/types/field_values.py,sha256=uuIWX-xmfvcinYPdfkWJeb56zzQY01mc9rmotMPMh24,503
|
|
@@ -162,7 +163,7 @@ uncountable/types/inputs_t.py,sha256=CpuuKRduZGET_wvkGUpUFN6rbZCHsdOIp1veEM-hspI
|
|
|
162
163
|
uncountable/types/integration_server.py,sha256=61NuGs1pbgovU5Vuje7oN9HpLwOGCCw9Q_CcUvt_0qI,385
|
|
163
164
|
uncountable/types/integration_server_t.py,sha256=wa45RWChRsj2oAvWcOfZXA2xZxyEEkzltuJqZwKTna8,1048
|
|
164
165
|
uncountable/types/job_definition.py,sha256=DEma_s-0oBo2tPI5u9IU_UDw-9MWbn4mTZsd_RHiYGE,1667
|
|
165
|
-
uncountable/types/job_definition_t.py,sha256=
|
|
166
|
+
uncountable/types/job_definition_t.py,sha256=whsat5825Jou1-67dbOkqiibpoavGcsaOhJ3APTUh2Q,7948
|
|
166
167
|
uncountable/types/outputs.py,sha256=sUZx_X-TKCZtLm1YCEH8OISX9DdPlv9ZuUfM3-askCc,281
|
|
167
168
|
uncountable/types/outputs_t.py,sha256=AdJZvIzqikHV9CnlC24WEo0OUe-5vrD4cjMqc2txEs0,765
|
|
168
169
|
uncountable/types/overrides.py,sha256=Mv-smwK1B3pvbt48fNOiqkeQn9wMgYlBFJKUBOJqceE,431
|
|
@@ -285,7 +286,7 @@ uncountable/types/api/triggers/__init__.py,sha256=gCgbynxG3jA8FQHzercKtrHKHkiIKr
|
|
|
285
286
|
uncountable/types/api/triggers/run_trigger.py,sha256=-oZgPyn43xEKSCs81DVNzwaYMCdRJxbM9GY6fsqKwf4,1090
|
|
286
287
|
uncountable/types/api/uploader/__init__.py,sha256=gCgbynxG3jA8FQHzercKtrHKHkiIKr8APdZYUniAor8,55
|
|
287
288
|
uncountable/types/api/uploader/invoke_uploader.py,sha256=6mwVG136oLp9JcbB2I-kZnrcm3aeZzYZB-SFjEImY2o,1314
|
|
288
|
-
UncountablePythonSDK-0.0.
|
|
289
|
-
UncountablePythonSDK-0.0.
|
|
290
|
-
UncountablePythonSDK-0.0.
|
|
291
|
-
UncountablePythonSDK-0.0.
|
|
289
|
+
UncountablePythonSDK-0.0.81.dist-info/METADATA,sha256=hfFny-tLIUG0nrKcCY0eAxGDFgo-Q7wUXyqSczrBKpU,2051
|
|
290
|
+
UncountablePythonSDK-0.0.81.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
|
|
291
|
+
UncountablePythonSDK-0.0.81.dist-info/top_level.txt,sha256=1UVGjAU-6hJY9qw2iJ7nCBeEwZ793AEN5ZfKX9A1uj4,31
|
|
292
|
+
UncountablePythonSDK-0.0.81.dist-info/RECORD,,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
from uncountable.integration.job import JobArguments, WebhookJob, register_job
|
|
4
|
+
from uncountable.types.job_definition_t import JobResult
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@register_job
|
|
8
|
+
class WebhookExample(WebhookJob):
|
|
9
|
+
@property
|
|
10
|
+
def payload_type(self) -> typing.Any:
|
|
11
|
+
return super().payload_type
|
|
12
|
+
|
|
13
|
+
def run(self, args: JobArguments, payload: typing.Any) -> JobResult:
|
|
14
|
+
args.logger.log_info(f"webhook invoked with payload: {payload}")
|
|
15
|
+
return JobResult(success=True)
|
|
@@ -13,7 +13,31 @@ jobs:
|
|
|
13
13
|
type: cron
|
|
14
14
|
name: MyCron - Example
|
|
15
15
|
cron_spec: "* * * * *"
|
|
16
|
-
executor:
|
|
16
|
+
executor:
|
|
17
17
|
type: script
|
|
18
18
|
import_path: example_cron
|
|
19
|
+
logging_settings:
|
|
20
|
+
enabled: true
|
|
21
|
+
share_with_user_groups:
|
|
22
|
+
- admin:
|
|
23
|
+
type: ref_name
|
|
24
|
+
ref_name: admin
|
|
19
25
|
|
|
26
|
+
- id: example_wh1
|
|
27
|
+
type: webhook
|
|
28
|
+
name: Webhook 1
|
|
29
|
+
signature_key_secret:
|
|
30
|
+
type: env
|
|
31
|
+
env_key: WH1_SIGNATURE_KEY
|
|
32
|
+
executor:
|
|
33
|
+
type: script
|
|
34
|
+
import_path: example_wh
|
|
35
|
+
- id: example_wh2
|
|
36
|
+
type: webhook
|
|
37
|
+
name: Webhook 2
|
|
38
|
+
signature_key_secret:
|
|
39
|
+
type: env
|
|
40
|
+
env_key: WH2_SIGNATURE_KEY
|
|
41
|
+
executor:
|
|
42
|
+
type: script
|
|
43
|
+
import_path: example_wh
|
|
@@ -96,6 +96,10 @@ class SerialClassDataInspector:
|
|
|
96
96
|
def named_type_path(self) -> Optional[str]:
|
|
97
97
|
return self.current.named_type_path
|
|
98
98
|
|
|
99
|
+
@property
|
|
100
|
+
def is_field_proper(self) -> bool:
|
|
101
|
+
return self.current.from_decorator and self.current.named_type_path is not None
|
|
102
|
+
|
|
99
103
|
|
|
100
104
|
def _get_merged_serial_class_data(type_class: type[Any]) -> _SerialClassData | None:
|
|
101
105
|
base_class_data = (
|
|
@@ -22,8 +22,8 @@ PureJsonScalar = Union[str, float, bool, None]
|
|
|
22
22
|
# Regular expressions for identifying ref names and IDs. Ref names should be
|
|
23
23
|
# using this regular expression as a constriant in the database.
|
|
24
24
|
REF_NAME_REGEX = r"^[a-zA-Z0-9_/-]+$"
|
|
25
|
-
#
|
|
26
|
-
ID_REGEX = r"[1-9][0-9]{0,20}"
|
|
25
|
+
# Ids matching a strict integer number are converted to integers
|
|
26
|
+
ID_REGEX = r"-?[1-9][0-9]{0,20}"
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
if TYPE_CHECKING:
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
from typing import assert_never
|
|
2
2
|
|
|
3
|
+
from uncountable.core.client import Client
|
|
3
4
|
from uncountable.integration.executors.generic_upload_executor import GenericUploadJob
|
|
4
5
|
from uncountable.integration.executors.script_executor import resolve_script_executor
|
|
5
6
|
from uncountable.integration.job import Job, JobArguments
|
|
6
|
-
from uncountable.types import
|
|
7
|
+
from uncountable.types import (
|
|
8
|
+
async_jobs_t,
|
|
9
|
+
entity_t,
|
|
10
|
+
field_values_t,
|
|
11
|
+
identifier_t,
|
|
12
|
+
job_definition_t,
|
|
13
|
+
transition_entity_phase_t,
|
|
14
|
+
)
|
|
7
15
|
|
|
8
16
|
|
|
9
17
|
def resolve_executor(
|
|
@@ -24,6 +32,49 @@ def resolve_executor(
|
|
|
24
32
|
assert_never(job_executor)
|
|
25
33
|
|
|
26
34
|
|
|
35
|
+
def _create_run_entity(
|
|
36
|
+
*, client: Client, logging_settings: job_definition_t.JobLoggingSettings
|
|
37
|
+
) -> entity_t.Entity:
|
|
38
|
+
run_entity = client.create_entity(
|
|
39
|
+
entity_type=entity_t.EntityType.ASYNC_JOB,
|
|
40
|
+
definition_key=identifier_t.IdentifierKeyRefName(
|
|
41
|
+
ref_name="unc_integration_server_run_definition"
|
|
42
|
+
),
|
|
43
|
+
field_values=[
|
|
44
|
+
field_values_t.FieldRefNameValue(
|
|
45
|
+
field_ref_name=async_jobs_t.ASYNC_JOB_TYPE_FIELD_REF_NAME,
|
|
46
|
+
value=async_jobs_t.AsyncJobType.INTEGRATION_SERVER_RUN,
|
|
47
|
+
),
|
|
48
|
+
field_values_t.FieldRefNameValue(
|
|
49
|
+
field_ref_name=async_jobs_t.ASYNC_JOB_STATUS_FIELD_REF_NAME,
|
|
50
|
+
value=async_jobs_t.AsyncJobStatus.IN_PROGRESS,
|
|
51
|
+
),
|
|
52
|
+
],
|
|
53
|
+
).entity
|
|
54
|
+
client.transition_entity_phase(
|
|
55
|
+
entity=run_entity,
|
|
56
|
+
transition=transition_entity_phase_t.TransitionIdentifierPhases(
|
|
57
|
+
phase_from_key=identifier_t.IdentifierKeyRefName(
|
|
58
|
+
ref_name="unc_integration_server_run__queued"
|
|
59
|
+
),
|
|
60
|
+
phase_to_key=identifier_t.IdentifierKeyRefName(
|
|
61
|
+
ref_name="unc_integration_server_run__started"
|
|
62
|
+
),
|
|
63
|
+
),
|
|
64
|
+
)
|
|
65
|
+
if logging_settings.share_with_user_groups is not None:
|
|
66
|
+
client.grant_entity_permissions(
|
|
67
|
+
entity_type=entity_t.EntityType.ASYNC_JOB,
|
|
68
|
+
entity_key=identifier_t.IdentifierKeyId(id=run_entity.id),
|
|
69
|
+
permission_types=[
|
|
70
|
+
entity_t.EntityPermissionType.READ,
|
|
71
|
+
entity_t.EntityPermissionType.WRITE,
|
|
72
|
+
],
|
|
73
|
+
user_group_keys=logging_settings.share_with_user_groups,
|
|
74
|
+
)
|
|
75
|
+
return run_entity
|
|
76
|
+
|
|
77
|
+
|
|
27
78
|
def execute_job(
|
|
28
79
|
*,
|
|
29
80
|
job_definition: job_definition_t.JobDefinition,
|
|
@@ -35,10 +86,28 @@ def execute_job(
|
|
|
35
86
|
|
|
36
87
|
job_logger.log_info("running job")
|
|
37
88
|
|
|
89
|
+
run_entity: entity_t.Entity | None = None
|
|
38
90
|
try:
|
|
91
|
+
if (
|
|
92
|
+
job_definition.logging_settings is not None
|
|
93
|
+
and job_definition.logging_settings.enabled
|
|
94
|
+
):
|
|
95
|
+
run_entity = _create_run_entity(
|
|
96
|
+
client=args.client, logging_settings=job_definition.logging_settings
|
|
97
|
+
)
|
|
39
98
|
result = job.run_outer(args=args)
|
|
40
99
|
except Exception as e:
|
|
41
100
|
job_logger.log_exception(e)
|
|
101
|
+
if run_entity is not None:
|
|
102
|
+
args.client.set_values(
|
|
103
|
+
entity=run_entity,
|
|
104
|
+
values=[
|
|
105
|
+
field_values_t.ArgumentValueRefName(
|
|
106
|
+
field_ref_name=async_jobs_t.ASYNC_JOB_STATUS_FIELD_REF_NAME,
|
|
107
|
+
value=async_jobs_t.AsyncJobStatus.ERROR,
|
|
108
|
+
),
|
|
109
|
+
],
|
|
110
|
+
)
|
|
42
111
|
return job_definition_t.JobResult(success=False)
|
|
43
112
|
|
|
44
113
|
if args.batch_processor.current_queue_size() != 0:
|
|
@@ -52,5 +121,17 @@ def execute_job(
|
|
|
52
121
|
"success": result.success,
|
|
53
122
|
},
|
|
54
123
|
)
|
|
124
|
+
if run_entity is not None:
|
|
125
|
+
args.client.set_values(
|
|
126
|
+
entity=run_entity,
|
|
127
|
+
values=[
|
|
128
|
+
field_values_t.ArgumentValueRefName(
|
|
129
|
+
field_ref_name=async_jobs_t.ASYNC_JOB_STATUS_FIELD_REF_NAME,
|
|
130
|
+
value=async_jobs_t.AsyncJobStatus.COMPLETED
|
|
131
|
+
if result.success
|
|
132
|
+
else async_jobs_t.AsyncJobStatus.ERROR,
|
|
133
|
+
),
|
|
134
|
+
],
|
|
135
|
+
)
|
|
55
136
|
|
|
56
137
|
return result
|
|
@@ -8,6 +8,7 @@ from opentelemetry.trace import get_current_span
|
|
|
8
8
|
from uncountable.integration.db.connect import IntegrationDBService, create_db_engine
|
|
9
9
|
from uncountable.integration.db.session import get_session_maker
|
|
10
10
|
from uncountable.integration.queue_runner.command_server import (
|
|
11
|
+
CommandEnqueueJob,
|
|
11
12
|
CommandEnqueueJobResponse,
|
|
12
13
|
CommandQueue,
|
|
13
14
|
CommandTask,
|
|
@@ -99,6 +100,41 @@ async def start_scheduler(command_queue: CommandQueue) -> None:
|
|
|
99
100
|
return
|
|
100
101
|
await worker.listen_queue.put(queued_job)
|
|
101
102
|
|
|
103
|
+
async def _enqueue_or_deduplicate_job(
|
|
104
|
+
job_ref_name: str,
|
|
105
|
+
payload: queued_job_t.QueuedJobPayload,
|
|
106
|
+
) -> str:
|
|
107
|
+
if isinstance(
|
|
108
|
+
payload.invocation_context,
|
|
109
|
+
queued_job_t.InvocationContextCron,
|
|
110
|
+
):
|
|
111
|
+
existing_queued_jobs = datastore.load_job_queue()
|
|
112
|
+
duplicate_job = next(
|
|
113
|
+
(
|
|
114
|
+
job
|
|
115
|
+
for job in existing_queued_jobs
|
|
116
|
+
if job.job_ref_name == job_ref_name
|
|
117
|
+
),
|
|
118
|
+
None,
|
|
119
|
+
)
|
|
120
|
+
if duplicate_job is not None:
|
|
121
|
+
return duplicate_job.queued_job_uuid
|
|
122
|
+
queued_job = datastore.add_job_to_queue(
|
|
123
|
+
job_payload=payload,
|
|
124
|
+
job_ref_name=job_ref_name,
|
|
125
|
+
)
|
|
126
|
+
await enqueue_queued_job(queued_job)
|
|
127
|
+
return queued_job.queued_job_uuid
|
|
128
|
+
|
|
129
|
+
async def _handle_enqueue_job_command(command: CommandEnqueueJob) -> None:
|
|
130
|
+
queued_job_uuid = await _enqueue_or_deduplicate_job(
|
|
131
|
+
job_ref_name=command.job_ref_name,
|
|
132
|
+
payload=command.payload,
|
|
133
|
+
)
|
|
134
|
+
await command.response_queue.put(
|
|
135
|
+
CommandEnqueueJobResponse(queued_job_uuid=queued_job_uuid)
|
|
136
|
+
)
|
|
137
|
+
|
|
102
138
|
for queued_job in queued_jobs:
|
|
103
139
|
await enqueue_queued_job(queued_job)
|
|
104
140
|
|
|
@@ -112,15 +148,11 @@ async def start_scheduler(command_queue: CommandQueue) -> None:
|
|
|
112
148
|
for task in finished:
|
|
113
149
|
if task == command_task:
|
|
114
150
|
command = command_task.result()
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
queued_job_uuid=queued_job.queued_job_uuid
|
|
121
|
-
)
|
|
122
|
-
)
|
|
123
|
-
await enqueue_queued_job(queued_job)
|
|
151
|
+
match command:
|
|
152
|
+
case CommandEnqueueJob():
|
|
153
|
+
await _handle_enqueue_job_command(command=command)
|
|
154
|
+
case _:
|
|
155
|
+
typing.assert_never(command)
|
|
124
156
|
command_task = asyncio.create_task(command_queue.get())
|
|
125
157
|
elif task == result_task:
|
|
126
158
|
queued_job_result = result_task.result()
|
uncountable/types/base_t.py
CHANGED
|
@@ -39,8 +39,8 @@ PureJsonScalar = Union[str, float, bool, None]
|
|
|
39
39
|
# Regular expressions for identifying ref names and IDs. Ref names should be
|
|
40
40
|
# using this regular expression as a constriant in the database.
|
|
41
41
|
REF_NAME_REGEX = r"^[a-zA-Z0-9_/-]+$"
|
|
42
|
-
#
|
|
43
|
-
ID_REGEX = r"[1-9][0-9]{0,20}"
|
|
42
|
+
# Ids matching a strict integer number are converted to integers
|
|
43
|
+
ID_REGEX = r"-?[1-9][0-9]{0,20}"
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
if TYPE_CHECKING:
|
uncountable/types/entity_t.py
CHANGED
|
@@ -70,10 +70,12 @@ __all__: list[str] = [
|
|
|
70
70
|
"ingredient": "Ingredient",
|
|
71
71
|
"ingredient_attribute": "Ingredient Attribute",
|
|
72
72
|
"ingredient_attribute_category": "Ingredient Attribute Category",
|
|
73
|
+
"ingredient_attribute_value": "Ingredient Attribute Value",
|
|
73
74
|
"ingredient_category": "Ingredient Category (Project)",
|
|
74
75
|
"ingredient_category_all": "Ingredient Category",
|
|
75
76
|
"ingredient_category_all_material_family": "Ingredient Category Material Family",
|
|
76
77
|
"ingredient_lot": "Ingredient Lot",
|
|
78
|
+
"ingredient_mat_family": "Ingredient Material Family",
|
|
77
79
|
"ingredient_role": "Ingredient Role",
|
|
78
80
|
"ingredient_tag": "Ingredient Subcategory",
|
|
79
81
|
"ingredient_tag_map": "Ingredient Tag Map",
|
|
@@ -225,10 +227,12 @@ class EntityType(StrEnum):
|
|
|
225
227
|
INGREDIENT = "ingredient"
|
|
226
228
|
INGREDIENT_ATTRIBUTE = "ingredient_attribute"
|
|
227
229
|
INGREDIENT_ATTRIBUTE_CATEGORY = "ingredient_attribute_category"
|
|
230
|
+
INGREDIENT_ATTRIBUTE_VALUE = "ingredient_attribute_value"
|
|
228
231
|
INGREDIENT_CATEGORY = "ingredient_category"
|
|
229
232
|
INGREDIENT_CATEGORY_ALL = "ingredient_category_all"
|
|
230
233
|
INGREDIENT_CATEGORY_ALL_MATERIAL_FAMILY = "ingredient_category_all_material_family"
|
|
231
234
|
INGREDIENT_LOT = "ingredient_lot"
|
|
235
|
+
INGREDIENT_MAT_FAMILY = "ingredient_mat_family"
|
|
232
236
|
INGREDIENT_ROLE = "ingredient_role"
|
|
233
237
|
INGREDIENT_TAG = "ingredient_tag"
|
|
234
238
|
INGREDIENT_TAG_MAP = "ingredient_tag_map"
|
|
@@ -12,9 +12,9 @@ import dataclasses
|
|
|
12
12
|
from pkgs.serialization import serial_class
|
|
13
13
|
from pkgs.serialization import serial_union_annotation
|
|
14
14
|
from . import auth_retrieval_t
|
|
15
|
-
from . import base_t
|
|
16
15
|
from . import client_config_t
|
|
17
16
|
from . import generic_upload_t
|
|
17
|
+
from . import identifier_t
|
|
18
18
|
from . import integration_server_t
|
|
19
19
|
from . import secret_retrieval_t
|
|
20
20
|
|
|
@@ -172,7 +172,7 @@ JobExecutor = typing.Annotated[
|
|
|
172
172
|
@dataclasses.dataclass(kw_only=True)
|
|
173
173
|
class JobLoggingSettings:
|
|
174
174
|
enabled: bool = False
|
|
175
|
-
share_with_user_groups: typing.Optional[list[
|
|
175
|
+
share_with_user_groups: typing.Optional[list[identifier_t.IdentifierKey]] = None
|
|
176
176
|
|
|
177
177
|
|
|
178
178
|
# DO NOT MODIFY -- This file is generated by type_spec
|
|
File without changes
|
{UncountablePythonSDK-0.0.79.dist-info → UncountablePythonSDK-0.0.81.dist-info}/top_level.txt
RENAMED
|
File without changes
|