shareddata 6.86.1__tar.gz → 6.94.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.

Potentially problematic release.


This version of shareddata might be problematic. Click here for more details.

Files changed (212) hide show
  1. {shareddata-6.86.1/src/shareddata.egg-info → shareddata-6.94.0}/PKG-INFO +1 -1
  2. {shareddata-6.86.1 → shareddata-6.94.0}/setup.py +3 -1
  3. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/__init__.py +8 -1
  4. shareddata-6.94.0/src/SharedData/API/access_log.py +306 -0
  5. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/auth.py +10 -2
  6. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/data.py +1 -1
  7. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/tables.py +24 -16
  8. shareddata-6.94.0/src/SharedData/Analytics/__init__.py +1 -0
  9. shareddata-6.94.0/src/SharedData/Analytics/cdie.py +283 -0
  10. shareddata-6.94.0/src/SharedData/Analytics/cdie_calendar.py +28 -0
  11. shareddata-6.94.0/src/SharedData/Analytics/cdie_store.py +74 -0
  12. shareddata-6.94.0/src/SharedData/Analytics/data/cdie/anbima_holidays.csv +235 -0
  13. shareddata-6.94.0/src/SharedData/Analytics/data/cdie/b3_session_overrides.csv +37 -0
  14. shareddata-6.94.0/src/SharedData/Analytics/data/cdie/copom.csv +33 -0
  15. shareddata-6.94.0/src/SharedData/Analytics/data/cdie/manifest.json +56 -0
  16. shareddata-6.94.0/src/SharedData/ConsensusGraph.py +869 -0
  17. shareddata-6.94.0/src/SharedData/DataAPI/cdie.py +72 -0
  18. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/DataAPI/service.py +6 -1
  19. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/ClientAPI.py +94 -51
  20. shareddata-6.94.0/src/SharedData/KnowledgeBase.py +1474 -0
  21. shareddata-6.94.0/src/SharedData/KnowledgeContract.py +978 -0
  22. shareddata-6.94.0/src/SharedData/KnowledgeEvaluation.py +232 -0
  23. shareddata-6.94.0/src/SharedData/KnowledgeExperiment.py +335 -0
  24. shareddata-6.94.0/src/SharedData/KnowledgeGraph.py +536 -0
  25. shareddata-6.94.0/src/SharedData/KnowledgeLookup.py +156 -0
  26. shareddata-6.94.0/src/SharedData/KnowledgeMarket.py +417 -0
  27. shareddata-6.94.0/src/SharedData/KnowledgeOntology.py +176 -0
  28. shareddata-6.94.0/src/SharedData/KnowledgeResearch.py +481 -0
  29. shareddata-6.94.0/src/SharedData/KnowledgeScenario.py +200 -0
  30. shareddata-6.94.0/src/SharedData/KnowledgeXBRL.py +273 -0
  31. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Logger.py +3 -0
  32. shareddata-6.94.0/src/SharedData/ResearchMCP.py +432 -0
  33. shareddata-6.94.0/src/SharedData/Routines/PackageRoutine.py +174 -0
  34. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/RoutineCommand.py +8 -1
  35. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/RoutineOrigin.py +6 -1
  36. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/WorkerLib.py +28 -3
  37. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/SharedData.py +21 -4
  38. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/SharedNumpy.py +124 -8
  39. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Table.py +120 -27
  40. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/TableDisk.py +5 -3
  41. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/TableIndex.py +96 -38
  42. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/TableIndexJitFunctions.py +1247 -48
  43. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/TableIndexJitGenerate.py +34 -14
  44. shareddata-6.94.0/src/SharedData/TableVector.py +140 -0
  45. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Utils.py +4 -2
  46. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/schedule_editor.py +9 -2
  47. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/workerpool.py +6 -1
  48. {shareddata-6.86.1 → shareddata-6.94.0/src/shareddata.egg-info}/PKG-INFO +1 -1
  49. {shareddata-6.86.1 → shareddata-6.94.0}/src/shareddata.egg-info/SOURCES.txt +25 -0
  50. {shareddata-6.86.1 → shareddata-6.94.0}/src/shareddata.egg-info/entry_points.txt +1 -0
  51. {shareddata-6.86.1 → shareddata-6.94.0}/LICENSE +0 -0
  52. {shareddata-6.86.1 → shareddata-6.94.0}/MANIFEST.in +0 -0
  53. {shareddata-6.86.1 → shareddata-6.94.0}/README.md +0 -0
  54. {shareddata-6.86.1 → shareddata-6.94.0}/pyproject.toml +0 -0
  55. {shareddata-6.86.1 → shareddata-6.94.0}/setup.cfg +0 -0
  56. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/ServerGunicorn.py +0 -0
  57. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/ServerWaitress.py +0 -0
  58. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/apidocs-dark.css +0 -0
  59. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/apidocs.yml +0 -0
  60. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/constants.py +0 -0
  61. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/download_paths.py +0 -0
  62. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/download_slots.py +0 -0
  63. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/install/worker.ps1 +0 -0
  64. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/install/worker.sh +0 -0
  65. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/listcache.py +0 -0
  66. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/__init__.py +0 -0
  67. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/cache.py +0 -0
  68. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/collections.py +0 -0
  69. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/downloads.py +0 -0
  70. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/metadata.py +0 -0
  71. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/operations.py +0 -0
  72. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/schedules.py +0 -0
  73. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/sqlite.py +0 -0
  74. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/system.py +0 -0
  75. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/timeseries.py +0 -0
  76. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/web_routes.py +0 -0
  77. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/routes/workers.py +0 -0
  78. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/API/utils.py +0 -0
  79. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Auth/__init__.py +0 -0
  80. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Auth/bootstrap.py +0 -0
  81. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Auth/migrate.py +0 -0
  82. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Auth/store.py +0 -0
  83. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Auth/workers.py +0 -0
  84. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/CacheRedis.py +0 -0
  85. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/CollectionMongoDB.py +0 -0
  86. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/DataAPI/__init__.py +0 -0
  87. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/DataAPI/catalog.py +0 -0
  88. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/DataAPI/config.py +0 -0
  89. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/DataAPI/errors.py +0 -0
  90. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/DataAPI/indexes.py +0 -0
  91. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/DataAPI/readers.py +0 -0
  92. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/DataAPI/resolve.py +0 -0
  93. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Database.py +0 -0
  94. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Defaults.py +0 -0
  95. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/AWSEC2.py +0 -0
  96. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/AWSS3.py +0 -0
  97. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/AutoDocstrings.py +0 -0
  98. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/ClientSocket.py +0 -0
  99. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/ClientWebSocket.py +0 -0
  100. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/LogHandlerAPI.py +0 -0
  101. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/LogReader.py +0 -0
  102. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/MongoDBClient.py +0 -0
  103. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/SaveTables.py +0 -0
  104. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/ServerSocket.py +0 -0
  105. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/ServerWebSocket.py +0 -0
  106. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/StreamsCache.py +0 -0
  107. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/StreamsPersist.py +0 -0
  108. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/SyncTable.py +0 -0
  109. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/TunnelWebSocket.py +0 -0
  110. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/IO/__init__.py +0 -0
  111. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Listing.py +0 -0
  112. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/LockWaiters.py +0 -0
  113. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/MCP/__init__.py +0 -0
  114. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/MCP/__main__.py +0 -0
  115. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/MCP/client.py +0 -0
  116. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/MCP/server.py +0 -0
  117. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Metadata.py +0 -0
  118. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/MultiProc.py +0 -0
  119. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/OpenFIGI.py +0 -0
  120. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Redaction.py +0 -0
  121. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/ArchiveOldCollections.py +0 -0
  122. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/BatchJob.py +0 -0
  123. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/ContainerHealth.py +0 -0
  124. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/JobStore.py +0 -0
  125. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/Schedule.py +0 -0
  126. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/ScheduleMirror.py +0 -0
  127. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/ScheduleMonitor.py +0 -0
  128. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/ScheduleStore.py +0 -0
  129. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/Scheduler.py +0 -0
  130. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/UpdateActiveJobs.py +0 -0
  131. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/Worker.py +0 -0
  132. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/WorkerBootstrap.py +0 -0
  133. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/WorkerPool.py +0 -0
  134. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Routines/__init__.py +0 -0
  135. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/SQLite.py +0 -0
  136. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/StreamKafka.py +0 -0
  137. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Symbol.py +0 -0
  138. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/TableIndexJitFunctionsManual.py +0 -0
  139. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/TableIndexJitHash.py +0 -0
  140. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/TableIndexJitLoc.py +0 -0
  141. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/TableProtocol.py +0 -0
  142. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/TableRead.py +0 -0
  143. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/TableRewrite.py +0 -0
  144. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/TimeSeriesDisk.py +0 -0
  145. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/TimeseriesContainer.py +0 -0
  146. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Users.py +0 -0
  147. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/ADDING_A_PAGE.md +0 -0
  148. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/__init__.py +0 -0
  149. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/activity_logger.py +0 -0
  150. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/app.py +0 -0
  151. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/assets/dashAgGridComponentFunctions.js +0 -0
  152. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/assets/dashAgGridFunctions.js +0 -0
  153. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/assets/google_logo.png +0 -0
  154. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/assets/kafka_keys.js +0 -0
  155. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/assets/logs.css +0 -0
  156. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/assets/sched.css +0 -0
  157. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/assets/styles.css +0 -0
  158. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/auth.py +0 -0
  159. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/backends.py +0 -0
  160. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/config.py +0 -0
  161. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/containers.py +0 -0
  162. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/identity.py +0 -0
  163. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/kafka_view.py +0 -0
  164. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/mongo_view.py +0 -0
  165. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/proc.py +0 -0
  166. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/redis_view.py +0 -0
  167. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/route_health.py +0 -0
  168. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/route_registry.py +0 -0
  169. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/sched.py +0 -0
  170. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/server.py +0 -0
  171. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/services.py +0 -0
  172. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/shell.py +0 -0
  173. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/standalone.py +0 -0
  174. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/static/account.js +0 -0
  175. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/static/custom.css +0 -0
  176. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/static/favicon.ico +0 -0
  177. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/static/favicon.png +0 -0
  178. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/static/logo.png +0 -0
  179. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/static/logo_96x96.png +0 -0
  180. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/static/shareddata-mark.svg +0 -0
  181. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/static/shell.css +0 -0
  182. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/static/shell.js +0 -0
  183. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/static/standalone.css +0 -0
  184. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/static/standalone.js +0 -0
  185. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/suggest.py +0 -0
  186. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/account.html +0 -0
  187. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/base.html +0 -0
  188. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/claim.html +0 -0
  189. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/claim_done.html +0 -0
  190. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/dash.html +0 -0
  191. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/index.html +0 -0
  192. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/login.html +0 -0
  193. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/login_2fa.html +0 -0
  194. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/partials/navbar.html +0 -0
  195. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/partials/scripts.html +0 -0
  196. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/recovery_codes.html +0 -0
  197. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/shell.html +0 -0
  198. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/templates/standalone.html +0 -0
  199. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/twofactor.py +0 -0
  200. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/Web/utils.py +0 -0
  201. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/__init__.py +0 -0
  202. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/build_info.py +0 -0
  203. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/fleet.py +0 -0
  204. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/preflight.py +0 -0
  205. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/private_files.py +0 -0
  206. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/release_backup.py +0 -0
  207. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/server.py +0 -0
  208. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/services.py +0 -0
  209. {shareddata-6.86.1 → shareddata-6.94.0}/src/SharedData/sharedmutexwin.pyd +0 -0
  210. {shareddata-6.86.1 → shareddata-6.94.0}/src/shareddata.egg-info/dependency_links.txt +0 -0
  211. {shareddata-6.86.1 → shareddata-6.94.0}/src/shareddata.egg-info/requires.txt +0 -0
  212. {shareddata-6.86.1 → shareddata-6.94.0}/src/shareddata.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shareddata
