omnata-plugin-runtime 0.10.22a276__tar.gz → 0.12.2a340__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of omnata-plugin-runtime might be problematic. Click here for more details.

Files changed (16) hide show
  1. omnata_plugin_runtime-0.12.2a340/PKG-INFO +56 -0
  2. omnata_plugin_runtime-0.12.2a340/pyproject.toml +57 -0
  3. {omnata_plugin_runtime-0.10.22a276 → omnata_plugin_runtime-0.12.2a340}/src/omnata_plugin_runtime/api.py +4 -4
  4. {omnata_plugin_runtime-0.10.22a276 → omnata_plugin_runtime-0.12.2a340}/src/omnata_plugin_runtime/configuration.py +49 -1
  5. {omnata_plugin_runtime-0.10.22a276 → omnata_plugin_runtime-0.12.2a340}/src/omnata_plugin_runtime/json_schema.py +354 -118
  6. {omnata_plugin_runtime-0.10.22a276 → omnata_plugin_runtime-0.12.2a340}/src/omnata_plugin_runtime/logging.py +2 -1
  7. {omnata_plugin_runtime-0.10.22a276 → omnata_plugin_runtime-0.12.2a340}/src/omnata_plugin_runtime/omnata_plugin.py +459 -125
  8. {omnata_plugin_runtime-0.10.22a276 → omnata_plugin_runtime-0.12.2a340}/src/omnata_plugin_runtime/plugin_entrypoints.py +18 -3
  9. omnata_plugin_runtime-0.12.2a340/src/omnata_plugin_runtime/threading_utils.py +27 -0
  10. omnata_plugin_runtime-0.10.22a276/PKG-INFO +0 -55
  11. omnata_plugin_runtime-0.10.22a276/pyproject.toml +0 -57
  12. {omnata_plugin_runtime-0.10.22a276 → omnata_plugin_runtime-0.12.2a340}/LICENSE +0 -0
  13. {omnata_plugin_runtime-0.10.22a276 → omnata_plugin_runtime-0.12.2a340}/README.md +0 -0
  14. {omnata_plugin_runtime-0.10.22a276 → omnata_plugin_runtime-0.12.2a340}/src/omnata_plugin_runtime/__init__.py +0 -0
  15. {omnata_plugin_runtime-0.10.22a276 → omnata_plugin_runtime-0.12.2a340}/src/omnata_plugin_runtime/forms.py +0 -0
  16. {omnata_plugin_runtime-0.10.22a276 → omnata_plugin_runtime-0.12.2a340}/src/omnata_plugin_runtime/rate_limiting.py +0 -0
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.4
2
+ Name: omnata-plugin-runtime
3
+ Version: 0.12.2a340
4
+ Summary: Classes and common runtime components for building and running Omnata Plugins
5
+ License-File: LICENSE
6
+ Author: James Weakley
7
+ Author-email: james.weakley@omnata.com
8
+ Requires-Python: >=3.10,<=3.13
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Requires-Dist: annotated-types (<=0.6.0)
15
+ Requires-Dist: certifi (<=2025.1.31)
16
+ Requires-Dist: cffi (<=2.0.0)
17
+ Requires-Dist: charset-normalizer (<=3.4.4)
18
+ Requires-Dist: cryptography (<=46.0.3)
19
+ Requires-Dist: filelock (<=3.20.0)
20
+ Requires-Dist: idna (<=3.11)
21
+ Requires-Dist: jinja2 (>=3.1.2,<=3.1.6)
22
+ Requires-Dist: markupsafe (<=3.0.2)
23
+ Requires-Dist: numpy (<=2.3.5)
24
+ Requires-Dist: opentelemetry-api (<=1.38.0)
25
+ Requires-Dist: packaging (<=25.0)
26
+ Requires-Dist: pandas (<=2.3.3)
27
+ Requires-Dist: platformdirs (<=4.5.0)
28
+ Requires-Dist: protobuf (<=6.33.0)
29
+ Requires-Dist: pyarrow (<=21.0.0)
30
+ Requires-Dist: pycparser (<=2.23)
31
+ Requires-Dist: pydantic (>=2,<=2.12.4)
32
+ Requires-Dist: pydantic-core (<=2.41.5)
33
+ Requires-Dist: pyjwt (<=2.10.1)
34
+ Requires-Dist: pyopenssl (<=225.3.0)
35
+ Requires-Dist: pytz (<=2025.2)
36
+ Requires-Dist: pyyaml (<=6.0.3)
37
+ Requires-Dist: requests (>=2,<=2.32.5)
38
+ Requires-Dist: setuptools (<=80.9.0)
39
+ Requires-Dist: snowflake-connector-python (>=3,<4)
40
+ Requires-Dist: snowflake-snowpark-python (>=1.20.0,<=1.43.0)
41
+ Requires-Dist: snowflake-telemetry-python (<=0.5.0)
42
+ Requires-Dist: tenacity (>=8,<9)
43
+ Requires-Dist: tomlkit (<=0.13.3)
44
+ Requires-Dist: urllib3 (<=2.5.0)
45
+ Requires-Dist: wheel (<=0.45.1)
46
+ Requires-Dist: wrapt (<=2.0.1)
47
+ Description-Content-Type: text/markdown
48
+
49
+ # omnata-plugin-runtime
50
+ This package is a runtime dependency for [Omnata Plugins](https://docs.omnata.com/omnata-product-documentation/omnata-sync-for-snowflake/plugins).
51
+
52
+ It contains data classes, interfaces and application logic used to perform plugin operations.
53
+
54
+ For instructions on creating plugins, visit our [docs site](https://docs.omnata.com/omnata-product-documentation/omnata-sync-for-snowflake/plugins/creating-plugins).
55
+
56
+
@@ -0,0 +1,57 @@
1
+ [tool.poetry]
2
+ name = "omnata-plugin-runtime"
3
+ version = "0.12.2a340"
4
+ description = "Classes and common runtime components for building and running Omnata Plugins"
5
+ authors = ["James Weakley <james.weakley@omnata.com>"]
6
+ readme = "README.md"
7
+ packages = [{include = "omnata_plugin_runtime", from = "src"}]
8
+
9
+ [tool.poetry.dependencies]
10
+ python = ">=3.10, <=3.13"
11
+ snowflake-snowpark-python = ">=1.20.0,<=1.43.0" # latest version available on Snowflake Anaconda, but allow pinning to 1.20.0 for to_pandas_batches workaround
12
+ snowflake-connector-python = "^3, <=4.1.0" # latest version available on Snowflake Anaconda
13
+ cryptography = "<=46.0.3"
14
+ annotated-types = "<=0.6.0"
15
+ pycparser = "<=2.23"
16
+ filelock = "<=3.20.0"
17
+ pydantic-core = "<=2.41.5"
18
+ # had to relax some of these thanks to snowcli pinning newer versions
19
+ certifi = "<=2025.1.31" # latest version available on Snowflake Anaconda which doesn't break the Snowflake connector
20
+ charset-normalizer = "<=3.4.4" # latest version available on Snowflake Anaconda
21
+ idna = "<=3.11" # latest version available on Snowflake Anaconda
22
+ jinja2 = ">=3.1.2,<=3.1.6" # 3.1.6 was latest version available on Snowflake Anaconda
23
+ markupsafe = "<=3.0.2" # latest version available on Snowflake Anaconda
24
+ numpy = "<=2.3.5" # latest version available on Snowflake Anaconda
25
+ packaging = "<=25.0" # latest version available on Snowflake Anaconda
26
+ pandas = "<=2.3.3" # latest version available on Snowflake Anaconda
27
+ platformdirs = "<=4.5.0" # latest version available on Snowflake Anaconda
28
+ pydantic = "^2, <=2.12.4" # latest version available on Snowflake Anaconda
29
+ pyjwt = "<=2.10.1" # latest version available on Snowflake Anaconda
30
+ pyopenssl = "<=225.3.0" # latest version available on Snowflake Anaconda
31
+ pytz = "<=2025.2" # latest version available on Snowflake Anaconda
32
+ requests = "^2, <=2.32.5" # latest version available on Snowflake Anaconda
33
+ setuptools = "<=80.9.0" # latest version available on Snowflake Anaconda
34
+ tomlkit = "<=0.13.3" # latest version available on Snowflake Anaconda
35
+ tenacity = "^8, <=9.1.2" # latest version available on Snowflake Anaconda
36
+ urllib3 = "<=2.5.0" # latest version available on Snowflake Anaconda
37
+ wheel = "<=0.45.1" # latest version available on Snowflake Anaconda
38
+ pyyaml = "<=6.0.3" # latest version available on Snowflake Anaconda
39
+ cffi = "<=2.0.0" # latest version available on Snowflake Anaconda
40
+ pyarrow = "<=21.0.0" # latest version available on Snowflake Anaconda
41
+ wrapt = "<=2.0.1" # latest version available on Snowflake Anaconda
42
+ opentelemetry-api = "<=1.38.0" # latest version available on Snowflake Anaconda
43
+ snowflake-telemetry-python = "<=0.5.0" # latest version available on Snowflake Anaconda
44
+ protobuf = "<=6.33.0" # latest version available on Snowflake Anaconda
45
+
46
+ [tool.poetry.dev-dependencies]
47
+ pytest = "^6.2.4"
48
+ deepdiff = "^6"
49
+ requests-mock = ">=1.9.3"
50
+
51
+ [tool.pytest.ini_options]
52
+ addopts = ["--import-mode=importlib"]
53
+ testpaths = ["tests"]
54
+
55
+ [build-system]
56
+ requires = ["poetry-core"]
57
+ build-backend = "poetry.core.masonry.api"
@@ -108,9 +108,9 @@ class OutboundSyncRequestPayload(BaseModel):
108
108
  Encapsulates the payload that is sent to the plugin when it is invoked to perform an outbound sync.
109
109
  """
110
110
 
111
- sync_id: int # only used by log handler
111
+ sync_id: int
112
112
  sync_branch_name: str = 'main'
113
- sync_branch_id: Optional[int] # only used by log handler
113
+ sync_branch_id: Optional[int]
114
114
  connection_id: int # only used by log handler
115
115
  run_id: int # used by log handler and for reporting back run status updates
116
116
  source_app_name: str # the name of the app which is invoking this plugin
@@ -139,8 +139,8 @@ class InboundSyncRequestPayload(BaseModel):
139
139
  Encapsulates the payload that is sent to the plugin when it is invoked to perform an inbound sync.
140
140
  """
141
141
 
142
- sync_id: int # only used by log handler
143
- sync_branch_name: str = 'main' # only used by rate limit updater
142
+ sync_id: int
143
+ sync_branch_name: str = 'main'
144
144
  sync_branch_id: Optional[int] = None # only used by log handler
145
145
  connection_id: int # only used by log handler
146
146
  run_id: int # used by log handler and for reporting back run status updates
@@ -614,6 +614,10 @@ class StreamConfiguration(SubscriptableBaseModel):
614
614
  None,
615
615
  description="Marks the stream as requiring another stream to be selected"
616
616
  )
617
+ mandatory: bool = Field(
618
+ False,
619
+ description="Marks the stream as mandatory, meaning it cannot be excluded from the sync configuration"
620
+ )
617
621
 
618
622
 
619
623
  class StoredConfigurationValue(SubscriptableBaseModel):
@@ -689,6 +693,9 @@ class ConnectionConfigurationParameters(SubscriptableBaseModel):
689
693
  _snowflake: Optional[Any] = PrivateAttr( # or use Any to annotate the type and use Field to initialize
690
694
  default=None
691
695
  )
696
+ _sync_request: Optional[Any] = PrivateAttr( # Reference to SyncRequest for worker thread access
697
+ default=None
698
+ )
692
699
 
693
700
  @model_validator(mode='after')
694
701
  def validate_ngrok_tunnel_settings(self) -> Self:
@@ -735,6 +742,23 @@ class ConnectionConfigurationParameters(SubscriptableBaseModel):
735
742
  """
736
743
  if parameter_name=='access_token' and self.access_token_secret_name is not None:
737
744
  import _snowflake # pylint: disable=import-error, import-outside-toplevel # type: ignore
745
+ from .threading_utils import is_managed_worker_thread
746
+
747
+ # Check if we're in a worker thread using the explicit flag
748
+ # This is more reliable than checking thread names
749
+ if is_managed_worker_thread() and self._sync_request is not None:
750
+ logger.debug(f"Worker thread requesting access_token via secrets service")
751
+ try:
752
+ secrets = self._sync_request.request_secrets_from_main_thread(
753
+ self.access_token_secret_name, None
754
+ )
755
+ if 'access_token' in secrets:
756
+ return secrets['access_token']
757
+ except Exception as e:
758
+ logger.error(f"Error requesting access_token from main thread: {e}")
759
+ raise
760
+
761
+ # Otherwise, call _snowflake directly (main thread)
738
762
  return StoredConfigurationValue(
739
763
  value=_snowflake.get_oauth_access_token(self.access_token_secret_name)
740
764
  )
@@ -1001,10 +1025,34 @@ StoredFieldMappings.model_rebuild()
1001
1025
  OutboundSyncConfigurationParameters.model_rebuild()
1002
1026
 
1003
1027
  @tracer.start_as_current_span("get_secrets")
1004
- def get_secrets(oauth_secret_name: Optional[str], other_secrets_name: Optional[str]
1028
+ def get_secrets(oauth_secret_name: Optional[str], other_secrets_name: Optional[str],
1029
+ sync_request: Optional[Any] = None
1005
1030
  ) -> Dict[str, StoredConfigurationValue]:
1031
+ """
1032
+ Get secrets from Snowflake. This function can be called from the main thread or worker threads.
1033
+ When called from worker threads (e.g., within @managed_inbound_processing), it will automatically
1034
+ route the request through the secrets service to avoid threading issues with _snowflake.get_oauth_access_token.
1035
+
1036
+ :param oauth_secret_name: The name of the OAuth secret to retrieve
1037
+ :param other_secrets_name: The name of other secrets to retrieve
1038
+ :param sync_request: Optional SyncRequest instance for worker threads. If not provided, will attempt to detect.
1039
+ :return: Dictionary of StoredConfigurationValue objects
1040
+ """
1041
+ from .threading_utils import is_managed_worker_thread
1006
1042
  connection_secrets = {}
1007
1043
  import _snowflake # pylint: disable=import-error, import-outside-toplevel # type: ignore
1044
+
1045
+ # Check if we're in a worker thread using the explicit flag
1046
+ # This is more reliable than checking thread names
1047
+ if is_managed_worker_thread() and sync_request is not None:
1048
+ logger.debug(f"Worker thread requesting secrets via secrets service")
1049
+ try:
1050
+ return sync_request.request_secrets_from_main_thread(oauth_secret_name, other_secrets_name)
1051
+ except Exception as e:
1052
+ logger.error(f"Error requesting secrets from main thread: {e}")
1053
+ raise
1054
+
1055
+ # Otherwise, call _snowflake functions directly (main thread)
1008
1056
  if oauth_secret_name is not None:
1009
1057
  connection_secrets["access_token"] = StoredConfigurationValue(
1010
1058
  value=_snowflake.get_oauth_access_token(oauth_secret_name)