querysource 4.5.6__tar.gz → 4.5.7__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 (627) hide show
  1. {querysource-4.5.6 → querysource-4.5.7}/PKG-INFO +1 -1
  2. {querysource-4.5.6 → querysource-4.5.7}/generated/SharepointSource.json +9 -1
  3. querysource-4.5.7/policies/authorized.yaml +73 -0
  4. {querysource-4.5.6 → querysource-4.5.7}/policies/baseline.yaml +5 -0
  5. {querysource-4.5.6 → querysource-4.5.7}/querysource/_version.py +3 -3
  6. {querysource-4.5.6 → querysource-4.5.7}/querysource/conf.py +12 -0
  7. querysource-4.5.7/querysource/datasources/introspection.py +426 -0
  8. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/abstract.py +53 -15
  9. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/executor.py +43 -0
  10. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/executor.py +42 -0
  11. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/sources/sharepoint.py +4 -2
  12. {querysource-4.5.6 → querysource-4.5.7}/querysource/services.py +3 -0
  13. {querysource-4.5.6 → querysource-4.5.7}/querysource/version.py +1 -1
  14. {querysource-4.5.6 → querysource-4.5.7}/querysource.egg-info/PKG-INFO +1 -1
  15. {querysource-4.5.6 → querysource-4.5.7}/querysource.egg-info/SOURCES.txt +3 -0
  16. {querysource-4.5.6 → querysource-4.5.7}/querysource.egg-info/scm_file_list.json +3 -0
  17. querysource-4.5.7/querysource.egg-info/scm_version.json +8 -0
  18. {querysource-4.5.6 → querysource-4.5.7}/tests/handlers/test_abstract_pbac_helpers.py +122 -0
  19. querysource-4.5.7/tests/policies/test_authorized_policy.py +164 -0
  20. querysource-4.5.6/querysource.egg-info/scm_version.json +0 -8
  21. {querysource-4.5.6 → querysource-4.5.7}/.agent/rules/async-programming-expert.md +0 -0
  22. {querysource-4.5.6 → querysource-4.5.7}/.agent/rules/code-reviewer.md +0 -0
  23. {querysource-4.5.6 → querysource-4.5.7}/.agent/rules/cython-development.md +0 -0
  24. {querysource-4.5.6 → querysource-4.5.7}/.agent/rules/prompt-expert.md +0 -0
  25. {querysource-4.5.6 → querysource-4.5.7}/.agent/rules/python-development.md +0 -0
  26. {querysource-4.5.6 → querysource-4.5.7}/.agent/rules/rust-development.md +0 -0
  27. {querysource-4.5.6 → querysource-4.5.7}/.agent/workflows/create-parrot-tool.md +0 -0
  28. {querysource-4.5.6 → querysource-4.5.7}/.agent/workflows/create-workflow.md +0 -0
  29. {querysource-4.5.6 → querysource-4.5.7}/.agent/workflows/debug-regressions-with-git-bisect-binary-search.md +0 -0
  30. {querysource-4.5.6 → querysource-4.5.7}/.agent/workflows/generate-tests.md +0 -0
  31. {querysource-4.5.6 → querysource-4.5.7}/.agent/workflows/git-new-feature.md +0 -0
  32. {querysource-4.5.6 → querysource-4.5.7}/.agent/workflows/parrot-mcp-server.md +0 -0
  33. {querysource-4.5.6 → querysource-4.5.7}/.agent/workflows/release_package.md +0 -0
  34. {querysource-4.5.6 → querysource-4.5.7}/.agent/workflows/start-flow.md +0 -0
  35. {querysource-4.5.6 → querysource-4.5.7}/.bumpversion.cfg +0 -0
  36. {querysource-4.5.6 → querysource-4.5.7}/.claude/agents/code-reviewer.md +0 -0
  37. {querysource-4.5.6 → querysource-4.5.7}/.claude/agents/sdd-autopilot.md +0 -0
  38. {querysource-4.5.6 → querysource-4.5.7}/.claude/agents/sdd-qa.md +0 -0
  39. {querysource-4.5.6 → querysource-4.5.7}/.claude/agents/sdd-research.md +0 -0
  40. {querysource-4.5.6 → querysource-4.5.7}/.claude/agents/sdd-worker.md +0 -0
  41. {querysource-4.5.6 → querysource-4.5.7}/.claude/commands/pr-review.md +0 -0
  42. {querysource-4.5.6 → querysource-4.5.7}/.claude/commands/sdd-brainstorm.md +0 -0
  43. {querysource-4.5.6 → querysource-4.5.7}/.claude/commands/sdd-codereview.md +0 -0
  44. {querysource-4.5.6 → querysource-4.5.7}/.claude/commands/sdd-done.md +0 -0
  45. {querysource-4.5.6 → querysource-4.5.7}/.claude/commands/sdd-fromjira.md +0 -0
  46. {querysource-4.5.6 → querysource-4.5.7}/.claude/commands/sdd-next.md +0 -0
  47. {querysource-4.5.6 → querysource-4.5.7}/.claude/commands/sdd-proposal.md +0 -0
  48. {querysource-4.5.6 → querysource-4.5.7}/.claude/commands/sdd-spec.md +0 -0
  49. {querysource-4.5.6 → querysource-4.5.7}/.claude/commands/sdd-start.md +0 -0
  50. {querysource-4.5.6 → querysource-4.5.7}/.claude/commands/sdd-status.md +0 -0
  51. {querysource-4.5.6 → querysource-4.5.7}/.claude/commands/sdd-task.md +0 -0
  52. {querysource-4.5.6 → querysource-4.5.7}/.claude/commands/sdd-tojira.md +0 -0
  53. {querysource-4.5.6 → querysource-4.5.7}/.claude/rules/aws-cost-optimization.md +0 -0
  54. {querysource-4.5.6 → querysource-4.5.7}/.claude/rules/code-reviewer.md +0 -0
  55. {querysource-4.5.6 → querysource-4.5.7}/.claude/rules/cython-development.md +0 -0
  56. {querysource-4.5.6 → querysource-4.5.7}/.claude/rules/python-development.md +0 -0
  57. {querysource-4.5.6 → querysource-4.5.7}/.claude/rules/rust-development.md +0 -0
  58. {querysource-4.5.6 → querysource-4.5.7}/.claude/rules/using-git-worktrees.md +0 -0
  59. {querysource-4.5.6 → querysource-4.5.7}/.claude/rules/worktree-pr-and-clean.md +0 -0
  60. {querysource-4.5.6 → querysource-4.5.7}/.claude/rules/worktree-start-feature.md +0 -0
  61. {querysource-4.5.6 → querysource-4.5.7}/.claude/rules/worktree-status.md +0 -0
  62. {querysource-4.5.6 → querysource-4.5.7}/.github/dependabot.yml +0 -0
  63. {querysource-4.5.6 → querysource-4.5.7}/.github/workflows/codeql-analysis.yml +0 -0
  64. {querysource-4.5.6 → querysource-4.5.7}/.github/workflows/release.yml +0 -0
  65. {querysource-4.5.6 → querysource-4.5.7}/.isort.cfg +0 -0
  66. {querysource-4.5.6 → querysource-4.5.7}/.jupyter/jupyter_notebook_config.py +0 -0
  67. {querysource-4.5.6 → querysource-4.5.7}/.pre-commit-config.yaml +0 -0
  68. {querysource-4.5.6 → querysource-4.5.7}/.pylintrc +0 -0
  69. {querysource-4.5.6 → querysource-4.5.7}/CHANGES.rst +0 -0
  70. {querysource-4.5.6 → querysource-4.5.7}/CODE_OF_CONDUCT.md +0 -0
  71. {querysource-4.5.6 → querysource-4.5.7}/CONTRIBUTING.md +0 -0
  72. {querysource-4.5.6 → querysource-4.5.7}/INSTALL +0 -0
  73. {querysource-4.5.6 → querysource-4.5.7}/JOIN_CONDITIONS_FEATURE.md +0 -0
  74. {querysource-4.5.6 → querysource-4.5.7}/JOIN_CONDITIONS_SUMMARY.md +0 -0
  75. {querysource-4.5.6 → querysource-4.5.7}/LICENSE +0 -0
  76. {querysource-4.5.6 → querysource-4.5.7}/MANIFEST.in +0 -0
  77. {querysource-4.5.6 → querysource-4.5.7}/Makefile +0 -0
  78. {querysource-4.5.6 → querysource-4.5.7}/README.md +0 -0
  79. {querysource-4.5.6 → querysource-4.5.7}/app.py +0 -0
  80. {querysource-4.5.6 → querysource-4.5.7}/bin/README.md +0 -0
  81. {querysource-4.5.6 → querysource-4.5.7}/conftest.py +0 -0
  82. {querysource-4.5.6 → querysource-4.5.7}/generated/AirtableSource.json +0 -0
  83. {querysource-4.5.6 → querysource-4.5.7}/generated/Concat.json +0 -0
  84. {querysource-4.5.6 → querysource-4.5.7}/generated/DWHDestination.json +0 -0
  85. {querysource-4.5.6 → querysource-4.5.7}/generated/DropCols.json +0 -0
  86. {querysource-4.5.6 → querysource-4.5.7}/generated/FileSource.json +0 -0
  87. {querysource-4.5.6 → querysource-4.5.7}/generated/Filter.json +0 -0
  88. {querysource-4.5.6 → querysource-4.5.7}/generated/FilterCols.json +0 -0
  89. {querysource-4.5.6 → querysource-4.5.7}/generated/Forecast.json +0 -0
  90. {querysource-4.5.6 → querysource-4.5.7}/generated/GoogleMaps.json +0 -0
  91. {querysource-4.5.6 → querysource-4.5.7}/generated/GroupBy.json +0 -0
  92. {querysource-4.5.6 → querysource-4.5.7}/generated/Info.json +0 -0
  93. {querysource-4.5.6 → querysource-4.5.7}/generated/Join.json +0 -0
  94. {querysource-4.5.6 → querysource-4.5.7}/generated/Map.json +0 -0
  95. {querysource-4.5.6 → querysource-4.5.7}/generated/Melt.json +0 -0
  96. {querysource-4.5.6 → querysource-4.5.7}/generated/Merge.json +0 -0
  97. {querysource-4.5.6 → querysource-4.5.7}/generated/NormalizeColumns.json +0 -0
  98. {querysource-4.5.6 → querysource-4.5.7}/generated/PluckCols.json +0 -0
  99. {querysource-4.5.6 → querysource-4.5.7}/generated/Query.json +0 -0
  100. {querysource-4.5.6 → querysource-4.5.7}/generated/S3Source.json +0 -0
  101. {querysource-4.5.6 → querysource-4.5.7}/generated/SmartSheetSource.json +0 -0
  102. {querysource-4.5.6 → querysource-4.5.7}/generated/Table.json +0 -0
  103. {querysource-4.5.6 → querysource-4.5.7}/generated/TableDestination.json +0 -0
  104. {querysource-4.5.6 → querysource-4.5.7}/generated/TableOutput.json +0 -0
  105. {querysource-4.5.6 → querysource-4.5.7}/generated/TableOutputAdapter.json +0 -0
  106. {querysource-4.5.6 → querysource-4.5.7}/generated/TableSource.json +0 -0
  107. {querysource-4.5.6 → querysource-4.5.7}/generated/ToS3.json +0 -0
  108. {querysource-4.5.6 → querysource-4.5.7}/generated/ToSharepoint.json +0 -0
  109. {querysource-4.5.6 → querysource-4.5.7}/generated/correlation.json +0 -0
  110. {querysource-4.5.6 → querysource-4.5.7}/generated/crosstab.json +0 -0
  111. {querysource-4.5.6 → querysource-4.5.7}/generated/pivot.json +0 -0
  112. {querysource-4.5.6 → querysource-4.5.7}/generated/tExplode.json +0 -0
  113. {querysource-4.5.6 → querysource-4.5.7}/generated/tOrder.json +0 -0
  114. {querysource-4.5.6 → querysource-4.5.7}/generated/tPandas.json +0 -0
  115. {querysource-4.5.6 → querysource-4.5.7}/gunicorn_config.py +0 -0
  116. {querysource-4.5.6 → querysource-4.5.7}/mypy.ini +0 -0
  117. {querysource-4.5.6 → querysource-4.5.7}/nav.py +0 -0
  118. {querysource-4.5.6 → querysource-4.5.7}/policies/HARDENING.md +0 -0
  119. {querysource-4.5.6 → querysource-4.5.7}/policies/datasources.yaml +0 -0
  120. {querysource-4.5.6 → querysource-4.5.7}/policies/defaults.yaml +0 -0
  121. {querysource-4.5.6 → querysource-4.5.7}/policies/drivers.yaml +0 -0
  122. {querysource-4.5.6 → querysource-4.5.7}/policies/raw_queries.yaml +0 -0
  123. {querysource-4.5.6 → querysource-4.5.7}/policies/slugs.yaml +0 -0
  124. {querysource-4.5.6 → querysource-4.5.7}/policies/superusers.yaml +0 -0
  125. {querysource-4.5.6 → querysource-4.5.7}/pyproject.toml +0 -0
  126. {querysource-4.5.6 → querysource-4.5.7}/pytest.ini +0 -0
  127. {querysource-4.5.6 → querysource-4.5.7}/querysource/__cli__.py +0 -0
  128. {querysource-4.5.6 → querysource-4.5.7}/querysource/__init__.py +0 -0
  129. {querysource-4.5.6 → querysource-4.5.7}/querysource/auth/__init__.py +0 -0
  130. {querysource-4.5.6 → querysource-4.5.7}/querysource/auth/_resource_types.py +0 -0
  131. {querysource-4.5.6 → querysource-4.5.7}/querysource/auth/credentials.py +0 -0
  132. {querysource-4.5.6 → querysource-4.5.7}/querysource/auth/pbac.py +0 -0
  133. {querysource-4.5.6 → querysource-4.5.7}/querysource/cache/__init__.py +0 -0
  134. {querysource-4.5.6 → querysource-4.5.7}/querysource/cache/backends/__init__.py +0 -0
  135. {querysource-4.5.6 → querysource-4.5.7}/querysource/cache/backends/abstract.py +0 -0
  136. {querysource-4.5.6 → querysource-4.5.7}/querysource/cache/backends/memcache.py +0 -0
  137. {querysource-4.5.6 → querysource-4.5.7}/querysource/cache/backends/redis.py +0 -0
  138. {querysource-4.5.6 → querysource-4.5.7}/querysource/cache/base.py +0 -0
  139. {querysource-4.5.6 → querysource-4.5.7}/querysource/cli/__init__.py +0 -0
  140. {querysource-4.5.6 → querysource-4.5.7}/querysource/cli/generate_docs.py +0 -0
  141. {querysource-4.5.6 → querysource-4.5.7}/querysource/connections.py +0 -0
  142. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/__init__.py +0 -0
  143. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/__init__.py +0 -0
  144. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/abstract.py +0 -0
  145. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/arangodb.py +0 -0
  146. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/athena.py +0 -0
  147. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/bigquery.py +0 -0
  148. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/cassandra.py +0 -0
  149. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/clickhouse.py +0 -0
  150. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/cockroachdb.py +0 -0
  151. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/couchbase.py +0 -0
  152. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/couchdb.py +0 -0
  153. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/countries.py +0 -0
  154. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/delta.py +0 -0
  155. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/documentdb.py +0 -0
  156. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/dynamodb.py +0 -0
  157. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/elastic.py +0 -0
  158. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/ga.py +0 -0
  159. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/gcalc.py +0 -0
  160. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/hazel.py +0 -0
  161. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/iceberg.py +0 -0
  162. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/influx.py +0 -0
  163. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/jdbc.py +0 -0
  164. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/jira.py +0 -0
  165. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/mariadb.py +0 -0
  166. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/memcached.py +0 -0
  167. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/mongo.py +0 -0
  168. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/mysql.py +0 -0
  169. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/odbc.py +0 -0
  170. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/openweather.py +0 -0
  171. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/oracle.py +0 -0
  172. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/pg.py +0 -0
  173. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/pg_admin.py +0 -0
  174. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/postgres.py +0 -0
  175. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/py.typed +0 -0
  176. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/qs.py +0 -0
  177. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/redis.py +0 -0
  178. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/rest.py +0 -0
  179. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/rethink.py +0 -0
  180. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/sa.py +0 -0
  181. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/salesforce.py +0 -0
  182. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/scylladb.py +0 -0
  183. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/sqlalchemy.py +0 -0
  184. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/sqlite.py +0 -0
  185. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/sqlserver.py +0 -0
  186. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/upc.py +0 -0
  187. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/drivers/zipcodeapi.py +0 -0
  188. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/handlers/__init__.py +0 -0
  189. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/handlers/datasource.py +0 -0
  190. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/handlers/utils.py +0 -0
  191. {querysource-4.5.6 → querysource-4.5.7}/querysource/datasources/models.py +0 -0
  192. {querysource-4.5.6 → querysource-4.5.7}/querysource/events/__init__.py +0 -0
  193. {querysource-4.5.6 → querysource-4.5.7}/querysource/exceptions.py +0 -0
  194. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/__init__.py +0 -0
  195. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/_pagination.py +0 -0
  196. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/components.py +0 -0
  197. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/integrations/__init__.py +0 -0
  198. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/integrations/airtable.py +0 -0
  199. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/log.py +0 -0
  200. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/manager.py +0 -0
  201. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/multi.py +0 -0
  202. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/outputs/__init__.py +0 -0
  203. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/outputs/tableOutput/__init__.py +0 -0
  204. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/outputs/tableOutput/postgres.py +0 -0
  205. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/outputs/tableOutput/table.py +0 -0
  206. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/scheduler.py +0 -0
  207. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/service.py +0 -0
  208. {querysource-4.5.6 → querysource-4.5.7}/querysource/handlers/variables.py +0 -0
  209. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/__init__.py +0 -0
  210. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/airtable.py +0 -0
  211. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/connections.py +0 -0
  212. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/credentials.py +0 -0
  213. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/databases/__init__.py +0 -0
  214. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/databases/abstract.py +0 -0
  215. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/databases/bigquery.py +0 -0
  216. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/databases/db.py +0 -0
  217. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/databases/mongo.py +0 -0
  218. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/databases/rethink.py +0 -0
  219. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/http.py +0 -0
  220. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/playwright_service.py +0 -0
  221. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/queries.py +0 -0
  222. {querysource-4.5.6 → querysource-4.5.7}/querysource/interfaces/selenium_service.py +0 -0
  223. {querysource-4.5.6 → querysource-4.5.7}/querysource/libs/__init__.py +0 -0
  224. {querysource-4.5.6 → querysource-4.5.7}/querysource/libs/encoders.py +0 -0
  225. {querysource-4.5.6 → querysource-4.5.7}/querysource/libs/functions/__init__.py +0 -0
  226. {querysource-4.5.6 → querysource-4.5.7}/querysource/libs/py.typed +0 -0
  227. {querysource-4.5.6 → querysource-4.5.7}/querysource/models.py +0 -0
  228. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/__init__.py +0 -0
  229. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/destinations/__init__.py +0 -0
  230. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/destinations/abstract.py +0 -0
  231. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/destinations/dwh.py +0 -0
  232. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/destinations/s3.py +0 -0
  233. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/destinations/sharepoint.py +0 -0
  234. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/destinations/table.py +0 -0
  235. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/dt/__init__.py +0 -0
  236. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/dt/abstract.py +0 -0
  237. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/dt/arrow.py +0 -0
  238. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/dt/dt.py +0 -0
  239. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/dt/factory.py +0 -0
  240. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/dt/iter.py +0 -0
  241. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/dt/modin.py +0 -0
  242. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/dt/pandas.py +0 -0
  243. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/dt/polars.py +0 -0
  244. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/output.py +0 -0
  245. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/tables/TableOutput/__init__.py +0 -0
  246. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/tables/TableOutput/abstract.py +0 -0
  247. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/tables/TableOutput/bigquery.py +0 -0
  248. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/tables/TableOutput/documentdb.py +0 -0
  249. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/tables/TableOutput/mongodb.py +0 -0
  250. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/tables/TableOutput/mysql.py +0 -0
  251. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/tables/TableOutput/postgres.py +0 -0
  252. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/tables/TableOutput/rethink.py +0 -0
  253. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/tables/TableOutput/sa.py +0 -0
  254. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/tables/TableOutput/table.py +0 -0
  255. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/tables/__init__.py +0 -0
  256. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/__init__.py +0 -0
  257. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/abstract.py +0 -0
  258. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/bokeh.py +0 -0
  259. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/clustering.py +0 -0
  260. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/csv.py +0 -0
  261. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/describe.py +0 -0
  262. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/eda.py +0 -0
  263. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/excel.py +0 -0
  264. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/html.py +0 -0
  265. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/json.py +0 -0
  266. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/pdf.py +0 -0
  267. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/pickle.py +0 -0
  268. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/plotly.py +0 -0
  269. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/profiling.py +0 -0
  270. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/report.py +0 -0
  271. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/table.py +0 -0
  272. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/tsv.py +0 -0
  273. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/txt.py +0 -0
  274. {querysource-4.5.6 → querysource-4.5.7}/querysource/outputs/writers/xml.py +0 -0
  275. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/__init__.py +0 -0
  276. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/abstract.c +0 -0
  277. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/abstract.pxd +0 -0
  278. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/abstract.pyx +0 -0
  279. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/arangodb.c +0 -0
  280. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/arangodb.pxd +0 -0
  281. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/arangodb.pyx +0 -0
  282. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/bigquery.c +0 -0
  283. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/bigquery.pxd +0 -0
  284. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/bigquery.pyx +0 -0
  285. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/cql.c +0 -0
  286. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/cql.pxd +0 -0
  287. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/cql.pyx +0 -0
  288. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/deltatbl.c +0 -0
  289. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/deltatbl.pxd +0 -0
  290. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/deltatbl.pyx +0 -0
  291. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/elastic.cpp +0 -0
  292. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/elastic.pxd +0 -0
  293. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/elastic.pyx +0 -0
  294. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/iceberg.c +0 -0
  295. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/iceberg.pxd +0 -0
  296. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/iceberg.pyx +0 -0
  297. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/influx.c +0 -0
  298. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/influx.pxd +0 -0
  299. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/influx.pyx +0 -0
  300. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/mongo.cpp +0 -0
  301. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/mongo.pxd +0 -0
  302. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/mongo.pyx +0 -0
  303. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/parser.c +0 -0
  304. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/parser.pxd +0 -0
  305. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/parser.pyx +0 -0
  306. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/pgsql.c +0 -0
  307. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/pgsql.pxd +0 -0
  308. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/pgsql.pyx +0 -0
  309. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/rethink.c +0 -0
  310. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/rethink.pxd +0 -0
  311. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/rethink.pyx +0 -0
  312. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/sosql.c +0 -0
  313. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/sosql.pxd +0 -0
  314. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/sosql.pyx +0 -0
  315. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/sql.c +0 -0
  316. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/sql.pxd +0 -0
  317. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/sql.pyx +0 -0
  318. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/sqlserver.c +0 -0
  319. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/sqlserver.pxd +0 -0
  320. {querysource-4.5.6 → querysource-4.5.7}/querysource/parsers/sqlserver.pyx +0 -0
  321. {querysource-4.5.6 → querysource-4.5.7}/querysource/plugins/__init__.py +0 -0
  322. {querysource-4.5.6 → querysource-4.5.7}/querysource/plugins/importer.py +0 -0
  323. {querysource-4.5.6 → querysource-4.5.7}/querysource/plugins/sources/__init__.py +0 -0
  324. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/__init__.py +0 -0
  325. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/abstract.py +0 -0
  326. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/arangodb.py +0 -0
  327. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/bigquery.py +0 -0
  328. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/cassandra.py +0 -0
  329. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/db.py +0 -0
  330. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/default.py +0 -0
  331. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/deltatbl.py +0 -0
  332. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/documentdb.py +0 -0
  333. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/dummy.py +0 -0
  334. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/elastic.py +0 -0
  335. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/external.py +0 -0
  336. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/http.py +0 -0
  337. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/iceberg.py +0 -0
  338. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/influx.py +0 -0
  339. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/mysql.py +0 -0
  340. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/pg.py +0 -0
  341. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/py.typed +0 -0
  342. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/rest.py +0 -0
  343. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/rethink.py +0 -0
  344. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/salesforce.py +0 -0
  345. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/scylladb.py +0 -0
  346. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/__init__.py +0 -0
  347. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/abstract.py +0 -0
  348. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/amazon.py +0 -0
  349. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/countries.py +0 -0
  350. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/ga.py +0 -0
  351. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/geofcc.py +0 -0
  352. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/gmaps.py +0 -0
  353. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/graphcountries.py +0 -0
  354. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/graphql.py +0 -0
  355. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/http.py +0 -0
  356. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/hubspot.py +0 -0
  357. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/openweather.py +0 -0
  358. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/parsers/__init__.py +0 -0
  359. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/parsers/amproduct.py +0 -0
  360. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/parsers/xpath.py +0 -0
  361. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/pokemon.py +0 -0
  362. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/populartimes.py +0 -0
  363. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/py.typed +0 -0
  364. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/rest.py +0 -0
  365. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/retailnext.py +0 -0
  366. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/rssapp.py +0 -0
  367. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/salesforce.py +0 -0
  368. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/scrapper.py +0 -0
  369. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/shoppertrack.py +0 -0
  370. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/swop.py +0 -0
  371. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/uap.py +0 -0
  372. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/upc.py +0 -0
  373. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/wm_stores.py +0 -0
  374. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/zammad.py +0 -0
  375. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sources/zipcodeapi.py +0 -0
  376. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sql.py +0 -0
  377. {querysource-4.5.6 → querysource-4.5.7}/querysource/providers/sqlserver.py +0 -0
  378. {querysource-4.5.6 → querysource-4.5.7}/querysource/py.typed +0 -0
  379. {querysource-4.5.6 → querysource-4.5.7}/querysource/qs_parsers/__init__.py +0 -0
  380. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/__init__.py +0 -0
  381. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/base.py +0 -0
  382. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/models.py +0 -0
  383. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/__init__.py +0 -0
  384. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/_introspect.py +0 -0
  385. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/abstract.py +0 -0
  386. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/components/__init__.py +0 -0
  387. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/components/abstract.py +0 -0
  388. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/destinations/__init__.py +0 -0
  389. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/destinations/dwh.py +0 -0
  390. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/destinations/s3.py +0 -0
  391. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/destinations/sharepoint.py +0 -0
  392. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/destinations/table.py +0 -0
  393. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/Concat.py +0 -0
  394. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/GroupBy.catalog.yaml +0 -0
  395. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/GroupBy.py +0 -0
  396. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/Info.py +0 -0
  397. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/Join.catalog.yaml +0 -0
  398. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/Join.py +0 -0
  399. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/Melt.catalog.yaml +0 -0
  400. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/Melt.py +0 -0
  401. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/Merge.catalog.yaml +0 -0
  402. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/Merge.py +0 -0
  403. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/__init__.py +0 -0
  404. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/abstract.py +0 -0
  405. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/filter/Filter.catalog.yaml +0 -0
  406. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/filter/__init__.py +0 -0
  407. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/operators/filter/flt.py +0 -0
  408. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/registry.py +0 -0
  409. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/sources/__init__.py +0 -0
  410. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/sources/airtable.py +0 -0
  411. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/sources/base.py +0 -0
  412. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/sources/executors.py +0 -0
  413. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/sources/file.py +0 -0
  414. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/sources/query.catalog.yaml +0 -0
  415. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/sources/query.py +0 -0
  416. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/sources/s3.py +0 -0
  417. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/sources/smartsheet.py +0 -0
  418. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/sources/table.py +0 -0
  419. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/DropCols.catalog.yaml +0 -0
  420. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/DropCols.py +0 -0
  421. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/FilterCols.catalog.yaml +0 -0
  422. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/FilterCols.py +0 -0
  423. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/Forecast.catalog.yaml +0 -0
  424. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/Forecast.py +0 -0
  425. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/Map.catalog.yaml +0 -0
  426. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/Map.py +0 -0
  427. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/NormalizeColumns.catalog.yaml +0 -0
  428. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/NormalizeColumns.py +0 -0
  429. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/PluckCols.catalog.yaml +0 -0
  430. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/PluckCols.py +0 -0
  431. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/__init__.py +0 -0
  432. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/abstract.py +0 -0
  433. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/correlation.catalog.yaml +0 -0
  434. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/correlation.py +0 -0
  435. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/crosstab.catalog.yaml +0 -0
  436. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/crosstab.py +0 -0
  437. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/google/GoogleMaps.catalog.yaml +0 -0
  438. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/google/__init__.py +0 -0
  439. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/google/maps.py +0 -0
  440. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/pivot.catalog.yaml +0 -0
  441. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/pivot.py +0 -0
  442. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/tExplode.catalog.yaml +0 -0
  443. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/tExplode.py +0 -0
  444. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/tOrder.catalog.yaml +0 -0
  445. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/tOrder.py +0 -0
  446. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/multi/transformations/tPandas.py +0 -0
  447. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/obj.py +0 -0
  448. {querysource-4.5.6 → querysource-4.5.7}/querysource/queries/qs.py +0 -0
  449. {querysource-4.5.6 → querysource-4.5.7}/querysource/scheduler/__init__.py +0 -0
  450. {querysource-4.5.6 → querysource-4.5.7}/querysource/scheduler/jobs.py +0 -0
  451. {querysource-4.5.6 → querysource-4.5.7}/querysource/scheduler/notifications.py +0 -0
  452. {querysource-4.5.6 → querysource-4.5.7}/querysource/scheduler/scheduler.py +0 -0
  453. {querysource-4.5.6 → querysource-4.5.7}/querysource/template/__init__.py +0 -0
  454. {querysource-4.5.6 → querysource-4.5.7}/querysource/template/parser.py +0 -0
  455. {querysource-4.5.6 → querysource-4.5.7}/querysource/types/__init__.py +0 -0
  456. {querysource-4.5.6 → querysource-4.5.7}/querysource/types/converters.cpp +0 -0
  457. {querysource-4.5.6 → querysource-4.5.7}/querysource/types/converters.pyx +0 -0
  458. {querysource-4.5.6 → querysource-4.5.7}/querysource/types/dt/__init__.py +0 -0
  459. {querysource-4.5.6 → querysource-4.5.7}/querysource/types/dt/filters.py +0 -0
  460. {querysource-4.5.6 → querysource-4.5.7}/querysource/types/dt/transforms.py +0 -0
  461. {querysource-4.5.6 → querysource-4.5.7}/querysource/types/py.typed +0 -0
  462. {querysource-4.5.6 → querysource-4.5.7}/querysource/types/typedefs.c +0 -0
  463. {querysource-4.5.6 → querysource-4.5.7}/querysource/types/typedefs.pyx +0 -0
  464. {querysource-4.5.6 → querysource-4.5.7}/querysource/types/validators.cpp +0 -0
  465. {querysource-4.5.6 → querysource-4.5.7}/querysource/types/validators.pyx +0 -0
  466. {querysource-4.5.6 → querysource-4.5.7}/querysource/utils/__init__.py +0 -0
  467. {querysource-4.5.6 → querysource-4.5.7}/querysource/utils/cache_serialization.py +0 -0
  468. {querysource-4.5.6 → querysource-4.5.7}/querysource/utils/errors.py +0 -0
  469. {querysource-4.5.6 → querysource-4.5.7}/querysource/utils/events.py +0 -0
  470. {querysource-4.5.6 → querysource-4.5.7}/querysource/utils/fn.py +0 -0
  471. {querysource-4.5.6 → querysource-4.5.7}/querysource/utils/functions.cpp +0 -0
  472. {querysource-4.5.6 → querysource-4.5.7}/querysource/utils/functions.pyx +0 -0
  473. {querysource-4.5.6 → querysource-4.5.7}/querysource/utils/getfunc.py +0 -0
  474. {querysource-4.5.6 → querysource-4.5.7}/querysource/utils/handlers.py +0 -0
  475. {querysource-4.5.6 → querysource-4.5.7}/querysource/utils/parseqs.cpp +0 -0
  476. {querysource-4.5.6 → querysource-4.5.7}/querysource/utils/parseqs.pyx +0 -0
  477. {querysource-4.5.6 → querysource-4.5.7}/querysource/utils/validators.py +0 -0
  478. {querysource-4.5.6 → querysource-4.5.7}/querysource.egg-info/dependency_links.txt +0 -0
  479. {querysource-4.5.6 → querysource-4.5.7}/querysource.egg-info/entry_points.txt +0 -0
  480. {querysource-4.5.6 → querysource-4.5.7}/querysource.egg-info/not-zip-safe +0 -0
  481. {querysource-4.5.6 → querysource-4.5.7}/querysource.egg-info/requires.txt +0 -0
  482. {querysource-4.5.6 → querysource-4.5.7}/querysource.egg-info/top_level.txt +0 -0
  483. {querysource-4.5.6 → querysource-4.5.7}/run.py +0 -0
  484. {querysource-4.5.6 → querysource-4.5.7}/rust/Cargo.lock +0 -0
  485. {querysource-4.5.6 → querysource-4.5.7}/rust/Cargo.toml +0 -0
  486. {querysource-4.5.6 → querysource-4.5.7}/rust/pyproject.toml +0 -0
  487. {querysource-4.5.6 → querysource-4.5.7}/rust/src/arangodb_parser.rs +0 -0
  488. {querysource-4.5.6 → querysource-4.5.7}/rust/src/bigquery_parser.rs +0 -0
  489. {querysource-4.5.6 → querysource-4.5.7}/rust/src/cql_parser.rs +0 -0
  490. {querysource-4.5.6 → querysource-4.5.7}/rust/src/elastic_parser.rs +0 -0
  491. {querysource-4.5.6 → querysource-4.5.7}/rust/src/filter_common.rs +0 -0
  492. {querysource-4.5.6 → querysource-4.5.7}/rust/src/flux_parser.rs +0 -0
  493. {querysource-4.5.6 → querysource-4.5.7}/rust/src/lib.rs +0 -0
  494. {querysource-4.5.6 → querysource-4.5.7}/rust/src/mongo_parser.rs +0 -0
  495. {querysource-4.5.6 → querysource-4.5.7}/rust/src/mssql_parser.rs +0 -0
  496. {querysource-4.5.6 → querysource-4.5.7}/rust/src/parseqs.rs +0 -0
  497. {querysource-4.5.6 → querysource-4.5.7}/rust/src/pgsql_parser.rs +0 -0
  498. {querysource-4.5.6 → querysource-4.5.7}/rust/src/rethink_parser.rs +0 -0
  499. {querysource-4.5.6 → querysource-4.5.7}/rust/src/safe_dict.rs +0 -0
  500. {querysource-4.5.6 → querysource-4.5.7}/rust/src/soql_parser.rs +0 -0
  501. {querysource-4.5.6 → querysource-4.5.7}/rust/src/sql_parser.rs +0 -0
  502. {querysource-4.5.6 → querysource-4.5.7}/rust/src/validators.rs +0 -0
  503. {querysource-4.5.6 → querysource-4.5.7}/setup.cfg +0 -0
  504. {querysource-4.5.6 → querysource-4.5.7}/setup.py +0 -0
  505. {querysource-4.5.6 → querysource-4.5.7}/static/notebook/bundle.js +0 -0
  506. {querysource-4.5.6 → querysource-4.5.7}/templates/__init__.py +0 -0
  507. {querysource-4.5.6 → querysource-4.5.7}/templates/base.html +0 -0
  508. {querysource-4.5.6 → querysource-4.5.7}/templates/default.html +0 -0
  509. {querysource-4.5.6 → querysource-4.5.7}/templates/default_table.html +0 -0
  510. {querysource-4.5.6 → querysource-4.5.7}/templates/fontlist-v330.json +0 -0
  511. {querysource-4.5.6 → querysource-4.5.7}/templates/fontlist-v390.json +0 -0
  512. {querysource-4.5.6 → querysource-4.5.7}/templates/table_charts.html +0 -0
  513. {querysource-4.5.6 → querysource-4.5.7}/tests/auth/__init__.py +0 -0
  514. {querysource-4.5.6 → querysource-4.5.7}/tests/auth/test_credentials.py +0 -0
  515. {querysource-4.5.6 → querysource-4.5.7}/tests/auth/test_pbac_bootstrap.py +0 -0
  516. {querysource-4.5.6 → querysource-4.5.7}/tests/check_concurrent_get_slug.py +0 -0
  517. {querysource-4.5.6 → querysource-4.5.7}/tests/conftest.py +0 -0
  518. {querysource-4.5.6 → querysource-4.5.7}/tests/datasources/__init__.py +0 -0
  519. {querysource-4.5.6 → querysource-4.5.7}/tests/datasources/test_datasource_view_pbac.py +0 -0
  520. {querysource-4.5.6 → querysource-4.5.7}/tests/datasources/test_driver_factory_session.py +0 -0
  521. {querysource-4.5.6 → querysource-4.5.7}/tests/datasources/test_pg_admin_registration.py +0 -0
  522. {querysource-4.5.6 → querysource-4.5.7}/tests/datasources/test_pg_params_for.py +0 -0
  523. {querysource-4.5.6 → querysource-4.5.7}/tests/handlers/__init__.py +0 -0
  524. {querysource-4.5.6 → querysource-4.5.7}/tests/handlers/conftest.py +0 -0
  525. {querysource-4.5.6 → querysource-4.5.7}/tests/handlers/test_airtable_oauth.py +0 -0
  526. {querysource-4.5.6 → querysource-4.5.7}/tests/handlers/test_multiquery_pbac_smoke.py +0 -0
  527. {querysource-4.5.6 → querysource-4.5.7}/tests/handlers/test_query_param_exclusion.py +0 -0
  528. {querysource-4.5.6 → querysource-4.5.7}/tests/handlers/test_queryexecutor_pbac_smoke.py +0 -0
  529. {querysource-4.5.6 → querysource-4.5.7}/tests/handlers/test_querymanager_pagination.py +0 -0
  530. {querysource-4.5.6 → querysource-4.5.7}/tests/handlers/test_queryservice_pbac_smoke.py +0 -0
  531. {querysource-4.5.6 → querysource-4.5.7}/tests/integration/__init__.py +0 -0
  532. {querysource-4.5.6 → querysource-4.5.7}/tests/integration/test_datasource_endpoint.py +0 -0
  533. {querysource-4.5.6 → querysource-4.5.7}/tests/integration/test_pbac_credentials.py +0 -0
  534. {querysource-4.5.6 → querysource-4.5.7}/tests/integration/test_pbac_enforcement.py +0 -0
  535. {querysource-4.5.6 → querysource-4.5.7}/tests/integration/test_pbac_listing.py +0 -0
  536. {querysource-4.5.6 → querysource-4.5.7}/tests/integration/test_slug_injection.py +0 -0
  537. {querysource-4.5.6 → querysource-4.5.7}/tests/integration/test_slug_regression.py +0 -0
  538. {querysource-4.5.6 → querysource-4.5.7}/tests/interfaces/__init__.py +0 -0
  539. {querysource-4.5.6 → querysource-4.5.7}/tests/interfaces/test_airtable_interface.py +0 -0
  540. {querysource-4.5.6 → querysource-4.5.7}/tests/multi/__init__.py +0 -0
  541. {querysource-4.5.6 → querysource-4.5.7}/tests/multi/sources/__init__.py +0 -0
  542. {querysource-4.5.6 → querysource-4.5.7}/tests/multi/sources/test_airtable_source.py +0 -0
  543. {querysource-4.5.6 → querysource-4.5.7}/tests/multi/sources/test_registry.py +0 -0
  544. {querysource-4.5.6 → querysource-4.5.7}/tests/perf/__init__.py +0 -0
  545. {querysource-4.5.6 → querysource-4.5.7}/tests/perf/test_pbac_overhead.py +0 -0
  546. {querysource-4.5.6 → querysource-4.5.7}/tests/policies/__init__.py +0 -0
  547. {querysource-4.5.6 → querysource-4.5.7}/tests/policies/test_default_policies_load.py +0 -0
  548. {querysource-4.5.6 → querysource-4.5.7}/tests/scheduler/__init__.py +0 -0
  549. {querysource-4.5.6 → querysource-4.5.7}/tests/scheduler/test_parse_trigger_shorthands.py +0 -0
  550. {querysource-4.5.6 → querysource-4.5.7}/tests/scheduler/test_shorthand_loaders.py +0 -0
  551. {querysource-4.5.6 → querysource-4.5.7}/tests/services/__init__.py +0 -0
  552. {querysource-4.5.6 → querysource-4.5.7}/tests/services/test_querysource_setup_pbac.py +0 -0
  553. {querysource-4.5.6 → querysource-4.5.7}/tests/test_abstract_multi.py +0 -0
  554. {querysource-4.5.6 → querysource-4.5.7}/tests/test_abstract_refactor.py +0 -0
  555. {querysource-4.5.6 → querysource-4.5.7}/tests/test_api.py +0 -0
  556. {querysource-4.5.6 → querysource-4.5.7}/tests/test_arangodb_parser.py +0 -0
  557. {querysource-4.5.6 → querysource-4.5.7}/tests/test_catalog_colcols.py +0 -0
  558. {querysource-4.5.6 → querysource-4.5.7}/tests/test_catalog_correlation.py +0 -0
  559. {querysource-4.5.6 → querysource-4.5.7}/tests/test_catalog_filter.py +0 -0
  560. {querysource-4.5.6 → querysource-4.5.7}/tests/test_catalog_forecast.py +0 -0
  561. {querysource-4.5.6 → querysource-4.5.7}/tests/test_catalog_googlemaps.py +0 -0
  562. {querysource-4.5.6 → querysource-4.5.7}/tests/test_catalog_groupby.py +0 -0
  563. {querysource-4.5.6 → querysource-4.5.7}/tests/test_catalog_map.py +0 -0
  564. {querysource-4.5.6 → querysource-4.5.7}/tests/test_catalog_pivot.py +0 -0
  565. {querysource-4.5.6 → querysource-4.5.7}/tests/test_catalog_remote.py +0 -0
  566. {querysource-4.5.6 → querysource-4.5.7}/tests/test_catalog_texplode.py +0 -0
  567. {querysource-4.5.6 → querysource-4.5.7}/tests/test_catalog_torder.py +0 -0
  568. {querysource-4.5.6 → querysource-4.5.7}/tests/test_cli_generate_docs.py +0 -0
  569. {querysource-4.5.6 → querysource-4.5.7}/tests/test_column_filters.py +0 -0
  570. {querysource-4.5.6 → querysource-4.5.7}/tests/test_component_handler.py +0 -0
  571. {querysource-4.5.6 → querysource-4.5.7}/tests/test_component_registry.py +0 -0
  572. {querysource-4.5.6 → querysource-4.5.7}/tests/test_conf_airtable.py +0 -0
  573. {querysource-4.5.6 → querysource-4.5.7}/tests/test_destination_base.py +0 -0
  574. {querysource-4.5.6 → querysource-4.5.7}/tests/test_destination_dwh.py +0 -0
  575. {querysource-4.5.6 → querysource-4.5.7}/tests/test_destination_integration.py +0 -0
  576. {querysource-4.5.6 → querysource-4.5.7}/tests/test_destination_s3.py +0 -0
  577. {querysource-4.5.6 → querysource-4.5.7}/tests/test_destination_sharepoint.py +0 -0
  578. {querysource-4.5.6 → querysource-4.5.7}/tests/test_destination_table.py +0 -0
  579. {querysource-4.5.6 → querysource-4.5.7}/tests/test_destinations_documentation_endpoint.py +0 -0
  580. {querysource-4.5.6 → querysource-4.5.7}/tests/test_elastic_parser.py +0 -0
  581. {querysource-4.5.6 → querysource-4.5.7}/tests/test_error_formatter.py +0 -0
  582. {querysource-4.5.6 → querysource-4.5.7}/tests/test_eval.py +0 -0
  583. {querysource-4.5.6 → querysource-4.5.7}/tests/test_feat102_error_redaction.py +0 -0
  584. {querysource-4.5.6 → querysource-4.5.7}/tests/test_grouping_sync.py +0 -0
  585. {querysource-4.5.6 → querysource-4.5.7}/tests/test_info_eda.py +0 -0
  586. {querysource-4.5.6 → querysource-4.5.7}/tests/test_info_eda_e2e.py +0 -0
  587. {querysource-4.5.6 → querysource-4.5.7}/tests/test_info_eda_integration.py +0 -0
  588. {querysource-4.5.6 → querysource-4.5.7}/tests/test_join_conditions.py +0 -0
  589. {querysource-4.5.6 → querysource-4.5.7}/tests/test_join_with_column_filter.py +0 -0
  590. {querysource-4.5.6 → querysource-4.5.7}/tests/test_local_executor.py +0 -0
  591. {querysource-4.5.6 → querysource-4.5.7}/tests/test_multi_destinations_subpackage.py +0 -0
  592. {querysource-4.5.6 → querysource-4.5.7}/tests/test_multiqs_column_transforms.py +0 -0
  593. {querysource-4.5.6 → querysource-4.5.7}/tests/test_multiqs_destination_dispatch.py +0 -0
  594. {querysource-4.5.6 → querysource-4.5.7}/tests/test_multiqs_remote_dispatch.py +0 -0
  595. {querysource-4.5.6 → querysource-4.5.7}/tests/test_multiqs_sources_integration.py +0 -0
  596. {querysource-4.5.6 → querysource-4.5.7}/tests/test_queryslug_concurrency.py +0 -0
  597. {querysource-4.5.6 → querysource-4.5.7}/tests/test_querysource_setup_airtable.py +0 -0
  598. {querysource-4.5.6 → querysource-4.5.7}/tests/test_qworker_config.py +0 -0
  599. {querysource-4.5.6 → querysource-4.5.7}/tests/test_remote_executor.py +0 -0
  600. {querysource-4.5.6 → querysource-4.5.7}/tests/test_route_registration.py +0 -0
  601. {querysource-4.5.6 → querysource-4.5.7}/tests/test_rss.py +0 -0
  602. {querysource-4.5.6 → querysource-4.5.7}/tests/test_rust_parsers.py +0 -0
  603. {querysource-4.5.6 → querysource-4.5.7}/tests/test_scheduler_core.py +0 -0
  604. {querysource-4.5.6 → querysource-4.5.7}/tests/test_scheduler_handler_integration.py +0 -0
  605. {querysource-4.5.6 → querysource-4.5.7}/tests/test_scheduler_handler_unit.py +0 -0
  606. {querysource-4.5.6 → querysource-4.5.7}/tests/test_scheduler_integration.py +0 -0
  607. {querysource-4.5.6 → querysource-4.5.7}/tests/test_scheduler_jobs.py +0 -0
  608. {querysource-4.5.6 → querysource-4.5.7}/tests/test_scheduler_multi_routing.py +0 -0
  609. {querysource-4.5.6 → querysource-4.5.7}/tests/test_scheduler_notifications.py +0 -0
  610. {querysource-4.5.6 → querysource-4.5.7}/tests/test_schema_introspectable.py +0 -0
  611. {querysource-4.5.6 → querysource-4.5.7}/tests/test_source_registry.py +0 -0
  612. {querysource-4.5.6 → querysource-4.5.7}/tests/test_source_s3.py +0 -0
  613. {querysource-4.5.6 → querysource-4.5.7}/tests/test_source_sharepoint.py +0 -0
  614. {querysource-4.5.6 → querysource-4.5.7}/tests/test_source_smartsheet.py +0 -0
  615. {querysource-4.5.6 → querysource-4.5.7}/tests/test_source_table.py +0 -0
  616. {querysource-4.5.6 → querysource-4.5.7}/tests/test_sql_parser_combinations.py +0 -0
  617. {querysource-4.5.6 → querysource-4.5.7}/tests/test_texplode.py +0 -0
  618. {querysource-4.5.6 → querysource-4.5.7}/tests/test_thread_file_refactor.py +0 -0
  619. {querysource-4.5.6 → querysource-4.5.7}/tests/test_thread_query_refactor.py +0 -0
  620. {querysource-4.5.6 → querysource-4.5.7}/tests/test_thread_source_base.py +0 -0
  621. {querysource-4.5.6 → querysource-4.5.7}/tests/test_threadquery_executor.py +0 -0
  622. {querysource-4.5.6 → querysource-4.5.7}/tests/test_zammad_search.py +0 -0
  623. {querysource-4.5.6 → querysource-4.5.7}/tests/unit/test_cython_filter_fallback.py +0 -0
  624. {querysource-4.5.6 → querysource-4.5.7}/tests/unit/test_datasource_redaction.py +0 -0
  625. {querysource-4.5.6 → querysource-4.5.7}/tests/unit/test_provider_raw_query_validated.py +0 -0
  626. {querysource-4.5.6 → querysource-4.5.7}/tests/unit/test_qs_parsers_validated.py +0 -0
  627. {querysource-4.5.6 → querysource-4.5.7}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: querysource
