UncountablePythonSDK 0.0.24__py3-none-any.whl → 0.0.131__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.

Files changed (373) hide show
  1. docs/conf.py +60 -8
  2. docs/index.md +107 -4
  3. docs/integration_examples/create_ingredient.md +43 -0
  4. docs/integration_examples/create_output.md +56 -0
  5. docs/integration_examples/index.md +6 -0
  6. docs/justfile +2 -2
  7. docs/requirements.txt +7 -5
  8. examples/async_batch.py +5 -6
  9. examples/basic_auth.py +7 -0
  10. examples/create_entity.py +4 -6
  11. examples/create_ingredient_sdk.py +34 -0
  12. examples/download_files.py +26 -0
  13. examples/edit_recipe_inputs.py +50 -0
  14. examples/integration-server/jobs/materials_auto/concurrent_cron.py +11 -0
  15. examples/integration-server/jobs/materials_auto/example_cron.py +21 -0
  16. examples/integration-server/jobs/materials_auto/example_http.py +47 -0
  17. examples/integration-server/jobs/materials_auto/example_instrument.py +100 -0
  18. examples/integration-server/jobs/materials_auto/example_parse.py +140 -0
  19. examples/integration-server/jobs/materials_auto/example_predictions.py +61 -0
  20. examples/integration-server/jobs/materials_auto/example_runsheet_wh.py +39 -0
  21. examples/integration-server/jobs/materials_auto/example_wh.py +23 -0
  22. examples/integration-server/jobs/materials_auto/profile.yaml +104 -0
  23. examples/integration-server/pyproject.toml +224 -0
  24. examples/invoke_uploader.py +26 -0
  25. examples/oauth.py +7 -0
  26. examples/set_recipe_metadata_file.py +40 -0
  27. examples/set_recipe_output_file_sdk.py +26 -0
  28. examples/upload_files.py +2 -3
  29. pkgs/argument_parser/__init__.py +9 -0
  30. pkgs/argument_parser/_is_namedtuple.py +3 -0
  31. pkgs/argument_parser/argument_parser.py +295 -74
  32. pkgs/argument_parser/case_convert.py +4 -3
  33. pkgs/filesystem_utils/__init__.py +20 -0
  34. pkgs/filesystem_utils/_blob_session.py +144 -0
  35. pkgs/filesystem_utils/_gdrive_session.py +309 -0
  36. pkgs/filesystem_utils/_local_session.py +69 -0
  37. pkgs/filesystem_utils/_s3_session.py +118 -0
  38. pkgs/filesystem_utils/_sftp_session.py +151 -0
  39. pkgs/filesystem_utils/file_type_utils.py +91 -0
  40. pkgs/filesystem_utils/filesystem_session.py +39 -0
  41. pkgs/py.typed +0 -0
  42. pkgs/serialization/__init__.py +8 -1
  43. pkgs/serialization/annotation.py +64 -0
  44. pkgs/serialization/missing_sentry.py +1 -1
  45. pkgs/serialization/opaque_key.py +1 -1
  46. pkgs/serialization/serial_alias.py +47 -0
  47. pkgs/serialization/serial_class.py +69 -54
  48. pkgs/serialization/serial_generic.py +16 -0
  49. pkgs/serialization/serial_union.py +84 -0
  50. pkgs/serialization/yaml.py +57 -0
  51. pkgs/serialization_util/__init__.py +7 -7
  52. pkgs/serialization_util/convert_to_snakecase.py +27 -0
  53. pkgs/serialization_util/dataclasses.py +14 -0
  54. pkgs/serialization_util/serialization_helpers.py +117 -71
  55. pkgs/type_spec/actions_registry/__main__.py +0 -4
  56. pkgs/type_spec/actions_registry/emit_typescript.py +5 -5
  57. pkgs/type_spec/builder.py +438 -109
  58. pkgs/type_spec/builder_types.py +9 -0
  59. pkgs/type_spec/config.py +52 -24
  60. pkgs/type_spec/cross_output_links.py +99 -0
  61. pkgs/type_spec/emit_io_ts.py +1 -1
  62. pkgs/type_spec/emit_open_api.py +160 -41
  63. pkgs/type_spec/emit_open_api_util.py +13 -7
  64. pkgs/type_spec/emit_python.py +450 -136
  65. pkgs/type_spec/emit_typescript.py +117 -250
  66. pkgs/type_spec/emit_typescript_util.py +293 -4
  67. pkgs/type_spec/load_types.py +20 -5
  68. pkgs/type_spec/non_discriminated_union_exceptions.py +14 -0
  69. pkgs/type_spec/open_api_util.py +29 -4
  70. pkgs/type_spec/parts/base.py.prepart +13 -10
  71. pkgs/type_spec/parts/base.ts.prepart +4 -0
  72. pkgs/type_spec/type_info/__main__.py +3 -1
  73. pkgs/type_spec/type_info/emit_type_info.py +161 -32
  74. pkgs/type_spec/ui_entry_actions/__init__.py +4 -0
  75. pkgs/type_spec/ui_entry_actions/generate_ui_entry_actions.py +308 -0
  76. pkgs/type_spec/util.py +4 -4
  77. pkgs/type_spec/value_spec/__main__.py +27 -10
  78. pkgs/type_spec/value_spec/convert_type.py +21 -1
  79. pkgs/type_spec/value_spec/emit_python.py +25 -7
  80. pkgs/type_spec/value_spec/types.py +1 -1
  81. uncountable/__init__.py +1 -2
  82. uncountable/core/__init__.py +11 -3
  83. uncountable/core/async_batch.py +16 -1
  84. uncountable/core/client.py +247 -52
  85. uncountable/core/environment.py +41 -0
  86. uncountable/core/file_upload.py +67 -22
  87. uncountable/core/types.py +8 -13
  88. uncountable/integration/cli.py +142 -0
  89. uncountable/integration/construct_client.py +43 -27
  90. uncountable/integration/cron.py +12 -11
  91. uncountable/integration/db/connect.py +12 -2
  92. uncountable/integration/db/session.py +25 -0
  93. uncountable/integration/entrypoint.py +4 -34
  94. uncountable/integration/executors/executors.py +147 -0
  95. uncountable/integration/executors/generic_upload_executor.py +336 -0
  96. uncountable/integration/executors/script_executor.py +15 -9
  97. uncountable/integration/http_server/__init__.py +5 -0
  98. uncountable/integration/http_server/types.py +69 -0
  99. uncountable/integration/job.py +246 -19
  100. uncountable/integration/queue_runner/__init__.py +0 -0
  101. uncountable/integration/queue_runner/command_server/__init__.py +28 -0
  102. uncountable/integration/queue_runner/command_server/command_client.py +133 -0
  103. uncountable/integration/queue_runner/command_server/command_server.py +142 -0
  104. uncountable/integration/queue_runner/command_server/constants.py +4 -0
  105. uncountable/integration/queue_runner/command_server/protocol/__init__.py +0 -0
  106. uncountable/integration/queue_runner/command_server/protocol/command_server.proto +58 -0
  107. uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.py +57 -0
  108. uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.pyi +114 -0
  109. uncountable/integration/queue_runner/command_server/protocol/command_server_pb2_grpc.py +264 -0
  110. uncountable/integration/queue_runner/command_server/types.py +75 -0
  111. uncountable/integration/queue_runner/datastore/__init__.py +3 -0
  112. uncountable/integration/queue_runner/datastore/datastore_sqlite.py +250 -0
  113. uncountable/integration/queue_runner/datastore/interface.py +29 -0
  114. uncountable/integration/queue_runner/datastore/model.py +24 -0
  115. uncountable/integration/queue_runner/job_scheduler.py +200 -0
  116. uncountable/integration/queue_runner/queue_runner.py +34 -0
  117. uncountable/integration/queue_runner/types.py +7 -0
  118. uncountable/integration/queue_runner/worker.py +116 -0
  119. uncountable/integration/scan_profiles.py +67 -0
  120. uncountable/integration/scheduler.py +199 -0
  121. uncountable/integration/secret_retrieval/__init__.py +3 -0
  122. uncountable/integration/secret_retrieval/retrieve_secret.py +93 -0
  123. uncountable/integration/server.py +103 -54
  124. uncountable/integration/telemetry.py +251 -0
  125. uncountable/integration/webhook_server/entrypoint.py +97 -0
  126. uncountable/types/__init__.py +149 -30
  127. uncountable/types/api/batch/execute_batch.py +16 -9
  128. uncountable/types/api/batch/execute_batch_load_async.py +13 -7
  129. uncountable/types/api/chemical/convert_chemical_formats.py +20 -8
  130. uncountable/types/api/condition_parameters/__init__.py +1 -0
  131. uncountable/types/api/condition_parameters/upsert_condition_match.py +72 -0
  132. uncountable/types/api/entity/create_entities.py +24 -12
  133. uncountable/types/api/entity/create_entity.py +22 -13
  134. uncountable/types/api/entity/create_or_update_entity.py +48 -0
  135. uncountable/types/api/entity/export_entities.py +59 -0
  136. uncountable/types/api/entity/get_entities_data.py +18 -9
  137. uncountable/types/api/entity/grant_entity_permissions.py +48 -0
  138. uncountable/types/api/entity/list_aggregate.py +79 -0
  139. uncountable/types/api/entity/list_entities.py +53 -14
  140. uncountable/types/api/entity/lock_entity.py +45 -0
  141. uncountable/types/api/entity/lookup_entity.py +116 -0
  142. uncountable/types/api/entity/resolve_entity_ids.py +19 -10
  143. uncountable/types/api/entity/set_entity_field_values.py +44 -0
  144. uncountable/types/api/entity/set_values.py +15 -8
  145. uncountable/types/api/entity/transition_entity_phase.py +27 -12
  146. uncountable/types/api/entity/unlock_entity.py +44 -0
  147. uncountable/types/api/equipment/__init__.py +1 -0
  148. uncountable/types/api/equipment/associate_equipment_input.py +43 -0
  149. uncountable/types/api/field_options/__init__.py +1 -0
  150. uncountable/types/api/field_options/upsert_field_options.py +55 -0
  151. uncountable/types/api/files/__init__.py +1 -0
  152. uncountable/types/api/files/download_file.py +77 -0
  153. uncountable/types/api/id_source/list_id_source.py +20 -11
  154. uncountable/types/api/id_source/match_id_source.py +15 -10
  155. uncountable/types/api/input_groups/get_input_group_names.py +16 -7
  156. uncountable/types/api/inputs/create_inputs.py +28 -14
  157. uncountable/types/api/inputs/get_input_data.py +34 -16
  158. uncountable/types/api/inputs/get_input_names.py +19 -10
  159. uncountable/types/api/inputs/get_inputs_data.py +29 -11
  160. uncountable/types/api/inputs/set_input_attribute_values.py +16 -10
  161. uncountable/types/api/inputs/set_input_category.py +44 -0
  162. uncountable/types/api/inputs/set_input_subcategories.py +45 -0
  163. uncountable/types/api/inputs/set_intermediate_type.py +50 -0
  164. uncountable/types/api/integrations/__init__.py +1 -0
  165. uncountable/types/api/integrations/publish_realtime_data.py +41 -0
  166. uncountable/types/api/integrations/push_notification.py +49 -0
  167. uncountable/types/api/integrations/register_sockets_token.py +41 -0
  168. uncountable/types/api/listing/__init__.py +1 -0
  169. uncountable/types/api/listing/fetch_listing.py +58 -0
  170. uncountable/types/api/material_families/__init__.py +1 -0
  171. uncountable/types/api/material_families/update_entity_material_families.py +47 -0
  172. uncountable/types/api/notebooks/__init__.py +1 -0
  173. uncountable/types/api/notebooks/add_notebook_content.py +119 -0
  174. uncountable/types/api/outputs/get_output_data.py +32 -17
  175. uncountable/types/api/outputs/get_output_names.py +18 -9
  176. uncountable/types/api/outputs/get_output_organization.py +173 -0
  177. uncountable/types/api/outputs/resolve_output_conditions.py +23 -11
  178. uncountable/types/api/permissions/set_core_permissions.py +31 -15
  179. uncountable/types/api/project/get_projects.py +20 -11
  180. uncountable/types/api/project/get_projects_data.py +23 -14
  181. uncountable/types/api/recipe_links/create_recipe_link.py +17 -10
  182. uncountable/types/api/recipe_links/remove_recipe_link.py +45 -0
  183. uncountable/types/api/recipe_metadata/get_recipe_metadata_data.py +19 -10
  184. uncountable/types/api/recipes/add_recipe_to_project.py +42 -0
  185. uncountable/types/api/recipes/add_time_series_data.py +64 -0
  186. uncountable/types/api/recipes/archive_recipes.py +14 -7
  187. uncountable/types/api/recipes/associate_recipe_as_input.py +16 -8
  188. uncountable/types/api/recipes/associate_recipe_as_lot.py +14 -7
  189. uncountable/types/api/recipes/clear_recipe_outputs.py +42 -0
  190. uncountable/types/api/recipes/create_mix_order.py +44 -0
  191. uncountable/types/api/recipes/create_recipe.py +21 -14
  192. uncountable/types/api/recipes/create_recipes.py +25 -13
  193. uncountable/types/api/recipes/disassociate_recipe_as_input.py +14 -7
  194. uncountable/types/api/recipes/edit_recipe_inputs.py +208 -19
  195. uncountable/types/api/recipes/get_column_calculation_values.py +57 -0
  196. uncountable/types/api/recipes/get_curve.py +15 -9
  197. uncountable/types/api/recipes/get_recipe_calculations.py +17 -11
  198. uncountable/types/api/recipes/get_recipe_links.py +14 -8
  199. uncountable/types/api/recipes/get_recipe_names.py +16 -7
  200. uncountable/types/api/recipes/get_recipe_output_metadata.py +16 -10
  201. uncountable/types/api/recipes/get_recipes_data.py +96 -45
  202. uncountable/types/api/recipes/lock_recipes.py +64 -0
  203. uncountable/types/api/recipes/remove_recipe_from_project.py +42 -0
  204. uncountable/types/api/recipes/set_recipe_inputs.py +19 -13
  205. uncountable/types/api/recipes/set_recipe_metadata.py +14 -7
  206. uncountable/types/api/recipes/set_recipe_output_annotations.py +114 -0
  207. uncountable/types/api/recipes/set_recipe_output_file.py +55 -0
  208. uncountable/types/api/recipes/set_recipe_outputs.py +40 -15
  209. uncountable/types/api/recipes/set_recipe_tags.py +30 -13
  210. uncountable/types/api/recipes/set_recipe_total.py +59 -0
  211. uncountable/types/api/recipes/unarchive_recipes.py +41 -0
  212. uncountable/types/api/recipes/unlock_recipes.py +51 -0
  213. uncountable/types/api/runsheet/__init__.py +1 -0
  214. uncountable/types/api/runsheet/complete_async_upload.py +41 -0
  215. uncountable/types/api/triggers/run_trigger.py +15 -8
  216. uncountable/types/api/uploader/__init__.py +1 -0
  217. uncountable/types/api/uploader/complete_async_parse.py +46 -0
  218. uncountable/types/api/uploader/invoke_uploader.py +46 -0
  219. uncountable/types/api/user/__init__.py +1 -0
  220. uncountable/types/api/user/get_current_user_info.py +40 -0
  221. uncountable/types/async_batch.py +8 -52
  222. uncountable/types/async_batch_processor.py +694 -18
  223. uncountable/types/async_batch_t.py +108 -0
  224. uncountable/types/async_jobs.py +8 -0
  225. uncountable/types/async_jobs_t.py +52 -0
  226. uncountable/types/auth_retrieval.py +11 -0
  227. uncountable/types/auth_retrieval_t.py +75 -0
  228. uncountable/types/base.py +5 -80
  229. uncountable/types/base_t.py +87 -0
  230. uncountable/types/calculations.py +3 -19
  231. uncountable/types/calculations_t.py +26 -0
  232. uncountable/types/chemical_structure.py +3 -23
  233. uncountable/types/chemical_structure_t.py +28 -0
  234. uncountable/types/client_base.py +1170 -88
  235. uncountable/types/client_config.py +8 -0
  236. uncountable/types/client_config_t.py +36 -0
  237. uncountable/types/curves.py +5 -43
  238. uncountable/types/curves_t.py +50 -0
  239. uncountable/types/data.py +12 -0
  240. uncountable/types/data_t.py +103 -0
  241. uncountable/types/entity.py +8 -270
  242. uncountable/types/entity_t.py +446 -0
  243. uncountable/types/experiment_groups.py +3 -19
  244. uncountable/types/experiment_groups_t.py +26 -0
  245. uncountable/types/exports.py +8 -0
  246. uncountable/types/exports_t.py +34 -0
  247. uncountable/types/field_values.py +25 -61
  248. uncountable/types/field_values_t.py +302 -0
  249. uncountable/types/fields.py +3 -20
  250. uncountable/types/fields_t.py +27 -0
  251. uncountable/types/generic_upload.py +14 -0
  252. uncountable/types/generic_upload_t.py +119 -0
  253. uncountable/types/id_source.py +7 -45
  254. uncountable/types/id_source_t.py +68 -0
  255. uncountable/types/identifier.py +6 -50
  256. uncountable/types/identifier_t.py +62 -0
  257. uncountable/types/input_attributes.py +3 -25
  258. uncountable/types/input_attributes_t.py +29 -0
  259. uncountable/types/inputs.py +6 -57
  260. uncountable/types/inputs_t.py +82 -0
  261. uncountable/types/integration_server.py +8 -0
  262. uncountable/types/integration_server_t.py +46 -0
  263. uncountable/types/integration_session.py +10 -0
  264. uncountable/types/integration_session_t.py +60 -0
  265. uncountable/types/integrations.py +10 -0
  266. uncountable/types/integrations_t.py +62 -0
  267. uncountable/types/job_definition.py +28 -0
  268. uncountable/types/job_definition_t.py +285 -0
  269. uncountable/types/listing.py +9 -0
  270. uncountable/types/listing_t.py +51 -0
  271. uncountable/types/notices.py +8 -0
  272. uncountable/types/notices_t.py +37 -0
  273. uncountable/types/notifications.py +11 -0
  274. uncountable/types/notifications_t.py +74 -0
  275. uncountable/types/outputs.py +3 -22
  276. uncountable/types/outputs_t.py +29 -0
  277. uncountable/types/overrides.py +9 -0
  278. uncountable/types/overrides_t.py +49 -0
  279. uncountable/types/permissions.py +3 -42
  280. uncountable/types/permissions_t.py +45 -0
  281. uncountable/types/phases.py +3 -19
  282. uncountable/types/phases_t.py +26 -0
  283. uncountable/types/post_base.py +3 -26
  284. uncountable/types/post_base_t.py +29 -0
  285. uncountable/types/queued_job.py +17 -0
  286. uncountable/types/queued_job_t.py +140 -0
  287. uncountable/types/recipe_identifiers.py +7 -58
  288. uncountable/types/recipe_identifiers_t.py +75 -0
  289. uncountable/types/recipe_inputs.py +4 -26
  290. uncountable/types/recipe_inputs_t.py +29 -0
  291. uncountable/types/recipe_links.py +4 -46
  292. uncountable/types/recipe_links_t.py +53 -0
  293. uncountable/types/recipe_metadata.py +5 -48
  294. uncountable/types/recipe_metadata_t.py +57 -0
  295. uncountable/types/recipe_output_metadata.py +3 -20
  296. uncountable/types/recipe_output_metadata_t.py +27 -0
  297. uncountable/types/recipe_tags.py +3 -19
  298. uncountable/types/recipe_tags_t.py +26 -0
  299. uncountable/types/recipe_workflow_steps.py +9 -73
  300. uncountable/types/recipe_workflow_steps_t.py +95 -0
  301. uncountable/types/recipes.py +7 -0
  302. uncountable/types/recipes_t.py +25 -0
  303. uncountable/types/response.py +3 -21
  304. uncountable/types/response_t.py +26 -0
  305. uncountable/types/secret_retrieval.py +11 -0
  306. uncountable/types/secret_retrieval_t.py +75 -0
  307. uncountable/types/sockets.py +20 -0
  308. uncountable/types/sockets_t.py +169 -0
  309. uncountable/types/structured_filters.py +25 -0
  310. uncountable/types/structured_filters_t.py +248 -0
  311. uncountable/types/units.py +3 -19
  312. uncountable/types/units_t.py +26 -0
  313. uncountable/types/uploader.py +24 -0
  314. uncountable/types/uploader_t.py +222 -0
  315. uncountable/types/users.py +3 -20
  316. uncountable/types/users_t.py +27 -0
  317. uncountable/types/webhook_job.py +9 -0
  318. uncountable/types/webhook_job_t.py +48 -0
  319. uncountable/types/workflows.py +4 -28
  320. uncountable/types/workflows_t.py +38 -0
  321. uncountablepythonsdk-0.0.131.dist-info/METADATA +64 -0
  322. uncountablepythonsdk-0.0.131.dist-info/RECORD +363 -0
  323. {UncountablePythonSDK-0.0.24.dist-info → uncountablepythonsdk-0.0.131.dist-info}/WHEEL +1 -1
  324. {UncountablePythonSDK-0.0.24.dist-info → uncountablepythonsdk-0.0.131.dist-info}/top_level.txt +0 -1
  325. UncountablePythonSDK-0.0.24.dist-info/METADATA +0 -47
  326. UncountablePythonSDK-0.0.24.dist-info/RECORD +0 -216
  327. docs/quickstart.md +0 -19
  328. examples/recipe-import/importer.py +0 -39
  329. type_spec/external/api/batch/execute_batch.yaml +0 -56
  330. type_spec/external/api/batch/execute_batch_load_async.yaml +0 -18
  331. type_spec/external/api/chemical/convert_chemical_formats.yaml +0 -33
  332. type_spec/external/api/entity/create_entities.yaml +0 -45
  333. type_spec/external/api/entity/create_entity.yaml +0 -51
  334. type_spec/external/api/entity/get_entities_data.yaml +0 -29
  335. type_spec/external/api/entity/list_entities.yaml +0 -52
  336. type_spec/external/api/entity/resolve_entity_ids.yaml +0 -29
  337. type_spec/external/api/entity/set_values.yaml +0 -18
  338. type_spec/external/api/entity/transition_entity_phase.yaml +0 -44
  339. type_spec/external/api/id_source/list_id_source.yaml +0 -35
  340. type_spec/external/api/id_source/match_id_source.yaml +0 -32
  341. type_spec/external/api/input_groups/get_input_group_names.yaml +0 -29
  342. type_spec/external/api/inputs/create_inputs.yaml +0 -48
  343. type_spec/external/api/inputs/get_input_data.yaml +0 -95
  344. type_spec/external/api/inputs/get_input_names.yaml +0 -38
  345. type_spec/external/api/inputs/get_inputs_data.yaml +0 -82
  346. type_spec/external/api/inputs/set_input_attribute_values.yaml +0 -33
  347. type_spec/external/api/outputs/get_output_data.yaml +0 -92
  348. type_spec/external/api/outputs/get_output_names.yaml +0 -35
  349. type_spec/external/api/outputs/resolve_output_conditions.yaml +0 -50
  350. type_spec/external/api/permissions/set_core_permissions.yaml +0 -69
  351. type_spec/external/api/project/get_projects.yaml +0 -42
  352. type_spec/external/api/project/get_projects_data.yaml +0 -50
  353. type_spec/external/api/recipe_links/create_recipe_link.yaml +0 -25
  354. type_spec/external/api/recipe_metadata/get_recipe_metadata_data.yaml +0 -41
  355. type_spec/external/api/recipes/archive_recipes.yaml +0 -20
  356. type_spec/external/api/recipes/associate_recipe_as_input.yaml +0 -19
  357. type_spec/external/api/recipes/associate_recipe_as_lot.yaml +0 -19
  358. type_spec/external/api/recipes/create_recipe.yaml +0 -39
  359. type_spec/external/api/recipes/create_recipes.yaml +0 -47
  360. type_spec/external/api/recipes/disassociate_recipe_as_input.yaml +0 -16
  361. type_spec/external/api/recipes/edit_recipe_inputs.yaml +0 -85
  362. type_spec/external/api/recipes/get_curve.yaml +0 -21
  363. type_spec/external/api/recipes/get_recipe_calculations.yaml +0 -39
  364. type_spec/external/api/recipes/get_recipe_links.yaml +0 -26
  365. type_spec/external/api/recipes/get_recipe_names.yaml +0 -29
  366. type_spec/external/api/recipes/get_recipe_output_metadata.yaml +0 -36
  367. type_spec/external/api/recipes/get_recipes_data.yaml +0 -244
  368. type_spec/external/api/recipes/set_recipe_inputs.yaml +0 -42
  369. type_spec/external/api/recipes/set_recipe_metadata.yaml +0 -20
  370. type_spec/external/api/recipes/set_recipe_outputs.yaml +0 -52
  371. type_spec/external/api/recipes/set_recipe_tags.yaml +0 -62
  372. type_spec/external/api/triggers/run_trigger.yaml +0 -18
  373. uncountable/integration/types.py +0 -89
