tigrbl_tests 0.3.12.dev6__tar.gz → 0.3.12.dev8__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 (321) hide show
  1. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/PKG-INFO +1 -1
  2. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/pyproject.toml +1 -1
  3. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/architecture/test_transport_dispatch_convergence.py +7 -0
  4. tigrbl_tests-0.3.12.dev8/tests/harness_v3/test_route_runtime_fallback_atoms.py +114 -0
  5. tigrbl_tests-0.3.12.dev8/tests/i9n/test_op_ctx_uvicorn_scopes.py +170 -0
  6. tigrbl_tests-0.3.12.dev8/tests/i9n/test_uvicorn_transport_behavior.py +150 -0
  7. tigrbl_tests-0.3.12.dev8/tests/unit/runtime/test_payload_select_invalid_rpc_params.py +27 -0
  8. tigrbl_tests-0.3.12.dev8/tests/unit/test_engine_session_database_availability.py +51 -0
  9. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_jsonrpc_openrpc.py +48 -0
  10. tigrbl_tests-0.3.12.dev8/tests/unit/test_op_ctx_custom_target_persist.py +79 -0
  11. tigrbl_tests-0.3.12.dev8/tests/unit/test_op_ctx_parameter_matrix.py +88 -0
  12. tigrbl_tests-0.3.12.dev8/tests/unit/test_openapi_documentation_security_behavior.py +127 -0
  13. tigrbl_tests-0.3.12.dev8/tests/unit/test_openrpc_documentation_security_behavior.py +127 -0
  14. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/LICENSE +0 -0
  15. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/README.md +0 -0
  16. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/__init__.py +0 -0
  17. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/architecture/test_atoms_do_not_depend_on_mapping.py +0 -0
  18. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/architecture/test_import_graph_audit.py +0 -0
  19. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/architecture/test_no_bindings_imports.py +0 -0
  20. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/architecture/test_operation_resolution_parity.py +0 -0
  21. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/architecture/test_runtime_structure.py +0 -0
  22. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/architecture/test_trace_plan_parity.py +0 -0
  23. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/architecture/test_transport_boundaries.py +0 -0
  24. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/conftest.py +0 -0
  25. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness/test_00_appspec_contract.py +0 -0
  26. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness/test_01_kernel_plan_compilation.py +0 -0
  27. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness/test_02_bootstrap_plan.py +0 -0
  28. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness/test_03_appspec_uvicorn_e2e.py +0 -0
  29. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness_e2e/test_00_appspec_uvicorn_rest_rpc.py +0 -0
  30. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness_e2e/test_01_imperative_uvicorn_rest_rpc.py +0 -0
  31. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness_v3/__init__.py +0 -0
  32. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness_v3/_support.py +0 -0
  33. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness_v3/test_appspec_prefixes.py +0 -0
  34. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness_v3/test_bootstrap_kernel_compilation.py +0 -0
  35. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness_v3/test_default_opspec_bindings.py +0 -0
  36. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness_v3/test_kernel_plan_routing.py +0 -0
  37. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness_v3/test_mapping_plan_compilation.py +0 -0
  38. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness_v3/test_route_rpc_prebinding.py +0 -0
  39. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/harness_v3/test_uvicorn_e2e_appspec.py +0 -0
  40. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/hooks/test_hook_ctx_phase_validation.py +0 -0
  41. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/__init__.py +0 -0
  42. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_acronym_route_name.py +0 -0
  43. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_allow_anon.py +0 -0
  44. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_apikey_generation.py +0 -0
  45. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_authn_provider_integration.py +0 -0
  46. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_bindings_integration.py +0 -0
  47. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_bindings_modules.py +0 -0
  48. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_bulk_docs_client.py +0 -0
  49. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_core_access.py +0 -0
  50. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_engine_install_uvicorn.py +0 -0
  51. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_engine_resolver_uvicorn.py +0 -0
  52. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_error_mappings.py +0 -0
  53. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_field_spec_effects.py +0 -0
  54. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_header_io_uvicorn.py +0 -0
  55. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_healthz_methodz_hookz.py +0 -0
  56. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_hook_ctx_v3_i9n.py +0 -0
  57. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_hook_lifecycle.py +0 -0
  58. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_iospec_attributes.py +0 -0
  59. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_iospec_integration.py +0 -0
  60. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_jsonrpc_batch_behavior.py +0 -0
  61. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_key_digest_uvicorn.py +0 -0
  62. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_list_filters_optional.py +0 -0
  63. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_mixins.py +0 -0
  64. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_mountable_favicon_uvicorn.py +0 -0
  65. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_mountable_lens_uvicorn.py +0 -0
  66. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_mountable_openapi_uvicorn.py +0 -0
  67. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_mountable_openrpc_uvicorn.py +0 -0
  68. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_mountable_swagger_uvicorn.py +0 -0
  69. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_nested_path_schema_and_rpc.py +0 -0
  70. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_nested_routing_depth.py +0 -0
  71. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_op_ctx_alias_examples.py +0 -0
  72. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_op_ctx_behavior.py +0 -0
  73. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_op_ctx_core_crud_order.py +0 -0
  74. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_openapi_clear_response_schema.py +0 -0
  75. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_openapi_schema_examples_presence.py +0 -0
  76. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_opspec_effects_i9n_test.py +0 -0
  77. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_opspec_pre_tx_deps.py +0 -0
  78. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_owner_tenant_policy.py +0 -0
  79. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_request_extras.py +0 -0
  80. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_request_extras_provider.py +0 -0
  81. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_response_extras_provider.py +0 -0
  82. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_rest_fallback_serialization.py +0 -0
  83. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_rest_row_serialization.py +0 -0
  84. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_rest_rpc_parity_v3.py +0 -0
  85. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_row_result_serialization.py +0 -0
  86. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_schema.py +0 -0
  87. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_schema_ctx_attributes_integration.py +0 -0
  88. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_schema_ctx_op_ctx_integration.py +0 -0
  89. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_schema_ctx_spec_integration.py +0 -0
  90. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_sqlite_attachments.py +0 -0
  91. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_storage_spec_integration.py +0 -0
  92. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_symmetry_parity.py +0 -0
  93. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_tigrbl_api_app_usage_uvicorn.py +0 -0
  94. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_tigrbl_api_usage_uvicorn.py +0 -0
  95. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_tigrbl_api_uvicorn.py +0 -0
  96. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_tigrbl_app_include_api_uvicorn.py +0 -0
  97. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_tigrbl_app_multi_api_uvicorn.py +0 -0
  98. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_tigrbl_app_usage_uvicorn.py +0 -0
  99. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_tigrbl_app_uvicorn.py +0 -0
  100. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_transport_dispatch_parity.py +0 -0
  101. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_types_deprecation_exports.py +0 -0
  102. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_v3_bulk_rest_endpoints.py +0 -0
  103. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_v3_default_rest_ops.py +0 -0
  104. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_v3_default_rpc_ops.py +0 -0
  105. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_v3_opspec_attributes.py +0 -0
  106. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/test_verb_alias_policy.py +0 -0
  107. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/i9n/uvicorn_utils.py +0 -0
  108. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/mount/__init__.py +0 -0
  109. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/mount/test_mount_favico.py +0 -0
  110. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/options/test_rest_options.py +0 -0
  111. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/options/test_rpc_options.py +0 -0
  112. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/parity/__init__.py +0 -0
  113. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/parity/test_hook_runtime_phase_parity.py +0 -0
  114. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/parity/test_stdapi_openapi_docs.py +0 -0
  115. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/parity/test_stdapi_primitives.py +0 -0
  116. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/parity/test_stdapi_routing.py +0 -0
  117. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/perf/__init__.py +0 -0
  118. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/perf/test_collect_caching.py +0 -0
  119. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/perf/test_hookz_performance.py +0 -0
  120. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/perf/test_methodz_performance.py +0 -0
  121. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/request/test_request_asgi_scope_compat.py +0 -0
  122. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/request/test_request_authn_strip.py +0 -0
  123. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/request/test_request_dot_notation.py +0 -0
  124. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/request/test_request_response_conveniences.py +0 -0
  125. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/request/test_request_transport_convenience_dot_notation.py +0 -0
  126. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/requests/test_request_json_modes.py +0 -0
  127. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/response/test_response_dot_notation.py +0 -0
  128. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/response/test_response_transport_convenience_dot_notation.py +0 -0
  129. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/security/test_dot_notation_schemes.py +0 -0
  130. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/security/test_schemes.py +0 -0
  131. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/test_secdeps_execute_in_pre_tx.py +0 -0
  132. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/__init__.py +0 -0
  133. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/decorators/test_alias_ctx_bindings.py +0 -0
  134. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/decorators/test_engine_ctx_bindings.py +0 -0
  135. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/decorators/test_hook_ctx_bindings.py +0 -0
  136. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/decorators/test_op_alias_bindings.py +0 -0
  137. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/decorators/test_op_ctx_bindings.py +0 -0
  138. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/decorators/test_response_ctx_bindings.py +0 -0
  139. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/decorators/test_schema_ctx_bindings.py +0 -0
  140. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/response_utils.py +0 -0
  141. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_emit_paired_post.py +0 -0
  142. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_emit_paired_pre.py +0 -0
  143. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_emit_readtime_alias.py +0 -0
  144. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_out_masking.py +0 -0
  145. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_refresh_demand.py +0 -0
  146. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_resolve_assemble.py +0 -0
  147. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_resolve_paired_gen.py +0 -0
  148. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_route_protocol_detect.py +0 -0
  149. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_schema_collect_in.py +0 -0
  150. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_schema_collect_out.py +0 -0
  151. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_storage_to_stored.py +0 -0
  152. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_wire_build_in.py +0 -0
  153. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_wire_build_out.py +0 -0
  154. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_wire_dump.py +0 -0
  155. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/atoms/test_wire_validate_in.py +0 -0
  156. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/test_compilation_runtime_behavior.py +0 -0
  157. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/test_events_phases.py +0 -0
  158. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/test_events_runtime_behavior.py +0 -0
  159. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/test_ingress_egress_phase_access.py +0 -0
  160. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/test_kernel_plan_event_ordering.py +0 -0
  161. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/test_kernel_plan_full_ordering.py +0 -0
  162. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/test_kernel_runtime_behavior.py +0 -0
  163. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/test_ordering_runtime_behavior.py +0 -0
  164. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/runtime/test_payload_select_header_merge.py +0 -0
  165. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_acol_vcol_knobs.py +0 -0
  166. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_alias_ctx_op_alias_attributes.py +0 -0
  167. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_alias_ctx_op_attributes.py +0 -0
  168. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_api_level_set_auth.py +0 -0
  169. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_app_model_defaults.py +0 -0
  170. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_app_reexport.py +0 -0
  171. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_attrdict_vs_simplenamespace.py +0 -0
  172. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_authorize_runtime_secdep.py +0 -0
  173. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_base_columnspec_inheritance.py +0 -0
  174. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_base_facade_initialize.py +0 -0
  175. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_build_list_params_spec_model.py +0 -0
  176. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_bulk_body_annotation.py +0 -0
  177. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_bulk_response_schema.py +0 -0
  178. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_colspec_map_isolation.py +0 -0
  179. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_column_collect_mixins.py +0 -0
  180. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_column_mro_collect_namespace.py +0 -0
  181. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_column_rest_rpc_results.py +0 -0
  182. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_column_table_orm_binding.py +0 -0
  183. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_config_dataclass_none.py +0 -0
  184. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_core_crud_bulk_ops.py +0 -0
  185. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_core_crud_default_ops.py +0 -0
  186. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_core_crud_methods.py +0 -0
  187. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_core_wrap_memoization.py +0 -0
  188. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_db_dependency.py +0 -0
  189. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_decorator_and_collect.py +0 -0
  190. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_default_schema_selection.py +0 -0
  191. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_default_tags.py +0 -0
  192. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_diagnostics_no_compat_module.py +0 -0
  193. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_docs_security_parity.py +0 -0
  194. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_engine_install_api.py +0 -0
  195. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_engine_install_app.py +0 -0
  196. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_engine_install_op.py +0 -0
  197. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_engine_install_table.py +0 -0
  198. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_engine_spec_and_shortcuts.py +0 -0
  199. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_engine_usage_levels.py +0 -0
  200. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_field_spec_attrs.py +0 -0
  201. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_file_response.py +0 -0
  202. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_get_schema.py +0 -0
  203. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_handler_step_qualname.py +0 -0
  204. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_hook_ctx_attributes.py +0 -0
  205. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_hook_ctx_binding.py +0 -0
  206. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_hookz_empty_phase.py +0 -0
  207. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_hybrid_session_run_sync.py +0 -0
  208. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_in_tx.py +0 -0
  209. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_include_model_columns_namespace.py +0 -0
  210. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_include_models_base_prefix.py +0 -0
  211. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_include_tables_base_prefix.py +0 -0
  212. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_initialize_async_task.py +0 -0
  213. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_initialize_cross_ddl.py +0 -0
  214. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_initialize_mixed_engines.py +0 -0
  215. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_initialize_task_schedule.py +0 -0
  216. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_instance_naming_conventions.py +0 -0
  217. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_io_spec_attributes.py +0 -0
  218. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_iospec_attributes.py +0 -0
  219. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_iospec_effects.py +0 -0
  220. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_jsonrpc_id_example.py +0 -0
  221. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_jsonrpc_router_default_tag.py +0 -0
  222. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_kernel_invoke_ctx.py +0 -0
  223. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_kernel_opview_on_demand.py +0 -0
  224. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_kernel_plan_labels.py +0 -0
  225. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_kernelz_endpoint.py +0 -0
  226. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_make_column_shortcuts.py +0 -0
  227. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_mapping_bind_response_export.py +0 -0
  228. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_mapping_plan_precedence.py +0 -0
  229. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_middleware_http_and_cors.py +0 -0
  230. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_mixins_sqlalchemy.py +0 -0
  231. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_op_alias.py +0 -0
  232. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_op_class_engine_binding.py +0 -0
  233. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_op_ctx_arity_paths.py +0 -0
  234. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_op_ctx_attributes.py +0 -0
  235. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_op_ctx_core_crud_integration.py +0 -0
  236. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_op_ctx_dynamic_attach.py +0 -0
  237. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_op_ctx_persist_options.py +0 -0
  238. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_openapi_openrpc_schema_separation.py +0 -0
  239. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_opspec_effects.py +0 -0
  240. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_postgres_engine_errors.py +0 -0
  241. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_postgres_env_vars.py +0 -0
  242. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_relationship_alias_cols.py +0 -0
  243. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_request_body_schema.py +0 -0
  244. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_request_response_examples.py +0 -0
  245. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_resolver_interning_warmup.py +0 -0
  246. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_resolver_precedence.py +0 -0
  247. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_response_alias_table_rpc.py +0 -0
  248. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_response_ctx_precedence.py +0 -0
  249. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_response_diagnostics_kernelz.py +0 -0
  250. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_response_html_jinja_behavior.py +0 -0
  251. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_response_parity.py +0 -0
  252. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_response_rest.py +0 -0
  253. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_response_rpc.py +0 -0
  254. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_response_template.py +0 -0
  255. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_response_uuid.py +0 -0
  256. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_rest_all_default_op_verbs.py +0 -0
  257. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_rest_bulk_delete_suppresses_clear.py +0 -0
  258. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_rest_no_schema_jsonable.py +0 -0
  259. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_rest_operation_id_uniqueness.py +0 -0
  260. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_rest_output_serialization_extras.py +0 -0
  261. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_rest_request_mapping_access.py +0 -0
  262. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_rest_rpc_parity_default_ops.py +0 -0
  263. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_rest_rpc_prefixes.py +0 -0
  264. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_rest_rpc_symmetry.py +0 -0
  265. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_router_compatibility_shims.py +0 -0
  266. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_router_dependency_execution_blocked.py +0 -0
  267. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_rpc_all_default_op_verbs.py +0 -0
  268. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_rpc_default_ops.py +0 -0
  269. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_schema_ctx_attributes.py +0 -0
  270. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_schema_ctx_plain_class.py +0 -0
  271. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_schema_spec_presence.py +0 -0
  272. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_schemas_binding.py +0 -0
  273. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_security_per_route.py +0 -0
  274. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_should_wire_canonical.py +0 -0
  275. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_spec_api.py +0 -0
  276. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_spec_app.py +0 -0
  277. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_spec_column.py +0 -0
  278. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_spec_engine.py +0 -0
  279. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_spec_field.py +0 -0
  280. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_spec_hook.py +0 -0
  281. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_spec_io.py +0 -0
  282. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_spec_op.py +0 -0
  283. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_spec_storage.py +0 -0
  284. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_spec_table.py +0 -0
  285. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_sqlite_attachments.py +0 -0
  286. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_sqlite_uuid_type.py +0 -0
  287. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_stdapi_request_injection.py +0 -0
  288. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_stdapi_transport_asgi_wsgi.py +0 -0
  289. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_storage_spec_attributes.py +0 -0
  290. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_sys_handler_crud.py +0 -0
  291. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_sys_run_rollback.py +0 -0
  292. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_sys_tx_async_begin.py +0 -0
  293. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_sys_tx_begin.py +0 -0
  294. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_sys_tx_commit.py +0 -0
  295. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_system_docs_builders.py +0 -0
  296. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_table_base_exports.py +0 -0
  297. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_table_collect_spec.py +0 -0
  298. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_table_columns_namespace.py +0 -0
  299. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_table_model_attribute_contract.py +0 -0
  300. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_table_namespace_init.py +0 -0
  301. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_table_namespace_isolation.py +0 -0
  302. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_tigrbl_api_app_configuration.py +0 -0
  303. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_tigrbl_api_app_instantiation.py +0 -0
  304. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_tigrbl_api_app_subclass_definition.py +0 -0
  305. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_tigrbl_api_configuration.py +0 -0
  306. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_tigrbl_api_instantiation.py +0 -0
  307. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_tigrbl_api_subclass_definition.py +0 -0
  308. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_tigrbl_app_configuration.py +0 -0
  309. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_tigrbl_app_event_handlers.py +0 -0
  310. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_tigrbl_app_instantiation.py +0 -0
  311. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_tigrbl_app_state.py +0 -0
  312. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_tigrbl_app_subclass_definition.py +0 -0
  313. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_transport_gw_contract.py +0 -0
  314. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_transport_security_runtime_only.py +0 -0
  315. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_v3_favicon_endpoint.py +0 -0
  316. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_v3_healthz_endpoint.py +0 -0
  317. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_v3_op_alias.py +0 -0
  318. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_v3_op_ctx_attributes.py +0 -0
  319. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_v3_schemas_and_decorators.py +0 -0
  320. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_v3_storage_spec_attributes.py +0 -0
  321. {tigrbl_tests-0.3.12.dev6 → tigrbl_tests-0.3.12.dev8}/tests/unit/test_verbosity.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tigrbl_tests
