dnaStreaming 2.3.1__tar.gz → 2.4.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. dnastreaming-2.4.0/.github/workflows/publish.yaml +32 -0
  2. dnastreaming-2.4.0/.gitignore +132 -0
  3. dnastreaming-2.4.0/CHANGELOG.md +152 -0
  4. {dnastreaming-2.3.1 → dnastreaming-2.4.0}/LICENSE +1 -1
  5. dnastreaming-2.4.0/PKG-INFO +279 -0
  6. dnastreaming-2.4.0/README.md +253 -0
  7. {dnastreaming-2.3.1 → dnastreaming-2.4.0}/demo/pubsub_stream.py +60 -32
  8. {dnastreaming-2.3.1 → dnastreaming-2.4.0}/demo/show_ha_stream_async.py +32 -17
  9. {dnastreaming-2.3.1 → dnastreaming-2.4.0}/demo/show_stream.py +28 -16
  10. {dnastreaming-2.3.1 → dnastreaming-2.4.0}/demo/show_stream_async.py +30 -15
  11. dnastreaming-2.4.0/pyproject.toml +117 -0
  12. dnastreaming-2.4.0/setup.cfg +4 -0
  13. {dnastreaming-2.3.1 → dnastreaming-2.4.0/src}/dnaStreaming/__init__.py +10 -8
  14. dnastreaming-2.4.0/src/dnaStreaming/config.py +170 -0
  15. dnastreaming-2.4.0/src/dnaStreaming/customer_config.json +5 -0
  16. {dnastreaming-2.3.1 → dnastreaming-2.4.0/src}/dnaStreaming/listener.py +102 -58
  17. {dnastreaming-2.3.1 → dnastreaming-2.4.0/src}/dnaStreaming/services/availability_service.py +34 -19
  18. {dnastreaming-2.3.1 → dnastreaming-2.4.0/src}/dnaStreaming/services/credentials_service.py +10 -9
  19. {dnastreaming-2.3.1 → dnastreaming-2.4.0/src}/dnaStreaming/services/pubsub_service.py +5 -4
  20. dnastreaming-2.4.0/src/dnaStreaming.egg-info/PKG-INFO +279 -0
  21. dnastreaming-2.4.0/src/dnaStreaming.egg-info/SOURCES.txt +27 -0
  22. dnastreaming-2.4.0/src/dnaStreaming.egg-info/requires.txt +9 -0
  23. {dnastreaming-2.3.1 → dnastreaming-2.4.0/src}/dnaStreaming.egg-info/top_level.txt +0 -1
  24. dnastreaming-2.4.0/tests/test_async.py +47 -0
  25. dnastreaming-2.4.0/tests/test_sync.py +40 -0
  26. dnastreaming-2.3.1/MANIFEST.in +0 -1
  27. dnastreaming-2.3.1/PKG-INFO +0 -280
  28. dnastreaming-2.3.1/README.rst +0 -254
  29. dnastreaming-2.3.1/dnaStreaming/config.py +0 -109
  30. dnastreaming-2.3.1/dnaStreaming/customer_config.json +0 -5
  31. dnastreaming-2.3.1/dnaStreaming/test/__init__.py +0 -3
  32. dnastreaming-2.3.1/dnaStreaming/test/test_config.py +0 -119
  33. dnastreaming-2.3.1/dnaStreaming.egg-info/PKG-INFO +0 -280
  34. dnastreaming-2.3.1/dnaStreaming.egg-info/SOURCES.txt +0 -26
  35. dnastreaming-2.3.1/dnaStreaming.egg-info/requires.txt +0 -9
  36. dnastreaming-2.3.1/setup.cfg +0 -7
  37. dnastreaming-2.3.1/setup.py +0 -47
  38. {dnastreaming-2.3.1 → dnastreaming-2.4.0}/demo/__init__.py +0 -0
  39. {dnastreaming-2.3.1 → dnastreaming-2.4.0/src}/dnaStreaming/services/__init__.py +0 -0
  40. {dnastreaming-2.3.1 → dnastreaming-2.4.0/src}/dnaStreaming/services/authentication_service.py +0 -0
  41. {dnastreaming-2.3.1 → dnastreaming-2.4.0/src}/dnaStreaming.egg-info/dependency_links.txt +0 -0
