shareddata 6.83.22__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.
Files changed (198) hide show
  1. shareddata-6.85.0/LICENSE +21 -0
  2. shareddata-6.85.0/MANIFEST.in +5 -0
  3. {shareddata-6.83.22/src/shareddata.egg-info → shareddata-6.85.0}/PKG-INFO +87 -39
  4. {shareddata-6.83.22 → shareddata-6.85.0}/README.md +31 -12
  5. {shareddata-6.83.22 → shareddata-6.85.0}/pyproject.toml +1 -0
  6. shareddata-6.85.0/setup.py +110 -0
  7. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/ServerGunicorn.py +19 -2
  8. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/ServerWaitress.py +3 -1
  9. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/__init__.py +47 -23
  10. shareddata-6.85.0/src/SharedData/API/apidocs-dark.css +97 -0
  11. shareddata-6.85.0/src/SharedData/API/apidocs.yml +3347 -0
  12. shareddata-6.85.0/src/SharedData/API/auth.py +244 -0
  13. shareddata-6.85.0/src/SharedData/API/install/worker.ps1 +102 -0
  14. shareddata-6.85.0/src/SharedData/API/install/worker.sh +105 -0
  15. shareddata-6.85.0/src/SharedData/API/listcache.py +236 -0
  16. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/routes/cache.py +2 -0
  17. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/routes/collections.py +79 -8
  18. shareddata-6.85.0/src/SharedData/API/routes/data.py +66 -0
  19. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/routes/downloads.py +10 -0
  20. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/routes/metadata.py +2 -0
  21. shareddata-6.85.0/src/SharedData/API/routes/operations.py +82 -0
  22. shareddata-6.85.0/src/SharedData/API/routes/schedules.py +99 -0
  23. shareddata-6.85.0/src/SharedData/API/routes/sqlite.py +145 -0
  24. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/routes/system.py +43 -6
  25. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/routes/tables.py +104 -21
  26. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/routes/timeseries.py +26 -4
  27. shareddata-6.85.0/src/SharedData/API/routes/web_routes.py +79 -0
  28. shareddata-6.85.0/src/SharedData/API/routes/workers.py +361 -0
  29. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/utils.py +44 -0
  30. shareddata-6.85.0/src/SharedData/Auth/__init__.py +1 -0
  31. shareddata-6.85.0/src/SharedData/Auth/bootstrap.py +70 -0
  32. shareddata-6.85.0/src/SharedData/Auth/migrate.py +270 -0
  33. shareddata-6.85.0/src/SharedData/Auth/store.py +279 -0
  34. shareddata-6.85.0/src/SharedData/Auth/workers.py +669 -0
  35. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/CacheRedis.py +245 -45
  36. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/CollectionMongoDB.py +31 -0
  37. shareddata-6.85.0/src/SharedData/DataAPI/__init__.py +19 -0
  38. shareddata-6.85.0/src/SharedData/DataAPI/catalog.py +286 -0
  39. shareddata-6.85.0/src/SharedData/DataAPI/config.py +81 -0
  40. shareddata-6.85.0/src/SharedData/DataAPI/errors.py +31 -0
  41. shareddata-6.85.0/src/SharedData/DataAPI/indexes.py +75 -0
  42. shareddata-6.85.0/src/SharedData/DataAPI/readers.py +291 -0
  43. shareddata-6.85.0/src/SharedData/DataAPI/resolve.py +222 -0
  44. shareddata-6.85.0/src/SharedData/DataAPI/service.py +824 -0
  45. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Defaults.py +51 -18
  46. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/AWSS3.py +18 -6
  47. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/ClientAPI.py +349 -14
  48. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/LogHandlerAPI.py +16 -15
  49. shareddata-6.85.0/src/SharedData/IO/LogReader.py +139 -0
  50. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/MongoDBClient.py +10 -3
  51. shareddata-6.85.0/src/SharedData/IO/SaveTables.py +144 -0
  52. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/ServerWebSocket.py +9 -7
  53. shareddata-6.85.0/src/SharedData/Listing.py +31 -0
  54. shareddata-6.85.0/src/SharedData/LockWaiters.py +102 -0
  55. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Logger.py +28 -15
  56. shareddata-6.85.0/src/SharedData/MCP/__init__.py +3 -0
  57. shareddata-6.85.0/src/SharedData/MCP/__main__.py +3 -0
  58. shareddata-6.85.0/src/SharedData/MCP/client.py +132 -0
  59. shareddata-6.85.0/src/SharedData/MCP/server.py +885 -0
  60. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Metadata.py +21 -1
  61. shareddata-6.85.0/src/SharedData/Redaction.py +965 -0
  62. shareddata-6.85.0/src/SharedData/Routines/ContainerHealth.py +50 -0
  63. shareddata-6.85.0/src/SharedData/Routines/JobStore.py +432 -0
  64. shareddata-6.85.0/src/SharedData/Routines/RoutineCommand.py +36 -0
  65. shareddata-6.85.0/src/SharedData/Routines/RoutineOrigin.py +161 -0
  66. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Routines/Schedule.py +125 -74
  67. shareddata-6.85.0/src/SharedData/Routines/ScheduleMirror.py +109 -0
  68. shareddata-6.85.0/src/SharedData/Routines/ScheduleStore.py +430 -0
  69. shareddata-6.85.0/src/SharedData/Routines/Scheduler.py +214 -0
  70. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Routines/Worker.py +42 -6
  71. shareddata-6.85.0/src/SharedData/Routines/WorkerBootstrap.py +141 -0
  72. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Routines/WorkerLib.py +331 -189
  73. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Routines/WorkerPool.py +120 -13
  74. shareddata-6.85.0/src/SharedData/SQLite.py +477 -0
  75. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/SharedData.py +322 -92
  76. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/SharedNumpy.py +298 -299
  77. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Table.py +299 -102
  78. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/TableDisk.py +49 -64
  79. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/TableIndex.py +150 -142
  80. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/TableIndexJitFunctions.py +389 -296
  81. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/TableIndexJitGenerate.py +33 -21
  82. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/TableIndexJitHash.py +14 -1
  83. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/TableIndexJitLoc.py +96 -146
  84. shareddata-6.85.0/src/SharedData/TableProtocol.py +196 -0
  85. shareddata-6.85.0/src/SharedData/TableRead.py +155 -0
  86. shareddata-6.85.0/src/SharedData/TableRewrite.py +301 -0
  87. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/TimeSeriesDisk.py +206 -285
  88. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/TimeseriesContainer.py +80 -45
  89. shareddata-6.85.0/src/SharedData/Users.py +36 -0
  90. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Utils.py +37 -6
  91. shareddata-6.85.0/src/SharedData/Web/ADDING_A_PAGE.md +18 -0
  92. shareddata-6.85.0/src/SharedData/Web/__init__.py +37 -0
  93. shareddata-6.85.0/src/SharedData/Web/activity_logger.py +231 -0
  94. shareddata-6.85.0/src/SharedData/Web/app.py +38 -0
  95. shareddata-6.85.0/src/SharedData/Web/assets/dashAgGridComponentFunctions.js +33 -0
  96. shareddata-6.85.0/src/SharedData/Web/assets/dashAgGridFunctions.js +36 -0
  97. shareddata-6.85.0/src/SharedData/Web/assets/google_logo.png +0 -0
  98. shareddata-6.85.0/src/SharedData/Web/assets/kafka_keys.js +19 -0
  99. shareddata-6.85.0/src/SharedData/Web/assets/logs.css +201 -0
  100. shareddata-6.85.0/src/SharedData/Web/assets/sched.css +452 -0
  101. shareddata-6.85.0/src/SharedData/Web/assets/styles.css +1059 -0
  102. shareddata-6.85.0/src/SharedData/Web/auth.py +357 -0
  103. shareddata-6.85.0/src/SharedData/Web/backends.py +73 -0
  104. shareddata-6.85.0/src/SharedData/Web/config.py +254 -0
  105. shareddata-6.85.0/src/SharedData/Web/containers.py +426 -0
  106. shareddata-6.85.0/src/SharedData/Web/identity.py +140 -0
  107. shareddata-6.85.0/src/SharedData/Web/kafka_view.py +181 -0
  108. shareddata-6.85.0/src/SharedData/Web/mongo_view.py +125 -0
  109. shareddata-6.85.0/src/SharedData/Web/redis_view.py +286 -0
  110. shareddata-6.85.0/src/SharedData/Web/route_health.py +249 -0
  111. shareddata-6.85.0/src/SharedData/Web/route_registry.py +463 -0
  112. shareddata-6.85.0/src/SharedData/Web/sched.py +321 -0
  113. shareddata-6.85.0/src/SharedData/Web/schedule_editor.py +156 -0
  114. shareddata-6.85.0/src/SharedData/Web/server.py +176 -0
  115. shareddata-6.85.0/src/SharedData/Web/services.py +335 -0
  116. shareddata-6.85.0/src/SharedData/Web/shell.py +441 -0
  117. shareddata-6.85.0/src/SharedData/Web/standalone.py +710 -0
  118. shareddata-6.85.0/src/SharedData/Web/static/account.js +54 -0
  119. shareddata-6.85.0/src/SharedData/Web/static/custom.css +300 -0
  120. shareddata-6.85.0/src/SharedData/Web/static/favicon.ico +0 -0
  121. shareddata-6.85.0/src/SharedData/Web/static/favicon.png +0 -0
  122. shareddata-6.85.0/src/SharedData/Web/static/logo.png +0 -0
  123. shareddata-6.85.0/src/SharedData/Web/static/logo_96x96.png +0 -0
  124. shareddata-6.85.0/src/SharedData/Web/static/shareddata-mark.svg +6 -0
  125. shareddata-6.85.0/src/SharedData/Web/static/shell.css +493 -0
  126. shareddata-6.85.0/src/SharedData/Web/static/shell.js +461 -0
  127. shareddata-6.85.0/src/SharedData/Web/static/standalone.css +480 -0
  128. shareddata-6.85.0/src/SharedData/Web/static/standalone.js +2020 -0
  129. shareddata-6.85.0/src/SharedData/Web/suggest.py +251 -0
  130. shareddata-6.85.0/src/SharedData/Web/templates/account.html +15 -0
  131. shareddata-6.85.0/src/SharedData/Web/templates/base.html +47 -0
  132. shareddata-6.85.0/src/SharedData/Web/templates/claim.html +10 -0
  133. shareddata-6.85.0/src/SharedData/Web/templates/claim_done.html +2 -0
  134. shareddata-6.85.0/src/SharedData/Web/templates/dash.html +18 -0
  135. shareddata-6.85.0/src/SharedData/Web/templates/index.html +17 -0
  136. shareddata-6.85.0/src/SharedData/Web/templates/login.html +350 -0
  137. shareddata-6.85.0/src/SharedData/Web/templates/login_2fa.html +19 -0
  138. shareddata-6.85.0/src/SharedData/Web/templates/partials/navbar.html +317 -0
  139. shareddata-6.85.0/src/SharedData/Web/templates/partials/scripts.html +12 -0
  140. shareddata-6.85.0/src/SharedData/Web/templates/recovery_codes.html +9 -0
  141. shareddata-6.85.0/src/SharedData/Web/templates/shell.html +63 -0
  142. shareddata-6.85.0/src/SharedData/Web/templates/standalone.html +124 -0
  143. shareddata-6.85.0/src/SharedData/Web/twofactor.py +250 -0
  144. shareddata-6.85.0/src/SharedData/Web/utils.py +23 -0
  145. shareddata-6.85.0/src/SharedData/Web/workerpool.py +451 -0
  146. shareddata-6.85.0/src/SharedData/__init__.py +7 -0
  147. shareddata-6.85.0/src/SharedData/build_info.py +23 -0
  148. shareddata-6.85.0/src/SharedData/fleet.py +101 -0
  149. shareddata-6.85.0/src/SharedData/preflight.py +140 -0
  150. shareddata-6.85.0/src/SharedData/private_files.py +71 -0
  151. shareddata-6.85.0/src/SharedData/release_backup.py +250 -0
  152. shareddata-6.85.0/src/SharedData/server.py +35 -0
  153. shareddata-6.85.0/src/SharedData/services.py +11 -0
  154. {shareddata-6.83.22 → shareddata-6.85.0/src/shareddata.egg-info}/PKG-INFO +87 -39
  155. shareddata-6.85.0/src/shareddata.egg-info/SOURCES.txt +184 -0
  156. shareddata-6.85.0/src/shareddata.egg-info/entry_points.txt +4 -0
  157. shareddata-6.85.0/src/shareddata.egg-info/requires.txt +49 -0
  158. shareddata-6.83.22/LICENSE +0 -674
  159. shareddata-6.83.22/MANIFEST.in +0 -3
  160. shareddata-6.83.22/setup.py +0 -51
  161. shareddata-6.83.22/src/SharedData/API/auth.py +0 -211
  162. shareddata-6.83.22/src/SharedData/API/listcache.py +0 -91
  163. shareddata-6.83.22/src/SharedData/API/routes/workers.py +0 -202
  164. shareddata-6.83.22/src/SharedData/IO/SaveTables.py +0 -58
  165. shareddata-6.83.22/src/SharedData/Routines/Scheduler.py +0 -109
  166. shareddata-6.83.22/src/SharedData/Users.py +0 -32
  167. shareddata-6.83.22/src/SharedData/__init__.py +0 -0
  168. shareddata-6.83.22/src/shareddata.egg-info/SOURCES.txt +0 -80
  169. shareddata-6.83.22/src/shareddata.egg-info/requires.txt +0 -28
  170. {shareddata-6.83.22 → shareddata-6.85.0}/setup.cfg +0 -0
  171. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/constants.py +0 -0
  172. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/download_paths.py +0 -0
  173. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/download_slots.py +0 -0
  174. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/API/routes/__init__.py +0 -0
  175. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Database.py +0 -0
  176. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/AWSEC2.py +0 -0
  177. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/AutoDocstrings.py +0 -0
  178. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/ClientSocket.py +0 -0
  179. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/ClientWebSocket.py +0 -0
  180. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/ServerSocket.py +0 -0
  181. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/StreamsCache.py +0 -0
  182. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/StreamsPersist.py +0 -0
  183. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/SyncTable.py +0 -0
  184. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/TunnelWebSocket.py +0 -0
  185. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/IO/__init__.py +0 -0
  186. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/MultiProc.py +0 -0
  187. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/OpenFIGI.py +0 -0
  188. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Routines/ArchiveOldCollections.py +0 -0
  189. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Routines/BatchJob.py +0 -0
  190. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Routines/ScheduleMonitor.py +0 -0
  191. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Routines/UpdateActiveJobs.py +0 -0
  192. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Routines/__init__.py +0 -0
  193. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/StreamKafka.py +0 -0
  194. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/Symbol.py +0 -0
  195. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/TableIndexJitFunctionsManual.py +0 -0
  196. {shareddata-6.83.22 → shareddata-6.85.0}/src/SharedData/sharedmutexwin.pyd +0 -0
  197. {shareddata-6.83.22 → shareddata-6.85.0}/src/shareddata.egg-info/dependency_links.txt +0 -0
  198. {shareddata-6.83.22 → 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.
@@ -0,0 +1,5 @@
1
+ include src/SharedData/sharedmutexwin.pyd
2
+ include src/SharedData/API/apidocs.yml
3
+ include src/SharedData/API/apidocs-dark.css
4
+ include src/SharedData/API/install/*
5
+ prune tests
@@ -1,45 +1,74 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shareddata
3
- Version: 6.83.22
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.9, <3.13
15
+ Requires-Python: >=3.11, <3.13
9
16
  Description-Content-Type: text/markdown
10
17
  License-File: LICENSE
11
- Requires-Dist: ipykernel==6.23.3
12
- Requires-Dist: boto3==1.26.160
13
- Requires-Dist: python-json-logger==2.0.7
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==1.14.0
17
- Requires-Dist: numpy==1.26.2
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==3.1.2
20
- Requires-Dist: openpyxl==3.1.2
21
- Requires-Dist: tqdm==4.65.0
22
- Requires-Dist: cffi==1.17.1
23
- Requires-Dist: tzlocal==5.0.1
24
- Requires-Dist: websockets==12.0
25
- Requires-Dist: cryptography==41.0.7
26
- Requires-Dist: lz4==4.3.3
27
- Requires-Dist: flask==3.0.0
28
- Requires-Dist: waitress==3.0.0
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==4.8.0
32
- Requires-Dist: setuptools==74.1.2
33
- Requires-Dist: filelock==3.18.0
34
- Requires-Dist: gunicorn==23.0.0
35
- Requires-Dist: confluent-kafka==2.10.0
36
- Requires-Dist: aiokafka==0.12.0
37
- Requires-Dist: aiohttp==3.12.13
38
- Requires-Dist: redis==6.2.0
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 for details.
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 for details.
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
- required_env = ("SHAREDDATA_SECRET_KEY", "SHAREDDATA_TOKEN")
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
- required_env = ('SHAREDDATA_SECRET_KEY', 'SHAREDDATA_TOKEN')
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['SECRET_KEY'] = os.environ['SHAREDDATA_SECRET_KEY']
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': 'list'
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(shdata, authenticate_fn)
84
- init_collections_routes(shdata, authenticate_fn)
85
- init_timeseries_routes(shdata, authenticate_fn)
86
- init_workers_routes(shdata, authenticate_fn)
87
- init_metadata_routes(shdata, authenticate_fn)
88
- init_cache_routes(shdata, authenticate_fn)
89
- downloads_bp = init_downloads_routes(shdata, authenticate_fn)
90
- init_system_routes(shdata, authenticate_fn)
91
-
92
- # Register blueprints with /api prefix
93
- app.register_blueprint(tables_bp, url_prefix='/api')
94
- app.register_blueprint(collections_bp, url_prefix='/api')
95
- app.register_blueprint(timeseries_bp, url_prefix='/api')
96
- app.register_blueprint(workers_bp, url_prefix='/api')
97
- app.register_blueprint(metadata_bp, url_prefix='/api')
98
- app.register_blueprint(cache_bp, url_prefix='/api')
99
- app.register_blueprint(downloads_bp, url_prefix='/api')
100
- app.register_blueprint(system_bp, url_prefix='/api')
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)