3
- Version: 0.3.12.dev6
3
+ Version: 0.3.12.dev8
4
4
  Summary: Test suite and fixtures for the Tigrbl framework.
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tigrbl_tests"
3
- version = "0.3.12.dev6"
3
+ version = "0.3.12.dev8"
4
4
  description = "Test suite and fixtures for the Tigrbl framework."
5
5
  license = "Apache-2.0"
6
6
  readme = "README.md"
@@ -29,6 +29,13 @@ def test_gateway_invoke_invokes_runtime_kernel_plan_and_executor():
29
29
  assert "await _invoke(" in source
30
30
 
31
31
 
32
+ def test_gateway_invoke_uses_runtime_atoms_for_fallback_and_errors():
33
+ source = _source("runtime/gw/invoke.py")
34
+ assert "_runtime_route_handler" in source
35
+ assert "_error_to_transport" in source
36
+ assert "except Exception" not in source
37
+
38
+
32
39
  def test_mapping_does_not_import_dispatch_modules():
33
40
  rest_collection = ROOT / "mapping" / "rest" / "collection.py"
34
41
  rest_member = ROOT / "mapping" / "rest" / "member.py"
@@ -0,0 +1,114 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+
5
+ import pytest
6
+ from types import SimpleNamespace
7
+
8
+ from tigrbl.runtime.atoms.route import jsonrpc_batch_intercept, op_resolve
9
+
10
+
11
+ def _ctx_for_route(*, method: str, path: str, routes: list[object]):
12
+ request = SimpleNamespace(method=method, path=path, url=SimpleNamespace(path=path))
13
+ return SimpleNamespace(
14
+ temp={"route": {}},
15
+ request=request,
16
+ app=SimpleNamespace(routes=routes),
17
+ )
18
+
19
+
20
+ def test_op_resolve_discovers_runtime_route_handler() -> None:
21
+ captured = {"ok": True}
22
+
23
+ def handler() -> dict[str, bool]:
24
+ return captured
25
+
26
+ route = SimpleNamespace(
27
+ pattern=re.compile(r"^/items/(?P<item_id>[^/]+)$"),
28
+ methods={"GET"},
29
+ handler=handler,
30
+ )
31
+ ctx = _ctx_for_route(method="GET", path="/items/abc", routes=[route])
32
+
33
+ op_resolve.run(None, ctx)
34
+
35
+ route_ns = ctx.temp["route"]
36
+ assert route_ns["handler"] is handler
37
+ assert route_ns["path_params"] == {"item_id": "abc"}
38
+ assert route_ns.get("method_not_allowed") is None
39
+
40
+
41
+ def test_op_resolve_marks_method_not_allowed_for_runtime_route() -> None:
42
+ route = SimpleNamespace(
43
+ pattern=re.compile(r"^/items/(?P<item_id>[^/]+)$"),
44
+ methods={"GET"},
45
+ handler=lambda: {"ok": True},
46
+ )
47
+ ctx = _ctx_for_route(method="POST", path="/items/abc", routes=[route])
48
+
49
+ op_resolve.run(None, ctx)
50
+
51
+ route_ns = ctx.temp["route"]
52
+ assert route_ns.get("handler") is None
53
+ assert route_ns["method_not_allowed"] is True
54
+
55
+
56
+ def test_op_resolve_finds_opmeta_index_from_proto_and_selector() -> None:
57
+ ctx = SimpleNamespace(
58
+ temp={"route": {}},
59
+ proto="http.jsonrpc",
60
+ selector="Widget.create",
61
+ kernel_plan=SimpleNamespace(
62
+ opmeta=[SimpleNamespace(alias="create", model=object, target="create")],
63
+ opkey_to_meta={},
64
+ ),
65
+ )
66
+
67
+ # SimpleNamespace is unhashable; use tiny hashable opkey object.
68
+ class _OpKey:
69
+ def __init__(self, proto: str, selector: str) -> None:
70
+ self.proto = proto
71
+ self.selector = selector
72
+
73
+ def __hash__(self) -> int:
74
+ return hash((self.proto, self.selector))
75
+
76
+ def __eq__(self, other: object) -> bool:
77
+ return (
78
+ isinstance(other, _OpKey)
79
+ and other.proto == self.proto
80
+ and other.selector == self.selector
81
+ )
82
+
83
+ ctx.kernel_plan.opkey_to_meta = {_OpKey("http.jsonrpc", "Widget.create"): 0}
84
+
85
+ op_resolve.run(None, ctx)
86
+
87
+ assert ctx.temp["route"]["opmeta_index"] == 0
88
+
89
+
90
+ @pytest.mark.asyncio
91
+ async def test_jsonrpc_batch_intercept_short_circuits_response() -> None:
92
+ class _App:
93
+ jsonrpc_prefix = "/rpc"
94
+
95
+ async def rpc_call(self, model: str, op: str, params: dict, **_: object):
96
+ return {"model": model, "op": op, "params": params}
97
+
98
+ payload = [
99
+ {"jsonrpc": "2.0", "method": "Widget.create", "params": {"name": "x"}, "id": 1}
100
+ ]
101
+ ctx = SimpleNamespace(
102
+ payload=payload,
103
+ app=_App(),
104
+ raw=SimpleNamespace(scope={"path": "/rpc"}),
105
+ temp={"route": {}},
106
+ )
107
+
108
+ await jsonrpc_batch_intercept.run(None, ctx)
109
+
110
+ route = ctx.temp["route"]
111
+ response = ctx.temp["egress"]["transport_response"]
112
+ assert route["short_circuit"] is True
113
+ assert response["status_code"] == 200
114
+ assert response["body"][0]["result"]["op"] == "create"
@@ -0,0 +1,170 @@
1
+ import uuid
2
+ from itertools import product
3
+
4
+ import httpx
5
+ import pytest
6
+
7
+ from tigrbl import TigrblApp, TigrblRouter, op_ctx
8
+ from tigrbl.orm.mixins import GUIDPk
9
+ from tigrbl.orm.tables import TableBase
10
+ from tigrbl.shortcuts.engine import mem
11
+ from tigrbl.types import BaseModel, Column, String
12
+
13
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
14
+
15
+
16
+ class TokenInventorySchema(BaseModel):
17
+ access_tokens: int
18
+ refresh_tokens: int
19
+
20
+
21
+ PERSIST_VARIANTS = (
22
+ "default",
23
+ "write",
24
+ "append",
25
+ "prepend",
26
+ "override",
27
+ "skip",
28
+ "none",
29
+ "read",
30
+ )
31
+ ARITY_VARIANTS = ("collection", "member")
32
+ RESPONSE_SCHEMA_VARIANTS = (None, TokenInventorySchema)
33
+ SCOPE_VARIANTS = ("table", "router", "app")
34
+
35
+
36
+ def _op_payload() -> dict[str, int]:
37
+ return {"access_tokens": 3, "refresh_tokens": 1}
38
+
39
+
40
+ def _member_path(resource: str, alias: str) -> str:
41
+ return f"/{resource}/{uuid.uuid4()}/{alias}"
42
+
43
+
44
+ def _collection_path(resource: str, alias: str) -> str:
45
+ return f"/{resource}/{alias}"
46
+
47
+
48
+ def _build_table_app(
49
+ arity: str, response_schema, persist: str
50
+ ) -> tuple[TigrblApp, str]:
51
+ TableBase.metadata.clear()
52
+ schema_tag = "with_schema" if response_schema is not None else "no_schema"
53
+
54
+ class InventoryTable(TableBase, GUIDPk):
55
+ __tablename__ = f"inventory_table_op_ctx_uvicorn_{arity}_{persist}_{schema_tag}"
56
+ __resource__ = "inventory"
57
+ name = Column(String)
58
+
59
+ @op_ctx(
60
+ alias="token_inventory",
61
+ target="custom",
62
+ arity=arity,
63
+ response_schema=response_schema,
64
+ persist=persist,
65
+ )
66
+ def token_inventory(cls, ctx):
67
+ return _op_payload()
68
+
69
+ app = TigrblApp(engine=mem(async_=False))
70
+ app.include_table(InventoryTable, prefix="")
71
+ path = (
72
+ _collection_path("inventory", "token_inventory")
73
+ if arity == "collection"
74
+ else _member_path("inventory", "token_inventory")
75
+ )
76
+ return app, path
77
+
78
+
79
+ async def _build_router_app(
80
+ arity: str, response_schema, persist: str
81
+ ) -> tuple[TigrblApp, str]:
82
+ TableBase.metadata.clear()
83
+ schema_tag = "with_schema" if response_schema is not None else "no_schema"
84
+
85
+ class InventoryTable(TableBase, GUIDPk):
86
+ __tablename__ = (
87
+ f"inventory_router_op_ctx_uvicorn_{arity}_{persist}_{schema_tag}"
88
+ )
89
+ __resource__ = "inventory"
90
+ name = Column(String)
91
+
92
+ @op_ctx(
93
+ alias="token_inventory",
94
+ target="custom",
95
+ arity=arity,
96
+ response_schema=response_schema,
97
+ persist=persist,
98
+ )
99
+ def token_inventory(cls, ctx):
100
+ return _op_payload()
101
+
102
+ router = TigrblRouter(engine=mem(async_=False))
103
+ router.include_table(InventoryTable, prefix="")
104
+ await router.initialize()
105
+
106
+ app = TigrblApp(engine=mem(async_=False))
107
+ app.include_router(router)
108
+ path = (
109
+ _collection_path("inventory", "token_inventory")
110
+ if arity == "collection"
111
+ else _member_path("inventory", "token_inventory")
112
+ )
113
+ return app, path
114
+
115
+
116
+ def _build_app_local_op(
117
+ arity: str, response_schema, persist: str
118
+ ) -> tuple[TigrblApp, str]:
119
+ TableBase.metadata.clear()
120
+
121
+ class InventoryApp(TigrblApp):
122
+ @op_ctx(
123
+ alias="token_inventory",
124
+ target="custom",
125
+ arity=arity,
126
+ response_schema=response_schema,
127
+ persist=persist,
128
+ )
129
+ def token_inventory(cls, ctx):
130
+ return _op_payload()
131
+
132
+ app = InventoryApp(engine=mem(async_=False))
133
+ path = (
134
+ _collection_path("inventoryapp", "token_inventory")
135
+ if arity == "collection"
136
+ else _member_path("inventoryapp", "token_inventory")
137
+ )
138
+ return app, path
139
+
140
+
141
+ @pytest.mark.i9n
142
+ @pytest.mark.asyncio
143
+ @pytest.mark.parametrize(
144
+ "scope,arity,response_schema,persist",
145
+ list(
146
+ product(
147
+ SCOPE_VARIANTS, ARITY_VARIANTS, RESPONSE_SCHEMA_VARIANTS, PERSIST_VARIANTS
148
+ )
149
+ ),
150
+ ids=lambda v: getattr(v, "__name__", str(v)),
151
+ )
152
+ async def test_uvicorn_client_call_with_op_ctx_parameter_combinations(
153
+ scope: str, arity: str, response_schema, persist: str
154
+ ) -> None:
155
+ if scope == "table":
156
+ app, path = _build_table_app(arity, response_schema, persist)
157
+ elif scope == "router":
158
+ app, path = await _build_router_app(arity, response_schema, persist)
159
+ else:
160
+ app, path = _build_app_local_op(arity, response_schema, persist)
161
+
162
+ base_url, server, task = await run_uvicorn_in_task(app)
163
+ try:
164
+ async with httpx.AsyncClient() as client:
165
+ response = await client.post(f"{base_url}{path}", json={})
166
+
167
+ assert response.status_code == 200
168
+ assert response.json() == _op_payload()
169
+ finally:
170
+ await stop_uvicorn_server(server, task)
@@ -0,0 +1,150 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import json
5
+ import ssl
6
+ from typing import Any
7
+
8
+ import httpx
9
+ import pytest
10
+ from tigrbl import Request
11
+ from tigrbl import TigrblApp
12
+ from tigrbl import TigrblRouter
13
+ from tigrbl_tests.examples._support import pick_unique_port, start_uvicorn, stop_uvicorn
14
+
15
+
16
+ async def _probe_http3_over_quic(host: str, port: int) -> dict[str, Any]:
17
+ try:
18
+ from aioquic.asyncio.client import connect
19
+ from aioquic.quic.configuration import QuicConfiguration
20
+ except Exception:
21
+ return {
22
+ "supported": False,
23
+ "status": 0,
24
+ "error": "aioquic-not-installed",
25
+ }
26
+
27
+ configuration = QuicConfiguration(
28
+ is_client=True,
29
+ alpn_protocols=["h3"],
30
+ verify_mode=ssl.CERT_NONE,
31
+ )
32
+
33
+ try:
34
+ async with asyncio.timeout(2.0):
35
+ async with connect(
36
+ host,
37
+ port,
38
+ configuration=configuration,
39
+ wait_connected=True,
40
+ ):
41
+ return {"supported": True, "status": 200, "error": None}
42
+ except Exception as exc:
43
+ return {
44
+ "supported": False,
45
+ "status": 0,
46
+ "error": type(exc).__name__,
47
+ }
48
+
49
+
50
+ @pytest.mark.asyncio
51
+ async def test_tigrblapp_uvicorn_h1_h2_h3_behavior() -> None:
52
+ app = TigrblApp()
53
+
54
+ router = TigrblRouter()
55
+
56
+ @router.get("/echo")
57
+ async def echo(request: Request) -> dict[str, Any]:
58
+ return {
59
+ "method": request.method,
60
+ "x_test": request.headers.get("x-test"),
61
+ "http_version": request.scope.get("http_version"),
62
+ }
63
+
64
+ @router.post("/jsonrpc")
65
+ async def jsonrpc(request: Request) -> dict[str, Any]:
66
+ payload = json.loads(request.body.decode("utf-8") or "{}")
67
+ return {
68
+ "jsonrpc": "2.0",
69
+ "id": payload.get("id"),
70
+ "result": payload.get("params"),
71
+ }
72
+
73
+ app.include_router(router)
74
+ app.attach_diagnostics(prefix="")
75
+
76
+ port = pick_unique_port()
77
+ base_url, server, task = await start_uvicorn(app, port=port)
78
+
79
+ try:
80
+ async with httpx.AsyncClient(base_url=base_url, timeout=5.0) as client:
81
+ h1 = await client.get("/echo", headers={"x-test": "h1"})
82
+
83
+ h2: httpx.Response | None = None
84
+ h2_error: str | None = None
85
+ try:
86
+ async with httpx.AsyncClient(
87
+ base_url=base_url,
88
+ timeout=5.0,
89
+ http2=True,
90
+ ) as client:
91
+ h2 = await client.get("/echo", headers={"x-test": "h2"})
92
+ except ImportError as exc:
93
+ h2_error = type(exc).__name__
94
+
95
+ async with httpx.AsyncClient(base_url=base_url, timeout=5.0) as client:
96
+ rpc = await client.post(
97
+ "/jsonrpc",
98
+ json={
99
+ "jsonrpc": "2.0",
100
+ "method": "echo",
101
+ "params": {"msg": "hi"},
102
+ "id": 1,
103
+ },
104
+ )
105
+
106
+ h3 = await _probe_http3_over_quic("127.0.0.1", port)
107
+
108
+ out = {
109
+ "http1": {
110
+ "status": h1.status_code,
111
+ "http_version": h1.http_version,
112
+ "body": h1.json(),
113
+ },
114
+ "http2": {
115
+ "status": h2.status_code if h2 else 0,
116
+ "http_version": h2.http_version if h2 else None,
117
+ "body": h2.json() if h2 else None,
118
+ "error": h2_error,
119
+ },
120
+ "jsonrpc": {
121
+ "status": rpc.status_code,
122
+ "http_version": rpc.http_version,
123
+ "body": rpc.json(),
124
+ },
125
+ "http3": h3,
126
+ }
127
+
128
+ assert out["http1"]["status"] == 200
129
+ assert out["http1"]["http_version"] == "HTTP/1.1"
130
+ assert out["http1"]["body"]["x_test"] == "h1"
131
+
132
+ if h2 is not None:
133
+ assert out["http2"]["status"] == 200
134
+ assert out["http2"]["http_version"] == "HTTP/1.1"
135
+ assert out["http2"]["body"]["x_test"] == "h2"
136
+ assert out["http2"]["error"] is None
137
+ else:
138
+ assert out["http2"]["status"] == 0
139
+ assert out["http2"]["error"] == "ImportError"
140
+
141
+ assert out["jsonrpc"]["status"] == 200
142
+ assert out["jsonrpc"]["body"] == {
143
+ "jsonrpc": "2.0",
144
+ "id": 1,
145
+ "result": {"msg": "hi"},
146
+ }
147
+
148
+ assert out["http3"]["supported"] is False
149
+ finally:
150
+ await stop_uvicorn(server, task)
@@ -0,0 +1,27 @@
1
+ from types import SimpleNamespace
2
+
3
+ from tigrbl.runtime.atoms.route import payload_select
4
+
5
+
6
+ def test_payload_select_invalid_jsonrpc_string_params_returns_invalid_rpc_error():
7
+ ctx = SimpleNamespace(
8
+ temp={
9
+ "route": {
10
+ "rpc_envelope": {
11
+ "jsonrpc": "2.0",
12
+ "method": "Widget.create",
13
+ "params": "not-a-mapping",
14
+ "id": 1,
15
+ },
16
+ "params": {},
17
+ },
18
+ }
19
+ )
20
+
21
+ payload_select.run(None, ctx)
22
+
23
+ assert isinstance(ctx.temp["route"].get("payload"), dict)
24
+ assert ctx.payload == {}
25
+ assert ctx.temp.get("rpc_error", {}).get("code") == -32602
26
+ assert ctx.temp["rpc_error"]["message"] == "Invalid params"
27
+ assert ctx.temp["rpc_error"]["data"]["value_type"] == "str"
@@ -0,0 +1,51 @@
1
+ from sqlalchemy import text
2
+
3
+ from tigrbl import TableBase, TigrblApp, resolver
4
+ from tigrbl.orm.mixins import GUIDPk
5
+ from tigrbl.shortcuts.engine import engine, mem
6
+ from tigrbl.types import Column, String
7
+
8
+
9
+ class AvailabilityRecord(TableBase, GUIDPk):
10
+ __tablename__ = "availability_records"
11
+ name = Column(String(100), nullable=False)
12
+
13
+
14
+ def test_engine_availability_via_shortcut():
15
+ eng = engine(mem(async_=False))
16
+ sql_engine, session_factory = eng.raw()
17
+
18
+ assert sql_engine is not None
19
+ assert callable(session_factory)
20
+
21
+
22
+ def test_session_availability_via_engine_context_manager():
23
+ eng = engine(mem(async_=False))
24
+
25
+ with eng.session() as db:
26
+ assert db.execute(text("SELECT 1")).scalar_one() == 1
27
+
28
+
29
+ def test_database_availability_after_app_initialize():
30
+ app = TigrblApp(engine=mem(async_=False))
31
+ app.include_table(AvailabilityRecord)
32
+ app.initialize()
33
+
34
+ provider = resolver.resolve_provider(router=app)
35
+ assert provider is not None
36
+
37
+ _, session_factory = provider.ensure()
38
+
39
+ with session_factory() as db:
40
+ assert db.execute(text("SELECT 1")).scalar_one() == 1
41
+ db.execute(
42
+ text(
43
+ "CREATE TABLE IF NOT EXISTS availability_probe "
44
+ "(id INTEGER PRIMARY KEY, note TEXT)"
45
+ )
46
+ )
47
+ db.commit()
48
+ names = db.execute(
49
+ text("SELECT name FROM sqlite_master WHERE type='table'")
50
+ ).scalars()
51
+ assert "availability_probe" in set(names)
@@ -125,6 +125,54 @@ def test_mount_lens_uses_latest_openrpc_path_by_default() -> None:
125
125
  assert "/schema/openrpc.json" in html