3
- Version: 6.86.1
3
+ Version: 6.94.0
4
4
  Summary: Memory-mapped record and time-series store with an HTTP API and a distributed scheduler
5
5
  Home-page: https://shareddata.net
6
6
  Author: shareddata
@@ -66,7 +66,7 @@ test_requires = [
66
66
 
67
67
  setup(
68
68
  name='shareddata',
69
- version='6.86.1',
69
+ version='6.94.0',
70
70
  description='Memory-mapped record and time-series store with an HTTP API and a distributed scheduler',
71
71
  author='shareddata',
72
72
  author_email='admin@shareddata.net',
@@ -92,6 +92,7 @@ setup(
92
92
  extras_require={'test': test_requires, 's3': [], 'kafka': [], 'redis': [], 'all': []},
93
93
  include_package_data=True,
94
94
  package_data={
95
+ 'SharedData.Analytics': ['data/cdie/*.csv', 'data/cdie/*.json'],
95
96
  'SharedData.API': ['apidocs.yml', 'apidocs-dark.css', 'install/*'],
96
97
  'SharedData.Web': [
97
98
  'templates/*', 'templates/**/*',
@@ -105,6 +106,7 @@ setup(
105
106
  'shdata-web=SharedData.Web.server:main',
106
107
  'shdata-server=SharedData.server:main',
107
108
  'shareddata-mcp=SharedData.MCP.server:main',
109
+ 'shareddata-research-mcp=SharedData.ResearchMCP:main',
108
110
  ],
109
111
  },
110
112
  )
@@ -111,12 +111,16 @@ def create_app(shdata=None, quiet=True, app=None):
111
111
 
112
112
  @app.before_request
113
113
  def auth_availability():
114
+ from flask import g
114
115
  from SharedData.Auth.store import StoreUnavailable
115
116
  # Worker install scripts and enrollment take a one-time install code instead of a token.
116
117
  public = request.path in ('/api/health', '/api/heartbeat', '/api/workers/enroll') or \
117
118
  request.path.startswith(('/api/auth/', '/api/web/', '/api/workers/install/'))
118
119
  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
+ if local_log_token_ok(request):
121
+ g.client_user = 'local-log'
122
+ return
123
+ if request.path.startswith('/api/') and not public:
120
124
  try:
121
125
  if not authenticate_fn(request, shdata):
122
126
  return jsonify(error='unauthorized'), 401
@@ -126,6 +130,9 @@ def create_app(shdata=None, quiet=True, app=None):
126
130
  # Register request lifecycle hooks
127
131
  register_request_hooks(app)
128
132
 
133
+ from SharedData.API import access_log
134
+ access_log.register(app, shdata)
135
+
129
136
  # Store shdata on app for access in routes
130
137
  app.shdata = shdata
131
138
 
@@ -0,0 +1,306 @@
1
+ """
2
+ access_log.py — per-client API access logging, two-tier, never on the request path.
3
+
4
+ Tier 1 (always): per-minute aggregate counters keyed by
5
+ (user, route, status_class) — requests, bytes_in, bytes_out, total_ms, max_ms.
6
+ Small docs; powers bandwidth / usage / route-preference analytics.
7
+
8
+ Tier 2 (events): one document per request, but only for security-relevant or
9
+ sampled traffic — status >= 300, failed authentication, unmatched paths, plus a
10
+ configurable sample of successful requests.
11
+
12
+ Flush: a daemon thread drains both tiers every FLUSH_INTERVAL_S seconds and
13
+ writes through the in-process SharedData handle — Requests/RT/API/ACCESS_AGG
14
+ and Requests/RT/API/ACCESS_EVT (hasindex=False collections → insert_many).
15
+ No HTTP loopback: a ClientAPI.post_collection call would itself be a request
16
+ and self-log. Each server worker process flushes its own buffer (worker_pid).
17
+
18
+ Overhead: the request path does one dict update under a short lock and, for
19
+ events, a put_nowait — no I/O, no body reads. A full event queue drops the
20
+ record (counted in dropped_events). The request path never blocks on Mongo.
21
+
22
+ Secrets: the token itself is never logged — only token_fp (first 8 chars of the
23
+ server-side token_hash, stashed on flask.g by API/auth.py). The raw query
24
+ string is never logged either (it can carry ?token=); only the allow-listed
25
+ data-path arguments are kept.
26
+
27
+ Client IP: X-Real-IP / X-Forwarded-For are trusted only when the direct peer
28
+ is a known proxy; a LAN client hitting the API port directly cannot spoof its
29
+ address. Built in: loopback only (a same-host proxy). A proxy on another
30
+ address, or one that reaches the API by its LAN address, is listed in env
31
+ SHAREDDATA_ACCESSLOG_TRUSTED (comma-separated, replaces the built-in list).
32
+ """
33
+
34
+ import os
35
+ import queue
36
+ import random
37
+ import socket
38
+ import threading
39
+ import time
40
+ from collections import defaultdict
41
+ from datetime import datetime, timezone
42
+
43
+ from flask import g, request
44
+
45
+ from SharedData.Logger import Logger
46
+
47
+ # ─── Configuration ──────────────────────────────────────────────────────────
48
+
49
+ FLUSH_INTERVAL_S = float(os.environ.get('SHAREDDATA_ACCESSLOG_FLUSH_S', 30))
50
+ MAX_QUEUE_SIZE = int(os.environ.get('SHAREDDATA_ACCESSLOG_QUEUE', 10_000))
51
+ EVENT_SAMPLE = float(os.environ.get('SHAREDDATA_ACCESSLOG_SAMPLE', 0.01))
52
+ DISABLED = os.environ.get('SHAREDDATA_ACCESSLOG', '1') in ('0', 'false', 'off')
53
+
54
+ DATABASE = 'Requests'
55
+ PERIOD = 'RT'
56
+ SOURCE = 'API'
57
+ AGG_TABLE = 'ACCESS_AGG'
58
+ EVT_TABLE = 'ACCESS_EVT'
59
+
60
+ # Peers allowed to supply client addresses in X-Real-IP / X-Forwarded-For:
61
+ # loopback (same-host proxy), unless the deployment lists its own proxies.
62
+ _TRUSTED_PROXIES = frozenset(
63
+ part.strip() for part in (os.environ.get('SHAREDDATA_ACCESSLOG_TRUSTED') or '127.0.0.1,::1').split(',')
64
+ if part.strip()
65
+ )
66
+
67
+ # Public/polled endpoints and noise that is not worth a counter.
68
+ _SKIP_PREFIXES = (
69
+ '/api/health',
70
+ '/api/heartbeat',
71
+ '/flasgger_static',
72
+ '/favicon.ico',
73
+ )
74
+
75
+ # Data-path arguments worth keeping on event records (the object a client
76
+ # read/wrote). Everything else — most of all 'token' — stays out.
77
+ _DATA_ARGS = ('database', 'period', 'source', 'tablename', 'tablesubfolder',
78
+ 'timeseries', 'symbol', 'user')
79
+
80
+ _PATH_MAX = 200
81
+ _UA_MAX = 160
82
+
83
+ # ─── Internal state ─────────────────────────────────────────────────────────
84
+
85
+ _evt_queue: 'queue.Queue[dict]' = queue.Queue(maxsize=MAX_QUEUE_SIZE)
86
+
87
+ # {(minute_epoch, user, route, status_class): [requests, bytes_in, bytes_out, total_ms, max_ms]}
88
+ _agg = defaultdict(lambda: [0, 0, 0, 0.0, 0.0])
89
+ _agg_lock = threading.Lock()
90
+
91
+ _pending_evts: list = [] # evt docs retained across a failed flush
92
+ _pending_lock = threading.Lock()
93
+ dropped_events = 0 # events lost to a full queue / retained-buffer cap
94
+
95
+ _shdata = None
96
+ _sink = None # fn(collection_name, docs); injectable for tests
97
+ _HOSTNAME = socket.gethostname()
98
+
99
+
100
+ def _client_ip() -> str:
101
+ """The real client address: the peer itself, unless the peer is a known
102
+ proxy that supplied X-Real-IP / X-Forwarded-For (original client first)."""
103
+ peer = request.remote_addr or ''
104
+ if peer in _TRUSTED_PROXIES:
105
+ real = request.headers.get('X-Real-IP')
106
+ if real:
107
+ return real.split(',')[0].strip()
108
+ xff = request.headers.get('X-Forwarded-For')
109
+ if xff:
110
+ return xff.split(',')[0].strip()
111
+ return peer or 'unknown'
112
+
113
+
114
+ def _user() -> str:
115
+ """Auth identity resolved by API/auth.authenticate (or 'local-log' set by
116
+ the auth_availability hook). 'invalid-token' when a token was presented
117
+ and rejected, 'anonymous' when none was needed/presented."""
118
+ user = getattr(g, 'client_user', None)
119
+ if user:
120
+ return user
121
+ if getattr(g, 'auth_ok', None) is False:
122
+ return 'invalid-token'
123
+ return 'anonymous'
124
+
125
+
126
+ def _route() -> str:
127
+ rule = request.url_rule
128
+ return rule.rule if rule is not None else '<unmatched>'
129
+
130
+
131
+ def _record_event(response, ms, bytes_in, bytes_out):
132
+ rec = {
133
+ 'kind': 'evt',
134
+ 'ts': datetime.now(timezone.utc).isoformat(),
135
+ 'host': _HOSTNAME,
136
+ 'worker_pid': os.getpid(),
137
+ 'remote_ip': _client_ip(),
138
+ 'user': _user(),
139
+ 'method': request.method,
140
+ 'route': _route(),
141
+ 'status': response.status_code,
142
+ 'ms': round(ms, 3),
143
+ 'bytes_in': bytes_in,
144
+ 'bytes_out': bytes_out,
145
+ }
146
+ token_fp = getattr(g, 'token_fp', None)
147
+ if token_fp:
148
+ rec['token_fp'] = token_fp
149
+ if request.url_rule is None or response.status_code >= 300:
150
+ rec['path'] = request.path[:_PATH_MAX] # raw path: probes/errors only
151
+ ua = request.headers.get('User-Agent')
152
+ if ua:
153
+ rec['user_agent'] = ua[:_UA_MAX]
154
+ args = {k: request.args.get(k) for k in _DATA_ARGS if request.args.get(k) is not None}
155
+ if args:
156
+ rec['args'] = args
157
+ global dropped_events
158
+ try:
159
+ _evt_queue.put_nowait(rec)
160
+ except queue.Full:
161
+ dropped_events += 1
162
+
163
+
164
+ # ─── Flask hooks ────────────────────────────────────────────────────────────
165
+
166
+ def before_request():
167
+ g._accesslog_start = time.perf_counter()
168
+
169
+
170
+ def after_request(response):
171
+ try:
172
+ path = request.path
173
+ if any(path.startswith(p) for p in _SKIP_PREFIXES):
174
+ return response
175
+
176
+ start = getattr(g, '_accesslog_start', None)
177
+ ms = (time.perf_counter() - start) * 1000.0 if start is not None else 0.0
178
+ status = response.status_code
179
+
180
+ content_length = response.calculate_content_length()
181
+ bytes_out = content_length if content_length is not None else 0
182
+ bytes_in = g.get('request_bytes', request.content_length or 0)
183
+
184
+ minute = int(time.time() // 60) * 60
185
+ key = (minute, _user(), _route(), f'{status // 100}xx')
186
+ with _agg_lock:
187
+ bucket = _agg[key]
188
+ bucket[0] += 1
189
+ bucket[1] += bytes_in
190
+ bucket[2] += bytes_out
191
+ bucket[3] += ms
192
+ if ms > bucket[4]:
193
+ bucket[4] = ms
194
+
195
+ if status >= 300 or getattr(g, 'auth_ok', None) is False \
196
+ or random.random() < EVENT_SAMPLE:
197
+ _record_event(response, ms, bytes_in, bytes_out)
198
+
199
+ except Exception as exc: # logging must never break the app
200
+ try:
201
+ Logger.log.warning(f'access_log after_request: {exc}')
202
+ except Exception:
203
+ pass
204
+
205
+ return response
206
+
207
+
208
+ # ─── Flush ──────────────────────────────────────────────────────────────────
209
+
210
+ def _agg_docs(snapshot):
211
+ docs = []
212
+ for (minute, user, route, status_class), (n, bi, bo, total_ms, max_ms) in snapshot.items():
213
+ docs.append({
214
+ 'kind': 'agg',
215
+ 'ts': datetime.fromtimestamp(minute, tz=timezone.utc).isoformat(),
216
+ 'host': _HOSTNAME,
217
+ 'worker_pid': os.getpid(),
218
+ 'user': user,
219
+ 'route': route,
220
+ 'status_class': status_class,
221
+ 'requests': n,
222
+ 'bytes_in': bi,
223
+ 'bytes_out': bo,
224
+ 'total_ms': round(total_ms, 3),
225
+ 'max_ms': round(max_ms, 3),
226
+ })
227
+ return docs
228
+
229
+
230
+ def _flush_once(sink):
231
+ """Drain both tiers and hand them to sink(name, docs). Returns doc counts.
232
+ On sink failure event docs are retained for the next cycle (capped);
233
+ aggregate buckets are minute-resolution and simply lost on failure."""
234
+ global dropped_events, _agg
235
+ with _agg_lock:
236
+ snapshot = _agg
237
+ _agg = defaultdict(lambda: [0, 0, 0, 0.0, 0.0])
238
+ with _pending_lock:
239
+ evts = list(_pending_evts)
240
+ _pending_evts.clear()
241
+ while True:
242
+ try:
243
+ evts.append(_evt_queue.get_nowait())
244
+ except queue.Empty:
245
+ break
246
+
247
+ agg_docs = _agg_docs(snapshot)
248
+ if not agg_docs and not evts:
249
+ return 0, 0
250
+ try:
251
+ if agg_docs:
252
+ sink(AGG_TABLE, agg_docs)
253
+ if evts:
254
+ sink(EVT_TABLE, evts)
255
+ return len(agg_docs), len(evts)
256
+ except Exception as exc:
257
+ Logger.log.error(f'access_log flush error: {exc}')
258
+ with _pending_lock:
259
+ keep = _pending_evts + evts
260
+ if len(keep) > MAX_QUEUE_SIZE:
261
+ dropped_events += len(keep) - MAX_QUEUE_SIZE
262
+ keep = keep[-MAX_QUEUE_SIZE:]
263
+ _pending_evts[:] = keep
264
+ # aggs are minute-buckets; on failure they are simply lost (bounded)
265
+ return 0, 0
266
+
267
+
268
+ def _default_sink(name, docs):
269
+ coll = _shdata.collection(DATABASE, PERIOD, SOURCE, name,
270
+ hasindex=False, user='master')
271
+ coll.extend(docs)
272
+
273
+
274
+ def _flush_worker():
275
+ while True:
276
+ time.sleep(FLUSH_INTERVAL_S)
277
+ _flush_once(_sink or _default_sink)
278
+
279
+
280
+ # ─── Registration ───────────────────────────────────────────────────────────
281
+
282
+ def register(flask_app, shdata_instance, sink=None):
283
+ """Attach access logging to a Flask app; starts the flush thread once.
284
+
285
+ Parameters
286
+ ----------
287
+ flask_app : Flask application instance
288
+ shdata_instance : SharedData handle for the direct collection write
289
+ sink : optional fn(name, docs) override (tests)
290
+ """
291
+ global _shdata, _sink
292
+ if DISABLED:
293
+ Logger.log.info('access_log: disabled (SHAREDDATA_ACCESSLOG=0)')
294
+ return
295
+ if flask_app.extensions.get('shareddata_access_log'):
296
+ return
297
+ _shdata = shdata_instance
298
+ if sink is not None:
299
+ _sink = sink
300
+ flask_app.before_request(before_request)
301
+ flask_app.after_request(after_request)
302
+ flask_app.extensions['shareddata_access_log'] = True
303
+ threading.Thread(target=_flush_worker, daemon=True,
304
+ name='api-access-log-flush').start()
305
+ Logger.log.info('access_log: registered (flush every %ds, event sample %.3f)',
306
+ FLUSH_INTERVAL_S, EVENT_SAMPLE)
@@ -120,17 +120,21 @@ def check_permissions(reqpath: list, permissions: dict, method: str, identity=No
120
120
  def authenticate(request, shdata) -> bool:
121
121
  """
122
122
  Authenticate an incoming HTTP request by validating a token and verifying permissions.
123
-
123
+
124
124
  Parameters:
125
125
  request (flask.Request): The incoming HTTP request object.
126
126
  shdata: SharedData instance for accessing user table.
127
-
127
+
128
128
  Returns:
129
129
  bool: True if authenticated and authorized; False otherwise.
130
130
  """
131
+ from flask import g
131
132
  from SharedData.Auth.store import get_store, StoreUnavailable, token_hash
132
133
  token = get_token_from_request(request)
134
+ if token:
135
+ g.token_fp = token_hash(token)[:8]
133
136
  if not token:
137
+ g.auth_ok = False
134
138
  time.sleep(AUTH_FAILURE_SLEEP_SECONDS)
135
139
  return False
136
140
  try:
@@ -138,8 +142,12 @@ def authenticate(request, shdata) -> bool:
138
142
  except Exception as exc:
139
143
  raise StoreUnavailable('auth store lookup failed') from exc
140
144
  if not userdata:
145
+ g.auth_ok = False
146
+ g.client_user = 'invalid-token'
141
147
  time.sleep(AUTH_FAILURE_SLEEP_SECONDS)
142
148
  return False
149
+ g.auth_ok = True
150
+ g.client_user = userdata.get('email') or userdata.get('symbol') or 'unknown'
143
151
  with user_by_token_lock:
144
152
  if len(user_by_token) >= 4096:
145
153
  user_by_token.clear()
@@ -14,7 +14,7 @@ from SharedData.Auth.store import StoreUnavailable
14
14
  from SharedData.DataAPI import service
15
15
  from SharedData.DataAPI.errors import DataAPIError
16
16
 
17
- KEYED = ('symbol', 'marketdata', 'signals', 'portfolios', 'riskfactors', 'vol')
17
+ KEYED = ('symbol', 'marketdata', 'signals', 'portfolios', 'riskfactors', 'vol', 'cdie')
18
18
 
19
19
 
20
20
  def token_permissions(request):
@@ -16,6 +16,7 @@ from SharedData.CollectionMongoDB import CollectionMongoDB
16
16
  from SharedData.Database import DATABASE_PKEYS
17
17
  from SharedData.Table import TableNotFound
18
18
  from SharedData.SharedNumpy import IndexNotAvailable
19
+ from SharedData.TableVector import scalar_names
19
20
  from SharedData.TableRead import generation_read
20
21
  from SharedData.Listing import ListingBudget, ListingTimeout, ListingTooLarge
21
22
 
@@ -218,9 +219,16 @@ def init_tables_routes(shdata, authenticate_fn):
218
219
  since = np.datetime64(since.value, 'ns')
219
220
  plain = not (startdate or enddate or symbols or portfolios or tags or query)
220
221
 
222
+ if not tbl.count:
223
+ _require_filter_indexes(tbl, startdate, enddate, symbols, portfolios, tags)
224
+ return make_empty_response(204)
225
+
221
226
  loc = None
222
227
 
223
- if startdate is not None and enddate is not None:
228
+ if symbols is not None:
229
+ # symbol first: the symbols' own rows filtered by date, instead of every row in the date range
230
+ loc = tbl.get_symbols_date_loc(symbols.split(','), startdate, enddate)
231
+ elif startdate is not None and enddate is not None:
224
232
  loc = tbl.get_date_loc_gte_lte(startdate, enddate)
225
233
  elif startdate is not None:
226
234
  loc = tbl.get_date_loc_gte(startdate)
@@ -238,18 +246,6 @@ def init_tables_routes(shdata, authenticate_fn):
238
246
  _require_filter_indexes(tbl, startdate, enddate, symbols, portfolios, tags)
239
247
  return make_empty_response(204)
240
248
 
241
- # filter data by symbols
242
- if symbols is not None:
243
- symbols = symbols.split(',')
244
- symbolloc = []
245
- for symbol in symbols:
246
- symbolloc.extend(tbl.get_symbol_loc(symbol))
247
- symbolloc = np.array(symbolloc)
248
- if len(symbolloc) > 0:
249
- loc = np.intersect1d(loc, symbolloc)
250
- else:
251
- loc = np.array([])
252
-
253
249
  # filter data by portfolios
254
250
  if portfolios is not None:
255
251
  portfolios = portfolios.split(',')
@@ -278,8 +274,13 @@ def init_tables_routes(shdata, authenticate_fn):
278
274
  loc = np.array(loc)
279
275
 
280
276
  # cycle query keys
281
- if query.keys() is not None:
277
+ if not isinstance(query, dict):
278
+ return jsonify({'error': 'query must be a JSON object'}), 400
279
+ if query:
280
+ scalars = set(scalar_names(tbl.dtype))
282
281
  for key in query.keys():
282
+ if key not in scalars:
283
+ return jsonify({'error': f'Unknown filter column: {key}'}), 400
283
284
  # Take the column view FIRST, then index it.
284
285
  #
285
286
  # `tbl[key]` is zero-copy (SharedNumpy.__getitem__ slices to
@@ -342,8 +343,11 @@ def init_tables_routes(shdata, authenticate_fn):
342
343
  # projection for schemaless tables is applied to the decoded dict_list
343
344
  # further down instead.
344
345
  if columns and not tbl.is_schemaless:
345
- columns = columns.split(',')
346
- columns = np.array([c for c in columns if c not in pkey])
346
+ requested = [c for c in columns.split(',') if c and (c not in tbl.dtype.fields or tbl.dtype[c].subdtype is None)]
347
+ bad = [c for c in requested if c not in tbl.dtype.fields]
348
+ if bad:
349
+ return jsonify({'error': f'Unknown column: {bad[0]}'}), 400
350
+ columns = np.array([c for c in requested if c not in pkey])
347
351
  columns = pkey + list(np.unique(columns))
348
352
  names = columns
349
353
  formats = [tbl.dtype.fields[name][0].str for name in names]
@@ -423,6 +427,10 @@ def init_tables_routes(shdata, authenticate_fn):
423
427
  response.headers['Content-Length'] = len(response_data_json)
424
428
  return sent(response)
425
429
  else: # output_format=='bin'
430
+ if any(recs2send.dtype[name].subdtype is not None for name in recs2send.dtype.names):
431
+ # a vector column stays local: the wire layout carries one value per field per row
432
+ from numpy.lib import recfunctions
433
+ recs2send = recfunctions.repack_fields(recs2send[scalar_names(recs2send.dtype)])
426
434
  names = list(recs2send.dtype.names)
427
435
  formats = [recs2send.dtype.fields[name][0].str for name in names]
428
436
 
@@ -0,0 +1 @@
1
+ """Pure analytical calculations; importing this package does not connect to services."""