@@ -0,0 +1,32 @@
1
+ name: Publish a new version to PyPI when a new release is published
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ pypi-publish:
9
+ name: Publish release to PyPI
10
+ runs-on: ubuntu-latest
11
+ environment:
12
+ name: pypi
13
+ url: https://pypi.org/p/dnaStreaming
14
+ permissions:
15
+ id-token: write
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ with:
19
+ fetch-depth: 0 # retrieves git history with tag
20
+ - name: Set up Python
21
+ uses: actions/setup-python@v4
22
+ with:
23
+ python-version: "3.14"
24
+ - name: Install dependencies
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install setuptools wheel build
28
+ - name: Build package
29
+ run: |
30
+ python -m build
31
+ - name: Publish package distributions to PyPI
32
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,132 @@
1
+ .DS_Store
2
+ *.bak
3
+ *.pyc
4
+ .idea/*
5
+ .vscode/*
6
+ /src/tests/DowJonesDNA.json
7
+ r.sh
8
+ /build
9
+ dnaStreaming/logs
10
+ .cache
11
+
12
+ # Byte-compiled / optimized / DLL files
13
+ __pycache__/
14
+ *.py[cod]
15
+ *$py.class
16
+
17
+ # C extensions
18
+ *.so
19
+
20
+ # Dow Jones DNA Data folders
21
+ data*/
22
+ dicts/
23
+
24
+ # Dow Jones DNA local working files
25
+ ZZ*
26
+
27
+ # MacOS DS_Store
28
+ .DS_Store
29
+
30
+ # Distribution / packaging
31
+ .Python
32
+ build/
33
+ develop-eggs/
34
+ dist/
35
+ downloads/
36
+ eggs/
37
+ .eggs/
38
+ lib/
39
+ lib64/
40
+ parts/
41
+ sdist/
42
+ var/
43
+ wheels/
44
+ *.egg-info/
45
+ .installed.cfg
46
+ *.egg
47
+ MANIFEST
48
+
49
+ # PyInstaller
50
+ # Usually these files are written by a python script from a template
51
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
52
+ *.manifest
53
+ *.spec
54
+
55
+ # Installer logs
56
+ pip-log.txt
57
+ pip-delete-this-directory.txt
58
+
59
+ # Unit test / coverage reports
60
+ htmlcov/
61
+ .tox/
62
+ .coverage
63
+ .coverage.*
64
+ .cache
65
+ nosetests.xml
66
+ coverage.xml
67
+ *.cover
68
+ .hypothesis/
69
+ .pytest_cache/
70
+
71
+ # Translations
72
+ *.mo
73
+ *.pot
74
+
75
+ # Django stuff:
76
+ *.log
77
+ local_settings.py
78
+ db.sqlite3
79
+
80
+ # Flask stuff:
81
+ instance/
82
+ .webassets-cache
83
+
84
+ # Scrapy stuff:
85
+ .scrapy
86
+
87
+ # Sphinx documentation
88
+ docs/_build/
89
+
90
+ # PyBuilder
91
+ target/
92
+
93
+ # Jupyter Notebook
94
+ .ipynb_checkpoints
95
+
96
+ # pyenv
97
+ .python-version
98
+
99
+ # celery beat schedule file
100
+ celerybeat-schedule
101
+
102
+ # SageMath parsed files
103
+ *.sage.py
104
+
105
+ # Environments
106
+ .env
107
+ .venv
108
+ .envrc
109
+ env/
110
+ venv/
111
+ ENV/
112
+ env.bak/
113
+ venv.bak/
114
+
115
+ # Spyder project settings
116
+ .spyderproject
117
+ .spyproject
118
+
119
+ # Rope project settings
120
+ .ropeproject
121
+
122
+ # mkdocs documentation
123
+ /site
124
+
125
+ # mypy
126
+ .mypy_cache/
127
+
128
+ # Visual Studio Code
129
+ .vscode
130
+
131
+ # Ruff files
132
+ .ruff_cache
@@ -0,0 +1,152 @@
1
+ 0.9.2 / 2017-04-14
2
+ ==================
3
+ - [docs] Updated README.rst.
4
+ - [breaking] Removed subscriber module. Added 'listener'. This will simplify how customers run our code. No longer will they be creating
5
+ the subscription *and* consuming it. Instead they will just consume an already existing subscription.
6
+ - [Tests] Updated tests to use listener. Updated tests to use new name for sample credentials file. Deleted old subscriber test.
7
+
8
+ 0.9.3 / 2017-04-25
9
+ ==================
10
+ - [docs] Updated README.rst
11
+ - [breaking] Replaced references 'DOW_JONES_APPLICATION_CREDENTIALS' envinronmental variable for 'DOW_JONES_DNA_JSON_PATH'.
12
+ - [breaking] Replaced system's filename expectation for 'dowJonesApplicationCredentials.json' to 'DowJonesDNA.json':
13
+ - [Tests] Updated test to use the changes described above.
14
+
15
+ 1.0.0 / 2017-06-07
16
+ ==================
17
+ - [docs] Updated README.rst
18
+ - [breaking] - No longer using 'DowJonesDNA.json' file.
19
+ - [changed] - Added customer_config.json file. See README.rst for usage explanation.
20
+ - [changed] - Get the user's credentials information by making a REST call to Dow Jones extraction API service.
21
+ - [Tests] Updated tests to use the changes described above.
22
+
23
+ 1.0.1 / 2017-06-09
24
+ ==================
25
+ - [breaking] Removed ability to consume more than one stream at a time.
26
+ - [tests] Updated tests.
27
+ - [docs] Updated README.
28
+
29
+ 1.0.2 / 2017-06-29
30
+ ==================
31
+ - [changed] - Reduced the listed dependencies in requirements.txt and setup.py.
32
+ - [changed] - Corrected URI in setup.py.
33
+ - [tests] - Fixed 2 broken tests in test_config.py.
34
+ - [docs] - Updated README with more complete instructions.
35
+
36
+ 1.0.3 / 2017-06-29
37
+ ==================
38
+ - [changed] - Changed default PROD URI.
39
+
40
+ 1.0.4 / 2017-06-29
41
+ ==================
42
+ - [docs] - Updated README. Git project pip install should use 'https'.
43
+
44
+ 1.0.5 / 2017-08-02
45
+ ==================
46
+ - [changed] - Added Google API Extension (GaxError) error handling. Adding a logging file that will catch logged information. Log name is 'logs/dj-dna-streaming-python.log'.
47
+ - [docs] - Updated README with information about logs.
48
+
49
+ 1.0.6 / 2017-08-04
50
+ ==================
51
+ - [changed] - Fixed how we handle GaxErrors
52
+
53
+ 1.0.7 / 2017-08-04
54
+ ==================
55
+ - [changed] - Added tox tests to test against python2 and python3.
56
+ - [changed] - Made some python3 compatibility changes.
57
+
58
+ 1.0.8 / 2017-08-04
59
+ ==================
60
+ - [changed] - Refactored how we do pull and acknowledge messages to be more clear.
61
+
62
+ 1.0.9 / 2017-08-17
63
+ ==================
64
+ - [changed] - Created a Dockerfile for demo purposes.
65
+ - [docs] - Updated README.
66
+
67
+ 1.0.10 / 2017-08-22
68
+ ==================
69
+ - [changed] - Dependency now pulls in entire GCloud library due to compatibility concerns. Will revert back to more focused dependency list in the future.
70
+ - [changed] - Upgraded Google Cloud dependency version to fix incompatibility with Google language module in a related project.
71
+
72
+ 1.1.0 / 2018-03-19
73
+ ==================
74
+ - [changed] - Updated authentication to use new service account flow (while still supporting old account ID flow for backwards compatibility)
75
+ - [changed] - Updated demo code to accept environment variable that, when used, reduces the output volume.
76
+ - [changed] - Removed maximum messages parameter in listen call. It was unnecessary.
77
+ - [changed] - Added test shell script './dnaStreaming/test/test_run_docker.sh' for testing Docker and streams; to be used only with DNA Engineering assistance.
78
+
79
+ 1.4.2 / 2019-12-13
80
+ ==================
81
+ - [changed] - Removed support for Python 2, due to near end of life.
82
+ - [changed] - Updated all dependencies to latest ones.
83
+ - [docs] - Minor improvements.
84
+
85
+ 1.4.3 / 2020-01-28
86
+ ==================
87
+ - [changed] - Message format provided by the listener.
88
+ - [changed] - Default logging level (still hardcoded)
89
+ - [changed] - Demo files output, to be more explicit on current actions.
90
+ - [added] - Demo file that push messages to GCP Pub/Sub
91
+ - [docs] - Minor improvements.
92
+
93
+ 2.0.0 / 2020-05-11
94
+ ==================
95
+ - [changed] Phased out Python 2.7 support in preparation for PyPi publication
96
+ - [changed] Messages from the listener are parsed and returned, instead of requiring the user to access the JSON
97
+ - [docs] - Minor improvements.
98
+
99
+ 2.0.1 / 2020-11-03
100
+ ==================
101
+ - [changed] Updated dependencies and required versions of pubsub
102
+
103
+ 2.0.2 / 2020-12-03
104
+ ==================
105
+ - [changed] - Removed references to depreciated Extraction API service, now you may manually specify your API host by exporting API_HOST instead of EXTRACTION_API_HOST
106
+
107
+ 2.0.3 / 2022-09-15
108
+ ==================
109
+ - [changed] - Updated all GCP dependencies in requirements and setup.
110
+ - [changed] - Optimized for installation via PIP. Setup.py is deprecated.
111
+ - [changed] - Adapted Pub/Sub operations as per new library requirements.
112
+ - [docs] - Changed README removing legacy references and updated the running demo steps.
113
+
114
+ 2.0.4 / 2022-09-27
115
+ ==================
116
+ - [changed] - Updated all dependencies in requirements and setup.
117
+
118
+ 2.0.5 / 2022-11-02
119
+ ==================
120
+ - [changed] - Removed threaded article quota limit check.
121
+
122
+ 2.1.0 / 2023-03-15
123
+ ==================
124
+ - [removed] - Fully removed legacy authentication method by password
125
+ - [added] - Explicit argument to provide the path to the customer_config.json file to the Listener constructor (view README for more details)
126
+
127
+ 2.2.0 / 2024-05-21
128
+ ==================
129
+ - [added] - Support for highly-available streams with a new method under the `Listener` class: `listen_async_ha`
130
+
131
+ 2.2.1 / 2024-07-01
132
+ ==================
133
+ - [fixed] - Fixed the `subscription_id` parameter of the listener callback so it changes if the listener switches regions (for HA streams only)
134
+
135
+ 2.3.0 / 2025-05-08
136
+ ==================
137
+ - [added] - Allow the use of temporal log path
138
+ - [added] - Implement automatic builds via Github Actions
139
+ - [added] - Adds a minimum version requirement for the setuptools package to ensure compatibility and access to necessary features or fixes.
140
+
141
+
142
+ 2.3.1 / 2025-05-27
143
+ ==================
144
+ - [added] - Updated demo scripts to properly handle the new 'source_delete' event type as well as any future event types.
145
+ - [added] - Improve demo scripts folder location to be easier to found it
146
+
147
+ 2.4.0 / 2026-04-09
148
+ ==================
149
+ - [added] - Authentication via OAuth bearer token
150
+ - [changed] - Upgraded to Python 3.14
151
+ - [changed] - Upgraded dependencies
152
+ - [changed] - Upgraded package to work with pyproject.toml
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2016 Dow Jones Corporation
3
+ Copyright (c) 2026 Dow Jones Corporation
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,279 @@
1
+ Metadata-Version: 2.4
2
+ Name: dnaStreaming
3
+ Version: 2.4.0
4
+ Summary: A Python 3 library for Dow Jones customers to consume data from a Factiva Analytics Stream.
5
+ Author-email: Zachary Kagan <zachary.kagan@dowjones.com>, Daniel Morales <daniel.morales@dowjones.com>, Alan Fuentes <alan.fuentes@dowjones.com>, Carlos Blazquez <carlos.blazquez@dowjones.com>, Carlos Niño <carlos.ninoalarcon@dowjones.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/dowjones/dj-dna-streams-python
8
+ Project-URL: Download, https://github.com/dowjones/dj-dna-streams-python/archive/master.tar.gz
9
+ Keywords: DOWJONES,FACTIVA,STREAMS
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: google-cloud-pubsub>=2.36.0
18
+ Requires-Dist: google-auth>=2.49.0
19
+ Requires-Dist: google-api-core>=2.30.0
20
+ Requires-Dist: requests>=2.32.5
21
+ Provides-Extra: dev
22
+ Requires-Dist: tox; extra == "dev"
23
+ Requires-Dist: ruff; extra == "dev"
24
+ Requires-Dist: pytest; extra == "dev"
25
+ Dynamic: license-file
26
+
27
+ # Dow Jones DNA Streaming Python Library
28
+
29
+ A Python 3 library for Dow Jones customers to consume data from a Factiva Analytics Stream.
30
+
31
+ ## Installation
32
+
33
+ ### Without source code
34
+
35
+ If you don't wish to work with any of the demo snippets provided by this repository,
36
+ you can proceed with a clean installation of the package by running either of the
37
+ following commands.
38
+
39
+ ```bash
40
+ # Install the last published version
41
+ pip3 install dnaStreaming
42
+
43
+ # Install a specific published version
44
+ pip3 install dnaStreaming==<VERSION>
45
+
46
+ # Install from a specific Github branch
47
+ pip3 install git+https://github.com/dowjones/dj-dna-streams-python.git@<BRANCH_NAME>
48
+ ```
49
+
50
+ Alternatively, you can add add it as a dependency inside your `requirements.txt` file
51
+
52
+ ```txt
53
+ ...
54
+ # Include ONE of the following lines:
55
+ dnaStreaming
56
+ dnaStreaming==<VERSION>
57
+ git+https://github.com/dowjones/dj-dna-streams-python.git@<BRANCH_NAME>
58
+ ...
59
+ ```
60
+
61
+ Or inside your `pyproject.toml` file
62
+
63
+ ```toml
64
+ [project]
65
+ ...
66
+ dependencies = [
67
+ # Include only ONE of the following lines:
68
+ "dnaStreaming",
69
+ "dnaStreaming==<VERSION>",
70
+ "git+https://github.com/dowjones/dj-dna-streams-python.git@<BRANCH_NAME>",
71
+ ]
72
+ ```
73
+
74
+ ### With source code
75
+
76
+ On the other hand, if you wish to work with one of the code samples provided in this
77
+ repository, or you want to work with a customized version of the listener by you,
78
+ you can perform an installation from source code once you have cloned the
79
+ repository.
80
+
81
+ ```bash
82
+ cd dj-dna-streams-python
83
+ git switch <BRANCH> # optional if you wish to work on a specific branch
84
+ python3 install -m venv env
85
+ source env/bin/activate
86
+ pip3 install -e . # editable install, recommended
87
+ ```
88
+
89
+ #### Run the demo files
90
+
91
+ Once you're done installing from source code, make sure you set your credentials as environment variables as described by the [Authentication](#authentication) and [Configuration](#configuration) sections.
92
+
93
+ Then, you can run the demo file that you prefer:
94
+
95
+ ```bash
96
+ python3 demo/show_stream.py
97
+ # or
98
+ python3 demo/show_stream_async.py
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Authentication
104
+
105
+ You have two options to authenticate:
106
+ - By using your **user key**
107
+ - By using an **OAuth bearer token** (new)
108
+
109
+ ---
110
+
111
+ ## Configuration
112
+
113
+ To run this code, you need to provide credentials from one of the authentication methods, as well as your subscriptions. There are three ways you can do this:
114
+
115
+ ### 1. Environment Variables
116
+
117
+ To set your credentials, set either `USER_KEY` or `OAUTH_TOKEN` as an environment variable:
118
+
119
+ ```bash
120
+ export USER_KEY="<your_user_key>"
121
+ # or
122
+ export OAUTH_TOKEN="<your_oauth_bearer_token>"
123
+ ```
124
+
125
+ To set your subscription ID, set an environment variable named `SUBSCRIPTION_ID`:
126
+
127
+ ```bash
128
+ export SUBSCRIPTION_ID="ABC1234567889"
129
+ ```
130
+
131
+ To set your log folder path, set a directory variable named `LOG_PATH`:
132
+
133
+ ```bash
134
+ export LOG_PATH="/your/custom/log/path"
135
+ ```
136
+
137
+ ### 2. Configuration File
138
+
139
+ In this codebase, you will find a file named `customer_config.json`. You are not required to use this file, but if you prefer to, fill the JSON object within by adding your user key and your subscription ID. Follow basic JSON formatting and syntax conventions.
140
+
141
+ > **Note:** The listener will search for the `customer_config.json` file inside your `$HOME` directory by default.
142
+
143
+ If you prefer using an explicit path to your configuration file, pass the absolute path to the `Listener` constructor:
144
+
145
+ ```python
146
+ from dnaStreaming.listener import Listener
147
+
148
+ # Config file authentication
149
+ listener = Listener(config_file="<ABSOLUTE_PATH_TO_YOUR_CONFIG_FILE>")
150
+ ```
151
+
152
+ ### 3. Function Arguments
153
+
154
+ You may pass your user key or OAuth token to the `Listener` constructor and your subscription ID directly to the `listen` method:
155
+
156
+ ```python
157
+ from dnaStreaming.listener import Listener
158
+
159
+ # Use the user_key argument to provide your credentials
160
+ listener = Listener(user_key="<YOUR_USER_KEY>")
161
+
162
+ # Alternatively, use the oauth_token argument
163
+ listener = Listener(oauth_token="<YOUR_OAUTH_BEARER_TOKEN>")
164
+
165
+ # Use the subscription_id argument to provide your subscription id to the listener
166
+ listener.listen(callback, subscription_id="<YOUR_SUBSCRIPTION_ID>")
167
+
168
+ # The same parameter applies for the async variation
169
+ listener.listen_async(callback, subscription_id="<YOUR_SUBSCRIPTION_ID>")
170
+ ```
171
+
172
+ *Note: Passing credentials and subscription ID(s) via function arguments will override both environment variables and config file settings.*
173
+
174
+ If you choose to strictly rely on environment variables, you can simply initialize the listener empty:
175
+
176
+ ```python
177
+ from dnaStreaming.listener import Listener
178
+
179
+ listener = Listener()
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Listening to Messages
185
+
186
+ ### Synchronous Listening
187
+
188
+ If you want to listen to messages synchronously:
189
+
190
+ ```python
191
+ def callback(message, subscription_id):
192
+ print(f'Subscription ID: {subscription_id}: Message: {message.data}')
193
+ return True # Return False to stop the message flow and unblock the process.
194
+
195
+ # Omitting maximum_messages means you will continue to get messages as they appear.
196
+ # This can be a firehose. Use with caution.
197
+ listener.listen(callback, maximum_messages=10)
198
+ ```
199
+
200
+ ### Asynchronous Listening
201
+
202
+ If you want to listen to messages asynchronously:
203
+
204
+ ```python
205
+ from time import sleep
206
+
207
+ def callback(message, subscription_id):
208
+ print(f'Subscription ID: {subscription_id}: Message: {message.data}')
209
+
210
+ future = listener.listen_async(callback)
211
+
212
+ # After calling `listen_async`, you need to keep the main thread alive.
213
+ for count in range(0, 5):
214
+ sleep(1)
215
+
216
+ # Stop receiving messages after 5 seconds
217
+ if future.running():
218
+ future.cancel()
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Log Files
224
+
225
+ Minimal logging is written to a file named `dj-dna-streaming-python.log`.
226
+
227
+ By default, logs are written to the first available directory from the following list:
228
+ 1. A custom path set via the environment variable `LOG_PATH`.
229
+ 2. A `logs/` folder located within the package installation directory.
230
+ 3. A fallback directory: `~/.dj-dna-streaming-python/logs/`.
231
+
232
+ The first writable location found is selected. A message like `Will log to: /your/custom/log/path` is printed to the console on startup.
233
+
234
+ 💡 **Note:** The log file is overwritten each time the application starts to keep maintenance simple.
235
+
236
+ You can specify:
237
+ - **Absolute paths**: For example, `/var/log/dna-streaming`.
238
+ - **Relative paths**: For example, `./logs`, relative to the current working directory at runtime.
239
+
240
+ The code verifies that the specified path is writable. If it isn’t, it automatically falls back to the next available option.
241
+
242
+ ---
243
+
244
+ ## Development, Testing & Linting (for developers)
245
+
246
+ ### Setup
247
+
248
+ To prepare for local development and debugging, create a virtual environment and install
249
+ both runtime and dev dependencies (make sure to run with a recent version of Python 3):
250
+
251
+ ```bash
252
+ python3 install -m venv env
253
+ source env/bin/activate
254
+ # Install runtime dependencies from pyproject.toml (-e for recommended editable install)
255
+ pip3 install -e .
256
+ # Install dev dependencies from pyproject.toml
257
+ pip3 install -e ".[dev]"
258
+ ```
259
+
260
+ ### Running Tests
261
+ To test the library works over multiple Python versions (e.g., Python >= 3.10), use `tox`:
262
+
263
+ ```bash
264
+ # Make sure to set USER_KEY (or OAUTH_TOKEN), API_HOST and SUBSCRIPTION_ID accordingly
265
+ # Strong recommendation:
266
+ # - SUBSCRIPTION_ID should belong to an active stream with about 2000 queued messages
267
+ # for faster test execution times.
268
+ tox
269
+ ```
270
+
271
+ ### Linting
272
+ Before releasing, or ideally, before you commit, make sure to `ruff` your code
273
+ to align with minimal but recommended linting. At the project root, run:
274
+
275
+ ```bash
276
+ ruff check . # checks code without changing it
277
+ ruff check --fix . # checks code and applies changes
278
+ ruff format . # formats code
279
+ ```