126
126
 
127
127
 
128
+ def test_default_system_docs_endpoints_are_present_and_gettable() -> None:
129
+ app, _ = _build_app()
130
+ transport = ASGITransport(app=app)
131
+
132
+ with Client(transport=transport, base_url="http://test") as client:
133
+ docs = client.get("/docs")
134
+ lens = client.get("/lens")
135
+ openapi = client.get("/openapi.json")
136
+ openrpc = client.get("/openrpc.json")
137
+
138
+ assert docs.status_code == 200
139
+ assert "text/html" in docs.headers.get("content-type", "")
140
+ assert "swagger-ui" in docs.text
141
+
142
+ assert lens.status_code == 200
143
+ assert "text/html" in lens.headers.get("content-type", "")
144
+ assert 'id="root"' in lens.text
145
+
146
+ assert openapi.status_code == 200
147
+ assert openapi.json()["openapi"] == "3.1.0"
148
+
149
+ assert openrpc.status_code == 200
150
+ assert openrpc.json()["openrpc"] == "1.2.6"
151
+
152
+
153
+ def test_docs_lens_openapi_openrpc_are_rest_get_only_and_not_rpc_methods() -> None:
154
+ app, _ = _build_app()
155
+ transport = ASGITransport(app=app)
156
+
157
+ route_map = {route.path: route for route in app.routes}
158
+ for path in ("/docs", "/lens", "/openapi.json", "/openrpc.json"):
159
+ assert path in route_map
160
+ assert set(route_map[path].methods or []) == {"GET"}
161
+
162
+ with Client(transport=transport, base_url="http://test") as client:
163
+ assert client.post("/docs").status_code == 405
164
+ assert client.post("/lens").status_code == 405
165
+ assert client.post("/openapi.json").status_code == 405
166
+ assert client.post("/openrpc.json").status_code == 405
167
+
168
+ method_names = {
169
+ method["name"] for method in client.get("/openrpc.json").json()["methods"]
170
+ }
171
+
172
+ for forbidden in ("docs", "lens", "openapi", "openrpc"):
173
+ assert all(forbidden not in name.lower() for name in method_names)
174
+
175
+
128
176
  def test_openrpc_server_url_respects_router_mount_jsonrpc_prefix_argument():