@@ -0,0 +1,100 @@
1
+ import json
2
+ import time
3
+ from dataclasses import dataclass
4
+ from decimal import Decimal
5
+
6
+ from uncountable.integration.job import JobArguments, WebhookJob, register_job
7
+ from uncountable.types import (
8
+ base_t,
9
+ identifier_t,
10
+ job_definition_t,
11
+ sockets_t,
12
+ )
13
+ from uncountable.types.integration_session_t import IntegrationSessionInstrument
14
+ from websockets.sync.client import connect
15
+ from websockets.typing import Data
16
+
17
+ from pkgs.argument_parser.argument_parser import CachedParser
18
+ from pkgs.serialization_util import serialize_for_api
19
+
20
+
21
+ @dataclass(kw_only=True)
22
+ class InstrumentPayload:
23
+ equipment_id: base_t.ObjectId
24
+
25
+
26
+ @register_job
27
+ class InstrumentExample(WebhookJob[InstrumentPayload]):
28
+ def run(
29
+ self, args: JobArguments, payload: InstrumentPayload
30
+ ) -> job_definition_t.JobResult:
31
+ parser: CachedParser[sockets_t.SocketResponse] = CachedParser(
32
+ sockets_t.SocketResponse # type:ignore[arg-type]
33
+ )
34
+
35
+ def parse_message(message: Data) -> sockets_t.SocketEventData | None:
36
+ try:
37
+ return parser.parse_api(json.loads(message)).data
38
+ except ValueError:
39
+ return None
40
+
41
+ integration_session = IntegrationSessionInstrument(
42
+ equipment_key=identifier_t.IdentifierKeyId(id=payload.equipment_id)
43
+ )
44
+ registration_info = args.client.register_sockets_token(
45
+ socket_request=sockets_t.SocketRequestIntegrationSession(
46
+ integration_session=integration_session
47
+ )
48
+ ).response
49
+ token = registration_info.token
50
+ room_key = registration_info.room_key
51
+ args.logger.log_info(f"Token: {token}")
52
+
53
+ with connect(
54
+ "ws://host.docker.internal:8765",
55
+ additional_headers={
56
+ "Authorization": f"Bearer {token}",
57
+ "X-UNC-EXTERNAL": "true",
58
+ },
59
+ ) as ws:
60
+ ws.send(
61
+ json.dumps(
62
+ serialize_for_api(
63
+ sockets_t.JoinRoomWithTokenSocketClientMessage(token=token)
64
+ )
65
+ )
66
+ )
67
+ for i in range(10):
68
+ args.logger.log_info("Sending reading...")
69
+ ws.send(
70
+ json.dumps(
71
+ serialize_for_api(
72
+ sockets_t.SendInstrumentReadingClientMessage(
73
+ value=Decimal(i * 100), room_key=room_key
74
+ )
75
+ )
76
+ )
77
+ )
78
+ time.sleep(0.75)
79
+
80
+ while True:
81
+ message = parse_message(ws.recv())
82
+ match message:
83
+ case sockets_t.UsersInRoomUpdatedEventData():
84
+ num_users = len(message.user_ids)
85
+ if num_users <= 1:
86
+ break
87
+ else:
88
+ args.logger.log_info(
89
+ f"Session still open, {num_users} users in room."
90
+ )
91
+ case _:
92
+ args.logger.log_info("Session still open...")
93
+ continue
94
+
95
+ args.logger.log_info("Session closed.")
96
+ return job_definition_t.JobResult(success=True)
97
+
98
+ @property
99
+ def webhook_payload_type(self) -> type:
100
+ return InstrumentPayload
@@ -0,0 +1,140 @@
1
+ from dataclasses import dataclass
2
+ from decimal import Decimal
3
+
4
+ from uncountable.integration.job import JobArguments, WebhookJob, register_job
5
+ from uncountable.types import (
6
+ base_t,
7
+ entity_t,
8
+ generic_upload_t,
9
+ identifier_t,
10
+ job_definition_t,
11
+ notifications_t,
12
+ uploader_t,
13
+ )
14
+
15
+
16
+ @dataclass(kw_only=True)
17
+ class ParsePayload:
18
+ async_job_id: base_t.ObjectId
19
+
20
+
21
+ @register_job
22
+ class ParseExample(WebhookJob[ParsePayload]):
23
+ def run(
24
+ self, args: JobArguments, payload: ParsePayload
25
+ ) -> job_definition_t.JobResult:
26
+ user_id: base_t.ObjectId | None = None
27
+ recipe_id: base_t.ObjectId | None = None
28
+ file_name: str | None = None
29
+ data = args.client.get_entities_data(
30
+ entity_ids=[payload.async_job_id], entity_type=entity_t.EntityType.ASYNC_JOB
31
+ )
32
+ for field_value in data.entity_details[0].field_values:
33
+ if field_value.field_ref_name == "core_async_job_jobData":
34
+ assert isinstance(field_value.value, dict)
35
+ assert isinstance(field_value.value["user_id"], int)
36
+ user_id = field_value.value["user_id"]
37
+ elif (
38
+ field_value.field_ref_name
39
+ == "unc_async_job_custom_parser_recipe_ids_in_view"
40
+ ):
41
+ if field_value.value is None:
42
+ continue
43
+ assert isinstance(field_value.value, list)
44
+ if len(field_value.value) > 0:
45
+ assert isinstance(field_value.value[0], int)
46
+ recipe_id = field_value.value[0]
47
+ elif field_value.field_ref_name == "unc_async_job_custom_parser_input_file":
48
+ assert isinstance(field_value.value, list)
49
+ assert len(field_value.value) == 1
50
+ assert isinstance(field_value.value[0], dict)
51
+ assert isinstance(field_value.value[0]["name"], str)
52
+ file_name = field_value.value[0]["name"]
53
+
54
+ assert user_id is not None
55
+ assert file_name is not None
56
+
57
+ dummy_parsed_file_data: list[uploader_t.ParsedFileData] = [
58
+ uploader_t.ParsedFileData(
59
+ file_name=file_name,
60
+ file_structures=[
61
+ uploader_t.DataChannel(
62
+ type=uploader_t.StructureElementType.CHANNEL,
63
+ channel=uploader_t.TextChannelData(
64
+ name="column1",
65
+ type=uploader_t.ChannelType.TEXT_CHANNEL,
66
+ data=[
67
+ uploader_t.StringValue(value="value1"),
68
+ uploader_t.StringValue(value="value4"),
69
+ uploader_t.StringValue(value="value7"),
70
+ ],
71
+ ),
72
+ ),
73
+ uploader_t.DataChannel(
74
+ type=uploader_t.StructureElementType.CHANNEL,
75
+ channel=uploader_t.TextChannelData(
76
+ name="column2",
77
+ type=uploader_t.ChannelType.TEXT_CHANNEL,
78
+ data=[
79
+ uploader_t.StringValue(value="value2"),
80
+ uploader_t.StringValue(value="value5"),
81
+ uploader_t.StringValue(value="value8"),
82
+ ],
83
+ ),
84
+ ),
85
+ uploader_t.DataChannel(
86
+ type=uploader_t.StructureElementType.CHANNEL,
87
+ channel=uploader_t.TextChannelData(
88
+ name="column3",
89
+ type=uploader_t.ChannelType.TEXT_CHANNEL,
90
+ data=[
91
+ uploader_t.StringValue(value="value3"),
92
+ uploader_t.StringValue(value="value6"),
93
+ uploader_t.StringValue(value="value9"),
94
+ ],
95
+ ),
96
+ ),
97
+ uploader_t.HeaderEntry(
98
+ type=uploader_t.StructureElementType.HEADER,
99
+ value=uploader_t.TextHeaderData(
100
+ name="file_source",
101
+ type=uploader_t.HeaderType.TEXT_HEADER,
102
+ data=uploader_t.StringValue(value="my_file_to_upload.xlsx"),
103
+ ),
104
+ ),
105
+ uploader_t.HeaderEntry(
106
+ type=uploader_t.StructureElementType.HEADER,
107
+ value=uploader_t.NumericHeaderData(
108
+ name="file structure number",
109
+ data=uploader_t.DecimalValue(value=Decimal(99)),
110
+ ),
111
+ ),
112
+ ],
113
+ )
114
+ ]
115
+
116
+ complete_async_parse_req = args.batch_processor.complete_async_parse(
117
+ parsed_file_data=dummy_parsed_file_data,
118
+ async_job_key=identifier_t.IdentifierKeyId(id=payload.async_job_id),
119
+ upload_destination=generic_upload_t.UploadDestinationRecipe(
120
+ recipe_key=identifier_t.IdentifierKeyId(id=recipe_id or 1)
121
+ ),
122
+ )
123
+
124
+ args.batch_processor.push_notification(
125
+ depends_on=[complete_async_parse_req.batch_reference],
126
+ notification_targets=[
127
+ notifications_t.NotificationTargetUser(
128
+ user_key=identifier_t.IdentifierKeyId(id=user_id)
129
+ )
130
+ ],
131
+ subject="Upload complete",
132
+ message="Your file has been uploaded",
133
+ display_notice=True,
134
+ )
135
+
136
+ return job_definition_t.JobResult(success=True)
137
+
138
+ @property
139
+ def webhook_payload_type(self) -> type:
140
+ return ParsePayload
@@ -0,0 +1,61 @@
1
+ import random
2
+ from dataclasses import dataclass
3
+ from datetime import UTC, datetime
4
+ from decimal import Decimal
5
+
6
+ from uncountable.integration.job import JobArguments, WebhookJob, register_job
7
+ from uncountable.types import (
8
+ base_t,
9
+ identifier_t,
10
+ job_definition_t,
11
+ recipe_links_t,
12
+ set_recipe_outputs_t,
13
+ )
14
+
15
+
16
+ @dataclass(kw_only=True)
17
+ class PredictionsPayload:
18
+ output_id: base_t.ObjectId
19
+ recipe_ids: list[base_t.ObjectId]
20
+
21
+
22
+ @register_job
23
+ class PredictionsExample(WebhookJob[PredictionsPayload]):
24
+ def run(
25
+ self, args: JobArguments, payload: PredictionsPayload
26
+ ) -> job_definition_t.JobResult:
27
+ recipe_data = args.client.get_recipes_data(recipe_ids=payload.recipe_ids)
28
+ formatted_datetime = datetime.now(UTC).strftime("%Y-%m-%d %H:%M:%S")
29
+
30
+ for recipe in recipe_data.recipes:
31
+ test_sample_name = f"Predictions Model ({formatted_datetime})"
32
+ created_recipe_id = args.client.create_recipe(
33
+ name=test_sample_name,
34
+ material_family_id=1,
35
+ workflow_id=1,
36
+ definition_key=identifier_t.IdentifierKeyRefName(
37
+ ref_name="unc_test_sample"
38
+ ),
39
+ ).result_id
40
+ args.client.set_recipe_outputs(
41
+ output_data=[
42
+ set_recipe_outputs_t.RecipeOutputValue(
43
+ recipe_id=created_recipe_id,
44
+ output_id=payload.output_id,
45
+ experiment_num=1,
46
+ value_numeric=Decimal(random.random() * 10),
47
+ )
48
+ ]
49
+ )
50
+ args.client.create_recipe_link(
51
+ recipe_from_key=identifier_t.IdentifierKeyId(id=recipe.recipe_id),
52
+ recipe_to_key=identifier_t.IdentifierKeyId(id=created_recipe_id),
53
+ link_type=recipe_links_t.RecipeLinkType.CHILD,
54
+ name=test_sample_name,
55
+ )
56
+
57
+ return job_definition_t.JobResult(success=True)
58
+
59
+ @property
60
+ def webhook_payload_type(self) -> type:
61
+ return PredictionsPayload
@@ -0,0 +1,39 @@
1
+ from io import BytesIO
2
+
3
+ from uncountable.core.file_upload import DataFileUpload, FileUpload
4
+ from uncountable.integration.job import JobArguments, RunsheetWebhookJob, register_job
5
+ from uncountable.types import (
6
+ download_file_t,
7
+ entity_t,
8
+ identifier_t,
9
+ webhook_job_t,
10
+ )
11
+
12
+
13
+ @register_job
14
+ class StandardRunsheetGenerator(RunsheetWebhookJob):
15
+ def build_runsheet(
16
+ self,
17
+ *,
18
+ args: JobArguments,
19
+ payload: webhook_job_t.RunsheetWebhookPayload,
20
+ ) -> FileUpload:
21
+ args.logger.log_info("Retrieving pre-exported runsheet file from async job")
22
+
23
+ file_query = download_file_t.FileDownloadQueryEntityField(
24
+ entity=entity_t.EntityIdentifier(
25
+ type=entity_t.EntityType.ASYNC_JOB,
26
+ identifier_key=identifier_t.IdentifierKeyId(id=payload.async_job_id),
27
+ ),
28
+ field_key=identifier_t.IdentifierKeyRefName(
29
+ ref_name="unc_async_job_export_runsheet_recipe_export"
30
+ ),
31
+ )
32
+
33
+ downloaded_files = args.client.download_files(file_query=file_query)
34
+
35
+ file_data = downloaded_files[0].data.read()
36
+ return DataFileUpload(
37
+ data=BytesIO(file_data),
38
+ name=downloaded_files[0].name,
39
+ )
@@ -0,0 +1,23 @@
1
+ from dataclasses import dataclass
2
+
3
+ from uncountable.integration.job import JobArguments, WebhookJob, register_job
4
+ from uncountable.types import job_definition_t
5
+
6
+
7
+ @dataclass(kw_only=True)
8
+ class ExampleWebhookPayload:
9
+ id: int
10
+ message: str
11
+
12
+
13
+ @register_job
14
+ class WebhookExample(WebhookJob[ExampleWebhookPayload]):
15
+ def run(
16
+ self, args: JobArguments, payload: ExampleWebhookPayload
17
+ ) -> job_definition_t.JobResult:
18
+ args.logger.log_info(f"webhook invoked with payload: {payload}")
19
+ return job_definition_t.JobResult(success=True)
20
+
21
+ @property
22
+ def webhook_payload_type(self) -> type:
23
+ return ExampleWebhookPayload
@@ -0,0 +1,104 @@
1
+ base_url: http://host.docker.internal:5000
2
+ auth_retrieval:
3
+ type: basic
4
+ api_id_secret:
5
+ type: env
6
+ env_key: API_ID
7
+ api_key_secret:
8
+ type: env
9
+ env_key: API_SECRET_KEY
10
+ jobs:
11
+ - id: example_cron
12
+ enabled: true
13
+ type: cron
14
+ name: MyCron - Example
15
+ cron_spec: "* * * * *"
16
+ executor:
17
+ type: script
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
25
+ - id: concurrent_cron_1
26
+ enabled: true
27
+ type: cron
28
+ name: MyConcurrentCron - 1
29
+ cron_spec: "* * * * *"
30
+ executor:
31
+ type: script
32
+ import_path: concurrent_cron
33
+ subqueue_name: subqueue_1
34
+ - id: concurrent_cron_2
35
+ enabled: true
36
+ type: cron
37
+ name: MyConcurrentCron - 2
38
+ cron_spec: "* * * * *"
39
+ executor:
40
+ type: script
41
+ import_path: concurrent_cron
42
+ subqueue_name: subqueue_2
43
+
44
+
45
+ - id: example_wh1
46
+ type: webhook
47
+ name: Webhook 1
48
+ signature_key_secret:
49
+ type: env
50
+ env_key: WH1_SIGNATURE_KEY
51
+ executor:
52
+ type: script
53
+ import_path: example_wh
54
+ - id: example_wh2
55
+ type: webhook
56
+ name: Webhook 2
57
+ signature_key_secret:
58
+ type: env
59
+ env_key: WH2_SIGNATURE_KEY
60
+ executor:
61
+ type: script
62
+ import_path: example_wh
63
+ - id: example_http
64
+ type: custom_http
65
+ name: Custom HTTP
66
+ executor:
67
+ type: script
68
+ import_path: example_http
69
+ - id: example_runsheet_wh
70
+ type: webhook
71
+ name: Runsheet Webhook
72
+ signature_key_secret:
73
+ type: env
74
+ env_key: WH_RUNSHEET_SIGNATURE_KEY
75
+ executor:
76
+ type: script
77
+ import_path: example_runsheet_wh
78
+ - id: example_instrument
79
+ type: webhook
80
+ name: Webhook Instrument Connection
81
+ signature_key_secret:
82
+ type: env
83
+ env_key: WH_INSTRUMENT_SIGNATURE_KEY
84
+ executor:
85
+ type: script
86
+ import_path: example_instrument
87
+ - id: example_predictions
88
+ type: webhook
89
+ name: Webook Predictions
90
+ signature_key_secret:
91
+ type: env
92
+ env_key: WH_PREDICTIONS_SIGNATURE_KEY
93
+ executor:
94
+ type: script
95
+ import_path: example_predictions
96
+ - id: example_parse
97
+ type: webhook
98
+ name: Webhook Parse
99
+ signature_key_secret:
100
+ type: env
101
+ env_key: WH_PARSE_SIGNATURE_KEY
102
+ executor:
103
+ type: script
104
+ import_path: example_parse
@@ -0,0 +1,224 @@
1
+ [project]
2
+ # begin_project_name
3
+ # DO NOT MODIFY
4
+ name = "integration-server-testing"
5
+ # end_project_name
6
+ dynamic = ["version"]
7
+ dependencies = [
8
+ "mypy == 1.*",
9
+ "ruff == 0.*",
10
+ "openpyxl == 3.*",
11
+ "more_itertools == 10.*",
12
+ "types-paramiko ==4.0.0.20250822",
13
+ "types-openpyxl == 3.*",
14
+ "types-pysftp == 0.*",
15
+ "types-pytz ==2025.*",
16
+ "types-requests == 2.*",
17
+ "types-simplejson == 3.*",
18
+ "pandas-stubs",
19
+ "xlrd == 2.*",
20
+ "msgspec == 0.19.*",
21
+ "websockets==15.0.1",
22
+ ]
23
+
24
+ [tool.mypy]
25
+ strict = true
26
+ show_error_codes = true
27
+ check_untyped_defs = true
28
+ disallow_any_generics = false
29
+ disallow_incomplete_defs = true
30
+ disallow_subclassing_any = false
31
+ disallow_untyped_calls = false
32
+ disallow_untyped_decorators = true
33
+ disallow_untyped_defs = true
34
+ implicit_reexport = true
35
+ no_implicit_optional = true
36
+ no_implicit_reexport = true
37
+ strict_equality = true
38
+ warn_redundant_casts = true
39
+ warn_unused_ignores = false
40
+ warn_no_return = true
41
+ warn_return_any = true
42
+ local_partial_types = true
43
+ warn_unreachable = false
44
+ warn_unused_configs = true
45
+ exclude = [
46
+ "env"
47
+ ]
48
+
49
+ [tool.ruff]
50
+ preview = true
51
+ lint.select = ['ALL']
52
+ lint.ignore = [
53
+ "A001", # Variable shadows python built-in. Nice to have
54
+ "A002", # Variable shadows python built-in. Nice to have
55
+ "A003", # Class attribute shadows python built-in. Nice to have
56
+ "ANN", # Missing type annotations. Skip in favor of mypy
57
+ "ARG", # Unused arguments. Skip
58
+ "B006", # Do not use mutable data structures for argument defaults. Priority.
59
+ "B023", # Function doesn't bind loop variable. Priority
60
+ "B904", # Exception handling raise from. Skip
61
+ "BLE", # Blind exception. Should Add
62
+ "C401", # Unecessary generator. Skip
63
+ "C403", # Unnecessary list comprehension. Skip
64
+ "C405", # Unnecessary list. rewrite as set. Skip
65
+ "C408", # Unnecessary dict call. Skip
66
+ "C416", # Unnecessary list comprehension. Skip
67
+ "C417", # Unnecessary use of map. Should Add
68
+ "COM812", # Trailing comma. Too opinionated. Skip
69
+ "CPY", # Copyright notices. Skip
70
+ "D", # Docstrings. Skip
71
+ "DOC", # Docstrings. Skip
72
+ "DTZ001", # Missing tzinfo. Should add
73
+ "DTZ002", # Use of today instead of now. Should add
74
+ "DTZ003", # Use of utcnow not allowed. Should add
75
+ "DTZ004", # Use of utcfrom timestamp not allowed. Should add
76
+ "DTZ005", # now without tz not allowed. Should add
77
+ "DTZ006", # use of from timestamp without tz not allowed. Should add
78
+ "DTZ007", # replace timezone after strptime. Should add
79
+ "DTZ011", # Use of today not allowed. Should add
80
+ "E501", # Line length. Skip
81
+ "EM101", # exception must not use a string literal. skip
82
+ "EM102", # exception must not use an f string. skip
83
+ "EM103", # exception must not use a format string. skip
84
+ "ERA", # Rules around commented code. Skip
85
+ "EXE002", # Executable files need shebang. Skip
86
+ "F841", # TEMPORARY DISABLE TO CLEAR UP BUILD. Unused variables. Prioritize.
87
+ "FBT001", # boolean positional args. Skip
88
+ "FBT002", # boolean default positional. Skip
89
+ "FBT003", # boolean positional. Skip
90
+ "FIX001", # Fixme comment. Skip
91
+ "FIX002", # todo comment. Skip
92
+ "FIX004", # hack comment. Skip
93
+ "FLY002", # Use F-String instead of join. Should Add
94
+ "FURB101", # replace read function. Skip
95
+ "FURB103", # opinionated file opening. Skip
96
+ "FURB113", # extend vs append. Skip
97
+ "FURB118", # opinionated rules about lambdas. skip
98
+ "FURB140", # starmap vs generator. Skip
99
+ "G004", # avoid f strings in log statements. Should add
100
+ "INP001", # implicit imports. use __init__. Skip
101
+ "ISC001", # rule conflicts with formatter. Skip
102
+ "ISC003", # Explicitly concatenated string should be implicitly concatenated. Skip
103
+ "N801", # class name case. Skip
104
+ "N802", # function name lower case. Skip
105
+ "N803", # argument name lower cas. Skip
106
+ "N804", # cls_ first variable. Should add
107
+ "N806", # lower case variable. Skip
108
+ "N812", # case consistency on import. Skip
109
+ "N815", # mix casing, skip
110
+ "N817", # don't use acronym. Should add
111
+ "N818", # exception override should be named with error. should add
112
+ "N999", # module naming. Should add
113
+ "PD002", # avoid inplace. Skip
114
+ "PD004", # .notna. Should add
115
+ "PD010", # .pivottable. Should add
116
+ "PD011", # use .to_numpy. Skip
117
+ "PD015", # use .merge. Should add
118
+ "PERF203", # avoid try except in loop. Skip
119
+ "PERF401", # use list comprehension. Skip
120
+ "PERF402", # use list.copy. Skip
121
+ "PERF403", # use dictionary comprehension. Skip
122
+ "S307", # avoid eval. Should add
123
+ "PGH003", # ignore specific rules. Skip
124
+ "PGH004", # ignore specific rules. Skip
125
+ "PLC0414", # import alias doesn't rename. Skip
126
+ "PLC0415", # import at top level. Skip
127
+ "PLC1901", # falsy empty string. Skip
128
+ "PLR0124", # self comparison. Skip
129
+ "PLR0402", # alias import. Skip
130
+ "PLR0911", # too many return statements. Skip
131
+ "PLR0912", # too many branches. Skip
132
+ "PLR0913", # too many arguments. Skip
133
+ "PLR0915", # too many statements. Skip
134
+ "PLR0916", # too many expressions. Skip
135
+ "PLR0917", # too many positional arguments. Skip
136
+ "PLR1714", # multiple comparisons. Skip
137
+ "PLR2004", # magic values. skip
138
+ "PLR5501", # use elif instead of else if. skip
139
+ "PLR6104", # use augmented assignment. confuses strings, wait for fix. skip
140
+ "PLR6201", # use a set literal for membership test. skip
141
+ "PLR6301", # method inference. skip
142
+ "PLW0108", # inline lambda. skip
143
+ "PLW0120", # else without break. skip
144
+ "PLW0602", # global withotu assignment. consider
145
+ "PLW0603", # discourage global. skip
146
+ "PLW1510", # subprocess run without check arg. skip
147
+ "PLW1514", # open without encoding. skip
148
+ "PLW2901", # for loop variable overwritten. skip
149
+ "PT001", # change ficture decorator. should add
150
+ "PT011", # use more specific raises decorator. should add
151
+ "PT018", # break down complex assertsions. skip
152
+ "PTH", # enforces new python path library usage. skip
153
+ "PYI030", # turn union of literals to just literal with multiple. should add
154
+ "PYI041", # use float instead of int | float. should remove floats
155
+ "RET", # enforces return semantics. break up and re-evaluate later
156
+ "RSE102", # unnecessary parens on exception. skip.
157
+ "RUF001", # ambiguous characters. skip
158
+ "RUF005", # prefer star to concatenation. skip
159
+ "RUF010", # use explicit conversion flag. skip
160
+ "RUF012", # type with class var. should add
161
+ "RUF015", # prefer next for single element. skip
162
+ "RUF100", # unused noqa. should add
163
+ "S", # should split up
164
+ "S101", # allow asserts. skip
165
+ "SIM102", # use single if instead of nested. skip
166
+ "SIM105", # use exception supress. skip
167
+ "SIM108", # use ternary. skip
168
+ "SIM110", # use any/all. should add
169
+ "SIM112", # case of env variable. skip
170
+ "SIM114", # combine if branches. skip
171
+ "SIM115", # use context handler for files. should add
172
+ "SIM117", # use single with. should add
173
+ "SLF001", # private member access. should add
174
+ "SLOT000", # subclass of string should define slot. should add
175
+ "T201", # print. skip
176
+ "T203", # pprint. skip
177
+ "TC001", # move application import into type checking. skip
178
+ "TC002", # move third party import into type checking. consider
179
+ "TC003", # move library into type checking lbock. consider
180
+ "TD", # todo comments. skip
181
+ "TID252", # eliminate relative imports from parents. skip
182
+ "TRY002", # create your own exception. skip
183
+ "TRY003", # avoid long messages. skip
184
+ "TRY004", # prefer type error. should add
185
+ "TRY201", # raise without exception name. consider
186
+ "TRY300", # move statement to else block. consider
187
+ "TRY301", # move raise to inner function. skip
188
+ "UP007", # use union for type annotations. should add
189
+ "UP013", # eliminate typeddict. should add
190
+ "UP031", # use format specifiers. should add
191
+ "B905", # zip strict. we have a deprecated pattern here, consider
192
+ "UP036", # outdated version block, consider
193
+ "RUF007", # prefer itertools.pairwise over zip, consider
194
+ "RUF022", # __all__ is not sorted. skip due to isort complication
195
+ "UP017", # use datetime.UTC, TODO add back in
196
+ "UP035", # replacing List with list, TODO add back in
197
+ # ## FROM RUFF UPGRADE
198
+ "PLC2701", # private name imports. should add
199
+ "PLR1702", # too many nested blocks -- add with config. skip
200
+ "C420", # unnecessary dict comprehension. skip
201
+ "SIM113", # index variable should use enumerate. should add.
202
+ "PLR0914" # too many local variables. configure below. should add with config
203
+ ]
204
+ line-length = 90
205
+ target-version = "py311"
206
+
207
+ exclude = [
208
+ 'env'
209
+ ]
210
+ [tool.ruff.lint.per-file-ignores]
211
+ "__init__.py" = ["F401"]
212
+
213
+ [tool.ruff.lint.isort]
214
+ split-on-trailing-comma = true
215
+ known-first-party = ["pkgs"]
216
+
217
+ [tool.ruff.lint.mccabe]
218
+ max-complexity = 130 # goal would be to bring this down to ~50 or so
219
+
220
+ [tool.ruff.lint.pylint]
221
+ max-locals=50
222
+
223
+ [tool.setuptools]
224
+ py-modules = []