3
- Version: 4.5.6
3
+ Version: 4.5.7
4
4
  Summary: Aiohttp web service for querying several databases easily
5
5
  Author-email: Jesus Lara <jesuslarag@gmail.com>
6
6
  License: BSD-3-Clause
@@ -87,6 +87,13 @@
87
87
  "default": "",
88
88
  "required": false,
89
89
  "description": ""
90
+ },
91
+ {
92
+ "name": "source.masks",
93
+ "type": "Any",
94
+ "default": {},
95
+ "required": false,
96
+ "description": ""
90
97
  }
91
98
  ],
92
99
  "json_schema": {
@@ -113,7 +120,8 @@
113
120
  "directory": {},
114
121
  "sheet_name": {},
115
122
  "pd_args": {},
116
- "url": {}
123
+ "url": {},
124
+ "masks": {}
117
125
  }
118
126
  }
119
127
  },
@@ -0,0 +1,73 @@
1
+ version: "1.0"
2
+
3
+ defaults:
4
+ effect: deny
5
+
6
+ # ─── Sessionless-authorized clients ─────────────────────────────────────────
7
+ # Requests que navigator-auth deja pasar por un backend authz_* (whitelist de
8
+ # IP / host / User-Agent) están *autorizados* pero NO *autenticados*: no traen
9
+ # usuario ni sesión. Con QS_PBAC_ALLOW_SESSIONLESS_AUTHZ=True, QuerySource los
10
+ # evalúa bajo una identidad sintética:
11
+ #
12
+ # username: "authz:<backend>" (p.ej. authz:authz_useragent)
13
+ # groups: ["authorized", "<backend>"] (p.ej. authz_useragent)
14
+ #
15
+ # El baseline (baseline.yaml) los excluye explícitamente, así que SOLO las
16
+ # políticas de este archivo (o cualquier otra que apunte a esos grupos) les
17
+ # conceden acceso. Para restringir por backend concreto, usa el nombre del
18
+ # backend como grupo en vez de "authorized":
19
+ #
20
+ # subjects:
21
+ # groups:
22
+ # - authz_useragent # sólo grants de User-Agent (p.ej. Power BI)
23
+ #
24
+ # Para restringir slugs, estrecha el patrón de resources: "slug:epson_*".
25
+ # ────────────────────────────────────────────────────────────────────────────
26
+ policies:
27
+ - name: authorized_clients_execute_slugs
28
+ effect: allow
29
+ description: >
30
+ Sessionless clients authorized by a navigator-auth authz backend
31
+ (IP / host / User-Agent whitelists) may execute query slugs.
32
+ resources:
33
+ - "slug:*"
34
+ actions:
35
+ - "slug:execute"
36
+ subjects:
37
+ groups:
38
+ - authorized
39
+ priority: 10
40
+
41
+ # Ejecutar un slug encadena tres checks PBAC: slug:execute →
42
+ # datasource:use → driver:use (handlers/service.py y handlers/executor.py).
43
+ # Estas dos políticas completan la cadena. Sólo la acción ":use" — las
44
+ # acciones administrativas (datasource:read, datasource:list, …) siguen
45
+ # denegadas para los sessionless-authorized.
46
+ - name: authorized_clients_use_datasources
47
+ effect: allow
48
+ description: >
49
+ Sessionless-authorized clients may use the datasource backing a slug
50
+ they are allowed to execute. Grants only datasource:use — read/list
51
+ and management actions remain denied.
52
+ resources:
53
+ - "datasource:*"
54
+ actions:
55
+ - "datasource:use"
56
+ subjects:
57
+ groups:
58
+ - authorized
59
+ priority: 10
60
+
61
+ - name: authorized_clients_use_drivers
62
+ effect: allow
63
+ description: >
64
+ Sessionless-authorized clients may use the driver backing a slug
65
+ they are allowed to execute. Grants only driver:use.
66
+ resources:
67
+ - "driver:*"
68
+ actions:
69
+ - "driver:use"
70
+ subjects:
71
+ groups:
72
+ - authorized
73
+ priority: 10
@@ -24,6 +24,9 @@ policies:
24
24
  Soft baseline: any authenticated user may use all QuerySource resources.
