openlineage-python 0.30.1__tar.gz → 1.0.0__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.
Files changed (41) hide show
  1. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/PKG-INFO +6 -2
  2. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/README.md +5 -1
  3. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/client.py +1 -5
  4. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/constants.py +1 -1
  5. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/transport/http.py +38 -16
  6. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/pyproject.toml +1 -1
  7. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/test_http.py +12 -2
  8. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tox.ini +0 -9
  9. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/.gitignore +0 -0
  10. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/__init__.py +0 -0
  11. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/facet.py +0 -0
  12. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/filter.py +0 -0
  13. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/py.typed +0 -0
  14. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/run.py +0 -0
  15. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/serde.py +0 -0
  16. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/transport/__init__.py +0 -0
  17. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/transport/console.py +0 -0
  18. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/transport/factory.py +0 -0
  19. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/transport/file.py +0 -0
  20. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/transport/kafka.py +0 -0
  21. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/transport/noop.py +0 -0
  22. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/transport/transport.py +0 -0
  23. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/openlineage/client/utils.py +0 -0
  24. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/__init__.py +0 -0
  25. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/config/config.yml +0 -0
  26. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/config/exact_filter.yml +0 -0
  27. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/config/http.yml +0 -0
  28. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/config/openlineage.yml +0 -0
  29. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/config/regex_filter.yml +0 -0
  30. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/conftest.py +0 -0
  31. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/nominal_time_without_end.json +0 -0
  32. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/serde_example_dataset_event.json +0 -0
  33. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/serde_example_job_event.json +0 -0
  34. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/serde_example_run_event.json +0 -0
  35. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/test_client.py +0 -0
  36. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/test_events.py +0 -0
  37. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/test_facet.py +0 -0
  38. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/test_factory.py +0 -0
  39. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/test_file.py +0 -0
  40. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/test_kafka.py +0 -0
  41. {openlineage_python-0.30.1 → openlineage_python-1.0.0}/tests/transport.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openlineage-python
3
- Version: 0.30.1
3
+ Version: 1.0.0
4
4
  Summary: OpenLineage Python Client
5
5
  Author-email: OpenLineage <info@openlineage.io>
6
6
  Keywords: openlineage
@@ -60,7 +60,7 @@ transport:
60
60
  ```
61
61
 
62
62
  The `type` property is required. It can be one of the built-in transports or a custom one.
63
- There are three built-in transports, `http`, `kafka` and `console`.
63
+ There are four built-in transports, `http`, `kafka`, `console` and `file`.
64
64
  Custom transports `type` is a fully qualified class name that can be imported.
65
65
 
66
66
  The rest of the properties are defined by the particular transport.
@@ -85,6 +85,10 @@ You can also install `pip install openlineage-python[kafka]`
85
85
  * `topic` - required string parameter. The topic on what events will be sent.
86
86
  * `flush` - optional boolean parameter. If set to True, Kafka will flush after each event. By default true.
87
87
 
88
+ #### File
89
+
90
+ * `log_file_path` - required string parameter specifying the path of the file (if `append` is true a file path is expected, otherwise a file prefix is expected).
91
+ * `append` - optional boolean parameter. If set to True, each event will be appended to a single file (log_file_path), otherwise, all event would be written separatly in distinct files suffixed by a timestring. By default false.
88
92
 
89
93
  ### Custom transport
90
94
 
@@ -31,7 +31,7 @@ transport:
31
31
  ```
32
32
 
33
33
  The `type` property is required. It can be one of the built-in transports or a custom one.
34
- There are three built-in transports, `http`, `kafka` and `console`.
34
+ There are four built-in transports, `http`, `kafka`, `console` and `file`.
35
35
  Custom transports `type` is a fully qualified class name that can be imported.
36
36
 
37
37
  The rest of the properties are defined by the particular transport.
@@ -56,6 +56,10 @@ You can also install `pip install openlineage-python[kafka]`
56
56
  * `topic` - required string parameter. The topic on what events will be sent.
57
57
  * `flush` - optional boolean parameter. If set to True, Kafka will flush after each event. By default true.
58
58
 
