tigrbl-tests 0.3.2.dev1__tar.gz → 0.3.3.dev1__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 (214) hide show
  1. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/PKG-INFO +16 -1
  2. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/README.md +14 -0
  3. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/pyproject.toml +3 -1
  4. tigrbl_tests-0.3.3.dev1/tests/i9n/test_tigrbl_api_app_usage_uvicorn.py +98 -0
  5. tigrbl_tests-0.3.3.dev1/tests/i9n/test_tigrbl_api_usage_uvicorn.py +105 -0
  6. tigrbl_tests-0.3.3.dev1/tests/i9n/test_tigrbl_api_uvicorn.py +67 -0
  7. tigrbl_tests-0.3.3.dev1/tests/i9n/test_tigrbl_app_include_api_uvicorn.py +149 -0
  8. tigrbl_tests-0.3.3.dev1/tests/i9n/test_tigrbl_app_multi_api_uvicorn.py +80 -0
  9. tigrbl_tests-0.3.3.dev1/tests/i9n/test_tigrbl_app_usage_uvicorn.py +103 -0
  10. tigrbl_tests-0.3.3.dev1/tests/i9n/test_tigrbl_app_uvicorn.py +58 -0
  11. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_spec_app.py +1 -1
  12. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_table_collect_spec.py +1 -1
  13. tigrbl_tests-0.3.3.dev1/tests/unit/test_table_namespace_init.py +27 -0
  14. tigrbl_tests-0.3.3.dev1/tests/unit/test_table_namespace_isolation.py +43 -0
  15. tigrbl_tests-0.3.3.dev1/tests/unit/test_tigrbl_api_app_configuration.py +83 -0
  16. tigrbl_tests-0.3.3.dev1/tests/unit/test_tigrbl_api_app_instantiation.py +42 -0
  17. tigrbl_tests-0.3.3.dev1/tests/unit/test_tigrbl_api_app_subclass_definition.py +38 -0
  18. tigrbl_tests-0.3.3.dev1/tests/unit/test_tigrbl_api_configuration.py +47 -0
  19. tigrbl_tests-0.3.3.dev1/tests/unit/test_tigrbl_api_instantiation.py +37 -0
  20. tigrbl_tests-0.3.3.dev1/tests/unit/test_tigrbl_api_subclass_definition.py +37 -0
  21. tigrbl_tests-0.3.3.dev1/tests/unit/test_tigrbl_app_configuration.py +47 -0
  22. tigrbl_tests-0.3.3.dev1/tests/unit/test_tigrbl_app_instantiation.py +37 -0
  23. tigrbl_tests-0.3.3.dev1/tests/unit/test_tigrbl_app_subclass_definition.py +37 -0
  24. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/LICENSE +0 -0
  25. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/__init__.py +0 -0
  26. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/conftest.py +0 -0
  27. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/__init__.py +0 -0
  28. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_acronym_route_name.py +0 -0
  29. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_allow_anon.py +0 -0
  30. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_apikey_generation.py +0 -0
  31. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_authn_provider_integration.py +0 -0
  32. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_bindings_integration.py +0 -0
  33. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_bindings_modules.py +0 -0
  34. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_bulk_docs_client.py +0 -0
  35. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_core_access.py +0 -0
  36. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_error_mappings.py +0 -0
  37. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_field_spec_effects.py +0 -0
  38. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_header_io_uvicorn.py +0 -0
  39. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_healthz_methodz_hookz.py +0 -0
  40. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_hook_ctx_v3_i9n.py +0 -0
  41. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_hook_lifecycle.py +0 -0
  42. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_iospec_attributes.py +0 -0
  43. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_iospec_integration.py +0 -0
  44. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_key_digest_uvicorn.py +0 -0
  45. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_list_filters_optional.py +0 -0
  46. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_mixins.py +0 -0
  47. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_nested_path_schema_and_rpc.py +0 -0
  48. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_nested_routing_depth.py +0 -0
  49. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_op_ctx_alias_examples.py +0 -0
  50. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_op_ctx_behavior.py +0 -0
  51. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_op_ctx_core_crud_order.py +0 -0
  52. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_openapi_clear_response_schema.py +0 -0
  53. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_openapi_schema_examples_presence.py +0 -0
  54. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_opspec_effects_i9n_test.py +0 -0
  55. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_owner_tenant_policy.py +0 -0
  56. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_request_extras.py +0 -0
  57. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_request_extras_provider.py +0 -0
  58. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_response_extras_provider.py +0 -0
  59. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_rest_fallback_serialization.py +0 -0
  60. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_rest_row_serialization.py +0 -0
  61. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_rest_rpc_parity_v3.py +0 -0
  62. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_row_result_serialization.py +0 -0
  63. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_schema.py +0 -0
  64. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_schema_ctx_attributes_integration.py +0 -0
  65. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_schema_ctx_op_ctx_integration.py +0 -0
  66. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_schema_ctx_spec_integration.py +0 -0
  67. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_sqlite_attachments.py +0 -0
  68. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_storage_spec_integration.py +0 -0
  69. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_symmetry_parity.py +0 -0
  70. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_v3_bulk_rest_endpoints.py +0 -0
  71. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_v3_default_rest_ops.py +0 -0
  72. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_v3_default_rpc_ops.py +0 -0
  73. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_v3_opspec_attributes.py +0 -0
  74. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/test_verb_alias_policy.py +0 -0
  75. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/i9n/uvicorn_utils.py +0 -0
  76. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/perf/__init__.py +0 -0
  77. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/perf/test_collect_caching.py +0 -0
  78. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/perf/test_hookz_performance.py +0 -0
  79. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/perf/test_methodz_performance.py +0 -0
  80. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/__init__.py +0 -0
  81. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/decorators/test_alias_ctx_bindings.py +0 -0
  82. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/decorators/test_engine_ctx_bindings.py +0 -0
  83. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/decorators/test_hook_ctx_bindings.py +0 -0
  84. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/decorators/test_op_alias_bindings.py +0 -0
  85. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/decorators/test_op_ctx_bindings.py +0 -0
  86. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/decorators/test_response_ctx_bindings.py +0 -0
  87. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/decorators/test_schema_ctx_bindings.py +0 -0
  88. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/response_utils.py +0 -0
  89. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_emit_paired_post.py +0 -0
  90. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_emit_paired_pre.py +0 -0
  91. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_emit_readtime_alias.py +0 -0
  92. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_out_masking.py +0 -0
  93. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_refresh_demand.py +0 -0
  94. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_resolve_assemble.py +0 -0
  95. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_resolve_paired_gen.py +0 -0
  96. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_schema_collect_in.py +0 -0
  97. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_schema_collect_out.py +0 -0
  98. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_storage_to_stored.py +0 -0
  99. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_wire_build_in.py +0 -0
  100. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_wire_build_out.py +0 -0
  101. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_wire_dump.py +0 -0
  102. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/atoms/test_wire_validate_in.py +0 -0
  103. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/runtime/test_events_phases.py +0 -0
  104. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_acol_vcol_knobs.py +0 -0
  105. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_alias_ctx_op_alias_attributes.py +0 -0
  106. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_alias_ctx_op_attributes.py +0 -0
  107. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_api_level_set_auth.py +0 -0
  108. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_app_model_defaults.py +0 -0
  109. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_app_reexport.py +0 -0
  110. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_base_columnspec_inheritance.py +0 -0
  111. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_base_facade_initialize.py +0 -0
  112. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_build_list_params_spec_model.py +0 -0
  113. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_bulk_body_annotation.py +0 -0
  114. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_bulk_response_schema.py +0 -0
  115. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_colspec_map_isolation.py +0 -0
  116. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_column_collect_mixins.py +0 -0
  117. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_column_rest_rpc_results.py +0 -0
  118. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_column_table_orm_binding.py +0 -0
  119. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_config_dataclass_none.py +0 -0
  120. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_core_crud_bulk_ops.py +0 -0
  121. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_core_crud_default_ops.py +0 -0
  122. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_core_crud_methods.py +0 -0
  123. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_core_wrap_memoization.py +0 -0
  124. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_db_dependency.py +0 -0
  125. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_decorator_and_collect.py +0 -0
  126. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_default_tags.py +0 -0
  127. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_engine_spec_and_shortcuts.py +0 -0
  128. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_engine_usage_levels.py +0 -0
  129. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_field_spec_attrs.py +0 -0
  130. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_file_response.py +0 -0
  131. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_handler_step_qualname.py +0 -0
  132. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_hook_ctx_attributes.py +0 -0
  133. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_hook_ctx_binding.py +0 -0
  134. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_hookz_empty_phase.py +0 -0
  135. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_hybrid_session_run_sync.py +0 -0
  136. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_in_tx.py +0 -0
  137. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_include_model_columns_namespace.py +0 -0
  138. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_include_models_base_prefix.py +0 -0
  139. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_initialize_cross_ddl.py +0 -0
  140. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_io_spec_attributes.py +0 -0
  141. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_iospec_attributes.py +0 -0
  142. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_iospec_effects.py +0 -0
  143. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_jsonrpc_id_example.py +0 -0
  144. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_jsonrpc_router_default_tag.py +0 -0
  145. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_kernel_invoke_ctx.py +0 -0
  146. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_kernel_opview_on_demand.py +0 -0
  147. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_kernel_plan_labels.py +0 -0
  148. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_kernelz_endpoint.py +0 -0
  149. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_make_column_shortcuts.py +0 -0
  150. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_mixins_sqlalchemy.py +0 -0
  151. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_op_alias.py +0 -0
  152. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_op_class_engine_binding.py +0 -0
  153. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_op_ctx_arity_paths.py +0 -0
  154. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_op_ctx_attributes.py +0 -0
  155. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_op_ctx_core_crud_integration.py +0 -0
  156. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_op_ctx_dynamic_attach.py +0 -0
  157. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_op_ctx_persist_options.py +0 -0
  158. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_opspec_effects.py +0 -0
  159. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_postgres_engine_errors.py +0 -0
  160. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_postgres_env_vars.py +0 -0
  161. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_relationship_alias_cols.py +0 -0
  162. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_request_body_schema.py +0 -0
  163. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_request_response_examples.py +0 -0
  164. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_resolver_precedence.py +0 -0
  165. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_response_alias_table_rpc.py +0 -0
  166. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_response_ctx_precedence.py +0 -0
  167. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_response_diagnostics_kernelz.py +0 -0
  168. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_response_html_jinja_behavior.py +0 -0
  169. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_response_parity.py +0 -0
  170. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_response_rest.py +0 -0
  171. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_response_rpc.py +0 -0
  172. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_response_template.py +0 -0
  173. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_response_uuid.py +0 -0
  174. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_rest_all_default_op_verbs.py +0 -0
  175. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_rest_bulk_delete_suppresses_clear.py +0 -0
  176. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_rest_no_schema_jsonable.py +0 -0
  177. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_rest_operation_id_uniqueness.py +0 -0
  178. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_rest_rpc_parity_default_ops.py +0 -0
  179. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_rest_rpc_prefixes.py +0 -0
  180. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_rest_rpc_symmetry.py +0 -0
  181. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_rpc_all_default_op_verbs.py +0 -0
  182. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_rpc_default_ops.py +0 -0
  183. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_schema_ctx_attributes.py +0 -0
  184. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_schema_ctx_plain_class.py +0 -0
  185. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_schema_spec_presence.py +0 -0
  186. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_schemas_binding.py +0 -0
  187. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_security_per_route.py +0 -0
  188. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_should_wire_canonical.py +0 -0
  189. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_spec_api.py +0 -0
  190. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_spec_column.py +0 -0
  191. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_spec_engine.py +0 -0
  192. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_spec_field.py +0 -0
  193. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_spec_hook.py +0 -0
  194. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_spec_io.py +0 -0
  195. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_spec_op.py +0 -0
  196. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_spec_storage.py +0 -0
  197. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_spec_table.py +0 -0
  198. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_sqlite_attachments.py +0 -0
  199. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_sqlite_uuid_type.py +0 -0
  200. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_storage_spec_attributes.py +0 -0
  201. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_sys_handler_crud.py +0 -0
  202. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_sys_run_rollback.py +0 -0
  203. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_sys_tx_async_begin.py +0 -0
  204. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_sys_tx_begin.py +0 -0
  205. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_sys_tx_commit.py +0 -0
  206. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_table_base_exports.py +0 -0
  207. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_table_columns_namespace.py +0 -0
  208. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_v3_favicon_endpoint.py +0 -0
  209. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_v3_healthz_endpoint.py +0 -0
  210. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_v3_op_alias.py +0 -0
  211. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_v3_op_ctx_attributes.py +0 -0
  212. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_v3_schemas_and_decorators.py +0 -0
  213. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/tests/unit/test_v3_storage_spec_attributes.py +0 -0
  214. {tigrbl_tests-0.3.2.dev1 → tigrbl_tests-0.3.3.dev1}/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.2.dev1