25
25
  Lowest priority and non-enforcing so specific deny/allow policies override
26
26
  it without removing this file. Anonymous requests are still denied (404).
27
+ Sessionless-authorized clients (group "authorized", stamped by a
28
+ navigator-auth authz_* backend) are excluded: they are authorized, not
29
+ authenticated, and only get what policies/authorized.yaml grants them.
27
30
  resources:
28
31
  - "*:*"
29
32
  actions:
@@ -31,5 +34,7 @@ policies:
31
34
  subjects:
32
35
  groups:
33
36
  - "*"
37
+ exclude_groups:
38
+ - authorized
34
39
  priority: 1
35
40
  enforcing: false
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '4.5.7.dev0+g230b6a865.d20260629'
22
- __version_tuple__ = version_tuple = (4, 5, 7, 'dev0', 'g230b6a865.d20260629')
21
+ __version__ = version = '4.5.8.dev0+g201ef3bdd.d20260702'
22
+ __version_tuple__ = version_tuple = (4, 5, 8, 'dev0', 'g201ef3bdd.d20260702')
23
23
 
24
- __commit_id__ = commit_id = 'g230b6a865'
24
+ __commit_id__ = commit_id = 'g201ef3bdd'
@@ -430,6 +430,18 @@ QS_PBAC_ENABLED = config.getboolean('QS_PBAC_ENABLED', fallback=False)
430
430
  QS_POLICY_PATH = config.get('QS_POLICY_PATH', fallback=str(BASE_DIR / 'policies'))