59
+ #### File
60
+
61
+ * `log_file_path` - required string parameter specifying the path of the file (if `append` is true a file path is expected, otherwise a file prefix is expected).
62
+ * `append` - optional boolean parameter. If set to True, each event will be appended to a single file (log_file_path), otherwise, all event would be written separatly in distinct files suffixed by a timestring. By default false.
59
63
 
60
64
  ### Custom transport
61
65
 
@@ -59,10 +59,6 @@ class OpenLineageClient:
59
59
  # HTTP transport.
60
60
  if not options:
61
61
  options = OpenLineageClientOptions()
62
- if not session:
63
- from requests import Session
64
-
65
- session = Session()
66
62
  self._initialize_url(url, options, session)
67
63
  elif transport:
68
64
  self.transport = transport
@@ -81,7 +77,7 @@ class OpenLineageClient:
81
77
  self,
82
78
  url: str,
83
79
  options: OpenLineageClientOptions,
84
- session: Session,
80
+ session: Session | None,
85
81
  ) -> None:
86
82
  self.transport = HttpTransport(
87
83
  HttpConfig.from_options(
@@ -2,7 +2,7 @@
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = "0.30.1"
5
+ __version__ = "1.0.0"
6
6
 
7
7
  DEFAULT_TIMEOUT_MS = 5000
8
8
  DEFAULT_NAMESPACE_NAME = "default"
@@ -11,12 +11,13 @@ from urllib.parse import urljoin
11
11
  import attr
12
12
 
13
13
  if TYPE_CHECKING:
14
- from requests import Session
15
14
  from requests.adapters import HTTPAdapter, Response
16
15
 
17
16
  from openlineage.client.client import OpenLineageClientOptions
18
17
  from openlineage.client.run import DatasetEvent, JobEvent, RunEvent
19
18
 
19
+ from requests import Session
20
+
20
21
  from openlineage.client.serde import Serde
21
22
  from openlineage.client.transport.transport import Config, Transport
22
23
  from openlineage.client.utils import get_only_specified_fields, try_import_from_string
@@ -74,7 +75,7 @@ class HttpConfig(Config):
74
75
  verify: bool = attr.ib(default=True)
75
76
  auth: TokenProvider = attr.ib(factory=lambda: TokenProvider({}))
76
77
  # not set by TransportFactory
77
- session: Session = attr.ib(factory=get_session)
78
+ session: Session | None = attr.ib(default=None)
78
79
  # not set by TransportFactory
79
80
  adapter: HTTPAdapter | None = attr.ib(default=None)
80
81
 
@@ -101,7 +102,7 @@ class HttpConfig(Config):
101
102
  auth=ApiKeyTokenProvider({"api_key": options.api_key})
102
103
  if options.api_key
103
104
  else TokenProvider({}),
104
- session=session if session else get_session(),
105
+ session=session,
105
106
  adapter=options.adapter,
106
107
  )
107
108
 
@@ -112,8 +113,9 @@ class HttpTransport(Transport):
112
113
 
113
114
  def __init__(self, config: HttpConfig) -> None:
114
115
  url = config.url.strip()
116
+ self.config = config
115
117
 
116
- log.debug("Constructing openlineage client to send events to %s", url)
118
+ log.debug("Constructing openlineage client to send events to %s - config %s", url, config)
117
119
  try:
118
120
  from urllib3.util import parse_url
119
121
 
@@ -127,30 +129,50 @@ class HttpTransport(Transport):
127
129
  raise ValueError(msg)
128
130
  self.url = url
129
131
  self.endpoint = config.endpoint
130
- self.session = config.session
131
- self.session.headers["Content-Type"] = "application/json"
132
+ self.session = None
133
+ if config.session:
134
+ self.session = config.session
135
+ self.session.headers["Content-Type"] = "application/json"
136
+ auth_headers = self._auth_headers(config.auth)
137
+ self.session.headers.update(auth_headers)
132
138
  self.timeout = config.timeout
133
139
  self.verify = config.verify
134
140
 
135
- self._add_auth(config.auth)
136
141
  if config.adapter:
137
142
  self.set_adapter(config.adapter)
138
143
 
139
144
  def set_adapter(self, adapter: HTTPAdapter) -> None:
140
- self.session.mount(self.url, adapter)
145
+ if self.session:
146
+ self.session.mount(self.url, adapter)
141
147
 
142
148
  def emit(self, event: Union[RunEvent, DatasetEvent, JobEvent]) -> Response: # noqa: UP007
143
149
  event_str = Serde.to_json(event)
144
- resp = self.session.post(
145
- urljoin(self.url, self.endpoint),
146
- event_str,
147
- timeout=self.timeout,
148
- verify=self.verify,
149
- )
150
+ if self.session:
151
+ resp = self.session.post(
152
+ urljoin(self.url, self.endpoint),
153
+ event_str,
154
+ timeout=self.timeout,
155
+ verify=self.verify,
156
+ )
157
+ else:
158
+ headers = {
159
+ "Content-Type": "application/json",
160
+ }
161
+ headers.update(self._auth_headers(self.config.auth))
162
+ with Session() as session:
163
+ resp = session.post(
164
+ urljoin(self.url, self.endpoint),
165
+ event_str,
166
+ headers=headers,
167
+ timeout=self.timeout,
168
+ verify=self.verify,
169
+ )
170
+ resp.close()
150
171
  resp.raise_for_status()
151
172
  return resp
152
173
 
153
- def _add_auth(self, token_provider: TokenProvider) -> None:
174
+ def _auth_headers(self, token_provider: TokenProvider) -> dict: # type: ignore[type-arg]
154
175
  bearer = token_provider.get_bearer()
155
176
  if bearer:
156
- self.session.headers.update({"Authorization": bearer})
177
+ return {"Authorization": bearer}
178
+ return {}
@@ -6,7 +6,7 @@ requires = [
6
6
 
7
7
  [project]
8
8
  name = "openlineage-python"
9
- version = "0.30.1"
9
+ version = "1.0.0"
10
10
  description = "OpenLineage Python Client"
11
11
  readme = "README.md"
12
12
  keywords = [
@@ -35,7 +35,7 @@ def test_http_loads_full_config() -> None:
35
35
  assert config.endpoint == "api/v1/lineage"
36
36
  assert config.verify is False
37
37
  assert config.auth.api_key == "1500100900"
38
- assert isinstance(config.session, Session)
38
+ assert config.session is None
39
39
  assert config.adapter is None
40
40
 
41
41
 
@@ -49,7 +49,7 @@ def test_http_loads_minimal_config() -> None:
49
49
  assert config.url == "http://backend:5000/api/v1/lineage"
50
50
  assert config.verify is True
51
51
  assert not hasattr(config.auth, "api_key")
52
- assert isinstance(config.session, Session)
52
+ assert config.session is None
53
53
  assert config.adapter is None
54
54
 
55
55
 
@@ -111,3 +111,13 @@ def test_client_with_http_transport_emits_custom_endpoint(mocker: MockerFixture)
111
111
  timeout=5.0,
112
112
  verify=True,
113
113
  )
114
+
115
+
116
+ def test_http_config_configs_session() -> None:
117
+ with Session() as s:
118
+ config = HttpConfig(url="http://backend:5000/api/v1/lineage", session=s)
119
+ assert config.url == "http://backend:5000/api/v1/lineage"
120
+ assert config.verify is True
121
+ assert not hasattr(config.auth, "api_key")
122
+ assert config.session is s
123
+ assert config.adapter is None
@@ -8,7 +8,6 @@ env_list =
8
8
  py39
9
9
  py38
10
10
  type
11
- fix
12
11
  skip_missing_interpreters = true
13
12
 
14
13
  [testenv]
@@ -44,14 +43,6 @@ set_env =
44
43
  commands =
45
44
  mypy --namespace-packages --explicit-package-bases openlineage
46
45
 
47
- [testenv:fix]
48
- description = run static analysis and style check using flake8
49
- skip_install = true
50
- deps =
51
- pre-commit>=3.3.2
52
- commands =
53
- pre-commit run --all-files --show-diff-on-failure
54
-
55
46
  [testenv:dev]
56
47
  description = generate a DEV environment
57
48
  package = editable