3
+ Version: 0.3.3.dev1
4
4
  Summary: Test suite and fixtures for the Tigrbl framework.
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -30,6 +30,7 @@ Requires-Dist: python-dotenv
30
30
  Requires-Dist: requests (>=2.32.3)
31
31
  Requires-Dist: ruff (>=0.9.9)
32
32
  Requires-Dist: tigrbl
33
+ Requires-Dist: tigrbl_client
33
34
  Description-Content-Type: text/markdown
34
35
 
35
36
  ![Tigrbl Logo](https://github.com/swarmauri/swarmauri-sdk/blob/a170683ecda8ca1c4f912c966d4499649ffb8224/assets/tigrbl.brand.theme.svg)
@@ -100,4 +101,18 @@ Use pytest selectors to focus on specific suites:
100
101
  pytest standards/tigrbl_tests/tests/unit
101
102
  ```
102
103
 
104
+ ## Examples Curriculum 📚
105
+
106
+ The `examples/` directory contains downstream-facing pytest lessons that
107
+ demonstrate how to implement Tigrbl in real applications. These lessons are
108
+ organized as a multi-module curriculum with uvicorn-backed usage examples and
109
+ system diagnostics validation. See the full curriculum plan for the learning
110
+ sequence and module descriptions.[^tigrbl-examples]
111
+ Run the examples from the `pkgs` directory:
112
+
113
+ ```bash
114
+ uv run --package tigrbl-tests --directory standards/tigrbl_tests pytest examples
115
+ ```
116
+
117
+ [^tigrbl-examples]: examples/README.md
103
118
 
@@ -66,3 +66,17 @@ Use pytest selectors to focus on specific suites:
66
66
  pytest standards/tigrbl_tests/tests/unit
67
67
  ```
68
68
 
69
+ ## Examples Curriculum 📚
70
+
71
+ The `examples/` directory contains downstream-facing pytest lessons that
72
+ demonstrate how to implement Tigrbl in real applications. These lessons are
73
+ organized as a multi-module curriculum with uvicorn-backed usage examples and
74
+ system diagnostics validation. See the full curriculum plan for the learning
75
+ sequence and module descriptions.[^tigrbl-examples]
76
+ Run the examples from the `pkgs` directory:
77
+
78
+ ```bash
79
+ uv run --package tigrbl-tests --directory standards/tigrbl_tests pytest examples
80
+ ```
81
+
82
+ [^tigrbl-examples]: examples/README.md
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tigrbl-tests"
3
- version = "0.3.2.dev1"
3
+ version = "0.3.3.dev1"
4
4
  description = "Test suite and fixtures for the Tigrbl framework."
5
5
  license = "Apache-2.0"
6
6
  readme = "README.md"
@@ -20,6 +20,7 @@ classifiers = [
20
20
  authors = [{ name = "Jacob Stewart", email = "jacob@swarmauri.com" }]
21
21
  dependencies = [
22
22
  "tigrbl",
23
+ "tigrbl_client",
23
24
  "psycopg2-binary>=2.9.9",
24
25
  "asyncpg>=0.30.0",
25
26
  "pytest>=8.0",
@@ -46,6 +47,7 @@ keywords = [
46
47
 
47
48
  [tool.uv.sources]
48
49
  tigrbl = { workspace = true }
50
+ tigrbl-client = { workspace = true }
49
51
 
50
52
  [tool.pytest.ini_options]
51
53
  norecursedirs = ["combined", "scripts"]
@@ -0,0 +1,98 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+ from fastapi import Security
5
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
6
+
7
+ from tigrbl import Base, TigrblApi, TigrblApp
8
+ from tigrbl.engine.shortcuts import mem
9
+ from tigrbl.orm.mixins import GUIDPk
10
+ from tigrbl.specs import F, IO, S, acol
11
+ from tigrbl.types import Mapped, String
12
+
13
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
14
+
15
+
16
+ bearer = HTTPBearer()
17
+
18
+
19
+ def auth_dependency(
20
+ credentials: HTTPAuthorizationCredentials = Security(bearer),
21
+ ) -> HTTPAuthorizationCredentials:
22
+ return credentials
23
+
24
+
25
+ class Kappa(Base, GUIDPk):
26
+ __tablename__ = "kappa_api_app_usage"
27
+ __allow_unmapped__ = True
28
+
29
+ name: Mapped[str] = acol(
30
+ storage=S(type_=String, nullable=False),
31
+ field=F(py_type=str),
32
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
33
+ )
34
+
35
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
36
+
37
+
38
+ class KappaApi(TigrblApi):
39
+ MODELS = (Kappa,)
40
+
41
+
42
+ @pytest_asyncio.fixture()
43
+ async def running_api_app():
44
+ api = KappaApi(engine=mem(async_=False))
45
+ api.set_auth(authn=auth_dependency, allow_anon=False)
46
+ api.include_models([Kappa])
47
+ api.initialize()
48
+
49
+ class KappaApp(TigrblApp):
50
+ APIS = (api,)
51
+
52
+ app = KappaApp(engine=mem(async_=False))
53
+ app.include_router(api)
54
+
55
+ base_url, server, task = await run_uvicorn_in_task(app)
56
+ try:
57
+ yield base_url
58
+ finally:
59
+ await stop_uvicorn_server(server, task)
60
+
61
+
62
+ @pytest.mark.i9n
63
+ @pytest.mark.asyncio
64
+ async def test_tigrbl_api_app_deploys_and_serves_openapi(running_api_app) -> None:
65
+ base_url = running_api_app
66
+
67
+ async with httpx.AsyncClient() as client:
68
+ openapi_resp = await client.get(f"{base_url}/openapi.json")
69
+
70
+ assert openapi_resp.status_code == 200
71
+ openapi = openapi_resp.json()
72
+ paths = openapi["paths"]
73
+
74
+ assert "/kappa" in paths
75
+ assert "/kappa/{item_id}" in paths
76
+ assert {"get", "post", "delete"}.issubset(paths["/kappa"])
77
+ assert {"get", "patch", "put", "delete"}.issubset(paths["/kappa/{item_id}"])
78
+
79
+ security_schemes = openapi.get("components", {}).get("securitySchemes", {})
80
+ assert "HTTPBearer" in security_schemes
81
+
82
+
83
+ @pytest.mark.i9n
84
+ @pytest.mark.asyncio
85
+ async def test_tigrbl_api_app_handles_authenticated_request(running_api_app) -> None:
86
+ base_url = running_api_app
87
+ headers = {"Authorization": "Bearer demo"}
88
+
89
+ async with httpx.AsyncClient() as client:
90
+ resp = await client.post(
91
+ f"{base_url}/kappa",
92
+ json={"name": "Kappa"},
93
+ headers=headers,
94
+ )
95
+
96
+ assert resp.status_code == 201
97
+ payload = resp.json()
98
+ assert payload["name"] == "Kappa"
@@ -0,0 +1,105 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+ from fastapi import Security
5
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
6
+
7
+ from tigrbl import Base, TigrblApi
8
+ from tigrbl.engine.shortcuts import mem
9
+ from tigrbl.orm.mixins import GUIDPk
10
+ from tigrbl.specs import F, IO, S, acol
11
+ from tigrbl.types import App, Mapped, String
12
+
13
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
14
+
15
+
16
+ bearer = HTTPBearer()
17
+
18
+
19
+ def auth_dependency(
20
+ credentials: HTTPAuthorizationCredentials = Security(bearer),
21
+ ) -> HTTPAuthorizationCredentials:
22
+ return credentials
23
+
24
+
25
+ class Alpha(Base, GUIDPk):
26
+ __tablename__ = "alpha_api_usage"
27
+ __allow_unmapped__ = True
28
+
29
+ name: Mapped[str] = acol(
30
+ storage=S(type_=String, nullable=False),
31
+ field=F(py_type=str),
32
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
33
+ )
34
+
35
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
36
+
37
+
38
+ class Beta(Base, GUIDPk):
39
+ __tablename__ = "beta_api_usage"
40
+ __allow_unmapped__ = True
41
+
42
+ name: Mapped[str] = acol(
43
+ storage=S(type_=String, nullable=False),
44
+ field=F(py_type=str),
45
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
46
+ )
47
+
48
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
49
+
50
+
51
+ @pytest_asyncio.fixture()
52
+ async def running_api():
53
+ app = App()
54
+ api = TigrblApi(engine=mem(async_=False))
55
+ api.set_auth(authn=auth_dependency, allow_anon=False)
56
+ api.include_models([Alpha, Beta])
57
+ api.initialize()
58
+ app.include_router(api)
59
+
60
+ base_url, server, task = await run_uvicorn_in_task(app)
61
+ try:
62
+ yield base_url
63
+ finally:
64
+ await stop_uvicorn_server(server, task)
65
+
66
+
67
+ @pytest.mark.i9n
68
+ @pytest.mark.asyncio
69
+ async def test_tigrbl_api_deploys_and_serves_openapi(running_api) -> None:
70
+ base_url = running_api
71
+
72
+ async with httpx.AsyncClient() as client:
73
+ openapi_resp = await client.get(f"{base_url}/openapi.json")
74
+
75
+ assert openapi_resp.status_code == 200
76
+ openapi = openapi_resp.json()
77
+ paths = openapi["paths"]
78
+
79
+ assert "/alpha" in paths
80
+ assert "/alpha/{item_id}" in paths
81
+ assert "/beta" in paths
82
+ assert "/beta/{item_id}" in paths
83
+ assert {"get", "post", "delete"}.issubset(paths["/alpha"])
84
+ assert {"get", "patch", "put", "delete"}.issubset(paths["/alpha/{item_id}"])
85
+
86
+ security_schemes = openapi.get("components", {}).get("securitySchemes", {})
87
+ assert "HTTPBearer" in security_schemes
88
+
89
+
90
+ @pytest.mark.i9n
91
+ @pytest.mark.asyncio
92
+ async def test_tigrbl_api_handles_authenticated_request(running_api) -> None:
93
+ base_url = running_api
94
+ headers = {"Authorization": "Bearer demo"}
95
+
96
+ async with httpx.AsyncClient() as client:
97
+ resp = await client.post(
98
+ f"{base_url}/alpha",
99
+ json={"name": "Alpha"},
100
+ headers=headers,
101
+ )
102
+
103
+ assert resp.status_code == 201
104
+ payload = resp.json()
105
+ assert payload["name"] == "Alpha"
@@ -0,0 +1,67 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+
5
+ from tigrbl import Base, TigrblApi
6
+ from tigrbl.engine.shortcuts import mem
7
+ from tigrbl.orm.mixins import GUIDPk
8
+ from tigrbl.specs import F, IO, S, acol
9
+ from tigrbl.types import App, Mapped, String
10
+
11
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
12
+
13
+
14
+ class Gadget(Base, GUIDPk):
15
+ __tablename__ = "gadgets_api"
16
+ __resource__ = "gadget"
17
+
18
+ name: Mapped[str] = acol(
19
+ storage=S(String, nullable=False),
20
+ field=F(py_type=str),
21
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
22
+ )
23
+
24
+
25
+ @pytest_asyncio.fixture()
26
+ async def running_api_app():
27
+ api = TigrblApi(
28
+ engine=mem(async_=False),
29
+ models=[Gadget],
30
+ prefix="/gadgets",
31
+ system_prefix="/diagnostics",
32
+ )
33
+ await api.initialize()
34
+
35
+ app = App()
36
+ app.include_router(api.router)
37
+ api.attach_diagnostics(app=app)
38
+
39
+ base_url, server, task = await run_uvicorn_in_task(app)
40
+ try:
41
+ yield base_url
42
+ finally:
43
+ await stop_uvicorn_server(server, task)
44
+
45
+
46
+ @pytest.mark.i9n
47
+ @pytest.mark.asyncio
48
+ async def test_tigrbl_api_create_gadget(running_api_app):
49
+ async with httpx.AsyncClient() as client:
50
+ response = await client.post(
51
+ f"{running_api_app}/gadgets/gadget", json={"name": "gyro"}
52
+ )
53
+
54
+ assert response.status_code == 201
55
+ payload = response.json()
56
+ assert payload["name"] == "gyro"
57
+ assert "id" in payload
58
+
59
+
60
+ @pytest.mark.i9n
61
+ @pytest.mark.asyncio
62
+ async def test_tigrbl_api_healthz(running_api_app):
63
+ async with httpx.AsyncClient() as client:
64
+ response = await client.get(f"{running_api_app}/diagnostics/healthz")
65
+
66
+ assert response.status_code == 200
67
+ assert response.json()["ok"] is True
@@ -0,0 +1,149 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+
5
+ from tigrbl import Base, TigrblApi, TigrblApp
6
+ from tigrbl.engine.shortcuts import mem
7
+ from tigrbl.orm.mixins import GUIDPk
8
+ from tigrbl.specs import F, IO, S, acol
9
+ from tigrbl.types import Mapped, String
10
+
11
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
12
+
13
+
14
+ class AlphaWidget(Base, GUIDPk):
15
+ __tablename__ = "alpha_widgets_alt"
16
+ __resource__ = "alpha-widget"
17
+
18
+ name: Mapped[str] = acol(
19
+ storage=S(String, nullable=False),
20
+ field=F(py_type=str),
21
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
22
+ )
23
+
24
+
25
+ class BetaWidget(Base, GUIDPk):
26
+ __tablename__ = "beta_widgets_alt"
27
+ __resource__ = "beta-widget"
28
+
29
+ name: Mapped[str] = acol(
30
+ storage=S(String, nullable=False),
31
+ field=F(py_type=str),
32
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
33
+ )
34
+
35
+
36
+ class ZetaWidget(Base, GUIDPk):
37
+ __tablename__ = "zeta_widgets_alt"
38
+ __resource__ = "zeta-widget"
39
+
40
+ name: Mapped[str] = acol(
41
+ storage=S(String, nullable=False),
42
+ field=F(py_type=str),
43
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
44
+ )
45
+
46
+
47
+ @pytest_asyncio.fixture()
48
+ async def running_app_with_apis():
49
+ engine = mem(async_=False)
50
+ alpha_api = TigrblApi(engine=engine, models=[AlphaWidget], prefix="/alpha")
51
+ beta_api = TigrblApi(engine=engine)
52
+ beta_api.include_model(BetaWidget)
53
+ zeta_api = TigrblApi(engine=engine)
54
+ zeta_api.include_model(ZetaWidget)
55
+
56
+ app = TigrblApp(engine=engine, apis=[alpha_api, (zeta_api, "/zeta")])
57
+ app.include_api(beta_api, prefix="/beta")
58
+ await app.initialize()
59
+
60
+ base_url, server, task = await run_uvicorn_in_task(app)
61
+ try:
62
+ yield base_url
63
+ finally:
64
+ await stop_uvicorn_server(server, task)
65
+
66
+
67
+ @pytest_asyncio.fixture()
68
+ async def running_app_with_api_router():
69
+ engine = mem(async_=False)
70
+ alpha_api = TigrblApi(engine=engine)
71
+ alpha_api.include_model(AlphaWidget)
72
+ beta_api = TigrblApi(engine=engine)
73
+ beta_api.include_model(BetaWidget)
74
+
75
+ app = TigrblApp(engine=engine, apis=[alpha_api])
76
+ app.include_api(beta_api, prefix="/beta")
77
+ app.include_api(alpha_api.router, prefix="/alpha")
78
+ await app.initialize()
79
+
80
+ base_url, server, task = await run_uvicorn_in_task(app)
81
+ try:
82
+ yield base_url
83
+ finally:
84
+ await stop_uvicorn_server(server, task)
85
+
86
+
87
+ @pytest.mark.i9n
88
+ @pytest.mark.asyncio
89
+ async def test_tigrbl_app_api_list_alpha(running_app_with_apis):
90
+ async with httpx.AsyncClient() as client:
91
+ response = await client.post(
92
+ f"{running_app_with_apis}/alpha/alpha-widget", json={"name": "ace"}
93
+ )
94
+
95
+ assert response.status_code == 201
96
+ payload = response.json()
97
+ assert payload["name"] == "ace"
98
+
99
+
100
+ @pytest.mark.i9n
101
+ @pytest.mark.asyncio
102
+ async def test_tigrbl_app_include_api_beta(running_app_with_apis):
103
+ async with httpx.AsyncClient() as client:
104
+ response = await client.post(
105
+ f"{running_app_with_apis}/beta/beta-widget", json={"name": "bolt"}
106
+ )
107
+
108
+ assert response.status_code == 201
109
+ payload = response.json()
110
+ assert payload["name"] == "bolt"
111
+
112
+
113
+ @pytest.mark.i9n
114
+ @pytest.mark.asyncio
115
+ async def test_tigrbl_app_api_list_zeta(running_app_with_apis):
116
+ async with httpx.AsyncClient() as client:
117
+ response = await client.post(
118
+ f"{running_app_with_apis}/zeta/zeta-widget", json={"name": "zen"}
119
+ )
120
+
121
+ assert response.status_code == 201
122
+ payload = response.json()
123
+ assert payload["name"] == "zen"
124
+
125
+
126
+ @pytest.mark.i9n
127
+ @pytest.mark.asyncio
128
+ async def test_tigrbl_app_include_api_router_alpha(running_app_with_api_router):
129
+ async with httpx.AsyncClient() as client:
130
+ response = await client.post(
131
+ f"{running_app_with_api_router}/alpha/alpha-widget", json={"name": "ace"}
132
+ )
133
+
134
+ assert response.status_code == 201
135
+ payload = response.json()
136
+ assert payload["name"] == "ace"
137
+
138
+
139
+ @pytest.mark.i9n
140
+ @pytest.mark.asyncio
141
+ async def test_tigrbl_app_include_api_router_beta(running_app_with_api_router):
142
+ async with httpx.AsyncClient() as client:
143
+ response = await client.post(
144
+ f"{running_app_with_api_router}/beta/beta-widget", json={"name": "bolt"}
145
+ )
146
+
147
+ assert response.status_code == 201
148
+ payload = response.json()
149
+ assert payload["name"] == "bolt"
@@ -0,0 +1,80 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+
5
+ from tigrbl import Base, TigrblApi, TigrblApp
6
+ from tigrbl.engine.shortcuts import mem
7
+ from tigrbl.orm.mixins import GUIDPk
8
+ from tigrbl.specs import F, IO, S, acol
9
+ from tigrbl.types import Mapped, String
10
+
11
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
12
+
13
+
14
+ class AlphaWidget(Base, GUIDPk):
15
+ __tablename__ = "alpha_widgets"
16
+ __resource__ = "alpha-widget"
17
+
18
+ name: Mapped[str] = acol(
19
+ storage=S(String, nullable=False),
20
+ field=F(py_type=str),
21
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
22
+ )
23
+
24
+
25
+ class BetaWidget(Base, GUIDPk):
26
+ __tablename__ = "beta_widgets"
27
+ __resource__ = "beta-widget"
28
+
29
+ name: Mapped[str] = acol(
30
+ storage=S(String, nullable=False),
31
+ field=F(py_type=str),
32
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
33
+ )
34
+
35
+
36
+ @pytest_asyncio.fixture()
37
+ async def running_multi_api_app():
38
+ engine = mem(async_=False)
39
+ alpha_api = TigrblApi(engine=engine)
40
+ alpha_api.include_model(AlphaWidget)
41
+
42
+ beta_api = TigrblApi(engine=engine)
43
+ beta_api.include_model(BetaWidget)
44
+
45
+ app = TigrblApp(engine=engine, apis=[alpha_api])
46
+ app.include_router(beta_api, prefix="/beta")
47
+ app.include_router(alpha_api.router, prefix="/alpha")
48
+ await app.initialize()
49
+
50
+ base_url, server, task = await run_uvicorn_in_task(app)
51
+ try:
52
+ yield base_url
53
+ finally:
54
+ await stop_uvicorn_server(server, task)
55
+
56
+
57
+ @pytest.mark.i9n
58
+ @pytest.mark.asyncio
59
+ async def test_tigrbl_app_routes_alpha_api(running_multi_api_app):
60
+ async with httpx.AsyncClient() as client:
61
+ response = await client.post(
62
+ f"{running_multi_api_app}/alpha/alpha-widget", json={"name": "ace"}
63
+ )
64
+
65
+ assert response.status_code == 201
66
+ payload = response.json()
67
+ assert payload["name"] == "ace"
68
+
69
+
70
+ @pytest.mark.i9n
71
+ @pytest.mark.asyncio
72
+ async def test_tigrbl_app_routes_beta_api(running_multi_api_app):
73
+ async with httpx.AsyncClient() as client:
74
+ response = await client.post(
75
+ f"{running_multi_api_app}/beta/beta-widget", json={"name": "bolt"}
76
+ )
77
+
78
+ assert response.status_code == 201
79
+ payload = response.json()
80
+ assert payload["name"] == "bolt"
@@ -0,0 +1,103 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+ from fastapi import Security
5
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
6
+
7
+ from tigrbl import Base, TigrblApp
8
+ from tigrbl.engine.shortcuts import mem
9
+ from tigrbl.orm.mixins import GUIDPk
10
+ from tigrbl.specs import F, IO, S, acol
11
+ from tigrbl.types import Mapped, String
12
+
13
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
14
+
15
+
16
+ bearer = HTTPBearer()
17
+
18
+
19
+ def auth_dependency(
20
+ credentials: HTTPAuthorizationCredentials = Security(bearer),
21
+ ) -> HTTPAuthorizationCredentials:
22
+ return credentials
23
+
24
+
25
+ class Gamma(Base, GUIDPk):
26
+ __tablename__ = "gamma_app_usage"
27
+ __allow_unmapped__ = True
28
+
29
+ name: Mapped[str] = acol(
30
+ storage=S(type_=String, nullable=False),
31
+ field=F(py_type=str),
32
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
33
+ )
34
+
35
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
36
+
37
+
38
+ class Delta(Base, GUIDPk):
39
+ __tablename__ = "delta_app_usage"
40
+ __allow_unmapped__ = True
41
+
42
+ name: Mapped[str] = acol(
43
+ storage=S(type_=String, nullable=False),
44
+ field=F(py_type=str),
45
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
46
+ )
47
+
48
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
49
+
50
+
51
+ @pytest_asyncio.fixture()
52
+ async def running_app():
53
+ app = TigrblApp(engine=mem(async_=False))
54
+ app.set_auth(authn=auth_dependency, allow_anon=False)
55
+ app.include_models([Gamma, Delta])
56
+ app.initialize()
57
+
58
+ base_url, server, task = await run_uvicorn_in_task(app)
59
+ try:
60
+ yield base_url
61
+ finally:
62
+ await stop_uvicorn_server(server, task)
63
+
64
+
65
+ @pytest.mark.i9n
66
+ @pytest.mark.asyncio
67
+ async def test_tigrbl_app_deploys_and_serves_openapi(running_app) -> None:
68
+ base_url = running_app
69
+
70
+ async with httpx.AsyncClient() as client:
71
+ openapi_resp = await client.get(f"{base_url}/openapi.json")
72
+
73
+ assert openapi_resp.status_code == 200
74
+ openapi = openapi_resp.json()
75
+ paths = openapi["paths"]
76
+
77
+ assert "/gamma" in paths
78
+ assert "/gamma/{item_id}" in paths
79
+ assert "/delta" in paths
80
+ assert "/delta/{item_id}" in paths
81
+ assert {"get", "post", "delete"}.issubset(paths["/gamma"])
82
+ assert {"get", "patch", "put", "delete"}.issubset(paths["/gamma/{item_id}"])
83
+
84
+ security_schemes = openapi.get("components", {}).get("securitySchemes", {})
85
+ assert "HTTPBearer" in security_schemes
86
+
87
+
88
+ @pytest.mark.i9n
89
+ @pytest.mark.asyncio
90
+ async def test_tigrbl_app_handles_authenticated_request(running_app) -> None:
91
+ base_url = running_app
92
+ headers = {"Authorization": "Bearer demo"}
93
+
94
+ async with httpx.AsyncClient() as client:
95
+ resp = await client.post(
96
+ f"{base_url}/gamma",
97
+ json={"name": "Gamma"},
98
+ headers=headers,
99
+ )
100
+
101
+ assert resp.status_code == 201
102
+ payload = resp.json()
103
+ assert payload["name"] == "Gamma"