431
431
  QS_PBAC_CACHE_TTL = config.getint('QS_PBAC_CACHE_TTL', fallback=300)
432
432
 
433
+ # Allow requests that carry no user session but were authorized by a
434
+ # sessionless navigator-auth authz backend (IP / host / User-Agent, e.g.
435
+ # authz_allowed_ips, authz_useragent) to be evaluated by PBAC instead of being
436
+ # denied outright (fail-closed). The request must be stamped by navigator-auth
437
+ # (request[AUTHZ_BACKEND_KEY]); it is then evaluated under a synthetic identity
438
+ # with groups ['authorized', <backend>], so an explicit allow policy (see
439
+ # policies/authorized.yaml) must still grant access — this is NOT a bypass.
440
+ # Default: False (keep fail-closed behaviour).
441
+ QS_PBAC_ALLOW_SESSIONLESS_AUTHZ = config.getboolean(
442
+ 'QS_PBAC_ALLOW_SESSIONLESS_AUTHZ', fallback=False
443
+ )
444
+
433
445
  # ── Airtable Integration (FEAT-096) ───────────────────────────────────────────
434
446
  # OAuth2 client credentials (server-side; never sent to the browser).
435
447
  AIRTABLE_CLIENT_ID = config.get('AIRTABLE_CLIENT_ID')
