queryapigate 0.34.2__tar.gz → 0.35.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.
- {queryapigate-0.34.2/queryapigate.egg-info → queryapigate-0.35.0}/PKG-INFO +1 -1
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/__init__.py +1 -1
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/databases.py +2 -2
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/quotas.py +28 -21
- {queryapigate-0.34.2 → queryapigate-0.35.0/queryapigate.egg-info}/PKG-INFO +1 -1
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_data_protection.py +21 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_dependency_floors.py +3 -2
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_integration.py +92 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/LICENSE +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/README.md +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/pyproject.toml +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/__main__.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/accesslog.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/adminroles.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/admins.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/agentwrites.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/alerts.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/apikeys.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/app.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/auditchain.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/auditstream.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/aws.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/broadcast.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/bundle.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/cache.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/cli.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/collection_admin.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/config.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/configcode.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/AccessMapPage-BVQ6wRwp.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/AdministratorsPage-BiUGhISO.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/AgentsPage-CSA-qCUv.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/AlertsPage-MYZoziNZ.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/ApiKeysPage-BZISE5oJ.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/ApprovalsPage-CUiEkHq3.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/AuditLogPage-D9vrSHU7.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/CachingPage-2hjur6KQ.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/CodeBox-BZY9RBv5.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/ConnectionsPage-D26k-98S.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/DesignerPage-B_os91xI.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/DestinationsPage--bjoNE0y.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/ExportsPage-5ai6Ojbl.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/HelpPage-DNaGeh-8.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/HomePage-DINN_eBD.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/Managed-CVE0layM.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/MetricsPage-D6UAGhYP.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/RepositoryPage-BvsZyKvp.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/Results-D8fDmPdY.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/RolesPage-BdEQdLFD.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/SchemaBrowser-Bu0NvoUy.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/SettingsPage-BQhT4xlX.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/StatTile-DEmSFOkX.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/Time-MA05YtZP.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/forms-BSqwVHNJ.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/forms-C6RLe1F3.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/icons-DQ8_pv9M.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/index-BLd0t6vZ.css +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/index-sn5NUET1.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/maskRules-BGQ7mS0j.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/reach-2gDU11-l.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/shared-D5ownoD-.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/state-O13cl7cO.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/useMutation-BF7AWw3p.js +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/favicon.svg +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/index.html +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/cors.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/db.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/definitions.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/deprecations.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/descriptions.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/destinations.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/duckfiles.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/engine.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/errors.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/events.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/examples.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/experimental.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/exporting.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/exports.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/formats.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/governance.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/gunicorn_conf.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/history.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/instances.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/jwtauth.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/lib/h2-2.2.224.jar +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/limits.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/logging_setup.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/masking.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/mcp_server.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/metrics.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/mongotools.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/oidc.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/openapi.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/params.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/parquet.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/pool.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/postman.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/ratelimit.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/rediscache.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/rekey.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/runners.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/schema.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/secheaders.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/secretrefs.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/services/__init__.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/services/access.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/services/administrators.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/services/audit.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/services/collections.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/services/connections.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/services/descriptions.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/services/destinations.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/services/exports.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/services/mcp.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/services/queries.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/sqlflow.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/sqltools.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/sso.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/store.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/tableguard.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/tracing.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/usage.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/v1.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/v1_spec.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/vault.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate.egg-info/SOURCES.txt +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate.egg-info/dependency_links.txt +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate.egg-info/entry_points.txt +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate.egg-info/requires.txt +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate.egg-info/top_level.txt +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/setup.cfg +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_adhoc_history.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_adminroles.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_admins.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_agent_writes.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_alerts.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_api_administrators.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_api_keys.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_api_v1.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_audit_chain.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_audit_log.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_audit_siem.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_audit_stream.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_aws.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_backup_restore.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_broadcast.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_cli.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_collection_bundle.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_collection_postman.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_collections.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_configcode.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_connection_encryption.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_console.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_cors_and_rate_limit.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_databases.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_db.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_deprecations.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_descriptions.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_destinations.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_docs_site.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_duckdb.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_duckdb_files.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_errors.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_events.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_events_server.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_examples.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_experimental.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_export_security.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_exporting.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_exports.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_fips.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_helm.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_history.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_howto.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_instances.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_jdbc.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_jwt.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_key_rotation.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_limits.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_masking.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_masking_requests.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_mcp.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_mcp_keycloak.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_mcp_oauth.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_mongotools.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_multinode.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_observability.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_oidc.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_params.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_parquet.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_pool.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_publishing.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_query_window.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_queryapigate.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_quotas.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_rekey.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_release_check.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_response_cache.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_roles.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_rolling_upgrade.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_secretrefs.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_security_headers.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_settings.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_shared_rate_limit.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_sql_guard_fuzz.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_sql_guard_writes.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_sqlflow.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_sso.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_sso_keycloak.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_supply_chain.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_tableguard.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_tracing.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_upgrades.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_usage.py +0 -0
- {queryapigate-0.34.2 → queryapigate-0.35.0}/tests/test_vault.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: queryapigate
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.35.0
|
|
4
4
|
Summary: Turn SQL into governed REST APIs over MySQL, PostgreSQL, ClickHouse, SQLite, DuckDB, H2, MongoDB, and Parquet/CSV/JSON files - JSON, CSV, Parquet or Excel out, with scoped keys, an admin Console and MCP for AI agents.
|
|
5
5
|
Author-email: Anantha Raju C <arcswdev@gmail.com>
|
|
6
6
|
License-Expression: FSL-1.1-MIT
|
|
@@ -15,8 +15,8 @@ NAMES = {'postgres': 'PostgreSQL', 'mysql': 'MySQL', 'sqlite': 'SQLite', 'duckdb
|
|
|
15
15
|
TIER_1 = tuple(t for t in TYPES if t not in experimental.DB_TYPES)
|
|
16
16
|
|
|
17
17
|
# Run against a real server (or, for SQLite, a real file) on every CI push: tests/test_integration.py's classes, and
|
|
18
|
-
# the main suite for SQLite.
|
|
19
|
-
INTEGRATION_TESTED = frozenset({'postgres', 'mysql', 'clickhouse', 'duckdb', 'h2', 'jdbc', 'sqlite'})
|
|
18
|
+
# the main suite for SQLite. CI fails if one skips.
|
|
19
|
+
INTEGRATION_TESTED = frozenset({'postgres', 'mysql', 'clickhouse', 'duckdb', 'h2', 'jdbc', 'sqlite', 'mongo'})
|
|
20
20
|
|
|
21
21
|
# Where the database itself refuses writes in a read-only session, beside QueryAPIGate's own SQL check (sqltools):
|
|
22
22
|
# MySQL and PostgreSQL read-only transactions, ClickHouse readonly=1, SQLite mode=ro. DuckDB, H2 and JDBC rest on
|
|
@@ -109,6 +109,10 @@ class _Counter:
|
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
_counter = _Counter()
|
|
112
|
+
# Held from taking the unwritten counts to storing them, and by forget(): a forget that ran while a write was in flight
|
|
113
|
+
# found the counts in neither place - taken from _counter, not yet in the store - and the write then stored them after
|
|
114
|
+
# the person was forgotten (CI, 2026-10-14). Reentrant: forget() writes first, under it.
|
|
115
|
+
_writing = threading.RLock()
|
|
112
116
|
|
|
113
117
|
|
|
114
118
|
class _Shared:
|
|
@@ -209,20 +213,21 @@ def _stored(caller, key):
|
|
|
209
213
|
def write():
|
|
210
214
|
"""Add what's been counted to the store(s) it was counted against - the history writer's batch calls this (and
|
|
211
215
|
tests). A failed write puts the counts back, to be written next time rather than lost."""
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
216
|
+
with _writing:
|
|
217
|
+
taken = _counter.take()
|
|
218
|
+
if not taken:
|
|
219
|
+
return
|
|
220
|
+
by_target = {}
|
|
221
|
+
for (target, caller, key), counts in taken.items():
|
|
222
|
+
by_target.setdefault(target, {})[(caller, key)] = counts
|
|
223
|
+
stamp = datetime.now().strftime(_TIME)
|
|
224
|
+
try:
|
|
225
|
+
for target, counted in by_target.items():
|
|
226
|
+
_write(target, counted, stamp)
|
|
227
|
+
except Exception:
|
|
228
|
+
_counter.put_back(taken)
|
|
229
|
+
raise
|
|
230
|
+
_counter.forget_reads()
|
|
226
231
|
|
|
227
232
|
|
|
228
233
|
def _write(target, counted, stamp):
|
|
@@ -249,13 +254,15 @@ def _ensure_written():
|
|
|
249
254
|
def forget(caller):
|
|
250
255
|
"""Delete a caller's usage counts - unwritten, stored and in Redis (ADR 0016: forgetting a person). Their quota's
|
|
251
256
|
count for the period starts again. Returns how many periods there were: what this process hadn't written yet is
|
|
252
|
-
written first, so the answer doesn't depend on whether a background write happened to come first
|
|
253
|
-
|
|
254
|
-
with
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
257
|
+
written first, so the answer doesn't depend on whether a background write happened to come first - or was in
|
|
258
|
+
flight: that one is waited for (_writing)."""
|
|
259
|
+
with _writing:
|
|
260
|
+
write()
|
|
261
|
+
with _counter.lock:
|
|
262
|
+
for slot in [s for s in _counter.read if s[0] == caller]:
|
|
263
|
+
del _counter.read[slot]
|
|
264
|
+
with db.transaction() as tx:
|
|
265
|
+
stored = tx.execute('DELETE FROM usage_counters WHERE caller = ?', (caller,)).rowcount
|
|
259
266
|
shared = _redis()
|
|
260
267
|
if shared is not None:
|
|
261
268
|
try:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: queryapigate
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.35.0
|
|
4
4
|
Summary: Turn SQL into governed REST APIs over MySQL, PostgreSQL, ClickHouse, SQLite, DuckDB, H2, MongoDB, and Parquet/CSV/JSON files - JSON, CSV, Parquet or Excel out, with scoped keys, an admin Console and MCP for AI agents.
|
|
5
5
|
Author-email: Anantha Raju C <arcswdev@gmail.com>
|
|
6
6
|
License-Expression: FSL-1.1-MIT
|
|
@@ -147,6 +147,27 @@ class ForgetTests(unittest.TestCase):
|
|
|
147
147
|
quotas.write() # what was still unwritten was forgotten too
|
|
148
148
|
self.assertEqual(self.periods(self.PERSON), 0)
|
|
149
149
|
|
|
150
|
+
def test_a_write_in_flight_is_waited_for_not_missed(self):
|
|
151
|
+
# CI, 2026-10-14: the background writer had taken the unwritten month's count and was writing it when forget
|
|
152
|
+
# ran - forget found it in neither place, deleted the rest, and the writer then stored it after the person
|
|
153
|
+
# was forgotten. Forgetting now waits for a write in flight, and deletes what it wrote.
|
|
154
|
+
import threading
|
|
155
|
+
writing, release, original = threading.Event(), threading.Event(), quotas._write
|
|
156
|
+
|
|
157
|
+
def slow_write(target, counted, stamp):
|
|
158
|
+
writing.set()
|
|
159
|
+
release.wait(5)
|
|
160
|
+
original(target, counted, stamp)
|
|
161
|
+
with mock.patch.object(quotas, '_write', slow_write):
|
|
162
|
+
writer = threading.Thread(target=quotas.write)
|
|
163
|
+
writer.start()
|
|
164
|
+
self.assertTrue(writing.wait(5))
|
|
165
|
+
threading.Timer(0.3, release.set).start()
|
|
166
|
+
forgotten = history.forget(self.PERSON, 'owner')
|
|
167
|
+
writer.join(5)
|
|
168
|
+
self.assertEqual(forgotten['usage_periods'], 2)
|
|
169
|
+
self.assertEqual(self.periods(self.PERSON), 0)
|
|
170
|
+
|
|
150
171
|
def test_the_record_of_it_keeps_nothing_of_who(self):
|
|
151
172
|
history.forget(self.PERSON, 'owner')
|
|
152
173
|
entry = self.audit()[-1]
|
|
@@ -11,10 +11,11 @@ ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
11
11
|
|
|
12
12
|
# Each package whose floor CI tests, and the extra that declares it - None for a core dependency. Every core
|
|
13
13
|
# dependency is here, and every extra a stable feature needs (ADR 0017); the experimental features' extras (otel,
|
|
14
|
-
# aws,
|
|
14
|
+
# aws, h2) join when they graduate - mongo's already has, tested against a real server.
|
|
15
15
|
FLOORS = {'Flask': None, 'Werkzeug': None, 'PyYAML': None, 'openpyxl': None,
|
|
16
16
|
'duckdb': 'duckdb', 'sqlglot': 'flow', 'mcp': 'mcp', 'PyJWT': 'jwt', 'redis': 'redis',
|
|
17
|
-
'psycopg2-binary': 'postgres'
|
|
17
|
+
'psycopg2-binary': 'postgres', # the PostgreSQL store, and live events' notifications (ADR 0021)
|
|
18
|
+
'pymongo': 'mongo'}
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
def _project():
|
|
@@ -478,5 +478,97 @@ class DuckDBTests(IntegrationBase, unittest.TestCase):
|
|
|
478
478
|
self.assertEqual(len(self.query('SELECT * FROM queryapigate_it', '?page_size=100').get_json()), 7)
|
|
479
479
|
|
|
480
480
|
|
|
481
|
+
class MongoTests(unittest.TestCase):
|
|
482
|
+
"""MongoDB against a real server (QUERYAPIGATE_IT_MONGO): find() through /execute_mongo and saved queries, the
|
|
483
|
+
time limit, allowed_tables as collections, and the refusals that keep a find() a find() - each sent to the real
|
|
484
|
+
server's parser, not a mock's. Not IntegrationBase: there is no SQL to run."""
|
|
485
|
+
db, env_var = 'mongo', 'QUERYAPIGATE_IT_MONGO'
|
|
486
|
+
|
|
487
|
+
@classmethod
|
|
488
|
+
def setUpClass(cls):
|
|
489
|
+
raw = os.environ.get(cls.env_var)
|
|
490
|
+
if not raw:
|
|
491
|
+
raise unittest.SkipTest(f'{cls.env_var} not set')
|
|
492
|
+
cls.details = {**json.loads(raw), 'db': cls.db, 'active': True}
|
|
493
|
+
|
|
494
|
+
def setUp(self):
|
|
495
|
+
import pymongo
|
|
496
|
+
self.tmp = tempfile.TemporaryDirectory()
|
|
497
|
+
self.addCleanup(self.tmp.cleanup)
|
|
498
|
+
patcher = mock.patch.dict(os.environ, {'QUERYAPIGATE_HOME': self.tmp.name, 'QUERYAPIGATE_API_KEY': 'admin'})
|
|
499
|
+
patcher.start()
|
|
500
|
+
self.addCleanup(patcher.stop)
|
|
501
|
+
write_connections({'it': self.details})
|
|
502
|
+
self.client = create_app().test_client()
|
|
503
|
+
self.admin = {'X-API-Key': 'admin'}
|
|
504
|
+
server = pymongo.MongoClient(self.details['host'], int(self.details.get('port') or 27017))
|
|
505
|
+
self.addCleanup(server.close)
|
|
506
|
+
self.mongo = server[self.details['database']]
|
|
507
|
+
for name in ('queryapigate_it', 'queryapigate_it_secret', 'queryapigate_it_slow'):
|
|
508
|
+
self.mongo.drop_collection(name)
|
|
509
|
+
self.addCleanup(self.mongo.drop_collection, name)
|
|
510
|
+
self.mongo.queryapigate_it.insert_many([{'id': i, 'name': f'Item {i}', 'price': i + 0.5} for i in range(1, 8)])
|
|
511
|
+
self.mongo.queryapigate_it_secret.insert_one({'token': 'tok_live_123'})
|
|
512
|
+
|
|
513
|
+
def find(self, headers=None, query='', **body):
|
|
514
|
+
return self.client.post(f'/execute_mongo{query}', headers=headers or self.admin,
|
|
515
|
+
json={'connection_name': 'it', 'collection': 'queryapigate_it', **body})
|
|
516
|
+
|
|
517
|
+
def key(self, **grants):
|
|
518
|
+
res = self.client.post('/api/v1/api-keys', headers=self.admin, json={'name': 'partner', **grants})
|
|
519
|
+
self.assertEqual(res.status_code, 201, res.get_data(as_text=True))
|
|
520
|
+
return {'X-API-Key': res.get_json()['secret']}
|
|
521
|
+
|
|
522
|
+
def test_a_find_filters_projects_sorts_and_pages(self):
|
|
523
|
+
res = self.find(query='?page_size=2', filter={'price': {'$gte': 3}}, projection={'_id': 0, 'id': 1},
|
|
524
|
+
sort={'id': -1})
|
|
525
|
+
self.assertEqual(res.status_code, 200, res.get_data(as_text=True))
|
|
526
|
+
self.assertEqual(res.get_json(), [{'id': 7}, {'id': 6}])
|
|
527
|
+
self.assertEqual(res.headers['X-Has-More'], 'true')
|
|
528
|
+
|
|
529
|
+
def test_a_saved_query_binds_a_typed_parameter(self):
|
|
530
|
+
self.assertEqual(save_query(self.client, headers=self.admin, body={
|
|
531
|
+
'filename': 'by_id', 'author': 'a', 'description': 'd', 'query_type': 'mongo',
|
|
532
|
+
'mongo_collection': 'queryapigate_it', 'mongo_filter': {'id': ':id'},
|
|
533
|
+
'mongo_projection': {'_id': 0, 'name': 1}, 'query_parameters': {'id': 'int'},
|
|
534
|
+
'connection_name': 'it'}).status_code, 201)
|
|
535
|
+
res = self.client.get('/q/by_id?id=3', headers=self.admin)
|
|
536
|
+
self.assertEqual((res.status_code, res.get_json()), (200, [{'name': 'Item 3'}]))
|
|
537
|
+
|
|
538
|
+
def test_the_time_limit_cancels_a_find(self):
|
|
539
|
+
self.mongo.queryapigate_it_slow.insert_many([{'s': 'x' * 40 + str(i)} for i in range(100_000)])
|
|
540
|
+
res = self.find(collection='queryapigate_it_slow', filter={'s': {'$regex': 'y$'}}, timeout=0.001)
|
|
541
|
+
self.assertEqual((res.status_code, res.get_json()['code']), (504, 'query_timeout'))
|
|
542
|
+
unlimited = self.find(collection='queryapigate_it_slow', filter={'s': {'$regex': 'y$'}})
|
|
543
|
+
self.assertEqual(unlimited.status_code, 200) # the same find, given its time, simply finds nothing
|
|
544
|
+
|
|
545
|
+
def test_allowed_tables_are_the_collections_a_key_may_read(self):
|
|
546
|
+
partner = self.key(connections=['it'], allowed_tables=['queryapigate_it'])
|
|
547
|
+
self.assertEqual(self.find(partner).status_code, 200)
|
|
548
|
+
refused = self.find(partner, collection='queryapigate_it_secret')
|
|
549
|
+
self.assertEqual((refused.status_code, refused.get_json()['code']), (403, 'table_not_allowed'))
|
|
550
|
+
self.assertNotIn('tok_live', refused.get_data(as_text=True))
|
|
551
|
+
|
|
552
|
+
def test_server_side_javascript_and_injected_operators_never_reach_the_server(self):
|
|
553
|
+
js = {'$function': {'body': 'function() { return true; }', 'args': [], 'lang': 'js'}}
|
|
554
|
+
for body in ({'filter': {'$where': 'true'}}, {'filter': {'$expr': js}}, {'projection': {'x': js}},
|
|
555
|
+
{'sort': {'x': js}}):
|
|
556
|
+
with self.subTest(body=body):
|
|
557
|
+
res = self.find(**body)
|
|
558
|
+
self.assertEqual((res.status_code, res.get_json()['code']), (403, 'mongo_operator_forbidden'))
|
|
559
|
+
injected = self.find(filter={'name': ':u'}, params={'u': {'$ne': None}})
|
|
560
|
+
self.assertEqual((injected.status_code, injected.get_json()['code']), (400, 'param_invalid'))
|
|
561
|
+
|
|
562
|
+
def test_the_schema_lists_collections_and_the_server_its_databases(self):
|
|
563
|
+
res = self.client.get('/connections/it/schema', headers=self.admin)
|
|
564
|
+
self.assertEqual(res.status_code, 200, res.get_data(as_text=True))
|
|
565
|
+
self.assertIn('queryapigate_it', {t['name'] for t in res.get_json()['tables']})
|
|
566
|
+
listed = self.client.post('/api/v1/connections/databases', headers=self.admin, json=self.details)
|
|
567
|
+
self.assertEqual(listed.status_code, 200, listed.get_data(as_text=True))
|
|
568
|
+
self.assertIn(self.details['database'], json.dumps(listed.get_json()))
|
|
569
|
+
tested = self.client.post('/api/v1/connections/test', headers=self.admin, json=self.details)
|
|
570
|
+
self.assertEqual(tested.status_code, 200, tested.get_data(as_text=True))
|
|
571
|
+
|
|
572
|
+
|
|
481
573
|
if __name__ == '__main__':
|
|
482
574
|
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/AgentsPage-CSA-qCUv.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/AlertsPage-MYZoziNZ.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/ApiKeysPage-BZISE5oJ.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/CachingPage-2hjur6KQ.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/CodeBox-BZY9RBv5.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/ExportsPage-5ai6Ojbl.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/HelpPage-DNaGeh-8.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/HomePage-DINN_eBD.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/Managed-CVE0layM.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/MetricsPage-D6UAGhYP.js
RENAMED
|
File without changes
|
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/Results-D8fDmPdY.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/RolesPage-BdEQdLFD.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/StatTile-DEmSFOkX.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/Time-MA05YtZP.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/forms-BSqwVHNJ.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/forms-C6RLe1F3.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/icons-DQ8_pv9M.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/index-BLd0t6vZ.css
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/index-sn5NUET1.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/maskRules-BGQ7mS0j.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/reach-2gDU11-l.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/shared-D5ownoD-.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/state-O13cl7cO.js
RENAMED
|
File without changes
|
{queryapigate-0.34.2 → queryapigate-0.35.0}/queryapigate/console_dist/assets/useMutation-BF7AWw3p.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|