shareddata 6.83.21__tar.gz → 6.85.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.
- shareddata-6.85.0/LICENSE +21 -0
- shareddata-6.85.0/MANIFEST.in +5 -0
- {shareddata-6.83.21/src/shareddata.egg-info → shareddata-6.85.0}/PKG-INFO +87 -39
- {shareddata-6.83.21 → shareddata-6.85.0}/README.md +31 -12
- {shareddata-6.83.21 → shareddata-6.85.0}/pyproject.toml +1 -0
- shareddata-6.85.0/setup.py +110 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/ServerGunicorn.py +19 -2
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/ServerWaitress.py +3 -1
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/__init__.py +47 -23
- shareddata-6.85.0/src/SharedData/API/apidocs-dark.css +97 -0
- shareddata-6.85.0/src/SharedData/API/apidocs.yml +3347 -0
- shareddata-6.85.0/src/SharedData/API/auth.py +244 -0
- shareddata-6.85.0/src/SharedData/API/install/worker.ps1 +102 -0
- shareddata-6.85.0/src/SharedData/API/install/worker.sh +105 -0
- shareddata-6.85.0/src/SharedData/API/listcache.py +236 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/routes/cache.py +2 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/routes/collections.py +79 -8
- shareddata-6.85.0/src/SharedData/API/routes/data.py +66 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/routes/downloads.py +10 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/routes/metadata.py +2 -0
- shareddata-6.85.0/src/SharedData/API/routes/operations.py +82 -0
- shareddata-6.85.0/src/SharedData/API/routes/schedules.py +99 -0
- shareddata-6.85.0/src/SharedData/API/routes/sqlite.py +145 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/routes/system.py +43 -6
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/routes/tables.py +104 -21
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/routes/timeseries.py +26 -4
- shareddata-6.85.0/src/SharedData/API/routes/web_routes.py +79 -0
- shareddata-6.85.0/src/SharedData/API/routes/workers.py +361 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/utils.py +44 -0
- shareddata-6.85.0/src/SharedData/Auth/__init__.py +1 -0
- shareddata-6.85.0/src/SharedData/Auth/bootstrap.py +70 -0
- shareddata-6.85.0/src/SharedData/Auth/migrate.py +270 -0
- shareddata-6.85.0/src/SharedData/Auth/store.py +279 -0
- shareddata-6.85.0/src/SharedData/Auth/workers.py +669 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/CacheRedis.py +245 -45
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/CollectionMongoDB.py +31 -0
- shareddata-6.85.0/src/SharedData/DataAPI/__init__.py +19 -0
- shareddata-6.85.0/src/SharedData/DataAPI/catalog.py +286 -0
- shareddata-6.85.0/src/SharedData/DataAPI/config.py +81 -0
- shareddata-6.85.0/src/SharedData/DataAPI/errors.py +31 -0
- shareddata-6.85.0/src/SharedData/DataAPI/indexes.py +75 -0
- shareddata-6.85.0/src/SharedData/DataAPI/readers.py +291 -0
- shareddata-6.85.0/src/SharedData/DataAPI/resolve.py +222 -0
- shareddata-6.85.0/src/SharedData/DataAPI/service.py +824 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Defaults.py +70 -12
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/AWSS3.py +18 -6
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/ClientAPI.py +349 -14
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/LogHandlerAPI.py +16 -15
- shareddata-6.85.0/src/SharedData/IO/LogReader.py +139 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/MongoDBClient.py +11 -4
- shareddata-6.85.0/src/SharedData/IO/SaveTables.py +144 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/ServerWebSocket.py +9 -7
- shareddata-6.85.0/src/SharedData/Listing.py +31 -0
- shareddata-6.85.0/src/SharedData/LockWaiters.py +102 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Logger.py +39 -22
- shareddata-6.85.0/src/SharedData/MCP/__init__.py +3 -0
- shareddata-6.85.0/src/SharedData/MCP/__main__.py +3 -0
- shareddata-6.85.0/src/SharedData/MCP/client.py +132 -0
- shareddata-6.85.0/src/SharedData/MCP/server.py +885 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Metadata.py +21 -1
- shareddata-6.85.0/src/SharedData/Redaction.py +965 -0
- shareddata-6.85.0/src/SharedData/Routines/ContainerHealth.py +50 -0
- shareddata-6.85.0/src/SharedData/Routines/JobStore.py +432 -0
- shareddata-6.85.0/src/SharedData/Routines/RoutineCommand.py +36 -0
- shareddata-6.85.0/src/SharedData/Routines/RoutineOrigin.py +161 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Routines/Schedule.py +125 -74
- shareddata-6.85.0/src/SharedData/Routines/ScheduleMirror.py +109 -0
- shareddata-6.85.0/src/SharedData/Routines/ScheduleStore.py +430 -0
- shareddata-6.85.0/src/SharedData/Routines/Scheduler.py +214 -0
- shareddata-6.85.0/src/SharedData/Routines/UpdateActiveJobs.py +75 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Routines/Worker.py +43 -7
- shareddata-6.85.0/src/SharedData/Routines/WorkerBootstrap.py +141 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Routines/WorkerLib.py +331 -189
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Routines/WorkerPool.py +195 -93
- shareddata-6.85.0/src/SharedData/SQLite.py +477 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/SharedData.py +322 -92
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/SharedNumpy.py +298 -299
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Table.py +299 -102
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/TableDisk.py +49 -64
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/TableIndex.py +150 -142
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/TableIndexJitFunctions.py +389 -296
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/TableIndexJitGenerate.py +33 -21
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/TableIndexJitHash.py +14 -1
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/TableIndexJitLoc.py +96 -146
- shareddata-6.85.0/src/SharedData/TableProtocol.py +196 -0
- shareddata-6.85.0/src/SharedData/TableRead.py +155 -0
- shareddata-6.85.0/src/SharedData/TableRewrite.py +301 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/TimeSeriesDisk.py +206 -285
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/TimeseriesContainer.py +80 -45
- shareddata-6.85.0/src/SharedData/Users.py +36 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Utils.py +37 -6
- shareddata-6.85.0/src/SharedData/Web/ADDING_A_PAGE.md +18 -0
- shareddata-6.85.0/src/SharedData/Web/__init__.py +37 -0
- shareddata-6.85.0/src/SharedData/Web/activity_logger.py +231 -0
- shareddata-6.85.0/src/SharedData/Web/app.py +38 -0
- shareddata-6.85.0/src/SharedData/Web/assets/dashAgGridComponentFunctions.js +33 -0
- shareddata-6.85.0/src/SharedData/Web/assets/dashAgGridFunctions.js +36 -0
- shareddata-6.85.0/src/SharedData/Web/assets/google_logo.png +0 -0
- shareddata-6.85.0/src/SharedData/Web/assets/kafka_keys.js +19 -0
- shareddata-6.85.0/src/SharedData/Web/assets/logs.css +201 -0
- shareddata-6.85.0/src/SharedData/Web/assets/sched.css +452 -0
- shareddata-6.85.0/src/SharedData/Web/assets/styles.css +1059 -0
- shareddata-6.85.0/src/SharedData/Web/auth.py +357 -0
- shareddata-6.85.0/src/SharedData/Web/backends.py +73 -0
- shareddata-6.85.0/src/SharedData/Web/config.py +254 -0
- shareddata-6.85.0/src/SharedData/Web/containers.py +426 -0
- shareddata-6.85.0/src/SharedData/Web/identity.py +140 -0
- shareddata-6.85.0/src/SharedData/Web/kafka_view.py +181 -0
- shareddata-6.85.0/src/SharedData/Web/mongo_view.py +125 -0
- shareddata-6.85.0/src/SharedData/Web/redis_view.py +286 -0
- shareddata-6.85.0/src/SharedData/Web/route_health.py +249 -0
- shareddata-6.85.0/src/SharedData/Web/route_registry.py +463 -0
- shareddata-6.85.0/src/SharedData/Web/sched.py +321 -0
- shareddata-6.85.0/src/SharedData/Web/schedule_editor.py +156 -0
- shareddata-6.85.0/src/SharedData/Web/server.py +176 -0
- shareddata-6.85.0/src/SharedData/Web/services.py +335 -0
- shareddata-6.85.0/src/SharedData/Web/shell.py +441 -0
- shareddata-6.85.0/src/SharedData/Web/standalone.py +710 -0
- shareddata-6.85.0/src/SharedData/Web/static/account.js +54 -0
- shareddata-6.85.0/src/SharedData/Web/static/custom.css +300 -0
- shareddata-6.85.0/src/SharedData/Web/static/favicon.ico +0 -0
- shareddata-6.85.0/src/SharedData/Web/static/favicon.png +0 -0
- shareddata-6.85.0/src/SharedData/Web/static/logo.png +0 -0
- shareddata-6.85.0/src/SharedData/Web/static/logo_96x96.png +0 -0
- shareddata-6.85.0/src/SharedData/Web/static/shareddata-mark.svg +6 -0
- shareddata-6.85.0/src/SharedData/Web/static/shell.css +493 -0
- shareddata-6.85.0/src/SharedData/Web/static/shell.js +461 -0
- shareddata-6.85.0/src/SharedData/Web/static/standalone.css +480 -0
- shareddata-6.85.0/src/SharedData/Web/static/standalone.js +2020 -0
- shareddata-6.85.0/src/SharedData/Web/suggest.py +251 -0
- shareddata-6.85.0/src/SharedData/Web/templates/account.html +15 -0
- shareddata-6.85.0/src/SharedData/Web/templates/base.html +47 -0
- shareddata-6.85.0/src/SharedData/Web/templates/claim.html +10 -0
- shareddata-6.85.0/src/SharedData/Web/templates/claim_done.html +2 -0
- shareddata-6.85.0/src/SharedData/Web/templates/dash.html +18 -0
- shareddata-6.85.0/src/SharedData/Web/templates/index.html +17 -0
- shareddata-6.85.0/src/SharedData/Web/templates/login.html +350 -0
- shareddata-6.85.0/src/SharedData/Web/templates/login_2fa.html +19 -0
- shareddata-6.85.0/src/SharedData/Web/templates/partials/navbar.html +317 -0
- shareddata-6.85.0/src/SharedData/Web/templates/partials/scripts.html +12 -0
- shareddata-6.85.0/src/SharedData/Web/templates/recovery_codes.html +9 -0
- shareddata-6.85.0/src/SharedData/Web/templates/shell.html +63 -0
- shareddata-6.85.0/src/SharedData/Web/templates/standalone.html +124 -0
- shareddata-6.85.0/src/SharedData/Web/twofactor.py +250 -0
- shareddata-6.85.0/src/SharedData/Web/utils.py +23 -0
- shareddata-6.85.0/src/SharedData/Web/workerpool.py +451 -0
- shareddata-6.85.0/src/SharedData/__init__.py +7 -0
- shareddata-6.85.0/src/SharedData/build_info.py +23 -0
- shareddata-6.85.0/src/SharedData/fleet.py +101 -0
- shareddata-6.85.0/src/SharedData/preflight.py +140 -0
- shareddata-6.85.0/src/SharedData/private_files.py +71 -0
- shareddata-6.85.0/src/SharedData/release_backup.py +250 -0
- shareddata-6.85.0/src/SharedData/server.py +35 -0
- shareddata-6.85.0/src/SharedData/services.py +11 -0
- {shareddata-6.83.21 → shareddata-6.85.0/src/shareddata.egg-info}/PKG-INFO +87 -39
- shareddata-6.85.0/src/shareddata.egg-info/SOURCES.txt +184 -0
- shareddata-6.85.0/src/shareddata.egg-info/entry_points.txt +4 -0
- shareddata-6.85.0/src/shareddata.egg-info/requires.txt +49 -0
- shareddata-6.83.21/LICENSE +0 -674
- shareddata-6.83.21/MANIFEST.in +0 -3
- shareddata-6.83.21/setup.py +0 -51
- shareddata-6.83.21/src/SharedData/API/auth.py +0 -211
- shareddata-6.83.21/src/SharedData/API/listcache.py +0 -91
- shareddata-6.83.21/src/SharedData/API/routes/workers.py +0 -202
- shareddata-6.83.21/src/SharedData/IO/SaveTables.py +0 -58
- shareddata-6.83.21/src/SharedData/Routines/Scheduler.py +0 -109
- shareddata-6.83.21/src/SharedData/Routines/UpdateActiveJobs.py +0 -53
- shareddata-6.83.21/src/SharedData/Users.py +0 -32
- shareddata-6.83.21/src/SharedData/__init__.py +0 -0
- shareddata-6.83.21/src/shareddata.egg-info/SOURCES.txt +0 -80
- shareddata-6.83.21/src/shareddata.egg-info/requires.txt +0 -28
- {shareddata-6.83.21 → shareddata-6.85.0}/setup.cfg +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/constants.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/download_paths.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/download_slots.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/API/routes/__init__.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Database.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/AWSEC2.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/AutoDocstrings.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/ClientSocket.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/ClientWebSocket.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/ServerSocket.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/StreamsCache.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/StreamsPersist.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/SyncTable.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/TunnelWebSocket.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/IO/__init__.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/MultiProc.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/OpenFIGI.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Routines/ArchiveOldCollections.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Routines/BatchJob.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Routines/ScheduleMonitor.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Routines/__init__.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/StreamKafka.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/Symbol.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/TableIndexJitFunctionsManual.py +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/SharedData/sharedmutexwin.pyd +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/shareddata.egg-info/dependency_links.txt +0 -0
- {shareddata-6.83.21 → shareddata-6.85.0}/src/shareddata.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022-2026 The SharedData Authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,45 +1,74 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: shareddata
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.85.0
|
|
4
4
|
Summary: Memory Mapped / Shared Memory Database with S3 repository
|
|
5
|
+
Home-page: https://shareddata.net
|
|
6
|
+
Author: shareddata
|
|
7
|
+
Author-email: admin@shareddata.net
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://shareddata.net
|
|
5
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
6
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
7
14
|
Classifier: Operating System :: OS Independent
|
|
8
|
-
Requires-Python: >=3.
|
|
15
|
+
Requires-Python: >=3.11, <3.13
|
|
9
16
|
Description-Content-Type: text/markdown
|
|
10
17
|
License-File: LICENSE
|
|
11
|
-
Requires-Dist: ipykernel
|
|
12
|
-
Requires-Dist:
|
|
13
|
-
Requires-Dist: python-
|
|
14
|
-
Requires-Dist: python-dotenv==1.0.1
|
|
18
|
+
Requires-Dist: ipykernel<8,>=7.4
|
|
19
|
+
Requires-Dist: python-json-logger<5,>=4.2
|
|
20
|
+
Requires-Dist: python-dotenv<2,>=1.2.4
|
|
15
21
|
Requires-Dist: pandas<3,>=2.2
|
|
16
|
-
Requires-Dist: scipy
|
|
17
|
-
Requires-Dist: numpy
|
|
22
|
+
Requires-Dist: scipy<1.18,>=1.14
|
|
23
|
+
Requires-Dist: numpy<1.27,>=1.26.4
|
|
18
24
|
Requires-Dist: numba==0.59.1
|
|
19
|
-
Requires-Dist: XlsxWriter
|
|
20
|
-
Requires-Dist: openpyxl
|
|
21
|
-
Requires-Dist: tqdm
|
|
22
|
-
Requires-Dist: cffi
|
|
23
|
-
Requires-Dist: tzlocal
|
|
24
|
-
Requires-Dist: websockets
|
|
25
|
-
Requires-Dist:
|
|
26
|
-
Requires-Dist:
|
|
27
|
-
Requires-Dist:
|
|
28
|
-
Requires-Dist:
|
|
29
|
-
Requires-Dist: requests==2.31.0
|
|
25
|
+
Requires-Dist: XlsxWriter<4,>=3.2.9
|
|
26
|
+
Requires-Dist: openpyxl<4,>=3.1.5
|
|
27
|
+
Requires-Dist: tqdm<5,>=4.70.1
|
|
28
|
+
Requires-Dist: cffi<3,>=2.1
|
|
29
|
+
Requires-Dist: tzlocal<6,>=5.4.4
|
|
30
|
+
Requires-Dist: websockets<18,>=17.1
|
|
31
|
+
Requires-Dist: lz4<5,>=4.4.5
|
|
32
|
+
Requires-Dist: flask<4,>=3.1.3
|
|
33
|
+
Requires-Dist: waitress<4,>=3.0.2
|
|
34
|
+
Requires-Dist: requests<3,>=2.34.2
|
|
30
35
|
Requires-Dist: flasgger==0.9.7.1
|
|
31
|
-
Requires-Dist: pymongo
|
|
32
|
-
Requires-Dist: setuptools
|
|
33
|
-
Requires-Dist: filelock
|
|
34
|
-
Requires-Dist: gunicorn
|
|
35
|
-
Requires-Dist:
|
|
36
|
-
Requires-Dist:
|
|
37
|
-
Requires-Dist:
|
|
38
|
-
Requires-Dist:
|
|
36
|
+
Requires-Dist: pymongo<5,>=4.18.2
|
|
37
|
+
Requires-Dist: setuptools>=84
|
|
38
|
+
Requires-Dist: filelock<5,>=4.0.9
|
|
39
|
+
Requires-Dist: gunicorn<27,>=26.2
|
|
40
|
+
Requires-Dist: aiohttp<4,>=3.14.3
|
|
41
|
+
Requires-Dist: boto3<2,>=1.43
|
|
42
|
+
Requires-Dist: confluent-kafka<3,>=2.15.1
|
|
43
|
+
Requires-Dist: aiokafka<1,>=0.14
|
|
44
|
+
Requires-Dist: redis<9,>=8.1
|
|
45
|
+
Requires-Dist: Authlib<2,>=1.8
|
|
46
|
+
Requires-Dist: PyJWT<3,>=2.8
|
|
47
|
+
Requires-Dist: argon2-cffi<26,>=25.1
|
|
48
|
+
Requires-Dist: flask-jwt-extended<5,>=4.6
|
|
49
|
+
Requires-Dist: cryptography<51,>=50.0.2
|
|
50
|
+
Requires-Dist: segno<2,>=1.6
|
|
51
|
+
Requires-Dist: psutil<8,>=5.9
|
|
52
|
+
Requires-Dist: mcp>=1.27
|
|
53
|
+
Requires-Dist: httpx>=0.27
|
|
54
|
+
Provides-Extra: test
|
|
55
|
+
Requires-Dist: pytest<10,>=8.3.4; extra == "test"
|
|
56
|
+
Requires-Dist: pytest-asyncio<2,>=0.24; extra == "test"
|
|
57
|
+
Requires-Dist: playwright<2,>=1.63; extra == "test"
|
|
58
|
+
Provides-Extra: s3
|
|
59
|
+
Provides-Extra: kafka
|
|
60
|
+
Provides-Extra: redis
|
|
61
|
+
Provides-Extra: all
|
|
62
|
+
Dynamic: author
|
|
63
|
+
Dynamic: author-email
|
|
39
64
|
Dynamic: classifier
|
|
40
65
|
Dynamic: description
|
|
41
66
|
Dynamic: description-content-type
|
|
67
|
+
Dynamic: home-page
|
|
68
|
+
Dynamic: license
|
|
42
69
|
Dynamic: license-file
|
|
70
|
+
Dynamic: project-url
|
|
71
|
+
Dynamic: provides-extra
|
|
43
72
|
Dynamic: requires-dist
|
|
44
73
|
Dynamic: requires-python
|
|
45
74
|
Dynamic: summary
|
|
@@ -71,7 +100,7 @@ SharedData provides a comprehensive set of features for high-performance financi
|
|
|
71
100
|
- **📋 Comprehensive Logging System** - Enterprise-grade logging with multiple destinations
|
|
72
101
|
- **🌐 Remote API Client** - REST API for remote data access and operations
|
|
73
102
|
|
|
74
|
-
**📚 [Read the complete Core Features guide →](docs/CORE_FEATURES.md)**
|
|
103
|
+
**📚 [Read the complete Core Features guide →](https://shareddata.net/docs/CORE_FEATURES.md)**
|
|
75
104
|
|
|
76
105
|
## ⚡ Quick Start
|
|
77
106
|
|
|
@@ -111,7 +140,7 @@ data = tbl.loc['2025-01-05':, 'AAPL'] # Fast symbol lookup
|
|
|
111
140
|
print(f"Retrieved {data.shape[0]} rows")
|
|
112
141
|
```
|
|
113
142
|
|
|
114
|
-
**📚 [Read the complete Quick Start guide →](docs/QUICK_START.md)**
|
|
143
|
+
**📚 [Read the complete Quick Start guide →](https://shareddata.net/docs/QUICK_START.md)**
|
|
115
144
|
|
|
116
145
|
## 🔧 Configuration
|
|
117
146
|
|
|
@@ -127,7 +156,7 @@ MONGODB_HOST="your-mongodb-host"
|
|
|
127
156
|
SHAREDDATA_ENDPOINT="http://your-server:port"
|
|
128
157
|
```
|
|
129
158
|
|
|
130
|
-
**📚 [Read the complete Configuration guide →](docs/CONFIGURATION.md)**
|
|
159
|
+
**📚 [Read the complete Configuration guide →](https://shareddata.net/docs/CONFIGURATION.md)**
|
|
131
160
|
|
|
132
161
|
## 🚀 Advanced Usage
|
|
133
162
|
|
|
@@ -140,7 +169,26 @@ For power users and complex scenarios:
|
|
|
140
169
|
- **Production Deployment** - High availability and monitoring
|
|
141
170
|
- **Monitoring & Debugging** - Performance profiling and health checks
|
|
142
171
|
|
|
143
|
-
**📚 [Read the complete Advanced Usage guide →](docs/ADVANCED_USAGE.md)**
|
|
172
|
+
**📚 [Read the complete Advanced Usage guide →](https://shareddata.net/docs/ADVANCED_USAGE.md)**
|
|
173
|
+
|
|
174
|
+
## 🧭 Data by Symbol
|
|
175
|
+
|
|
176
|
+
Fetch data by what it is instead of where it is stored. The server picks the source, the
|
|
177
|
+
container and the partitions, and every answer says where its rows came from:
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
bars = shdata.dataframe('marketdata', 'AAPL', period='M15', start='2026-10-05')
|
|
181
|
+
bars.attrs['provenance']['dataset'] # which container answered
|
|
182
|
+
|
|
183
|
+
from SharedData.IO.ClientAPI import ClientAPI
|
|
184
|
+
surface = ClientAPI.get_vol('AAPL', product='tenor', tenor='1M')
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Market data, signals, portfolios, risk factors and volatility are served this way over
|
|
188
|
+
`GET /api/data/...`. This is a convenience, not the fast path: producers and other
|
|
189
|
+
performance-critical code keep using `table()`, `timeseries()` and `collection()`.
|
|
190
|
+
|
|
191
|
+
**📚 [Read the Data by Symbol guide →](https://shareddata.net/docs/data-api.md)**
|
|
144
192
|
|
|
145
193
|
## 🔄 Development & Documentation
|
|
146
194
|
|
|
@@ -164,11 +212,11 @@ make all
|
|
|
164
212
|
python -m pytest tests/
|
|
165
213
|
```
|
|
166
214
|
|
|
167
|
-
**📚 [Read the complete Development guide →](docs/DEVELOPMENT.md)**
|
|
215
|
+
**📚 [Read the complete Development guide →](https://shareddata.net/docs/DEVELOPMENT.md)**
|
|
168
216
|
|
|
169
217
|
## 📄 License
|
|
170
218
|
|
|
171
|
-
See [LICENSE](LICENSE) file
|
|
219
|
+
MIT: free to use, change and distribute, commercially too. See the [LICENSE](https://shareddata.net/LICENSE) file.
|
|
172
220
|
|
|
173
221
|
## 🤝 Contributing
|
|
174
222
|
|
|
@@ -178,17 +226,17 @@ See [LICENSE](LICENSE) file for details.
|
|
|
178
226
|
4. Update documentation: `make gitea`
|
|
179
227
|
5. Submit a pull request
|
|
180
228
|
|
|
181
|
-
**📚 [Read the complete Contributing guide →](docs/DEVELOPMENT.md#contributing-guidelines)**
|
|
229
|
+
**📚 [Read the complete Contributing guide →](https://shareddata.net/docs/DEVELOPMENT.md#contributing-guidelines)**
|
|
182
230
|
|
|
183
231
|
---
|
|
184
232
|
|
|
185
233
|
## 📚 Documentation Index
|
|
186
234
|
|
|
187
|
-
- **[🏗️ Core Features](docs/CORE_FEATURES.md)** - Comprehensive overview of all SharedData capabilities
|
|
188
|
-
- **[⚡ Quick Start](docs/QUICK_START.md)** - Get started with SharedData in minutes
|
|
189
|
-
- **[🔧 Configuration](docs/CONFIGURATION.md)** - Complete configuration reference
|
|
190
|
-
- **[🚀 Advanced Usage](docs/ADVANCED_USAGE.md)** - Advanced patterns and optimization
|
|
191
|
-
- **[🔄 Development](docs/DEVELOPMENT.md)** - Contributing and development guidelines
|
|
235
|
+
- **[🏗️ Core Features](https://shareddata.net/docs/CORE_FEATURES.md)** - Comprehensive overview of all SharedData capabilities
|
|
236
|
+
- **[⚡ Quick Start](https://shareddata.net/docs/QUICK_START.md)** - Get started with SharedData in minutes
|
|
237
|
+
- **[🔧 Configuration](https://shareddata.net/docs/CONFIGURATION.md)** - Complete configuration reference
|
|
238
|
+
- **[🚀 Advanced Usage](https://shareddata.net/docs/ADVANCED_USAGE.md)** - Advanced patterns and optimization
|
|
239
|
+
- **[🔄 Development](https://shareddata.net/docs/DEVELOPMENT.md)** - Contributing and development guidelines
|
|
192
240
|
|
|
193
241
|
---
|
|
194
242
|
|
|
@@ -25,7 +25,7 @@ SharedData provides a comprehensive set of features for high-performance financi
|
|
|
25
25
|
- **📋 Comprehensive Logging System** - Enterprise-grade logging with multiple destinations
|
|
26
26
|
- **🌐 Remote API Client** - REST API for remote data access and operations
|
|
27
27
|
|
|
28
|
-
**📚 [Read the complete Core Features guide →](docs/CORE_FEATURES.md)**
|
|
28
|
+
**📚 [Read the complete Core Features guide →](https://shareddata.net/docs/CORE_FEATURES.md)**
|
|
29
29
|
|
|
30
30
|
## ⚡ Quick Start
|
|
31
31
|
|
|
@@ -65,7 +65,7 @@ data = tbl.loc['2025-01-05':, 'AAPL'] # Fast symbol lookup
|
|
|
65
65
|
print(f"Retrieved {data.shape[0]} rows")
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
**📚 [Read the complete Quick Start guide →](docs/QUICK_START.md)**
|
|
68
|
+
**📚 [Read the complete Quick Start guide →](https://shareddata.net/docs/QUICK_START.md)**
|
|
69
69
|
|
|
70
70
|
## 🔧 Configuration
|
|
71
71
|
|
|
@@ -81,7 +81,7 @@ MONGODB_HOST="your-mongodb-host"
|
|
|
81
81
|
SHAREDDATA_ENDPOINT="http://your-server:port"
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
**📚 [Read the complete Configuration guide →](docs/CONFIGURATION.md)**
|
|
84
|
+
**📚 [Read the complete Configuration guide →](https://shareddata.net/docs/CONFIGURATION.md)**
|
|
85
85
|
|
|
86
86
|
## 🚀 Advanced Usage
|
|
87
87
|
|
|
@@ -94,7 +94,26 @@ For power users and complex scenarios:
|
|
|
94
94
|
- **Production Deployment** - High availability and monitoring
|
|
95
95
|
- **Monitoring & Debugging** - Performance profiling and health checks
|
|
96
96
|
|
|
97
|
-
**📚 [Read the complete Advanced Usage guide →](docs/ADVANCED_USAGE.md)**
|
|
97
|
+
**📚 [Read the complete Advanced Usage guide →](https://shareddata.net/docs/ADVANCED_USAGE.md)**
|
|
98
|
+
|
|
99
|
+
## 🧭 Data by Symbol
|
|
100
|
+
|
|
101
|
+
Fetch data by what it is instead of where it is stored. The server picks the source, the
|
|
102
|
+
container and the partitions, and every answer says where its rows came from:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
bars = shdata.dataframe('marketdata', 'AAPL', period='M15', start='2026-10-05')
|
|
106
|
+
bars.attrs['provenance']['dataset'] # which container answered
|
|
107
|
+
|
|
108
|
+
from SharedData.IO.ClientAPI import ClientAPI
|
|
109
|
+
surface = ClientAPI.get_vol('AAPL', product='tenor', tenor='1M')
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Market data, signals, portfolios, risk factors and volatility are served this way over
|
|
113
|
+
`GET /api/data/...`. This is a convenience, not the fast path: producers and other
|
|
114
|
+
performance-critical code keep using `table()`, `timeseries()` and `collection()`.
|
|
115
|
+
|
|
116
|
+
**📚 [Read the Data by Symbol guide →](https://shareddata.net/docs/data-api.md)**
|
|
98
117
|
|
|
99
118
|
## 🔄 Development & Documentation
|
|
100
119
|
|
|
@@ -118,11 +137,11 @@ make all
|
|
|
118
137
|
python -m pytest tests/
|
|
119
138
|
```
|
|
120
139
|
|
|
121
|
-
**📚 [Read the complete Development guide →](docs/DEVELOPMENT.md)**
|
|
140
|
+
**📚 [Read the complete Development guide →](https://shareddata.net/docs/DEVELOPMENT.md)**
|
|
122
141
|
|
|
123
142
|
## 📄 License
|
|
124
143
|
|
|
125
|
-
See [LICENSE](LICENSE) file
|
|
144
|
+
MIT: free to use, change and distribute, commercially too. See the [LICENSE](https://shareddata.net/LICENSE) file.
|
|
126
145
|
|
|
127
146
|
## 🤝 Contributing
|
|
128
147
|
|
|
@@ -132,17 +151,17 @@ See [LICENSE](LICENSE) file for details.
|
|
|
132
151
|
4. Update documentation: `make gitea`
|
|
133
152
|
5. Submit a pull request
|
|
134
153
|
|
|
135
|
-
**📚 [Read the complete Contributing guide →](docs/DEVELOPMENT.md#contributing-guidelines)**
|
|
154
|
+
**📚 [Read the complete Contributing guide →](https://shareddata.net/docs/DEVELOPMENT.md#contributing-guidelines)**
|
|
136
155
|
|
|
137
156
|
---
|
|
138
157
|
|
|
139
158
|
## 📚 Documentation Index
|
|
140
159
|
|
|
141
|
-
- **[🏗️ Core Features](docs/CORE_FEATURES.md)** - Comprehensive overview of all SharedData capabilities
|
|
142
|
-
- **[⚡ Quick Start](docs/QUICK_START.md)** - Get started with SharedData in minutes
|
|
143
|
-
- **[🔧 Configuration](docs/CONFIGURATION.md)** - Complete configuration reference
|
|
144
|
-
- **[🚀 Advanced Usage](docs/ADVANCED_USAGE.md)** - Advanced patterns and optimization
|
|
145
|
-
- **[🔄 Development](docs/DEVELOPMENT.md)** - Contributing and development guidelines
|
|
160
|
+
- **[🏗️ Core Features](https://shareddata.net/docs/CORE_FEATURES.md)** - Comprehensive overview of all SharedData capabilities
|
|
161
|
+
- **[⚡ Quick Start](https://shareddata.net/docs/QUICK_START.md)** - Get started with SharedData in minutes
|
|
162
|
+
- **[🔧 Configuration](https://shareddata.net/docs/CONFIGURATION.md)** - Complete configuration reference
|
|
163
|
+
- **[🚀 Advanced Usage](https://shareddata.net/docs/ADVANCED_USAGE.md)** - Advanced patterns and optimization
|
|
164
|
+
- **[🔄 Development](https://shareddata.net/docs/DEVELOPMENT.md)** - Contributing and development guidelines
|
|
146
165
|
|
|
147
166
|
---
|
|
148
167
|
|
|
@@ -9,6 +9,7 @@ build-backend = "setuptools.build_meta"
|
|
|
9
9
|
# Configure pytest to suppress asyncio warnings
|
|
10
10
|
asyncio_default_fixture_loop_scope = "function"
|
|
11
11
|
pythonpath = ["src"]
|
|
12
|
+
testpaths = ["tests"]
|
|
12
13
|
filterwarnings = [
|
|
13
14
|
"ignore::pytest.PytestDeprecationWarning",
|
|
14
15
|
"ignore::pytest.PytestReturnNotNoneWarning"
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from setuptools import setup, find_packages
|
|
3
|
+
|
|
4
|
+
install_requires = [
|
|
5
|
+
'ipykernel>=7.4,<8',
|
|
6
|
+
'python-json-logger>=4.2,<5',
|
|
7
|
+
'python-dotenv>=1.2.4,<2',
|
|
8
|
+
# pandas, numba and numpy stay where table and timeseries are tested:
|
|
9
|
+
# numba 0.59.1 caps numpy below 1.27, which in turn caps scipy at 1.17.
|
|
10
|
+
'pandas>=2.2,<3',
|
|
11
|
+
'scipy>=1.14,<1.18',
|
|
12
|
+
'numpy>=1.26.4,<1.27',
|
|
13
|
+
'numba==0.59.1',
|
|
14
|
+
'XlsxWriter>=3.2.9,<4',
|
|
15
|
+
'openpyxl>=3.1.5,<4',
|
|
16
|
+
'tqdm>=4.70.1,<5',
|
|
17
|
+
'cffi>=2.1,<3',
|
|
18
|
+
'tzlocal>=5.4.4,<6',
|
|
19
|
+
'websockets>=17.1,<18',
|
|
20
|
+
'lz4>=4.4.5,<5',
|
|
21
|
+
'flask>=3.1.3,<4',
|
|
22
|
+
'waitress>=3.0.2,<4',
|
|
23
|
+
'requests>=2.34.2,<3',
|
|
24
|
+
'flasgger==0.9.7.1',
|
|
25
|
+
'pymongo>=4.18.2,<5',
|
|
26
|
+
'setuptools>=84',
|
|
27
|
+
'filelock>=4.0.9,<5',
|
|
28
|
+
'gunicorn>=26.2,<27',
|
|
29
|
+
'aiohttp>=3.14.3,<4',
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
# The S3, Kafka and Redis clients: installed with the package, none is optional.
|
|
33
|
+
client_requires = [
|
|
34
|
+
'boto3>=1.43,<2',
|
|
35
|
+
'confluent-kafka>=2.15.1,<3',
|
|
36
|
+
'aiokafka>=0.14,<1',
|
|
37
|
+
'redis>=8.1,<9',
|
|
38
|
+
]
|
|
39
|
+
install_requires = install_requires + client_requires
|
|
40
|
+
|
|
41
|
+
# JavaScript WebUI backend.
|
|
42
|
+
dashboard_requires = [
|
|
43
|
+
'Authlib>=1.8,<2',
|
|
44
|
+
'PyJWT>=2.8,<3',
|
|
45
|
+
'argon2-cffi>=25.1,<26',
|
|
46
|
+
'flask-jwt-extended>=4.6,<5',
|
|
47
|
+
'cryptography>=50.0.2,<51', # two-factor secrets at rest
|
|
48
|
+
'segno>=1.6,<2', # two-factor QR codes (pure Python)
|
|
49
|
+
'psutil>=5.9,<8',
|
|
50
|
+
]
|
|
51
|
+
# Ship the web/dashboard layer by default (no optional extra).
|
|
52
|
+
install_requires = install_requires + dashboard_requires
|
|
53
|
+
|
|
54
|
+
# The MCP server (src/SharedData/MCP, the shareddata-mcp console script): reads the API over HTTP.
|
|
55
|
+
mcp_requires = [
|
|
56
|
+
'mcp>=1.27', # 1.27 is the oldest version the smoke test ran on; 2.x is included
|
|
57
|
+
'httpx>=0.27',
|
|
58
|
+
]
|
|
59
|
+
install_requires = install_requires + mcp_requires
|
|
60
|
+
|
|
61
|
+
test_requires = [
|
|
62
|
+
'pytest>=8.3.4,<10',
|
|
63
|
+
'pytest-asyncio>=0.24,<2',
|
|
64
|
+
'playwright>=1.63,<2',
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
setup(
|
|
68
|
+
name='shareddata',
|
|
69
|
+
version='6.85.0',
|
|
70
|
+
description='Memory Mapped / Shared Memory Database with S3 repository',
|
|
71
|
+
author='shareddata',
|
|
72
|
+
author_email='admin@shareddata.net',
|
|
73
|
+
url='https://shareddata.net',
|
|
74
|
+
project_urls={
|
|
75
|
+
'Homepage': 'https://shareddata.net',
|
|
76
|
+
},
|
|
77
|
+
license='MIT',
|
|
78
|
+
long_description=open('README.md').read(),
|
|
79
|
+
long_description_content_type='text/markdown',
|
|
80
|
+
classifiers=[
|
|
81
|
+
'Programming Language :: Python :: 3',
|
|
82
|
+
'Programming Language :: Python :: 3.11',
|
|
83
|
+
'Programming Language :: Python :: 3.12',
|
|
84
|
+
'License :: OSI Approved :: MIT License',
|
|
85
|
+
'Operating System :: OS Independent',
|
|
86
|
+
],
|
|
87
|
+
packages=find_packages(where='src'),
|
|
88
|
+
package_dir={'': 'src'},
|
|
89
|
+
python_requires='>=3.11, <3.13',
|
|
90
|
+
install_requires=install_requires,
|
|
91
|
+
# s3, kafka, redis and all are kept so that an install that names them still works: they add nothing.
|
|
92
|
+
extras_require={'test': test_requires, 's3': [], 'kafka': [], 'redis': [], 'all': []},
|
|
93
|
+
include_package_data=True,
|
|
94
|
+
package_data={
|
|
95
|
+
'SharedData.API': ['apidocs.yml', 'apidocs-dark.css', 'install/*'],
|
|
96
|
+
'SharedData.Web': [
|
|
97
|
+
'templates/*', 'templates/**/*',
|
|
98
|
+
'static/*', 'static/**/*',
|
|
99
|
+
'assets/*',
|
|
100
|
+
'ADDING_A_PAGE.md',
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
entry_points={
|
|
104
|
+
'console_scripts': [
|
|
105
|
+
'shdata-web=SharedData.Web.server:main',
|
|
106
|
+
'shdata-server=SharedData.server:main',
|
|
107
|
+
'shareddata-mcp=SharedData.MCP.server:main',
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
)
|
|
@@ -10,13 +10,14 @@ Usage:
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
12
|
import argparse
|
|
13
|
+
import logging
|
|
13
14
|
import os
|
|
14
15
|
import sys
|
|
15
16
|
import threading
|
|
16
17
|
import time
|
|
17
18
|
from gunicorn.app.base import BaseApplication
|
|
18
19
|
|
|
19
|
-
from SharedData.Logger import Logger
|
|
20
|
+
from SharedData.Logger import Logger, install_redaction
|
|
20
21
|
Logger.connect('SharedData.API.ServerGunicorn')
|
|
21
22
|
|
|
22
23
|
from SharedData.API import create_app
|
|
@@ -91,6 +92,10 @@ def parse_cli():
|
|
|
91
92
|
help="Number of request threads *per* worker (gthread)")
|
|
92
93
|
p.add_argument("--timeout", type=int, default=120,
|
|
93
94
|
help="Hard kill after N seconds")
|
|
95
|
+
p.add_argument("--table-waiters", type=int, default=None,
|
|
96
|
+
help="Request threads per worker that may wait for one locked table; "
|
|
97
|
+
"further requests for it get 503. Default: a quarter of --nthreads "
|
|
98
|
+
"(or SHAREDDATA_API_TABLE_WAITERS); 0 turns it off")
|
|
94
99
|
p.add_argument("--log-level", default="warning")
|
|
95
100
|
return p.parse_args()
|
|
96
101
|
|
|
@@ -131,6 +136,13 @@ def main():
|
|
|
131
136
|
# Launch in-process helper threads
|
|
132
137
|
start_background_threads()
|
|
133
138
|
|
|
139
|
+
# One locked table must not take every request thread: per worker, at most
|
|
140
|
+
# this many may wait for the same table's lock; the rest get 503 at once.
|
|
141
|
+
waiters = args.table_waiters
|
|
142
|
+
if waiters is None:
|
|
143
|
+
waiters = int(os.environ.get('SHAREDDATA_API_TABLE_WAITERS') or max(1, args.nthreads // 4))
|
|
144
|
+
flask_app.config['TABLE_WAITERS'] = max(0, waiters)
|
|
145
|
+
|
|
134
146
|
# Assemble Gunicorn config
|
|
135
147
|
gunicorn_opts = {
|
|
136
148
|
"bind": f"{args.host}:{args.port}",
|
|
@@ -148,13 +160,18 @@ def main():
|
|
|
148
160
|
"limit_request_line": 8190, # 8190 is HTTP/1.1 spec max
|
|
149
161
|
}
|
|
150
162
|
|
|
163
|
+
# Gunicorn's error log names the request it failed on, query string (token) and all.
|
|
164
|
+
install_redaction(logging.getLogger('gunicorn.error'))
|
|
165
|
+
|
|
151
166
|
# Block here; Gunicorn handles signals and will exit cleanly
|
|
152
167
|
GunicornEmbedded(flask_app, gunicorn_opts).run()
|
|
153
168
|
|
|
154
169
|
|
|
155
170
|
if __name__ == "__main__":
|
|
156
171
|
# Basic env-var sanity checks
|
|
157
|
-
|
|
172
|
+
# SHAREDDATA_TOKEN is the ClientAPI default, not a server setting: the API
|
|
173
|
+
# checks hashed tokens in the users store.
|
|
174
|
+
required_env = ("SHAREDDATA_SECRET_KEY",)
|
|
158
175
|
missing = [v for v in required_env if v not in os.environ]
|
|
159
176
|
if missing:
|
|
160
177
|
sys.exit(f"Missing environment variables: {', '.join(missing)}")
|
|
@@ -31,7 +31,9 @@ def parse_args():
|
|
|
31
31
|
|
|
32
32
|
def validate_environment():
|
|
33
33
|
"""Validate required environment variables are set."""
|
|
34
|
-
|
|
34
|
+
# SHAREDDATA_TOKEN is the ClientAPI default, not a server setting: the API
|
|
35
|
+
# checks hashed tokens in the users store.
|
|
36
|
+
required_env = ('SHAREDDATA_SECRET_KEY',)
|
|
35
37
|
missing = [v for v in required_env if v not in os.environ]
|
|
36
38
|
if missing:
|
|
37
39
|
sys.exit(f"Missing environment variables: {', '.join(missing)}")
|
|
@@ -7,11 +7,12 @@ This package provides a modular, blueprint-based Flask API for SharedData operat
|
|
|
7
7
|
import os
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
|
|
10
|
-
from flask import Flask
|
|
10
|
+
from flask import Flask, jsonify, request
|
|
11
11
|
from flasgger import Swagger
|
|
12
12
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
|
13
13
|
|
|
14
14
|
from SharedData.SharedData import SharedData
|
|
15
|
+
from SharedData.Redaction import install_flask_redaction
|
|
15
16
|
from SharedData.Logger import Logger
|
|
16
17
|
|
|
17
18
|
from SharedData.API.auth import authenticate
|
|
@@ -32,7 +33,7 @@ from SharedData.API.routes.system import (
|
|
|
32
33
|
)
|
|
33
34
|
|
|
34
35
|
|
|
35
|
-
def create_app(shdata=None, quiet=True):
|
|
36
|
+
def create_app(shdata=None, quiet=True, app=None):
|
|
36
37
|
"""
|
|
37
38
|
Create and configure the Flask application with all blueprints.
|
|
38
39
|
|
|
@@ -44,7 +45,8 @@ def create_app(shdata=None, quiet=True):
|
|
|
44
45
|
Configured Flask application instance.
|
|
45
46
|
"""
|
|
46
47
|
# Create Flask app
|
|
47
|
-
app = Flask(__name__)
|
|
48
|
+
app = app or Flask(__name__)
|
|
49
|
+
install_flask_redaction(app)
|
|
48
50
|
app.config['APP_NAME'] = 'SharedData API'
|
|
49
51
|
app.config['FLASK_ENV'] = 'production'
|
|
50
52
|
app.config['FLASK_DEBUG'] = '0'
|
|
@@ -53,12 +55,21 @@ def create_app(shdata=None, quiet=True):
|
|
|
53
55
|
if 'SHAREDDATA_SECRET_KEY' not in os.environ:
|
|
54
56
|
raise Exception('SHAREDDATA_SECRET_KEY environment variable not set')
|
|
55
57
|
|
|
56
|
-
app.config
|
|
58
|
+
if not app.config.get('SECRET_KEY'):
|
|
59
|
+
app.config['SECRET_KEY'] = os.environ['SHAREDDATA_SECRET_KEY']
|
|
60
|
+
dark_css = Path(__file__).parent / 'apidocs-dark.css'
|
|
57
61
|
app.config['SWAGGER'] = {
|
|
58
62
|
'title': 'SharedData API',
|
|
59
63
|
'uiversion': 3,
|
|
64
|
+
'openapi': '3.0.3', # apidocs.yml is OpenAPI 3
|
|
60
65
|
'hide_top_bar': True,
|
|
61
|
-
'doc_expansion': '
|
|
66
|
+
'doc_expansion': 'none', # tags collapsed: the overview first
|
|
67
|
+
# flasgger prints this straight into the page's script: without it the page gets
|
|
68
|
+
# `let auth_config = None;` and a script error (the docs still rendered).
|
|
69
|
+
'auth': {},
|
|
70
|
+
# Dark theme matching the WebUI.
|
|
71
|
+
'head_text': ('<meta name="viewport" content="width=device-width, initial-scale=1">'
|
|
72
|
+
+ ('<style>' + dark_css.read_text() + '</style>' if dark_css.exists() else '')),
|
|
62
73
|
}
|
|
63
74
|
|
|
64
75
|
# Setup Swagger documentation
|
|
@@ -80,24 +91,37 @@ def create_app(shdata=None, quiet=True):
|
|
|
80
91
|
return authenticate(request, sd)
|
|
81
92
|
|
|
82
93
|
# Initialize and register blueprints
|
|
83
|
-
init_tables_routes
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
app.register_blueprint(
|
|
95
|
-
|
|
96
|
-
app.register_blueprint(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
app
|
|
100
|
-
|
|
94
|
+
for factory in (init_tables_routes, init_collections_routes, init_timeseries_routes,
|
|
95
|
+
init_workers_routes, init_metadata_routes, init_cache_routes,
|
|
96
|
+
init_downloads_routes, init_system_routes):
|
|
97
|
+
app.register_blueprint(factory(shdata, authenticate_fn), url_prefix='/api')
|
|
98
|
+
from SharedData.API.routes.sqlite import init_sqlite_routes
|
|
99
|
+
app.register_blueprint(init_sqlite_routes(shdata, authenticate_fn), url_prefix='/api')
|
|
100
|
+
from SharedData.API.routes.web_routes import init_routes_routes
|
|
101
|
+
app.register_blueprint(init_routes_routes(shdata, authenticate_fn), url_prefix='/api')
|
|
102
|
+
from SharedData.API.routes.schedules import init_schedules_routes
|
|
103
|
+
app.register_blueprint(init_schedules_routes(shdata, authenticate_fn), url_prefix='/api')
|
|
104
|
+
from SharedData.API.routes.operations import init_operations_routes
|
|
105
|
+
app.register_blueprint(init_operations_routes(shdata, authenticate_fn), url_prefix='/api')
|
|
106
|
+
from SharedData.API.routes.data import init_data_routes
|
|
107
|
+
app.register_blueprint(init_data_routes(shdata, authenticate_fn), url_prefix='/api')
|
|
108
|
+
|
|
109
|
+
from SharedData.API.utils import init_table_waiters
|
|
110
|
+
init_table_waiters(app)
|
|
111
|
+
|
|
112
|
+
@app.before_request
|
|
113
|
+
def auth_availability():
|
|
114
|
+
from SharedData.Auth.store import StoreUnavailable
|
|
115
|
+
# Worker install scripts and enrollment take a one-time install code instead of a token.
|
|
116
|
+
public = request.path in ('/api/health', '/api/heartbeat', '/api/workers/enroll') or \
|
|
117
|
+
request.path.startswith(('/api/auth/', '/api/web/', '/api/workers/install/'))
|
|
118
|
+
from SharedData.API.auth import local_log_token_ok
|
|
119
|
+
if request.path.startswith('/api/') and not public and not local_log_token_ok(request):
|
|
120
|
+
try:
|
|
121
|
+
if not authenticate_fn(request, shdata):
|
|
122
|
+
return jsonify(error='unauthorized'), 401
|
|
123
|
+
except StoreUnavailable:
|
|
124
|
+
return jsonify(error='auth_store_unavailable'), 503
|
|
101
125
|
|
|
102
126
|
# Register request lifecycle hooks
|
|
103
127
|
register_request_hooks(app)
|