@@ -0,0 +1,426 @@
1
+ """Schema introspection strategies, one per driver family.
2
+
3
+ The QuerySource executor exposes a single ``/api/v1/queries/schema`` endpoint
4
+ (see ``querysource.handlers.executor.QueryExecutor.schema``). The frontend calls
5
+ it with a ``driver`` or ``datasource`` and renders a uniform tree:
6
+
7
+ schema → table → column
8
+
9
+ Every backend speaks a different dialect (ANSI ``information_schema`` for the
10
+ relational drivers, the BigQuery client API for datasets, Flux ``schema.*`` for
11
+ InfluxDB buckets/measurements, ``SCAN`` for Redis namespaces). This module hides
12
+ those differences behind a small ``Introspector`` contract so the handler — and
13
+ the frontend — stay driver-agnostic.
14
+
15
+ Adding a new driver = register one ``Introspector`` in ``INTROSPECTORS``. Nothing
16
+ else in the request path needs to change.
17
+
18
+ Uniform output shapes (keys are intentionally lowercase and stable, the frontend
19
+ relies on them):
20
+
21
+ * ``tables()`` -> ``[{"table_schema": str, "table_name": str, "col_count": int}]``
22
+ * ``columns()`` -> ``[{"column_name": str, "data_type": str, "is_nullable": str}]``
23
+ """
24
+ from __future__ import annotations
25
+
26
+ import logging
27
+ from abc import ABC, abstractmethod
28
+ from typing import Any, Optional
29
+
30
+
31
+ logger = logging.getLogger("querysource.introspection")
32
+
33
+
34
+ # ---------------------------------------------------------------------------
35
+ # Helpers
36
+ # ---------------------------------------------------------------------------
37
+ def _as_dicts(rows: Any) -> list[dict]:
38
+ """Normalize a driver's row collection to a list of plain dicts.
39
+
40
+ asyncpg returns ``Record`` objects, pymssql/pytds return dicts, others may
41
+ return mapping-like rows. ``dict(row)`` covers Record and Mapping; we fall
42
+ back gracefully so a single odd row never breaks introspection.
43
+ """
44
+ out: list[dict] = []
45
+ for row in rows or []:
46
+ if isinstance(row, dict):
47
+ out.append(row)
48
+ continue
49
+ if hasattr(row, "_asdict"):
50
+ out.append(dict(row._asdict()))
51
+ continue
52
+ try:
53
+ out.append(dict(row))
54
+ except (TypeError, ValueError):
55
+ logger.debug("introspection: could not coerce row to dict: %r", row)
56
+ return out
57
+
58
+
59
+ def _sql_quote(value: str) -> str:
60
+ """Escape a SQL string literal (double single quotes)."""
61
+ return "'" + str(value).replace("'", "''") + "'"
62
+
63
+
64
+ # ---------------------------------------------------------------------------
65
+ # Contract
66
+ # ---------------------------------------------------------------------------
67
+ class Introspector(ABC):
68
+ """Per-driver schema introspection contract.
69
+
70
+ ``supported`` lets a driver advertise that introspection is unavailable
71
+ (e.g. not yet implemented) without raising — the handler turns it into a
72
+ clean message instead of a 500.
73
+ """
74
+
75
+ supported: bool = True
76
+ #: Human-readable reason shown when ``supported`` is False.
77
+ reason: Optional[str] = None
78
+
79
+ @abstractmethod
80
+ async def tables(self, conn: Any) -> list[dict]:
81
+ """Return ``[{table_schema, table_name, col_count}]`` for the connection."""
82
+
83
+ @abstractmethod
84
+ async def columns(self, conn: Any, schema: str, table: str) -> list[dict]:
85
+ """Return ``[{column_name, data_type, is_nullable}]`` for one entity."""
86
+
87
+
88
+ class Unsupported(Introspector):
89
+ """Sentinel introspector for drivers without (yet) a strategy."""
90
+
91
+ supported = False
92
+
93
+ def __init__(self, reason: str) -> None:
94
+ self.reason = reason
95
+
96
+ async def tables(self, conn: Any) -> list[dict]:
97
+ return []
98
+
99
+ async def columns(self, conn: Any, schema: str, table: str) -> list[dict]:
100
+ return []
101
+
102
+
103
+ # ---------------------------------------------------------------------------
104
+ # ANSI information_schema (PostgreSQL, MySQL/MariaDB, SQL Server)
105
+ # ---------------------------------------------------------------------------
106
+ class AnsiSQLIntrospector(Introspector):
107
+ """Relational drivers exposing the ANSI ``information_schema.columns`` view.
108
+
109
+ Only two things actually differ between dialects, so they are parameters:
110
+
111
+ * ``count_expr`` — how to cast/produce an integer column count. PostgreSQL
112
+ accepts ``COUNT(*)::int``; that ``::`` cast is invalid in T-SQL and MySQL,
113
+ where a plain ``COUNT(*)`` is correct.
114
+ * ``excluded_schemas`` — engine-specific system schemas to hide.
115
+ """
116
+
117
+ def __init__(self, count_expr: str, excluded_schemas: tuple[str, ...]) -> None:
118
+ self.count_expr = count_expr
119
+ self.excluded_schemas = excluded_schemas
120
+
121
+ def _tables_sql(self) -> str:
122
+ sql = [
123
+ f"SELECT table_schema, table_name, {self.count_expr} AS col_count",
124
+ "FROM information_schema.columns",
125
+ ]
126
+ if self.excluded_schemas:
127
+ excluded = ", ".join(_sql_quote(s) for s in self.excluded_schemas)
128
+ sql.append(f"WHERE table_schema NOT IN ({excluded})")
129
+ sql += [
130
+ "GROUP BY table_schema, table_name",
131
+ "ORDER BY table_schema, table_name",
132
+ ]
133
+ return " ".join(sql)
134
+
135
+ def _columns_sql(self, schema: str, table: str) -> str:
136
+ return " ".join([
137
+ "SELECT column_name, data_type, is_nullable",
138
+ "FROM information_schema.columns",
139
+ f"WHERE table_schema = {_sql_quote(schema)} "
140
+ f"AND table_name = {_sql_quote(table)}",
141
+ "ORDER BY ordinal_position",
142
+ ])
143
+
144
+ async def _run(self, conn: Any, sql: str) -> list[dict]:
145
+ result, error = await conn.query(sql)
146
+ if error:
147
+ raise RuntimeError(str(error))
148
+ return _as_dicts(result)
149
+
150
+ async def tables(self, conn: Any) -> list[dict]:
151
+ rows = await self._run(conn, self._tables_sql())
152
+ return [
153
+ {
154
+ "table_schema": r.get("table_schema"),
155
+ "table_name": r.get("table_name"),
156
+ "col_count": int(r.get("col_count") or 0),
157
+ }
158
+ for r in rows
159
+ ]
160
+
161
+ async def columns(self, conn: Any, schema: str, table: str) -> list[dict]:
162
+ rows = await self._run(conn, self._columns_sql(schema, table))
163
+ return [
164
+ {
165
+ "column_name": r.get("column_name"),
166
+ "data_type": r.get("data_type"),
167
+ "is_nullable": r.get("is_nullable"),
168
+ }
169
+ for r in rows
170
+ ]
171
+
172
+
173
+ # ---------------------------------------------------------------------------
174
+ # BigQuery (Google client API — region-agnostic, no SQL billing)
175
+ # ---------------------------------------------------------------------------
176
+ class BigQueryIntrospector(Introspector):
177
+ """BigQuery introspection via the ``google.cloud.bigquery`` client.
178
+
179
+ BigQuery ``INFORMATION_SCHEMA`` is *region-scoped* (``region-us`` ≠
180
+ ``us-central1``), so a single SQL query cannot enumerate datasets that live
181
+ in different locations. The client REST API (``list_datasets`` /
182
+ ``list_tables`` / ``get_table``) is global and region-agnostic — exactly how
183
+ the BigQuery console lists everything — so we use it instead.
184
+
185
+ Dataset = ``table_schema``; table = ``table_name``; column = a BigQuery
186
+ field. ``col_count`` is left at 0 in ``tables()`` (the API does not return
187
+ it cheaply) and is implicitly available once columns are lazy-loaded.
188
+ """
189
+
190
+ def _client(self, conn: Any) -> Any:
191
+ # asyncdb BigQuery driver keeps the bq.Client on the connection.
192
+ client = getattr(conn, "get_connection", lambda: None)()
193
+ if client is None:
194
+ client = getattr(conn, "_connection", None)
195
+ if client is None:
196
+ raise RuntimeError("BigQuery client connection is not available")
197
+ return client
198
+
199
+ async def tables(self, conn: Any) -> list[dict]:
200
+ client = self._client(conn)
201
+ out: list[dict] = []
202
+ for dataset in client.list_datasets(): # global, all regions
203
+ ds_id = dataset.dataset_id
204
+ try:
205
+ for tbl in client.list_tables(dataset.reference):
206
+ out.append({
207
+ "table_schema": ds_id,
208
+ "table_name": tbl.table_id,
209
+ "col_count": 0,
210
+ })
211
+ except Exception as err: # noqa: BLE001 - one dataset must not break all
212
+ logger.warning("BigQuery list_tables failed for %s: %s", ds_id, err)
213
+ out.sort(key=lambda r: (r["table_schema"], r["table_name"]))
214
+ return out
215
+
216
+ async def columns(self, conn: Any, schema: str, table: str) -> list[dict]:
217
+ client = self._client(conn)
218
+ ref = f"{client.project}.{schema}.{table}"
219
+ tbl = client.get_table(ref)
220
+ return [
221
+ {
222
+ "column_name": field.name,
223
+ "data_type": field.field_type,
224
+ "is_nullable": "NO" if field.mode == "REQUIRED" else "YES",
225
+ }
226
+ for field in tbl.schema
227
+ ]
228
+
229
+
230
+ # ---------------------------------------------------------------------------
231
+ # InfluxDB 2.x (buckets / measurements / tags+fields via Flux schema.*)
232
+ # ---------------------------------------------------------------------------
233
+ class InfluxIntrospector(Introspector):
234
+ """InfluxDB 2.x introspection.
235
+
236
+ Maps the time-series model onto the common tree:
237
+ bucket = ``table_schema``; measurement = ``table_name``; tag/field keys =
238
+ columns. Buckets come from the management API (``list_buckets``);
239
+ measurements and keys come from the ``influxdata/influxdb/schema`` Flux
240
+ package. Best-effort: a bucket that rejects a schema query is skipped rather
241
+ than failing the whole call.
242
+ """
243
+
244
+ _FLUX_MEASUREMENTS = (
245
+ 'import "influxdata/influxdb/schema"\n'
246
+ 'schema.measurements(bucket: {bucket})'
247
+ )
248
+ _FLUX_FIELD_KEYS = (
249
+ 'import "influxdata/influxdb/schema"\n'
250
+ 'schema.measurementFieldKeys(bucket: {bucket}, measurement: {measurement})'
251
+ )
252
+ _FLUX_TAG_KEYS = (
253
+ 'import "influxdata/influxdb/schema"\n'
254
+ 'schema.measurementTagKeys(bucket: {bucket}, measurement: {measurement})'
255
+ )
256
+
257
+ @staticmethod
258
+ def _flux_str(value: str) -> str:
259
+ return '"' + str(value).replace('"', '\\"') + '"'
260
+
261
+ async def _flux_values(self, conn: Any, flux: str) -> list[str]:
262
+ result, error = await conn.query(flux, frmt="recordset")
263
+ if error:
264
+ raise RuntimeError(str(error))
265
+ values: list[str] = []
266
+ for row in _as_dicts(result):
267
+ # schema.* returns the value under `_value`.
268
+ val = row.get("_value")
269
+ if val is not None:
270
+ values.append(str(val))
271
+ return values
272
+
273
+ async def tables(self, conn: Any) -> list[dict]:
274
+ buckets = await conn.list_buckets()
275
+ out: list[dict] = []
276
+ for bucket in buckets:
277
+ name = getattr(bucket, "name", None) or str(bucket)
278
+ try:
279
+ flux = self._FLUX_MEASUREMENTS.format(bucket=self._flux_str(name))
280
+ for measurement in await self._flux_values(conn, flux):
281
+ out.append({
282
+ "table_schema": name,
283
+ "table_name": measurement,
284
+ "col_count": 0,
285
+ })
286
+ except Exception as err: # noqa: BLE001
287
+ logger.warning("Influx measurements failed for bucket %s: %s", name, err)
288
+ out.sort(key=lambda r: (r["table_schema"], r["table_name"]))
289
+ return out
290
+
291
+ async def columns(self, conn: Any, schema: str, table: str) -> list[dict]:
292
+ bucket, measurement = self._flux_str(schema), self._flux_str(table)
293
+ cols: list[dict] = []
294
+ try:
295
+ tag_flux = self._FLUX_TAG_KEYS.format(bucket=bucket, measurement=measurement)
296
+ for tag in await self._flux_values(conn, tag_flux):
297
+ if tag.startswith("_"):
298
+ continue
299
+ cols.append({"column_name": tag, "data_type": "tag", "is_nullable": "YES"})
300
+ except Exception as err: # noqa: BLE001
301
+ logger.warning("Influx tag keys failed for %s.%s: %s", schema, table, err)
302
+ try:
303
+ field_flux = self._FLUX_FIELD_KEYS.format(bucket=bucket, measurement=measurement)
304
+ for field in await self._flux_values(conn, field_flux):
305
+ cols.append({"column_name": field, "data_type": "field", "is_nullable": "YES"})
306
+ except Exception as err: # noqa: BLE001
307
+ logger.warning("Influx field keys failed for %s.%s: %s", schema, table, err)
308
+ return cols
309
+
310
+
311
+ # ---------------------------------------------------------------------------
312
+ # Redis (key namespaces via SCAN — best effort)
313
+ # ---------------------------------------------------------------------------
314
+ class RedisIntrospector(Introspector):
315
+ """Redis introspection.
316
+
317
+ Redis has no schema; we approximate one by sampling keys with ``SCAN`` and
318
+ grouping by their first ``:``-delimited segment (the common namespacing
319
+ convention, e.g. ``user:42`` → namespace ``user``). The single pseudo-schema
320
+ is ``keys``; each namespace becomes a ``table`` whose ``col_count`` is the
321
+ number of sampled keys. Columns of a namespace are a sample of concrete keys
322
+ with their Redis ``TYPE``. Sampling is capped to keep large keyspaces safe.
323
+ """
324
+
325
+ _SCAN_COUNT = 500
326
+ _MAX_KEYS = 5000
327
+ _SAMPLE_PER_NS = 50
328
+
329
+ async def _scan_keys(self, conn: Any) -> list[str]:
330
+ keys: list[str] = []
331
+ cursor = 0
332
+ while True:
333
+ cursor, batch = await conn.execute("SCAN", cursor, "COUNT", self._SCAN_COUNT)
334
+ for k in batch:
335
+ keys.append(k.decode() if isinstance(k, (bytes, bytearray)) else str(k))
336
+ cursor = int(cursor)
337
+ if cursor == 0 or len(keys) >= self._MAX_KEYS:
338
+ break
339
+ return keys
340
+
341
+ @staticmethod
342
+ def _namespace(key: str) -> str:
343
+ return key.split(":", 1)[0] if ":" in key else key
344
+
345
+ async def tables(self, conn: Any) -> list[dict]:
346
+ keys = await self._scan_keys(conn)
347
+ counts: dict[str, int] = {}
348
+ for key in keys:
349
+ ns = self._namespace(key)
350
+ counts[ns] = counts.get(ns, 0) + 1
351
+ out = [
352
+ {"table_schema": "keys", "table_name": ns, "col_count": n}
353
+ for ns, n in counts.items()
354
+ ]
355
+ out.sort(key=lambda r: r["table_name"])
356
+ return out
357
+
358
+ async def columns(self, conn: Any, schema: str, table: str) -> list[dict]:
359
+ # `table` is the namespace prefix; list a sample of concrete keys + type.
360
+ prefix = f"{table}:*" if table else "*"
361
+ cursor, sampled = 0, []
362
+ while len(sampled) < self._SAMPLE_PER_NS:
363
+ cursor, batch = await conn.execute("SCAN", cursor, "MATCH", prefix, "COUNT", self._SCAN_COUNT)
364
+ for k in batch:
365
+ sampled.append(k.decode() if isinstance(k, (bytes, bytearray)) else str(k))
366
+ if len(sampled) >= self._SAMPLE_PER_NS:
367
+ break
368
+ cursor = int(cursor)
369
+ if cursor == 0:
370
+ break
371
+ cols: list[dict] = []
372
+ for key in sampled:
373
+ try:
374
+ ktype = await conn.execute("TYPE", key)
375
+ ktype = ktype.decode() if isinstance(ktype, (bytes, bytearray)) else str(ktype)
376
+ except Exception: # noqa: BLE001
377
+ ktype = "unknown"
378
+ cols.append({"column_name": key, "data_type": ktype, "is_nullable": "YES"})
379
+ return cols
380
+
381
+
382
+ # ---------------------------------------------------------------------------
383
+ # Registry
384
+ # ---------------------------------------------------------------------------
385
+ INTROSPECTORS: dict[str, Introspector] = {
386
+ "postgres": AnsiSQLIntrospector(
387
+ count_expr="COUNT(*)::int",
388
+ excluded_schemas=("pg_catalog", "information_schema", "pg_toast"),
389
+ ),
390
+ "mysql": AnsiSQLIntrospector(
391
+ count_expr="COUNT(*)",
392
+ excluded_schemas=("information_schema", "mysql", "performance_schema", "sys"),
393
+ ),
394
+ "mssql": AnsiSQLIntrospector(
395
+ count_expr="COUNT(*)",
396
+ excluded_schemas=("sys", "INFORMATION_SCHEMA"),
397
+ ),
398
+ "bigquery": BigQueryIntrospector(),
399
+ "influx": InfluxIntrospector(),
400
+ "redis": RedisIntrospector(),
401
+ }
402
+
403
+
404
+ def driver_family(driver: str) -> str:
405
+ """Normalize a driver name to its introspection family."""
406
+ name = (driver or "").lower().strip()
407
+ if name in ("pg", "postgres", "postgresql"):
408
+ return "postgres"
409
+ if name in ("mysql", "mariadb"):
410
+ return "mysql"
411
+ if name in ("mssql", "sqlserver", "mstds"):
412
+ return "mssql"
413
+ if name in ("influx", "influxdb"):
414
+ return "influx"
415
+ return name # bigquery, redis, …
416
+
417
+
418
+ def get_introspector(driver: str) -> Introspector:
419
+ """Return the Introspector for ``driver`` (or an Unsupported sentinel)."""
420
+ family = driver_family(driver)
421
+ introspector = INTROSPECTORS.get(family)
422
+ if introspector is None:
423
+ return Unsupported(
424
+ reason=f'Schema introspection is not supported for driver "{driver}".'
425
+ )
426
+ return introspector
@@ -6,6 +6,8 @@ from navconfig import DEBUG
6
6
  from navconfig.logging import logging