129
177
  class Widget(TableBase, GUIDPk):
130
178
  __tablename__ = "widgets_openrpc_router_mount_prefix"
@@ -0,0 +1,79 @@
1
+ from itertools import product
2
+ from types import SimpleNamespace
3
+
4
+ import pytest
5
+
6
+ from tigrbl import op_ctx
7
+ from tigrbl.mapping import handlers
8
+ from tigrbl.mapping.op_mro_collect import mro_collect_decorated_ops
9
+ from tigrbl.types import BaseModel
10
+
11
+
12
+ class TokenInventorySchema(BaseModel):
13
+ access_tokens: int
14
+ refresh_tokens: int
15
+
16
+
17
+ PERSIST_VARIANTS = (
18
+ "default",
19
+ "write",
20
+ "append",
21
+ "prepend",
22
+ "override",
23
+ "skip",
24
+ "none",
25
+ "read",
26
+ )
27
+ ARITY_VARIANTS = ("collection", "member")
28
+ RESPONSE_SCHEMA_VARIANTS = (None, TokenInventorySchema)
29
+
30
+
31
+ def _normalize_persist(persist: str) -> str:
32
+ if persist in {"none", "read", "skip"}:
33
+ return "skip"
34
+ if persist in {"write", "default", "persist"}:
35
+ return "default"
36
+ return persist
37
+
38
+
39
+ def _build_custom_model(arity: str, response_schema, persist: str):
40
+ class Model:
41
+ __name__ = "Model"
42
+
43
+ @op_ctx(
44
+ alias="token_inventory",
45
+ target="custom",
46
+ arity=arity,
47
+ response_schema=response_schema,
48
+ persist=persist,
49
+ )
50
+ def token_inventory(
51
+ cls, ctx
52
+ ): # pragma: no cover - runtime execution not needed
53
+ return TokenInventorySchema(access_tokens=1, refresh_tokens=2)
54
+
55
+ specs = mro_collect_decorated_ops(Model)
56
+ Model.opspecs = SimpleNamespace(all=tuple(specs))
57
+ handlers.build_and_attach(Model, specs)
58
+ return Model, specs[0]
59
+
60
+
61
+ @pytest.mark.parametrize(
62
+ "arity,response_schema,persist",
63
+ list(product(ARITY_VARIANTS, RESPONSE_SCHEMA_VARIANTS, PERSIST_VARIANTS)),
64
+ ids=lambda v: getattr(v, "__name__", str(v)),
65
+ )
66
+ def test_op_ctx_custom_target_parameter_cross_product(
67
+ arity: str, response_schema, persist: str
68
+ ) -> None:
69
+ model, spec = _build_custom_model(arity, response_schema, persist)
70
+
71
+ assert spec.alias == "token_inventory"
72
+ assert spec.target == "custom"
73
+ assert spec.arity == arity
74
+ assert spec.response_model is response_schema
75
+ assert spec.persist == _normalize_persist(persist)
76
+
77
+ # For custom targets, persist controls transaction behavior elsewhere, not handler order.
78
+ handler_names = [fn.__name__ for fn in model.hooks.token_inventory.HANDLER]
79
+ assert handler_names == ["token_inventory"]