7
7
  from navigator.views import BaseHandler
8
8
  from navigator_session import get_session, SessionData
9
+ # Config:
10
+ from ..conf import QS_PBAC_ALLOW_SESSIONLESS_AUTHZ
9
11
  # Queries:
10
12
  from ..queries.qs import QS
11
13
  # Output Formats:
@@ -346,15 +348,46 @@ class AbstractHandler(BaseHandler):
346
348
  raise web.HTTPNotFound()
347
349
 
348
350
  session = await self._get_user_session(request)
351
+ authz_userinfo = None
349
352
  if session is None:
350
- # Fail-closed: no session → deny
351
- self.logger.info(
352
- "PBAC denied (no session): %s/%s action=%s",
353
- resource_type,
354
- resource_name,
355
- action,
356
- )
357
- raise web.HTTPNotFound()
353
+ # Sessionless authorization: requests authorized by a
354
+ # navigator-auth authz backend (IP / host / User-Agent, e.g.
355
+ # authz_allowed_ips, authz_useragent) legitimately carry no user
356
+ # session. When QS_PBAC_ALLOW_SESSIONLESS_AUTHZ is enabled and
357
+ # navigator-auth stamped the request, do NOT bypass PBAC: evaluate
358
+ # it under a synthetic identity whose groups are ``authorized``
359
+ # plus the granting backend name, so explicit allow policies
360
+ # (e.g. policies/authorized.yaml) decide what such clients may do.
361
+ if QS_PBAC_ALLOW_SESSIONLESS_AUTHZ:
362
+ try:
363
+ from navigator_auth.conf import AUTHZ_BACKEND_KEY
364
+ except ImportError:
365
+ AUTHZ_BACKEND_KEY = 'authz_backend'
366
+ authz_backend = request.get(AUTHZ_BACKEND_KEY)
367
+ if authz_backend:
368
+ backend = str(authz_backend)
369
+ authz_userinfo = {
370
+ 'username': f'authz:{backend}',
371
+ 'groups': ['authorized', backend],
372
+ 'roles': [],
373
+ }
374
+ self.logger.info(
375
+ "PBAC sessionless authz (backend=%s): evaluating "
376
+ "%s/%s action=%s as group 'authorized'",
377
+ backend,
378
+ resource_type,
379
+ resource_name,
380
+ action,
381
+ )
382
+ if authz_userinfo is None:
383
+ # Fail-closed: no session and no sessionless authz → deny
384
+ self.logger.info(
385
+ "PBAC denied (no session): %s/%s action=%s",
386
+ resource_type,
387
+ resource_name,
388
+ action,
389
+ )
390
+ raise web.HTTPNotFound()
358
391
 
359
392
  evaluator = request.app.get('policy_evaluator')
360
393
  if evaluator is None:
@@ -369,13 +402,18 @@ class AbstractHandler(BaseHandler):
369
402
  from navigator_auth.abac.policies.environment import Environment
370
403
  from navigator_auth.conf import AUTH_SESSION_OBJECT
371
404
 
372
- userinfo = (
373
- session.get(AUTH_SESSION_OBJECT, {})
374
- if hasattr(session, 'get') else {}
375
- )
376
- if not isinstance(userinfo, dict):
377
- userinfo = {}
378
- user = userinfo if userinfo else None
405
+ if authz_userinfo is not None:
406
+ # Authorized-but-not-authenticated: synthetic identity, no user.
407
+ userinfo = authz_userinfo
408
+ user = None
409
+ else:
410
+ userinfo = (
411
+ session.get(AUTH_SESSION_OBJECT, {})
412
+ if hasattr(session, 'get') else {}
413
+ )
414
+ if not isinstance(userinfo, dict):
415
+ userinfo = {}
416
+ user = userinfo if userinfo else None
379
417
 
380
418
  ctx = EvalContext(
381
419
  request=request,