pyfect-dev 0.1.0__py3-none-any.whl
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.
- pyfect/__init__.py +729 -0
- pyfect/_all.py +242 -0
- pyfect/_background.py +28 -0
- pyfect/_binary_codecs.py +124 -0
- pyfect/_cached.py +165 -0
- pyfect/_catch.py +128 -0
- pyfect/_catch_reason.py +574 -0
- pyfect/_concurrency.py +291 -0
- pyfect/_context_effects.py +163 -0
- pyfect/_context_managers.py +76 -0
- pyfect/_core.py +368 -0
- pyfect/_digits.py +71 -0
- pyfect/_effect_args.py +46 -0
- pyfect/_effect_base.py +71 -0
- pyfect/_effect_concurrency.py +133 -0
- pyfect/_effect_eager.py +103 -0
- pyfect/_effect_errors.py +344 -0
- pyfect/_effect_folding.py +110 -0
- pyfect/_effect_hash.py +140 -0
- pyfect/_effect_logging.py +57 -0
- pyfect/_effect_metrics.py +102 -0
- pyfect/_effect_resources.py +179 -0
- pyfect/_effect_services.py +25 -0
- pyfect/_effect_timing.py +199 -0
- pyfect/_effect_tracing.py +99 -0
- pyfect/_equal.py +195 -0
- pyfect/_extras.py +43 -0
- pyfect/_fiber.py +969 -0
- pyfect/_fiber_all.py +134 -0
- pyfect/_fiber_collections.py +106 -0
- pyfect/_fn.py +706 -0
- pyfect/_hamt.py +174 -0
- pyfect/_interrupt_reason.py +33 -0
- pyfect/_isaac.py +149 -0
- pyfect/_iterables.py +231 -0
- pyfect/_js.py +263 -0
- pyfect/_js_date.py +87 -0
- pyfect/_json_text.py +286 -0
- pyfect/_json_value.py +9 -0
- pyfect/_layer_core.py +403 -0
- pyfect/_layer_for_life.py +33 -0
- pyfect/_layer_tracing.py +70 -0
- pyfect/_locked_ref.py +147 -0
- pyfect/_loop_thread.py +152 -0
- pyfect/_metric_ref.py +29 -0
- pyfect/_one_or_many.py +14 -0
- pyfect/_os_wait.py +118 -0
- pyfect/_path_posix.py +129 -0
- pyfect/_primitives.py +434 -0
- pyfect/_public.py +36 -0
- pyfect/_reasons.py +64 -0
- pyfect/_released.py +67 -0
- pyfect/_root.py +87 -0
- pyfect/_round_robin.py +73 -0
- pyfect/_some.py +17 -0
- pyfect/_stack.py +52 -0
- pyfect/_stack_frame.py +114 -0
- pyfect/_string_hash.py +35 -0
- pyfect/_subscriber_queue.py +47 -0
- pyfect/_tags.py +14 -0
- pyfect/_tracer_ref.py +21 -0
- pyfect/_tx_ops.py +77 -0
- pyfect/_unsubscripted.py +23 -0
- pyfect/_url.py +54 -0
- pyfect/_waiters.py +127 -0
- pyfect/_wake_tracking.py +98 -0
- pyfect/_wire_codec.py +123 -0
- pyfect/ai/__init__.py +73 -0
- pyfect/ai/_approvals.py +249 -0
- pyfect/ai/_decision_answers.py +185 -0
- pyfect/ai/_generated_client.py +298 -0
- pyfect/ai/_generated_support.py +84 -0
- pyfect/ai/_mcp/__init__.py +1 -0
- pyfect/ai/_mcp/batch.py +68 -0
- pyfect/ai/_mcp/client_transport.py +412 -0
- pyfect/ai/_mcp/client_wire.py +284 -0
- pyfect/ai/_mcp/core.py +490 -0
- pyfect/ai/_mcp/dispatch.py +1048 -0
- pyfect/ai/_mcp/http.py +462 -0
- pyfect/ai/_mcp/http_admission.py +269 -0
- pyfect/ai/_mcp/http_status.py +27 -0
- pyfect/ai/_mcp/input_wire.py +226 -0
- pyfect/ai/_mcp/log_levels.py +55 -0
- pyfect/ai/_mcp/param_headers.py +63 -0
- pyfect/ai/_mcp/projection.py +248 -0
- pyfect/ai/_mcp/register.py +683 -0
- pyfect/ai/_mcp/reverse_policy.py +155 -0
- pyfect/ai/_mcp/routing_header.py +24 -0
- pyfect/ai/_mcp/sessions.py +114 -0
- pyfect/ai/_mcp/stdio.py +110 -0
- pyfect/ai/_mcp/subscriptions.py +134 -0
- pyfect/ai/_mcp/tool_schema.py +35 -0
- pyfect/ai/_noul_answers.py +64 -0
- pyfect/ai/_openai_all_of.py +137 -0
- pyfect/ai/_openai_errors.py +233 -0
- pyfect/ai/_provider.py +439 -0
- pyfect/ai/_provider_tools.py +129 -0
- pyfect/ai/_stream_resolution.py +231 -0
- pyfect/ai/_structured_output_checks.py +138 -0
- pyfect/ai/_structured_output_codec.py +229 -0
- pyfect/ai/_structured_output_json.py +109 -0
- pyfect/ai/_tool_call_ids.py +80 -0
- pyfect/ai/ai_error.py +785 -0
- pyfect/ai/anthropic/__init__.py +28 -0
- pyfect/ai/anthropic/_errors.py +164 -0
- pyfect/ai/anthropic/_prompt.py +375 -0
- pyfect/ai/anthropic/_response.py +443 -0
- pyfect/ai/anthropic/_schema.py +206 -0
- pyfect/ai/anthropic/_stream.py +377 -0
- pyfect/ai/anthropic/_tools.py +248 -0
- pyfect/ai/anthropic/client.py +289 -0
- pyfect/ai/anthropic/config.py +32 -0
- pyfect/ai/anthropic/error.py +27 -0
- pyfect/ai/anthropic/language_model.py +366 -0
- pyfect/ai/anthropic/telemetry.py +51 -0
- pyfect/ai/anthropic/tool.py +570 -0
- pyfect/ai/anthropic_structured_output.py +138 -0
- pyfect/ai/chat.py +548 -0
- pyfect/ai/cloudflare/__init__.py +15 -0
- pyfect/ai/cloudflare/_errors.py +108 -0
- pyfect/ai/cloudflare/client.py +174 -0
- pyfect/ai/cloudflare/decision_model.py +117 -0
- pyfect/ai/cloudflare/schema.py +144 -0
- pyfect/ai/decision.py +290 -0
- pyfect/ai/decision_model.py +283 -0
- pyfect/ai/embedding_model.py +177 -0
- pyfect/ai/id_generator.py +79 -0
- pyfect/ai/language_model.py +1077 -0
- pyfect/ai/mcp_client.py +682 -0
- pyfect/ai/mcp_client_error.py +223 -0
- pyfect/ai/mcp_protocol.py +205 -0
- pyfect/ai/mcp_schema.py +1300 -0
- pyfect/ai/mcp_server.py +404 -0
- pyfect/ai/model.py +56 -0
- pyfect/ai/openai/__init__.py +49 -0
- pyfect/ai/openai/_errors.py +89 -0
- pyfect/ai/openai/_prompt.py +527 -0
- pyfect/ai/openai/_requests.py +34 -0
- pyfect/ai/openai/_response.py +569 -0
- pyfect/ai/openai/_schema.py +769 -0
- pyfect/ai/openai/_stream.py +771 -0
- pyfect/ai/openai/_tools.py +128 -0
- pyfect/ai/openai/_web_socket.py +295 -0
- pyfect/ai/openai/client.py +296 -0
- pyfect/ai/openai/client_generated.py +123 -0
- pyfect/ai/openai/config.py +34 -0
- pyfect/ai/openai/decision_model.py +177 -0
- pyfect/ai/openai/embedding_model.py +116 -0
- pyfect/ai/openai/error.py +8 -0
- pyfect/ai/openai/generated/__init__.py +7213 -0
- pyfect/ai/openai/generated/_recursive.py +18 -0
- pyfect/ai/openai/generated/_schemas_0.py +1015 -0
- pyfect/ai/openai/generated/_schemas_1.py +1016 -0
- pyfect/ai/openai/generated/_schemas_2.py +1017 -0
- pyfect/ai/openai/generated/_schemas_3.py +615 -0
- pyfect/ai/openai/generated/client.py +5298 -0
- pyfect/ai/openai/generated/types.py +8123 -0
- pyfect/ai/openai/language_model.py +304 -0
- pyfect/ai/openai/telemetry.py +19 -0
- pyfect/ai/openai/tool.py +391 -0
- pyfect/ai/openai_compat/__init__.py +25 -0
- pyfect/ai/openai_compat/_prompt.py +191 -0
- pyfect/ai/openai_compat/_request.py +153 -0
- pyfect/ai/openai_compat/_response.py +407 -0
- pyfect/ai/openai_compat/_schema.py +97 -0
- pyfect/ai/openai_compat/client.py +234 -0
- pyfect/ai/openai_compat/config.py +32 -0
- pyfect/ai/openai_compat/embedding_model.py +139 -0
- pyfect/ai/openai_compat/error.py +7 -0
- pyfect/ai/openai_compat/language_model.py +245 -0
- pyfect/ai/openai_compat/telemetry.py +51 -0
- pyfect/ai/openai_structured_output.py +118 -0
- pyfect/ai/openrouter/__init__.py +36 -0
- pyfect/ai/openrouter/_errors.py +186 -0
- pyfect/ai/openrouter/_prompt.py +272 -0
- pyfect/ai/openrouter/_response.py +226 -0
- pyfect/ai/openrouter/_stream.py +320 -0
- pyfect/ai/openrouter/client.py +283 -0
- pyfect/ai/openrouter/config.py +36 -0
- pyfect/ai/openrouter/decision_model.py +161 -0
- pyfect/ai/openrouter/error.py +23 -0
- pyfect/ai/openrouter/generated/__init__.py +3029 -0
- pyfect/ai/openrouter/generated/_recursive.py +15 -0
- pyfect/ai/openrouter/generated/_schemas_0.py +1015 -0
- pyfect/ai/openrouter/generated/_schemas_1.py +522 -0
- pyfect/ai/openrouter/generated/client.py +1445 -0
- pyfect/ai/openrouter/generated/types.py +4769 -0
- pyfect/ai/openrouter/language_model.py +345 -0
- pyfect/ai/openrouter/schema.py +165 -0
- pyfect/ai/prompt.py +664 -0
- pyfect/ai/response.py +768 -0
- pyfect/ai/response_id_tracker.py +82 -0
- pyfect/ai/telemetry.py +126 -0
- pyfect/ai/tokenizer.py +61 -0
- pyfect/ai/tool.py +536 -0
- pyfect/ai/toolkit.py +490 -0
- pyfect/ai/typesafe/__init__.py +17 -0
- pyfect/ai/typesafe/_errors.py +120 -0
- pyfect/ai/typesafe/client.py +146 -0
- pyfect/ai/typesafe/config.py +34 -0
- pyfect/ai/typesafe/decision_model.py +90 -0
- pyfect/ai/typesafe/schema.py +140 -0
- pyfect/batching/__init__.py +58 -0
- pyfect/batching/_api.py +71 -0
- pyfect/batching/_engine.py +229 -0
- pyfect/batching/_from_effect.py +76 -0
- pyfect/batching/_persisted.py +98 -0
- pyfect/batching/_request.py +133 -0
- pyfect/batching/_resolver.py +477 -0
- pyfect/batching/_with_cache.py +90 -0
- pyfect/big_decimal.py +500 -0
- pyfect/brand.py +114 -0
- pyfect/byte_size.py +354 -0
- pyfect/cache/__init__.py +29 -0
- pyfect/cache/_cache.py +426 -0
- pyfect/cache/_expiry.py +69 -0
- pyfect/cache/_scoped_cache.py +546 -0
- pyfect/case.py +174 -0
- pyfect/cause.py +462 -0
- pyfect/channel/__init__.py +155 -0
- pyfect/channel/_base.py +92 -0
- pyfect/channel/_catch.py +158 -0
- pyfect/channel/_catch_reason.py +572 -0
- pyfect/channel/_channel.py +158 -0
- pyfect/channel/_combinators.py +220 -0
- pyfect/channel/_concurrency_methods.py +217 -0
- pyfect/channel/_concurrent_map.py +118 -0
- pyfect/channel/_constructors.py +349 -0
- pyfect/channel/_context.py +232 -0
- pyfect/channel/_error_methods.py +336 -0
- pyfect/channel/_errors.py +180 -0
- pyfect/channel/_filters.py +225 -0
- pyfect/channel/_lifecycle.py +71 -0
- pyfect/channel/_lifecycle_methods.py +206 -0
- pyfect/channel/_loop.py +100 -0
- pyfect/channel/_merge.py +246 -0
- pyfect/channel/_repeat.py +154 -0
- pyfect/channel/_run.py +149 -0
- pyfect/channel/_run_methods.py +341 -0
- pyfect/channel/_sinks.py +88 -0
- pyfect/channel/_sources.py +238 -0
- pyfect/channel/_text.py +176 -0
- pyfect/channel/_transform_methods.py +415 -0
- pyfect/channel/_upstream.py +67 -0
- pyfect/channel_schema.py +131 -0
- pyfect/cli/__init__.py +79 -0
- pyfect/cli/_ansi.py +82 -0
- pyfect/cli/_command.py +469 -0
- pyfect/cli/_config.py +164 -0
- pyfect/cli/_environment.py +10 -0
- pyfect/cli/_help.py +195 -0
- pyfect/cli/_lexer.py +81 -0
- pyfect/cli/_parser.py +465 -0
- pyfect/cli/_settings.py +85 -0
- pyfect/cli/_suggest.py +33 -0
- pyfect/cli/_width.py +134 -0
- pyfect/cli/_wizard.py +317 -0
- pyfect/cli/argument.py +212 -0
- pyfect/cli/cli_config.py +40 -0
- pyfect/cli/cli_error.py +242 -0
- pyfect/cli/cli_output.py +305 -0
- pyfect/cli/command.py +440 -0
- pyfect/cli/completions/__init__.py +50 -0
- pyfect/cli/completions/_completer.ps1 +190 -0
- pyfect/cli/completions/_descriptor.py +182 -0
- pyfect/cli/completions/bash.py +300 -0
- pyfect/cli/completions/fish.py +164 -0
- pyfect/cli/completions/powershell.py +156 -0
- pyfect/cli/completions/zsh.py +189 -0
- pyfect/cli/flag.py +246 -0
- pyfect/cli/global_flag.py +99 -0
- pyfect/cli/help_doc.py +63 -0
- pyfect/cli/param.py +789 -0
- pyfect/cli/primitive.py +308 -0
- pyfect/cli/prompt/__init__.py +75 -0
- pyfect/cli/prompt/_auto_complete.py +205 -0
- pyfect/cli/prompt/_choices.py +104 -0
- pyfect/cli/prompt/_confirm.py +195 -0
- pyfect/cli/prompt/_core.py +512 -0
- pyfect/cli/prompt/_date.py +173 -0
- pyfect/cli/prompt/_date_parts.py +387 -0
- pyfect/cli/prompt/_file.py +372 -0
- pyfect/cli/prompt/_multi_select.py +204 -0
- pyfect/cli/prompt/_number.py +257 -0
- pyfect/cli/prompt/_select.py +117 -0
- pyfect/cli/prompt/_text.py +239 -0
- pyfect/cli/terminal_capabilities.py +118 -0
- pyfect/clock.py +150 -0
- pyfect/cluster/__init__.py +155 -0
- pyfect/cluster/_cluster_abandon.py +36 -0
- pyfect/cluster/_cluster_layer.py +122 -0
- pyfect/cluster/_entity_activation.py +16 -0
- pyfect/cluster/_entity_manager/__init__.py +22 -0
- pyfect/cluster/_entity_manager/_activation.py +540 -0
- pyfect/cluster/_entity_manager/_core.py +186 -0
- pyfect/cluster/_entity_manager/_decode.py +60 -0
- pyfect/cluster/_entity_manager/_manager.py +423 -0
- pyfect/cluster/_entity_manager/_state.py +113 -0
- pyfect/cluster/_entity_reaper.py +94 -0
- pyfect/cluster/_hash.py +13 -0
- pyfect/cluster/_interruptors.py +88 -0
- pyfect/cluster/_resource_map.py +179 -0
- pyfect/cluster/_resource_ref.py +266 -0
- pyfect/cluster/_shard_lock.py +14 -0
- pyfect/cluster/cluster_cron.py +230 -0
- pyfect/cluster/cluster_error.py +81 -0
- pyfect/cluster/cluster_http.py +210 -0
- pyfect/cluster/cluster_metrics.py +54 -0
- pyfect/cluster/cluster_schema.py +137 -0
- pyfect/cluster/cluster_socket.py +197 -0
- pyfect/cluster/cluster_workflow_engine/__init__.py +24 -0
- pyfect/cluster/cluster_workflow_engine/_engine.py +1099 -0
- pyfect/cluster/cluster_workflow_engine/_entities.py +298 -0
- pyfect/cluster/deliver_at.py +31 -0
- pyfect/cluster/entity/__init__.py +39 -0
- pyfect/cluster/entity/_entity.py +332 -0
- pyfect/cluster/entity/_handlers.py +168 -0
- pyfect/cluster/entity/_keep_alive.py +74 -0
- pyfect/cluster/entity/_queue.py +103 -0
- pyfect/cluster/entity/_request.py +34 -0
- pyfect/cluster/entity/_services.py +23 -0
- pyfect/cluster/entity/_test_client.py +237 -0
- pyfect/cluster/entity_address.py +25 -0
- pyfect/cluster/entity_id.py +20 -0
- pyfect/cluster/entity_proxy.py +161 -0
- pyfect/cluster/entity_proxy_server.py +103 -0
- pyfect/cluster/entity_resource.py +122 -0
- pyfect/cluster/entity_type.py +20 -0
- pyfect/cluster/envelope.py +307 -0
- pyfect/cluster/http_runner.py +254 -0
- pyfect/cluster/k8s_http_client.py +281 -0
- pyfect/cluster/k8s_types.py +1394 -0
- pyfect/cluster/machine_id.py +21 -0
- pyfect/cluster/message.py +219 -0
- pyfect/cluster/message_storage/__init__.py +67 -0
- pyfect/cluster/message_storage/_encoded.py +393 -0
- pyfect/cluster/message_storage/_memory.py +386 -0
- pyfect/cluster/message_storage/_noop.py +109 -0
- pyfect/cluster/message_storage/_service.py +388 -0
- pyfect/cluster/reply.py +236 -0
- pyfect/cluster/runner.py +32 -0
- pyfect/cluster/runner_address.py +23 -0
- pyfect/cluster/runner_health.py +93 -0
- pyfect/cluster/runner_server.py +286 -0
- pyfect/cluster/runner_storage.py +212 -0
- pyfect/cluster/runners/__init__.py +55 -0
- pyfect/cluster/runners/_local.py +460 -0
- pyfect/cluster/runners/_noop.py +57 -0
- pyfect/cluster/runners/_rpc.py +290 -0
- pyfect/cluster/runners/_service.py +113 -0
- pyfect/cluster/shard_id.py +39 -0
- pyfect/cluster/sharding/__init__.py +12 -0
- pyfect/cluster/sharding/_acquisition.py +490 -0
- pyfect/cluster/sharding/_clients.py +271 -0
- pyfect/cluster/sharding/_make.py +388 -0
- pyfect/cluster/sharding/_routing.py +296 -0
- pyfect/cluster/sharding/_runners_sync.py +198 -0
- pyfect/cluster/sharding/_service.py +91 -0
- pyfect/cluster/sharding/_singletons.py +183 -0
- pyfect/cluster/sharding/_state.py +296 -0
- pyfect/cluster/sharding/_storage_loop.py +421 -0
- pyfect/cluster/sharding_config.py +230 -0
- pyfect/cluster/sharding_registration_event.py +28 -0
- pyfect/cluster/single_runner.py +49 -0
- pyfect/cluster/singleton.py +36 -0
- pyfect/cluster/singleton_address.py +20 -0
- pyfect/cluster/snowflake.py +133 -0
- pyfect/cluster/socket_runner.py +67 -0
- pyfect/cluster/sql_message_storage.py +1001 -0
- pyfect/cluster/sql_runner_storage.py +841 -0
- pyfect/cluster/test_runner.py +23 -0
- pyfect/config/__init__.py +93 -0
- pyfect/config/_all.py +96 -0
- pyfect/config/_collections.py +291 -0
- pyfect/config/_config.py +261 -0
- pyfect/config/_constructors.py +106 -0
- pyfect/config/_error.py +27 -0
- pyfect/config/_leaf.py +92 -0
- pyfect/config/_scalars.py +193 -0
- pyfect/config/_schema.py +340 -0
- pyfect/config_provider/__init__.py +60 -0
- pyfect/config_provider/_dir.py +84 -0
- pyfect/config_provider/_dotenv.py +127 -0
- pyfect/config_provider/_env.py +79 -0
- pyfect/config_provider/_layers.py +80 -0
- pyfect/config_provider/_node.py +90 -0
- pyfect/config_provider/_provider.py +118 -0
- pyfect/config_provider/_unknown.py +62 -0
- pyfect/console/__init__.py +63 -0
- pyfect/console/_effects.py +134 -0
- pyfect/console/_live.py +156 -0
- pyfect/console/_service.py +49 -0
- pyfect/console/_table.py +90 -0
- pyfect/context.py +414 -0
- pyfect/cron/__init__.py +30 -0
- pyfect/cron/_model.py +183 -0
- pyfect/cron/_search.py +268 -0
- pyfect/cron/_text.py +202 -0
- pyfect/cron/_wall.py +42 -0
- pyfect/crypto.py +257 -0
- pyfect/date_time/__init__.py +77 -0
- pyfect/date_time/_calendar.py +209 -0
- pyfect/date_time/_current.py +118 -0
- pyfect/date_time/_epoch.py +22 -0
- pyfect/date_time/_iso.py +80 -0
- pyfect/date_time/_zones.py +135 -0
- pyfect/date_time/intl.py +144 -0
- pyfect/deferred.py +145 -0
- pyfect/devtools/__init__.py +24 -0
- pyfect/devtools/client.py +323 -0
- pyfect/devtools/layers.py +32 -0
- pyfect/devtools/schema.py +301 -0
- pyfect/devtools/server.py +72 -0
- pyfect/duration.py +295 -0
- pyfect/effect.py +565 -0
- pyfect/effectable.py +37 -0
- pyfect/encoding/__init__.py +62 -0
- pyfect/encoding/_archive.py +197 -0
- pyfect/encoding/_json_array_scanner.py +477 -0
- pyfect/encoding/base64.py +23 -0
- pyfect/encoding/base64_url.py +19 -0
- pyfect/encoding/encoding_error.py +17 -0
- pyfect/encoding/hex.py +28 -0
- pyfect/encoding/ini.py +188 -0
- pyfect/encoding/json_array.py +246 -0
- pyfect/encoding/ndjson.py +461 -0
- pyfect/encoding/schema_binary/__init__.py +257 -0
- pyfect/encoding/schema_binary/_channels.py +173 -0
- pyfect/encoding/schema_binary/_compile.py +584 -0
- pyfect/encoding/schema_binary/_decode.py +848 -0
- pyfect/encoding/schema_binary/_dictionary.py +90 -0
- pyfect/encoding/schema_binary/_encode.py +838 -0
- pyfect/encoding/schema_binary/_fingerprint.py +168 -0
- pyfect/encoding/schema_binary/_layout.py +350 -0
- pyfect/encoding/schema_binary/_literals.py +47 -0
- pyfect/encoding/schema_binary/_parser.py +163 -0
- pyfect/encoding/schema_binary/_reader.py +148 -0
- pyfect/encoding/schema_binary/_target.py +310 -0
- pyfect/encoding/schema_binary/_values.py +133 -0
- pyfect/encoding/schema_binary/_wire.py +253 -0
- pyfect/encoding/sse.py +476 -0
- pyfect/encoding/tar/__init__.py +396 -0
- pyfect/encoding/tar/_decoder.py +220 -0
- pyfect/encoding/tar/_encoder.py +83 -0
- pyfect/encoding/tar/_header.py +494 -0
- pyfect/encoding/tar/_model.py +82 -0
- pyfect/encoding/toml.py +375 -0
- pyfect/encoding/xml/__init__.py +222 -0
- pyfect/encoding/xml/_chars.py +119 -0
- pyfect/encoding/xml/_collector.py +106 -0
- pyfect/encoding/xml/_inputs.py +126 -0
- pyfect/encoding/xml/_model.py +114 -0
- pyfect/encoding/xml/_parser.py +694 -0
- pyfect/encoding/xml/_scanner.py +180 -0
- pyfect/encoding/xml/_writer.py +238 -0
- pyfect/encoding/yaml.py +739 -0
- pyfect/encoding/zip/__init__.py +392 -0
- pyfect/encoding/zip/_decoder.py +378 -0
- pyfect/encoding/zip/_format.py +122 -0
- pyfect/encoding/zip/_inflate.py +65 -0
- pyfect/encoding/zip/_model.py +86 -0
- pyfect/encoding/zip/_writer.py +311 -0
- pyfect/error_reporter.py +240 -0
- pyfect/errors.py +321 -0
- pyfect/eventlog/__init__.py +77 -0
- pyfect/eventlog/_conflicts.py +94 -0
- pyfect/eventlog/_crypto.py +64 -0
- pyfect/eventlog/_identity.py +26 -0
- pyfect/eventlog/_identity_derivation.py +79 -0
- pyfect/eventlog/_transferable_bytes.py +55 -0
- pyfect/eventlog/_uuid.py +33 -0
- pyfect/eventlog/event.py +115 -0
- pyfect/eventlog/event_group.py +55 -0
- pyfect/eventlog/event_journal.py +630 -0
- pyfect/eventlog/event_log.py +1039 -0
- pyfect/eventlog/event_log_encryption.py +219 -0
- pyfect/eventlog/event_log_message.py +357 -0
- pyfect/eventlog/event_log_remote.py +465 -0
- pyfect/eventlog/event_log_server.py +442 -0
- pyfect/eventlog/event_log_server_encrypted.py +322 -0
- pyfect/eventlog/event_log_server_unencrypted.py +814 -0
- pyfect/eventlog/event_log_session_auth.py +250 -0
- pyfect/eventlog/event_row.py +423 -0
- pyfect/eventlog/sql_event_journal.py +692 -0
- pyfect/eventlog/sql_event_log_server_encrypted.py +440 -0
- pyfect/eventlog/sql_event_log_server_unencrypted.py +568 -0
- pyfect/execution_plan/__init__.py +42 -0
- pyfect/execution_plan/_events.py +128 -0
- pyfect/execution_plan/_model.py +108 -0
- pyfect/execution_plan/_run.py +176 -0
- pyfect/exit.py +205 -0
- pyfect/fiber_handle.py +305 -0
- pyfect/fiber_map.py +350 -0
- pyfect/fiber_set.py +232 -0
- pyfect/file_system/__init__.py +69 -0
- pyfect/file_system/_copy.py +116 -0
- pyfect/file_system/_errors.py +32 -0
- pyfect/file_system/_file.py +177 -0
- pyfect/file_system/_live.py +351 -0
- pyfect/file_system/_model.py +72 -0
- pyfect/file_system/_noop.py +189 -0
- pyfect/file_system/_service.py +336 -0
- pyfect/file_system/_stat.py +69 -0
- pyfect/file_system/_watch.py +107 -0
- pyfect/filters.py +245 -0
- pyfect/graph/__init__.py +101 -0
- pyfect/graph/_all_pairs.py +150 -0
- pyfect/graph/_combine.py +259 -0
- pyfect/graph/_compact.py +143 -0
- pyfect/graph/_components.py +200 -0
- pyfect/graph/_cycles.py +144 -0
- pyfect/graph/_enumerate.py +168 -0
- pyfect/graph/_errors.py +51 -0
- pyfect/graph/_flow.py +164 -0
- pyfect/graph/_forest.py +109 -0
- pyfect/graph/_graph.py +269 -0
- pyfect/graph/_lowlink.py +98 -0
- pyfect/graph/_matching.py +101 -0
- pyfect/graph/_mutate.py +211 -0
- pyfect/graph/_query.py +138 -0
- pyfect/graph/_records.py +119 -0
- pyfect/graph/_render.py +109 -0
- pyfect/graph/_shortest.py +274 -0
- pyfect/graph/_snapshot.py +50 -0
- pyfect/graph/_store.py +136 -0
- pyfect/graph/_traverse.py +289 -0
- pyfect/graph/_view.py +384 -0
- pyfect/graph/_walker.py +70 -0
- pyfect/graphql/__init__.py +87 -0
- pyfect/graphql/_codec.py +117 -0
- pyfect/graphql/_http.py +309 -0
- pyfect/graphql/_schemas.py +39 -0
- pyfect/graphql/_slices.py +110 -0
- pyfect/graphql/_template.py +111 -0
- pyfect/graphql/_types.py +115 -0
- pyfect/graphql/_ws.py +395 -0
- pyfect/graphql/_ws_messages.py +120 -0
- pyfect/graphql/client.py +428 -0
- pyfect/graphql/client_error.py +285 -0
- pyfect/graphql/group.py +142 -0
- pyfect/graphql/middleware.py +98 -0
- pyfect/graphql/operation.py +409 -0
- pyfect/graphql/protocol.py +119 -0
- pyfect/graphql/resolver.py +574 -0
- pyfect/graphql/template.py +61 -0
- pyfect/hash_map.py +317 -0
- pyfect/hash_ring.py +206 -0
- pyfect/hash_set.py +163 -0
- pyfect/http/__init__.py +125 -0
- pyfect/http/_asgi_listener.py +272 -0
- pyfect/http/_authority.py +63 -0
- pyfect/http/_brotli.py +27 -0
- pyfect/http/_compression.py +52 -0
- pyfect/http/_field.py +18 -0
- pyfect/http/_foreign_path.py +27 -0
- pyfect/http/_form_data.py +34 -0
- pyfect/http/_httpx_options.py +120 -0
- pyfect/http/_in_memory.py +76 -0
- pyfect/http/_request_state.py +59 -0
- pyfect/http/_vary.py +14 -0
- pyfect/http/abort.py +65 -0
- pyfect/http/asgi/__init__.py +59 -0
- pyfect/http/asgi/_app.py +155 -0
- pyfect/http/asgi/_http.py +201 -0
- pyfect/http/asgi/_mount.py +263 -0
- pyfect/http/asgi/_scope.py +86 -0
- pyfect/http/asgi/_serve.py +72 -0
- pyfect/http/asgi/_types.py +13 -0
- pyfect/http/asgi/_web_socket.py +325 -0
- pyfect/http/body.py +437 -0
- pyfect/http/client/__init__.py +111 -0
- pyfect/http/client/_circuit_breaker.py +113 -0
- pyfect/http/client/_cookie_jar.py +120 -0
- pyfect/http/client/_make.py +252 -0
- pyfect/http/client/_rate_limit.py +423 -0
- pyfect/http/client/_redirects.py +93 -0
- pyfect/http/client/_retry.py +115 -0
- pyfect/http/client/_service.py +497 -0
- pyfect/http/cookies.py +444 -0
- pyfect/http/error.py +188 -0
- pyfect/http/etag.py +96 -0
- pyfect/http/file_like.py +49 -0
- pyfect/http/find_my_way/__init__.py +10 -0
- pyfect/http/find_my_way/_nodes.py +186 -0
- pyfect/http/find_my_way/_paths.py +43 -0
- pyfect/http/find_my_way/_query_string.py +67 -0
- pyfect/http/find_my_way/_router.py +401 -0
- pyfect/http/headers.py +343 -0
- pyfect/http/http_effect.py +198 -0
- pyfect/http/httpx_client.py +291 -0
- pyfect/http/hypercorn_server.py +122 -0
- pyfect/http/incoming_message.py +140 -0
- pyfect/http/live_server/__init__.py +191 -0
- pyfect/http/live_server/_body.py +164 -0
- pyfect/http/live_server/_exchange.py +321 -0
- pyfect/http/live_server/_head.py +194 -0
- pyfect/http/live_server/_inbound.py +156 -0
- pyfect/http/live_server/_listener.py +211 -0
- pyfect/http/live_server/_serve.py +225 -0
- pyfect/http/live_server/_timers.py +20 -0
- pyfect/http/live_server/_upgrade.py +108 -0
- pyfect/http/live_server/_websocket.py +286 -0
- pyfect/http/live_server/_ws_frames.py +242 -0
- pyfect/http/method.py +30 -0
- pyfect/http/middleware/__init__.py +61 -0
- pyfect/http/middleware/_compression.py +156 -0
- pyfect/http/middleware/_cors.py +129 -0
- pyfect/http/middleware/_decompression.py +274 -0
- pyfect/http/middleware/_forwarded.py +113 -0
- pyfect/http/middleware/_logger.py +73 -0
- pyfect/http/middleware/_search_params.py +34 -0
- pyfect/http/middleware/_tracer.py +153 -0
- pyfect/http/middleware/_types.py +16 -0
- pyfect/http/mime/__init__.py +69 -0
- pyfect/http/mime/_types.py +361 -0
- pyfect/http/multipart.py +613 -0
- pyfect/http/multipart_parser/__init__.py +348 -0
- pyfect/http/multipart_parser/_content_type.py +109 -0
- pyfect/http/multipart_parser/_headers.py +206 -0
- pyfect/http/multipart_parser/_search.py +85 -0
- pyfect/http/origin.py +146 -0
- pyfect/http/platform.py +593 -0
- pyfect/http/prometheus.py +34 -0
- pyfect/http/request.py +384 -0
- pyfect/http/response.py +474 -0
- pyfect/http/router/__init__.py +82 -0
- pyfect/http/router/_api.py +462 -0
- pyfect/http/router/_in_memory.py +76 -0
- pyfect/http/router/_markers.py +47 -0
- pyfect/http/router/_middleware.py +181 -0
- pyfect/http/router/_middleware_stack.py +51 -0
- pyfect/http/router/_provided.py +31 -0
- pyfect/http/router/_route.py +114 -0
- pyfect/http/router/_router.py +308 -0
- pyfect/http/schema.py +276 -0
- pyfect/http/server.py +199 -0
- pyfect/http/server_error.py +261 -0
- pyfect/http/server_request.py +729 -0
- pyfect/http/server_respondable.py +77 -0
- pyfect/http/server_response.py +569 -0
- pyfect/http/static_server/__init__.py +257 -0
- pyfect/http/static_server/_conditional.py +72 -0
- pyfect/http/static_server/_mime.py +55 -0
- pyfect/http/static_server/_range.py +53 -0
- pyfect/http/status.py +51 -0
- pyfect/http/template.py +161 -0
- pyfect/http/trace_context.py +91 -0
- pyfect/http/url.py +442 -0
- pyfect/http/url_params.py +304 -0
- pyfect/http/uvicorn_server.py +119 -0
- pyfect/http/web.py +171 -0
- pyfect/http/web_handler.py +463 -0
- pyfect/http/wire.py +209 -0
- pyfect/http_api/__init__.py +83 -0
- pyfect/http_api/_assets/scalar.js +8 -0
- pyfect/http_api/_assets/swagger-ui.css +3 -0
- pyfect/http_api/_assets/swagger-ui.js +4 -0
- pyfect/http_api/_client_method.py +220 -0
- pyfect/http_api/_client_payload.py +144 -0
- pyfect/http_api/_client_response.py +377 -0
- pyfect/http_api/_handlers.py +282 -0
- pyfect/http_api/_html.py +38 -0
- pyfect/http_api/_media_type.py +6 -0
- pyfect/http_api/_openapi_responses.py +164 -0
- pyfect/http_api/_openapi_schemas.py +163 -0
- pyfect/http_api/_path.py +102 -0
- pyfect/http_api/_payload.py +260 -0
- pyfect/http_api/_response.py +363 -0
- pyfect/http_api/_security.py +174 -0
- pyfect/http_api/api.py +265 -0
- pyfect/http_api/builder.py +447 -0
- pyfect/http_api/client.py +474 -0
- pyfect/http_api/endpoint.py +969 -0
- pyfect/http_api/error.py +280 -0
- pyfect/http_api/group.py +215 -0
- pyfect/http_api/middleware.py +232 -0
- pyfect/http_api/openapi.py +396 -0
- pyfect/http_api/scalar.py +143 -0
- pyfect/http_api/schema.py +713 -0
- pyfect/http_api/security.py +91 -0
- pyfect/http_api/swagger.py +69 -0
- pyfect/http_api/test.py +105 -0
- pyfect/json_patch.py +255 -0
- pyfect/json_pointer.py +100 -0
- pyfect/json_schema/__init__.py +66 -0
- pyfect/json_schema/_api.py +96 -0
- pyfect/json_schema/_converter.py +258 -0
- pyfect/json_schema/_draft04.py +198 -0
- pyfect/json_schema/_draft07.py +203 -0
- pyfect/json_schema/_keywords.py +202 -0
- pyfect/json_schema/_model.py +201 -0
- pyfect/json_schema/_openapi.py +208 -0
- pyfect/latch.py +127 -0
- pyfect/layer.py +479 -0
- pyfect/layer_map.py +279 -0
- pyfect/layer_ref.py +208 -0
- pyfect/logger/__init__.py +91 -0
- pyfect/logger/_batched.py +49 -0
- pyfect/logger/_console.py +116 -0
- pyfect/logger/_file.py +31 -0
- pyfect/logger/_formats.py +104 -0
- pyfect/logger/_layer.py +50 -0
- pyfect/logger/_level.py +53 -0
- pyfect/logger/_log.py +142 -0
- pyfect/logger/_model.py +163 -0
- pyfect/logger/_refs.py +78 -0
- pyfect/logger/_stdlib.py +54 -0
- pyfect/logger/_text.py +263 -0
- pyfect/logger/_tracer.py +35 -0
- pyfect/managed_runtime.py +393 -0
- pyfect/metric/__init__.py +119 -0
- pyfect/metric/_boundaries.py +27 -0
- pyfect/metric/_kinds.py +417 -0
- pyfect/metric/_metric.py +302 -0
- pyfect/metric/_prometheus.py +150 -0
- pyfect/metric/_refs.py +78 -0
- pyfect/metric/_runtime.py +75 -0
- pyfect/metric/_snapshot.py +97 -0
- pyfect/metric/_state.py +74 -0
- pyfect/msgspec.py +98 -0
- pyfect/mutable_hash_map.py +140 -0
- pyfect/mutable_hash_set.py +95 -0
- pyfect/net/__init__.py +18 -0
- pyfect/net/_errors.py +29 -0
- pyfect/net/address_resolver.py +179 -0
- pyfect/net/dns/__init__.py +92 -0
- pyfect/net/dns/_error.py +43 -0
- pyfect/net/dns/_records.py +335 -0
- pyfect/net/dns/_service.py +287 -0
- pyfect/net/dns/_system.py +89 -0
- pyfect/net/host.py +311 -0
- pyfect/net/ip_interface.py +202 -0
- pyfect/net/ip_network.py +250 -0
- pyfect/net/net_address/__init__.py +245 -0
- pyfect/net/net_address/_inet.py +412 -0
- pyfect/net/net_address/_ip.py +348 -0
- pyfect/net/net_address/_mac.py +119 -0
- pyfect/optic/__init__.py +50 -0
- pyfect/optic/_builtins.py +90 -0
- pyfect/optic/_data.py +97 -0
- pyfect/optic/_optic.py +422 -0
- pyfect/optic/_steps.py +151 -0
- pyfect/option.py +362 -0
- pyfect/otel/__init__.py +22 -0
- pyfect/otel/_attributes.py +67 -0
- pyfect/otel/_producer.py +322 -0
- pyfect/otel/_shutdown.py +26 -0
- pyfect/otel/_span.py +292 -0
- pyfect/otel/_wrapper.py +92 -0
- pyfect/otel/logger.py +154 -0
- pyfect/otel/metrics.py +126 -0
- pyfect/otel/resource.py +111 -0
- pyfect/otel/sdk.py +195 -0
- pyfect/otel/tracer.py +157 -0
- pyfect/partitioned_semaphore.py +211 -0
- pyfect/path.py +304 -0
- pyfect/persistence/__init__.py +77 -0
- pyfect/persistence/_columns.py +32 -0
- pyfect/persistence/_error.py +14 -0
- pyfect/persistence/_seconds.py +68 -0
- pyfect/persistence/_sql_keys.py +47 -0
- pyfect/persistence/circuit_breaker/__init__.py +120 -0
- pyfect/persistence/circuit_breaker/_breaker.py +317 -0
- pyfect/persistence/circuit_breaker/_errors.py +67 -0
- pyfect/persistence/circuit_breaker/_memory.py +243 -0
- pyfect/persistence/circuit_breaker/_redis.py +509 -0
- pyfect/persistence/circuit_breaker/_store.py +60 -0
- pyfect/persistence/circuit_breaker/_types.py +191 -0
- pyfect/persistence/key_value_store/__init__.py +51 -0
- pyfect/persistence/key_value_store/_layers.py +216 -0
- pyfect/persistence/key_value_store/_schema_store.py +91 -0
- pyfect/persistence/key_value_store/_sql.py +197 -0
- pyfect/persistence/key_value_store/_store.py +212 -0
- pyfect/persistence/persistable.py +164 -0
- pyfect/persistence/persisted_cache.py +159 -0
- pyfect/persistence/persisted_queue/__init__.py +75 -0
- pyfect/persistence/persisted_queue/_error.py +42 -0
- pyfect/persistence/persisted_queue/_mailbox.py +101 -0
- pyfect/persistence/persisted_queue/_memory.py +182 -0
- pyfect/persistence/persisted_queue/_queue.py +272 -0
- pyfect/persistence/persisted_queue/_redis.py +455 -0
- pyfect/persistence/persisted_queue/_redis_scripts.py +395 -0
- pyfect/persistence/persisted_queue/_sql.py +334 -0
- pyfect/persistence/persisted_queue/_sql_migrations.py +319 -0
- pyfect/persistence/persisted_queue/_sql_statements.py +441 -0
- pyfect/persistence/persisted_queue/_store.py +147 -0
- pyfect/persistence/persistence/__init__.py +84 -0
- pyfect/persistence/persistence/_kvs.py +135 -0
- pyfect/persistence/persistence/_memory.py +62 -0
- pyfect/persistence/persistence/_redis.py +162 -0
- pyfect/persistence/persistence/_service.py +276 -0
- pyfect/persistence/persistence/_sql.py +499 -0
- pyfect/persistence/rate_limiter/__init__.py +82 -0
- pyfect/persistence/rate_limiter/_errors.py +59 -0
- pyfect/persistence/rate_limiter/_limiter.py +325 -0
- pyfect/persistence/rate_limiter/_memory.py +217 -0
- pyfect/persistence/rate_limiter/_redis.py +485 -0
- pyfect/persistence/rate_limiter/_store.py +89 -0
- pyfect/persistence/redis/__init__.py +52 -0
- pyfect/persistence/redis/_error.py +12 -0
- pyfect/persistence/redis/_make.py +234 -0
- pyfect/persistence/redis/_script.py +78 -0
- pyfect/persistence/redis/_service.py +104 -0
- pyfect/persistence/redis_py.py +303 -0
- pyfect/persistence/user_directories.py +195 -0
- pyfect/platform.py +26 -0
- pyfect/platform_error.py +256 -0
- pyfect/pool/__init__.py +36 -0
- pyfect/pool/_pool.py +707 -0
- pyfect/pool/_state.py +161 -0
- pyfect/pool/_ttl.py +105 -0
- pyfect/pool/_waiters.py +116 -0
- pyfect/primary_key.py +35 -0
- pyfect/process/__init__.py +82 -0
- pyfect/process/_child.py +213 -0
- pyfect/process/_command.py +358 -0
- pyfect/process/_handle.py +77 -0
- pyfect/process/_live.py +455 -0
- pyfect/process/_os.py +78 -0
- pyfect/process/_pipes.py +291 -0
- pyfect/process/_spawner.py +75 -0
- pyfect/pubsub/__init__.py +33 -0
- pyfect/pubsub/_atomic.py +181 -0
- pyfect/pubsub/_hub.py +214 -0
- pyfect/pubsub/_pubsub.py +214 -0
- pyfect/pubsub/_replay.py +107 -0
- pyfect/pubsub/_subscription.py +226 -0
- pyfect/pull.py +132 -0
- pyfect/py.typed +0 -0
- pyfect/pydantic.py +188 -0
- pyfect/queue/__init__.py +33 -0
- pyfect/queue/_queue.py +525 -0
- pyfect/queue/_state.py +111 -0
- pyfect/queue/_views.py +55 -0
- pyfect/random.py +146 -0
- pyfect/rc_map.py +363 -0
- pyfect/rc_ref.py +271 -0
- pyfect/reactivity/__init__.py +53 -0
- pyfect/reactivity/_async_result_schema.py +227 -0
- pyfect/reactivity/_hydration.py +18 -0
- pyfect/reactivity/_live.py +21 -0
- pyfect/reactivity/_reactivity.py +256 -0
- pyfect/reactivity/_result_effect.py +17 -0
- pyfect/reactivity/_time.py +11 -0
- pyfect/reactivity/async_result.py +679 -0
- pyfect/reactivity/atom/__init__.py +143 -0
- pyfect/reactivity/atom/_combinators.py +223 -0
- pyfect/reactivity/atom/_constructors.py +80 -0
- pyfect/reactivity/atom/_conversions.py +79 -0
- pyfect/reactivity/atom/_effect.py +252 -0
- pyfect/reactivity/atom/_fn.py +341 -0
- pyfect/reactivity/atom/_kvs.py +101 -0
- pyfect/reactivity/atom/_optimistic.py +162 -0
- pyfect/reactivity/atom/_runtime.py +323 -0
- pyfect/reactivity/atom/_serializable.py +65 -0
- pyfect/reactivity/atom/_subscription_ref.py +102 -0
- pyfect/reactivity/atom/_swr.py +69 -0
- pyfect/reactivity/atom/_types.py +435 -0
- pyfect/reactivity/atom_http_api.py +667 -0
- pyfect/reactivity/atom_ref.py +260 -0
- pyfect/reactivity/atom_registry/__init__.py +219 -0
- pyfect/reactivity/atom_registry/_batch.py +96 -0
- pyfect/reactivity/atom_registry/_dispatcher.py +60 -0
- pyfect/reactivity/atom_registry/_lifetime.py +202 -0
- pyfect/reactivity/atom_registry/_node.py +423 -0
- pyfect/reactivity/atom_registry/_registry.py +380 -0
- pyfect/reactivity/atom_rpc.py +283 -0
- pyfect/reactivity/hydration.py +200 -0
- pyfect/redacted.py +83 -0
- pyfect/ref.py +129 -0
- pyfect/resource.py +98 -0
- pyfect/result.py +306 -0
- pyfect/rpc/__init__.py +64 -0
- pyfect/rpc/_encoded_schema.py +86 -0
- pyfect/rpc/_json_rpc.py +246 -0
- pyfect/rpc/_methods.py +177 -0
- pyfect/rpc/_rpc.py +498 -0
- pyfect/rpc/client/__init__.py +100 -0
- pyfect/rpc/client/_core.py +449 -0
- pyfect/rpc/client/_http.py +257 -0
- pyfect/rpc/client/_protocol.py +171 -0
- pyfect/rpc/client/_serialized.py +321 -0
- pyfect/rpc/client/_transports.py +328 -0
- pyfect/rpc/client/_worker.py +283 -0
- pyfect/rpc/client_error.py +35 -0
- pyfect/rpc/group.py +296 -0
- pyfect/rpc/message.py +299 -0
- pyfect/rpc/middleware.py +182 -0
- pyfect/rpc/schema.py +89 -0
- pyfect/rpc/serialization.py +366 -0
- pyfect/rpc/server/__init__.py +181 -0
- pyfect/rpc/server/_core.py +549 -0
- pyfect/rpc/server/_protocol.py +123 -0
- pyfect/rpc/server/_serialized.py +363 -0
- pyfect/rpc/server/_stdio.py +101 -0
- pyfect/rpc/server/_transports.py +427 -0
- pyfect/rpc/server/_worker.py +108 -0
- pyfect/rpc/test.py +74 -0
- pyfect/rpc/worker.py +92 -0
- pyfect/run.py +393 -0
- pyfect/schedule/__init__.py +91 -0
- pyfect/schedule/_combinators.py +168 -0
- pyfect/schedule/_constructors.py +223 -0
- pyfect/schedule/_cron.py +49 -0
- pyfect/schedule/_drive.py +191 -0
- pyfect/schedule/_model.py +405 -0
- pyfect/scheduler.py +575 -0
- pyfect/schema/__init__.py +866 -0
- pyfect/schema/_adapters.py +39 -0
- pyfect/schema/_arbitrary_constraint.py +242 -0
- pyfect/schema/_arbitrary_graph.py +325 -0
- pyfect/schema/_arbitrary_links.py +179 -0
- pyfect/schema/_arbitrary_number.py +112 -0
- pyfect/schema/_arrays.py +287 -0
- pyfect/schema/_assignable.py +118 -0
- pyfect/schema/_boolean_literals.py +31 -0
- pyfect/schema/_checks_number.py +216 -0
- pyfect/schema/_checks_order.py +140 -0
- pyfect/schema/_checks_size.py +277 -0
- pyfect/schema/_checks_string.py +241 -0
- pyfect/schema/_class.py +569 -0
- pyfect/schema/_codec_derivation.py +227 -0
- pyfect/schema/_codec_links.py +221 -0
- pyfect/schema/_codecs.py +316 -0
- pyfect/schema/_collections.py +172 -0
- pyfect/schema/_constructor_default.py +89 -0
- pyfect/schema/_data.py +440 -0
- pyfect/schema/_data_codecs.py +145 -0
- pyfect/schema/_decimal_regexp.py +243 -0
- pyfect/schema/_declare.py +68 -0
- pyfect/schema/_derive.py +292 -0
- pyfect/schema/_duration_codecs.py +27 -0
- pyfect/schema/_ecma_pattern.py +416 -0
- pyfect/schema/_error.py +26 -0
- pyfect/schema/_error_instance.py +222 -0
- pyfect/schema/_graph.py +271 -0
- pyfect/schema/_instances.py +240 -0
- pyfect/schema/_jsonschema/__init__.py +90 -0
- pyfect/schema/_jsonschema/_annotations.py +114 -0
- pyfect/schema/_jsonschema/_checks.py +253 -0
- pyfect/schema/_jsonschema/_compile.py +346 -0
- pyfect/schema/_jsonschema/_exact.py +19 -0
- pyfect/schema/_jsonschema/_merge.py +211 -0
- pyfect/schema/_jsonschema/_objects.py +231 -0
- pyfect/schema/_jsonschema/_references.py +221 -0
- pyfect/schema/_jsonschema/_template.py +69 -0
- pyfect/schema/_literals.py +147 -0
- pyfect/schema/_middleware.py +209 -0
- pyfect/schema/_net.py +522 -0
- pyfect/schema/_options.py +49 -0
- pyfect/schema/_parse.py +351 -0
- pyfect/schema/_parsed_text.py +37 -0
- pyfect/schema/_primitives.py +48 -0
- pyfect/schema/_record.py +41 -0
- pyfect/schema/_refine.py +81 -0
- pyfect/schema/_schema.py +158 -0
- pyfect/schema/_semver.py +144 -0
- pyfect/schema/_strategy/__init__.py +258 -0
- pyfect/schema/_strategy/_big_decimal.py +203 -0
- pyfect/schema/_strategy/_composites.py +119 -0
- pyfect/schema/_strategy/_leaves.py +94 -0
- pyfect/schema/_strategy/_net.py +133 -0
- pyfect/schema/_struct.py +87 -0
- pyfect/schema/_struct_keys.py +128 -0
- pyfect/schema/_tagged.py +254 -0
- pyfect/schema/_template_literal.py +172 -0
- pyfect/schema/_to_codec_array_from_single.py +115 -0
- pyfect/schema/_to_codec_go_json.py +174 -0
- pyfect/schema/_to_codec_json.py +73 -0
- pyfect/schema/_to_codec_string_tree.py +115 -0
- pyfect/schema/_to_differ_json_patch.py +44 -0
- pyfect/schema/_to_encoder_xml.py +119 -0
- pyfect/schema/_to_equivalence.py +186 -0
- pyfect/schema/_to_formatter.py +180 -0
- pyfect/schema/_to_iso.py +73 -0
- pyfect/schema/_to_strategy.py +31 -0
- pyfect/schema/_transform.py +210 -0
- pyfect/schema/_tree.py +27 -0
- pyfect/schema/_type_walk.py +53 -0
- pyfect/schema/_undefined.py +58 -0
- pyfect/schema/_value_codecs.py +84 -0
- pyfect/schema/_values.py +123 -0
- pyfect/schema/_void.py +86 -0
- pyfect/schema/ast/__init__.py +227 -0
- pyfect/schema/ast/_annotations.py +43 -0
- pyfect/schema/ast/_arrays.py +210 -0
- pyfect/schema/ast/_base.py +295 -0
- pyfect/schema/ast/_candidates.py +309 -0
- pyfect/schema/ast/_check.py +181 -0
- pyfect/schema/ast/_class.py +159 -0
- pyfect/schema/ast/_constructors.py +65 -0
- pyfect/schema/ast/_declaration.py +97 -0
- pyfect/schema/ast/_encoding.py +111 -0
- pyfect/schema/ast/_json.py +129 -0
- pyfect/schema/ast/_keywords.py +125 -0
- pyfect/schema/ast/_literal.py +157 -0
- pyfect/schema/ast/_objects.py +356 -0
- pyfect/schema/ast/_record.py +36 -0
- pyfect/schema/ast/_result.py +116 -0
- pyfect/schema/ast/_steps.py +209 -0
- pyfect/schema/ast/_suspend.py +65 -0
- pyfect/schema/ast/_template_literal.py +256 -0
- pyfect/schema/ast/_union.py +172 -0
- pyfect/schema/getter/__init__.py +136 -0
- pyfect/schema/getter/_binary.py +104 -0
- pyfect/schema/getter/_coerce.py +196 -0
- pyfect/schema/getter/_getter.py +243 -0
- pyfect/schema/getter/_make.py +151 -0
- pyfect/schema/getter/_text.py +141 -0
- pyfect/schema/getter/_tree_record.py +170 -0
- pyfect/schema/issue.py +420 -0
- pyfect/schema/model/__init__.py +120 -0
- pyfect/schema/model/_class.py +245 -0
- pyfect/schema/model/_dates.py +103 -0
- pyfect/schema/model/_fields.py +77 -0
- pyfect/schema/model/_toolkit.py +114 -0
- pyfect/schema/model/_uuid.py +69 -0
- pyfect/schema/representation/__init__.py +424 -0
- pyfect/schema/representation/_builtin_revivers.py +331 -0
- pyfect/schema/representation/_code.py +106 -0
- pyfect/schema/representation/_code_builtins.py +281 -0
- pyfect/schema/representation/_code_document.py +563 -0
- pyfect/schema/representation/_code_sort.py +111 -0
- pyfect/schema/representation/_from.py +278 -0
- pyfect/schema/representation/_import/__init__.py +78 -0
- pyfect/schema/representation/_import/_finalize.py +121 -0
- pyfect/schema/representation/_import/_intersect.py +467 -0
- pyfect/schema/representation/_import/_js_order.py +66 -0
- pyfect/schema/representation/_import/_keywords.py +224 -0
- pyfect/schema/representation/_import/_nodes.py +199 -0
- pyfect/schema/representation/_import/_translate.py +455 -0
- pyfect/schema/representation/_json.py +520 -0
- pyfect/schema/representation/_json_schema.py +178 -0
- pyfect/schema/representation/_model.py +284 -0
- pyfect/schema/representation/_revivers.py +89 -0
- pyfect/schema/representation/_to.py +249 -0
- pyfect/schema/transformation/__init__.py +99 -0
- pyfect/schema/transformation/_builtins.py +314 -0
- pyfect/schema/transformation/_durations.py +150 -0
- pyfect/schema/transformation/_transformation.py +177 -0
- pyfect/schema/variant_schema/__init__.py +69 -0
- pyfect/schema/variant_schema/_class.py +188 -0
- pyfect/schema/variant_schema/_defaults.py +30 -0
- pyfect/schema/variant_schema/_field.py +32 -0
- pyfect/schema/variant_schema/_struct.py +130 -0
- pyfect/schema/variant_schema/_toolkit.py +160 -0
- pyfect/scope.py +374 -0
- pyfect/scoped_ref.py +124 -0
- pyfect/semaphore.py +276 -0
- pyfect/semver.py +403 -0
- pyfect/semver_range.py +420 -0
- pyfect/sink/__init__.py +131 -0
- pyfect/sink/_combinators.py +151 -0
- pyfect/sink/_constructors.py +187 -0
- pyfect/sink/_context.py +87 -0
- pyfect/sink/_folds.py +336 -0
- pyfect/sink/_for_each.py +87 -0
- pyfect/sink/_sink.py +265 -0
- pyfect/sink/_steps.py +34 -0
- pyfect/sink/_taking.py +183 -0
- pyfect/socket/__init__.py +146 -0
- pyfect/socket/_accepted.py +65 -0
- pyfect/socket/_connection.py +384 -0
- pyfect/socket/_errors.py +135 -0
- pyfect/socket/_loop.py +66 -0
- pyfect/socket/_net.py +281 -0
- pyfect/socket/_socket.py +245 -0
- pyfect/socket/_tls.py +88 -0
- pyfect/socket/_tls_session.py +117 -0
- pyfect/socket/_web_socket.py +555 -0
- pyfect/socket/datagram/__init__.py +110 -0
- pyfect/socket/datagram/_core.py +460 -0
- pyfect/socket/datagram/_errors.py +102 -0
- pyfect/socket/datagram/_live.py +675 -0
- pyfect/socket/datagram/_model.py +217 -0
- pyfect/socket/server.py +258 -0
- pyfect/socket/ws.py +484 -0
- pyfect/sql/__init__.py +60 -0
- pyfect/sql/_loop.py +134 -0
- pyfect/sql/clickhouse/__init__.py +74 -0
- pyfect/sql/clickhouse/_connection.py +237 -0
- pyfect/sql/clickhouse/_rows.py +87 -0
- pyfect/sql/clickhouse/client.py +322 -0
- pyfect/sql/clickhouse/config.py +241 -0
- pyfect/sql/clickhouse/driver.py +434 -0
- pyfect/sql/clickhouse/error.py +106 -0
- pyfect/sql/clickhouse/migrator.py +47 -0
- pyfect/sql/clickhouse/params.py +168 -0
- pyfect/sql/client/__init__.py +35 -0
- pyfect/sql/client/_client.py +309 -0
- pyfect/sql/client/_sqlite_acquirers.py +130 -0
- pyfect/sql/client/_transaction.py +410 -0
- pyfect/sql/connection.py +87 -0
- pyfect/sql/d1/__init__.py +48 -0
- pyfect/sql/d1/api.py +270 -0
- pyfect/sql/d1/client.py +344 -0
- pyfect/sql/d1/config.py +55 -0
- pyfect/sql/error.py +311 -0
- pyfect/sql/libsql/__init__.py +58 -0
- pyfect/sql/libsql/_connection.py +110 -0
- pyfect/sql/libsql/_hrana.py +258 -0
- pyfect/sql/libsql/_local.py +251 -0
- pyfect/sql/libsql/_targets.py +28 -0
- pyfect/sql/libsql/_values.py +46 -0
- pyfect/sql/libsql/client.py +225 -0
- pyfect/sql/libsql/config.py +170 -0
- pyfect/sql/libsql/migrator.py +43 -0
- pyfect/sql/libsql/sdk.py +123 -0
- pyfect/sql/migrator.py +434 -0
- pyfect/sql/model.py +324 -0
- pyfect/sql/mssql/__init__.py +79 -0
- pyfect/sql/mssql/_connection.py +169 -0
- pyfect/sql/mssql/_driver.py +103 -0
- pyfect/sql/mssql/_names.py +9 -0
- pyfect/sql/mssql/_pool.py +125 -0
- pyfect/sql/mssql/_tds.py +447 -0
- pyfect/sql/mssql/_tds_params.py +155 -0
- pyfect/sql/mssql/_worker.py +155 -0
- pyfect/sql/mssql/client.py +344 -0
- pyfect/sql/mssql/config.py +118 -0
- pyfect/sql/mssql/error.py +111 -0
- pyfect/sql/mssql/migrator.py +43 -0
- pyfect/sql/mssql/parameter.py +44 -0
- pyfect/sql/mssql/procedure.py +119 -0
- pyfect/sql/mssql/types.py +137 -0
- pyfect/sql/mysql/__init__.py +60 -0
- pyfect/sql/mysql/_asyncmy.py +168 -0
- pyfect/sql/mysql/_bind.py +76 -0
- pyfect/sql/mysql/_connection.py +156 -0
- pyfect/sql/mysql/_pool.py +63 -0
- pyfect/sql/mysql/_session.py +262 -0
- pyfect/sql/mysql/client.py +244 -0
- pyfect/sql/mysql/config.py +108 -0
- pyfect/sql/mysql/error.py +104 -0
- pyfect/sql/mysql/migrator.py +44 -0
- pyfect/sql/pg/__init__.py +82 -0
- pyfect/sql/pg/_resolve.py +284 -0
- pyfect/sql/pg/_session.py +380 -0
- pyfect/sql/pg/client.py +398 -0
- pyfect/sql/pg/config.py +142 -0
- pyfect/sql/pg/connection.py +585 -0
- pyfect/sql/pg/error.py +131 -0
- pyfect/sql/pg/migrator.py +139 -0
- pyfect/sql/pg/pool.py +265 -0
- pyfect/sql/resolver.py +294 -0
- pyfect/sql/result.py +24 -0
- pyfect/sql/schema.py +116 -0
- pyfect/sql/sqlite/__init__.py +26 -0
- pyfect/sql/sqlite/_connection.py +230 -0
- pyfect/sql/sqlite/_worker.py +71 -0
- pyfect/sql/sqlite/client.py +248 -0
- pyfect/sql/sqlite/migrator.py +43 -0
- pyfect/sql/statement/__init__.py +144 -0
- pyfect/sql/statement/_compiler.py +384 -0
- pyfect/sql/statement/_segments.py +487 -0
- pyfect/sql/statement/_statement.py +526 -0
- pyfect/sql/statement/_transforms.py +93 -0
- pyfect/sql/stream.py +88 -0
- pyfect/stdio.py +206 -0
- pyfect/stream/__init__.py +151 -0
- pyfect/stream/_async_iterable.py +129 -0
- pyfect/stream/_base.py +69 -0
- pyfect/stream/_bridge_methods.py +139 -0
- pyfect/stream/_catch.py +135 -0
- pyfect/stream/_catch_reason.py +558 -0
- pyfect/stream/_channel_methods.py +61 -0
- pyfect/stream/_chunk_methods.py +169 -0
- pyfect/stream/_chunking.py +310 -0
- pyfect/stream/_concat.py +65 -0
- pyfect/stream/_constructors.py +341 -0
- pyfect/stream/_context.py +147 -0
- pyfect/stream/_error_methods.py +254 -0
- pyfect/stream/_execution_plan.py +199 -0
- pyfect/stream/_fanout.py +154 -0
- pyfect/stream/_fanout_methods.py +183 -0
- pyfect/stream/_filter_methods.py +203 -0
- pyfect/stream/_grouping.py +168 -0
- pyfect/stream/_many.py +65 -0
- pyfect/stream/_map_methods.py +233 -0
- pyfect/stream/_mapping.py +126 -0
- pyfect/stream/_run.py +114 -0
- pyfect/stream/_run_methods.py +114 -0
- pyfect/stream/_service_methods.py +36 -0
- pyfect/stream/_sink_methods.py +151 -0
- pyfect/stream/_sinking.py +277 -0
- pyfect/stream/_sources.py +124 -0
- pyfect/stream/_stream.py +162 -0
- pyfect/stream/_taking.py +330 -0
- pyfect/stream/_text.py +43 -0
- pyfect/stream/_timing.py +294 -0
- pyfect/stream/_timing_methods.py +252 -0
- pyfect/stream/_zip_methods.py +279 -0
- pyfect/stream/_zipping.py +213 -0
- pyfect/subscription_ref.py +66 -0
- pyfect/synchronized_ref.py +38 -0
- pyfect/take.py +36 -0
- pyfect/terminal/__init__.py +41 -0
- pyfect/terminal/_keys.py +113 -0
- pyfect/terminal/_live.py +223 -0
- pyfect/terminal/_service.py +73 -0
- pyfect/testing/__init__.py +122 -0
- pyfect/testing/_assertions.py +92 -0
- pyfect/testing/_clock.py +309 -0
- pyfect/testing/_console.py +164 -0
- pyfect/testing/_crypto.py +44 -0
- pyfect/testing/_decorators.py +211 -0
- pyfect/testing/_flaky.py +34 -0
- pyfect/testing/_layers.py +153 -0
- pyfect/testing/_prop.py +255 -0
- pyfect/testing/_runners.py +84 -0
- pyfect/testing/_runtime.py +174 -0
- pyfect/testing/_schema.py +238 -0
- pyfect/testing/plugin.py +59 -0
- pyfect/tracer/__init__.py +107 -0
- pyfect/tracer/_model.py +176 -0
- pyfect/tracer/_native.py +172 -0
- pyfect/tracer/_refs.py +87 -0
- pyfect/tracer/_spans.py +269 -0
- pyfect/transaction.py +340 -0
- pyfect/trie.py +317 -0
- pyfect/tx_chunk.py +127 -0
- pyfect/tx_deferred.py +75 -0
- pyfect/tx_hash_map.py +265 -0
- pyfect/tx_hash_set.py +151 -0
- pyfect/tx_priority_queue.py +224 -0
- pyfect/tx_pubsub.py +194 -0
- pyfect/tx_queue/__init__.py +27 -0
- pyfect/tx_queue/_queue.py +359 -0
- pyfect/tx_queue/_views.py +60 -0
- pyfect/tx_reentrant_lock.py +201 -0
- pyfect/tx_ref.py +79 -0
- pyfect/tx_semaphore.py +136 -0
- pyfect/tx_subscription_ref.py +118 -0
- pyfect/workers/__init__.py +62 -0
- pyfect/workers/_frames.py +82 -0
- pyfect/workers/_mailbox.py +51 -0
- pyfect/workers/_port.py +106 -0
- pyfect/workers/_process.py +155 -0
- pyfect/workers/_thread.py +100 -0
- pyfect/workers/python_worker.py +133 -0
- pyfect/workers/python_worker_runner.py +112 -0
- pyfect/workers/transferable.py +103 -0
- pyfect/workers/worker.py +273 -0
- pyfect/workers/worker_error.py +86 -0
- pyfect/workers/worker_runner.py +85 -0
- pyfect/workflow/__init__.py +78 -0
- pyfect/workflow/_crypto.py +23 -0
- pyfect/workflow/_encoded.py +381 -0
- pyfect/workflow/_memory.py +424 -0
- pyfect/workflow/_result.py +43 -0
- pyfect/workflow/_services.py +241 -0
- pyfect/workflow/_suspension.py +153 -0
- pyfect/workflow/activity.py +427 -0
- pyfect/workflow/durable_clock.py +72 -0
- pyfect/workflow/durable_deferred.py +403 -0
- pyfect/workflow/durable_queue.py +259 -0
- pyfect/workflow/workflow.py +509 -0
- pyfect/workflow/workflow_engine.py +42 -0
- pyfect/workflow/workflow_proxy.py +161 -0
- pyfect/workflow/workflow_proxy_server.py +146 -0
- pyfect_dev-0.1.0.dist-info/METADATA +296 -0
- pyfect_dev-0.1.0.dist-info/RECORD +1265 -0
- pyfect_dev-0.1.0.dist-info/WHEEL +4 -0
- pyfect_dev-0.1.0.dist-info/entry_points.txt +3 -0
- pyfect_dev-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""The ``httpx.AsyncClient`` options that would add to every request
|
|
2
|
+
(``headers``, ``params``, ``cookies``, ``auth``), taken out of httpx's hands.
|
|
3
|
+
|
|
4
|
+
httpx merges them into each request it sends, after pyfect's request
|
|
5
|
+
transformations (``follow_redirects`` stripping credentials on a hop to
|
|
6
|
+
another origin among them) have run. Parsed here once into a
|
|
7
|
+
``RequestDefaults`` that the pyfect client applies as a request
|
|
8
|
+
preprocessing step instead, so the request pyfect sees is the request sent.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from collections.abc import Mapping
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from typing import Any, Final
|
|
16
|
+
|
|
17
|
+
from pyfect._extras import missing_extra
|
|
18
|
+
from pyfect.http.request import HttpClientRequest
|
|
19
|
+
|
|
20
|
+
REQUEST_DEFAULT_OPTIONS: Final = frozenset(("headers", "params", "cookies", "auth"))
|
|
21
|
+
"""The ``httpx.AsyncClient`` parameters httpx merges into every request."""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True, slots=True)
|
|
25
|
+
class RequestDefaults:
|
|
26
|
+
"""What each request gets unless it sets the same name itself."""
|
|
27
|
+
|
|
28
|
+
headers: tuple[tuple[str, str], ...] = ()
|
|
29
|
+
params: tuple[tuple[str, str], ...] = ()
|
|
30
|
+
basic_auth: tuple[str, str] | None = None
|
|
31
|
+
|
|
32
|
+
def is_empty(self) -> bool:
|
|
33
|
+
return not self.headers and not self.params and self.basic_auth is None
|
|
34
|
+
|
|
35
|
+
def apply(self, request: HttpClientRequest) -> HttpClientRequest:
|
|
36
|
+
if self.basic_auth is not None and "authorization" not in request.headers:
|
|
37
|
+
request = request.basic_auth(*self.basic_auth)
|
|
38
|
+
missing = [(name, value) for name, value in self.headers if name not in request.headers]
|
|
39
|
+
if missing:
|
|
40
|
+
request = request.update_headers(lambda headers: headers.set_all(missing))
|
|
41
|
+
params = request.url_params
|
|
42
|
+
added = [(name, value) for name, value in self.params if not params.get_all(name)]
|
|
43
|
+
if added:
|
|
44
|
+
request = request.set_url_params(params.append_all(added))
|
|
45
|
+
return request
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _text(value: str | bytes) -> str:
|
|
49
|
+
return value.decode("latin-1") if isinstance(value, bytes) else value
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _basic_auth(auth: object) -> tuple[str, str] | None:
|
|
53
|
+
match auth:
|
|
54
|
+
case None:
|
|
55
|
+
return None
|
|
56
|
+
case (str() | bytes() as username, str() | bytes() as password):
|
|
57
|
+
return _text(username), _text(password)
|
|
58
|
+
case _:
|
|
59
|
+
raise TypeError(
|
|
60
|
+
"httpx_client: auth must be a (username, password) pair; set any other "
|
|
61
|
+
"credential per request (client.map_request(lambda r: r.bearer_token(...))) "
|
|
62
|
+
"so follow_redirects can drop it on a hop to another origin"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _cookie_header(cookies: object) -> tuple[tuple[str, str], ...]:
|
|
67
|
+
match cookies:
|
|
68
|
+
case None:
|
|
69
|
+
return ()
|
|
70
|
+
case Mapping():
|
|
71
|
+
pairs = [(str(name), str(value)) for name, value in cookies.items()] # pyright: ignore[reportUnknownVariableType, reportUnknownArgumentType]
|
|
72
|
+
return (
|
|
73
|
+
(("cookie", "; ".join(f"{name}={value}" for name, value in pairs)),)
|
|
74
|
+
if pairs
|
|
75
|
+
else ()
|
|
76
|
+
)
|
|
77
|
+
case _:
|
|
78
|
+
raise TypeError(
|
|
79
|
+
"httpx_client: cookies must be a mapping of names to values; "
|
|
80
|
+
"use HttpClientService.with_cookies_ref for a cookie jar"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def import_httpx(): # the inferred return type is the httpx module
|
|
85
|
+
"""The ``httpx`` module, imported when a client is made, so that
|
|
86
|
+
``pyfect.http`` imports without the ``httpx`` extra."""
|
|
87
|
+
try:
|
|
88
|
+
import httpx
|
|
89
|
+
except ImportError as error:
|
|
90
|
+
raise missing_extra("pyfect.http.httpx_client", "httpx") from error
|
|
91
|
+
return httpx
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _header_pairs(headers: Any) -> tuple[tuple[str, str], ...]:
|
|
95
|
+
if headers is None:
|
|
96
|
+
return ()
|
|
97
|
+
return tuple(
|
|
98
|
+
(name.lower(), value) for name, value in import_httpx().Headers(headers).multi_items()
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _param_pairs(params: Any) -> tuple[tuple[str, str], ...]:
|
|
103
|
+
if params is None:
|
|
104
|
+
return ()
|
|
105
|
+
return tuple(import_httpx().QueryParams(params).multi_items())
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def split_options(options: Mapping[str, Any]) -> tuple[RequestDefaults, dict[str, Any]]:
|
|
109
|
+
"""``options`` split into the request defaults and the rest (passed to
|
|
110
|
+
``httpx.AsyncClient``). Raises ``TypeError`` for a default pyfect could
|
|
111
|
+
not keep from following a redirect to another origin."""
|
|
112
|
+
transport = {
|
|
113
|
+
name: value for name, value in options.items() if name not in REQUEST_DEFAULT_OPTIONS
|
|
114
|
+
}
|
|
115
|
+
defaults = RequestDefaults(
|
|
116
|
+
headers=_header_pairs(options.get("headers")) + _cookie_header(options.get("cookies")),
|
|
117
|
+
params=_param_pairs(options.get("params")),
|
|
118
|
+
basic_auth=_basic_auth(options.get("auth")),
|
|
119
|
+
)
|
|
120
|
+
return defaults, transport
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""An ``HttpClientService`` answered by an app in the same process (the
|
|
2
|
+
client Effect's ``HttpApiTest.groups`` builds).
|
|
3
|
+
|
|
4
|
+
Each request runs the app on the requesting fiber, in its own scope forked
|
|
5
|
+
from the client's. A streamed response body is not buffered: the client
|
|
6
|
+
reads it as the app writes it, one chunk per pull, and the request's scope
|
|
7
|
+
closes when the body ends or the reader stops (or with the client's scope,
|
|
8
|
+
for a body never read).
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import Any, Never
|
|
14
|
+
|
|
15
|
+
from pyfect._core import Effect
|
|
16
|
+
from pyfect.effect import gen, provide_service, succeed
|
|
17
|
+
from pyfect.exit import Exit, Success
|
|
18
|
+
from pyfect.http._request_state import CurrentRequestState, RequestState
|
|
19
|
+
from pyfect.http.client import HttpClientService
|
|
20
|
+
from pyfect.http.client import make as make_http_client
|
|
21
|
+
from pyfect.http.error import HttpClientError
|
|
22
|
+
from pyfect.http.http_effect import scope_transfer_to_stream
|
|
23
|
+
from pyfect.http.request import HttpClientRequest
|
|
24
|
+
from pyfect.http.server_request import HttpServerRequest, from_client_request
|
|
25
|
+
from pyfect.http.server_response import HttpServerResponse, to_client_response
|
|
26
|
+
from pyfect.scope import CloseableScope, Scope
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def client(
|
|
30
|
+
app: Effect[HttpServerResponse, Any, Any], scope: CloseableScope
|
|
31
|
+
) -> HttpClientService[HttpClientError, Any]:
|
|
32
|
+
"""A client whose requests ``app`` answers; ``app`` 's failures are
|
|
33
|
+
defects of the request. Bodies left open close with ``scope``."""
|
|
34
|
+
return make_http_client(lambda request, _url, _signal, _fiber: _handle(app, scope, request))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _handle(
|
|
38
|
+
app: Effect[HttpServerResponse, Any, Any],
|
|
39
|
+
scope: CloseableScope,
|
|
40
|
+
request: HttpClientRequest,
|
|
41
|
+
) -> Effect[Any, Never, Any]:
|
|
42
|
+
def run() -> Any:
|
|
43
|
+
request_scope: CloseableScope = yield from scope.fork()
|
|
44
|
+
server_request = from_client_request(request)
|
|
45
|
+
state = RequestState()
|
|
46
|
+
transferred = False
|
|
47
|
+
|
|
48
|
+
def pre_response(response: HttpServerResponse) -> Effect[HttpServerResponse, Any, Any]:
|
|
49
|
+
pre = state.pre_response_handler
|
|
50
|
+
return succeed(response) if pre is None else pre(server_request, response)
|
|
51
|
+
|
|
52
|
+
def to_client(response: HttpServerResponse) -> Any:
|
|
53
|
+
nonlocal transferred
|
|
54
|
+
transfer = scope_transfer_to_stream(response)
|
|
55
|
+
transferred = transfer is not response
|
|
56
|
+
return to_client_response(transfer, request=request)
|
|
57
|
+
|
|
58
|
+
def on_exit(exit_: Exit[Any, Any]) -> Effect[None]:
|
|
59
|
+
if transferred and isinstance(exit_, Success):
|
|
60
|
+
return succeed(None)
|
|
61
|
+
return request_scope.close(exit_)
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
yield from app.flat_map(pre_response)
|
|
65
|
+
.map(to_client)
|
|
66
|
+
.pipe(provide_service(HttpServerRequest, server_request))
|
|
67
|
+
.pipe(provide_service(CurrentRequestState, state))
|
|
68
|
+
.pipe(provide_service(Scope, request_scope))
|
|
69
|
+
.or_die()
|
|
70
|
+
.on_exit(on_exit)
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
return gen(run)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
__all__ = ["client"]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""What a request being handled keeps besides its context: the handlers
|
|
2
|
+
run on its response before it is sent, whether the logger is off, and
|
|
3
|
+
whether its scope closes with the handler or with the response stream."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from collections.abc import Callable
|
|
8
|
+
from typing import TYPE_CHECKING, Any
|
|
9
|
+
|
|
10
|
+
from pyfect._core import Effect
|
|
11
|
+
from pyfect.context import Context, Tag
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from pyfect.http.server_error import HttpServerError
|
|
15
|
+
from pyfect.http.server_request import ServerRequest
|
|
16
|
+
from pyfect.http.server_response import HttpServerResponse
|
|
17
|
+
|
|
18
|
+
type PreResponseHandler = Callable[
|
|
19
|
+
[ServerRequest, HttpServerResponse], Effect[HttpServerResponse, HttpServerError]
|
|
20
|
+
]
|
|
21
|
+
"""Runs on a response before it is sent, and may replace it."""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class RequestState:
|
|
25
|
+
__slots__ = ("handled", "logger_disabled", "pre_response_handler", "scope_ejected")
|
|
26
|
+
|
|
27
|
+
def __init__(self) -> None:
|
|
28
|
+
self.pre_response_handler: PreResponseHandler | None = None
|
|
29
|
+
self.logger_disabled = False
|
|
30
|
+
self.handled = False
|
|
31
|
+
self.scope_ejected = False
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class CurrentRequestState(Tag[RequestState], key="effect/http/HttpEffect/CurrentRequestState"):
|
|
35
|
+
"""The state of the request being handled."""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get(context: Context[Any]) -> RequestState | None:
|
|
39
|
+
found, state = context.lookup(CurrentRequestState)
|
|
40
|
+
return state if found else None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def append_pre_response_handler_unsafe(context: Context[Any], handler: PreResponseHandler) -> None:
|
|
44
|
+
"""Run ``handler`` after the handlers already added (outside a request
|
|
45
|
+
being handled, nothing)."""
|
|
46
|
+
state = get(context)
|
|
47
|
+
if state is None:
|
|
48
|
+
return
|
|
49
|
+
previous = state.pre_response_handler
|
|
50
|
+
if previous is None:
|
|
51
|
+
state.pre_response_handler = handler
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
def both(
|
|
55
|
+
request: ServerRequest, response: HttpServerResponse
|
|
56
|
+
) -> Effect[HttpServerResponse, HttpServerError]:
|
|
57
|
+
return previous(request, response).flat_map(lambda changed: handler(request, changed))
|
|
58
|
+
|
|
59
|
+
state.pre_response_handler = both
|
pyfect/http/_vary.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""The ``Vary`` header a middleware extends."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Mapping
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def vary_with(headers: Mapping[str, str], dimension: str) -> str:
|
|
9
|
+
"""``Vary`` with ``dimension`` added, unless it (or ``*``) is there."""
|
|
10
|
+
vary = headers.get("vary")
|
|
11
|
+
if vary is None:
|
|
12
|
+
return dimension
|
|
13
|
+
members = [member.strip().lower() for member in vary.split(",")]
|
|
14
|
+
return vary if "*" in members or dimension.lower() in members else f"{vary}, {dimension}"
|
pyfect/http/abort.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Aborting a request in flight (the ``AbortController`` / ``AbortSignal``
|
|
2
|
+
pair Effect's clients use).
|
|
3
|
+
|
|
4
|
+
A client backend gets the request's ``AbortSignal`` and listens on it: the
|
|
5
|
+
signal fires when the request is interrupted, when an unread response is
|
|
6
|
+
garbage collected, when its stream ends or when its ``with_scope`` scope
|
|
7
|
+
closes. Listeners run once, on the thread that aborts.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import threading
|
|
13
|
+
from collections.abc import Callable
|
|
14
|
+
from typing import final
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _noop() -> None:
|
|
18
|
+
return None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@final
|
|
22
|
+
class AbortSignal:
|
|
23
|
+
__slots__ = ("_listeners", "_lock", "aborted")
|
|
24
|
+
|
|
25
|
+
def __init__(self) -> None:
|
|
26
|
+
self.aborted = False
|
|
27
|
+
self._listeners: list[Callable[[], object]] = []
|
|
28
|
+
self._lock = threading.Lock()
|
|
29
|
+
|
|
30
|
+
def add_listener(self, listener: Callable[[], object]) -> Callable[[], object]:
|
|
31
|
+
"""Run ``listener`` on abort (now, if aborted already); returns a
|
|
32
|
+
function that removes it."""
|
|
33
|
+
with self._lock:
|
|
34
|
+
if not self.aborted:
|
|
35
|
+
self._listeners.append(listener)
|
|
36
|
+
return lambda: self._remove(listener)
|
|
37
|
+
listener()
|
|
38
|
+
return _noop
|
|
39
|
+
|
|
40
|
+
def _remove(self, listener: Callable[[], object]) -> None:
|
|
41
|
+
with self._lock:
|
|
42
|
+
if listener in self._listeners:
|
|
43
|
+
self._listeners.remove(listener)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@final
|
|
47
|
+
class AbortController:
|
|
48
|
+
__slots__ = ("signal",)
|
|
49
|
+
|
|
50
|
+
def __init__(self) -> None:
|
|
51
|
+
self.signal = AbortSignal()
|
|
52
|
+
|
|
53
|
+
def abort(self) -> None:
|
|
54
|
+
"""Fire the signal; later calls do nothing."""
|
|
55
|
+
signal = self.signal
|
|
56
|
+
with signal._lock: # pyright: ignore[reportPrivateUsage]
|
|
57
|
+
if signal.aborted:
|
|
58
|
+
return
|
|
59
|
+
signal.aborted = True
|
|
60
|
+
listeners, signal._listeners = signal._listeners, [] # pyright: ignore[reportPrivateUsage]
|
|
61
|
+
for listener in listeners:
|
|
62
|
+
listener()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
__all__ = ["AbortController", "AbortSignal"]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""ASGI: HTTP apps on any ASGI 3 server, and ASGI applications inside
|
|
2
|
+
apps.
|
|
3
|
+
|
|
4
|
+
``to_asgi(app, layer)`` is an ASGI application for uvicorn, hypercorn,
|
|
5
|
+
granian or a host framework (FastAPI's ``app.mount``). Its ``lifespan``
|
|
6
|
+
scope builds the layer in a ``ManagedRuntime`` and releases it at
|
|
7
|
+
shutdown; each request runs on its own fiber on the server's loop::
|
|
8
|
+
|
|
9
|
+
app = router.to_http_effect(routes)
|
|
10
|
+
asgi_app = asgi.to_asgi(app, services) # uvicorn module:asgi_app
|
|
11
|
+
|
|
12
|
+
Request bodies are streams that wait for the client; streamed responses
|
|
13
|
+
are sent chunk by chunk; a client disconnect interrupts the request (a
|
|
14
|
+
client abort, 499) and stops its body. A ``websocket`` scope is a ``GET``
|
|
15
|
+
request whose ``upgrade`` is a WebSocket ``Socket`` (``request.upgrade``
|
|
16
|
+
accepts it); an app that does not upgrade answers with its response.
|
|
17
|
+
Under a host framework's ``Mount``, ``root_path`` is removed from the
|
|
18
|
+
request's URL. Host frameworks send no lifespan to mounted apps: pass
|
|
19
|
+
``asgi_app.lifespan()`` to the host's own (``FastAPI(lifespan=lambda _:
|
|
20
|
+
asgi_app.lifespan())``).
|
|
21
|
+
|
|
22
|
+
``router.to_asgi(routes)`` serves a router's routes the same way.
|
|
23
|
+
|
|
24
|
+
The other way round, ``from_asgi(fastapi_app)`` is an app answering with
|
|
25
|
+
another framework's application, mountable under a router prefix
|
|
26
|
+
(``root_path`` is the prefix), and ``lifespan(fastapi_app)`` runs its
|
|
27
|
+
startup and shutdown in a scope. ``pyfect.http.uvicorn_server`` serves an
|
|
28
|
+
app on a port with uvicorn (extra ``pyfect-dev[server]``).
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from pyfect._public import publish
|
|
32
|
+
from pyfect.http.asgi._app import AsgiApp, to_asgi, to_asgi_with
|
|
33
|
+
from pyfect.http.asgi._http import HIGH_WATER_MARK, ClientDisconnectedError
|
|
34
|
+
from pyfect.http.asgi._mount import AsgiLifespanError, AsgiNoResponseError, from_asgi, lifespan
|
|
35
|
+
from pyfect.http.asgi._serve import AsgiHandler, UnsupportedScopeError
|
|
36
|
+
from pyfect.http.asgi._types import AsgiApplication, Message, Receive, Scope, Send
|
|
37
|
+
from pyfect.http.asgi._web_socket import AsgiWebSocket
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
"HIGH_WATER_MARK",
|
|
41
|
+
"AsgiApp",
|
|
42
|
+
"AsgiApplication",
|
|
43
|
+
"AsgiHandler",
|
|
44
|
+
"AsgiLifespanError",
|
|
45
|
+
"AsgiNoResponseError",
|
|
46
|
+
"AsgiWebSocket",
|
|
47
|
+
"ClientDisconnectedError",
|
|
48
|
+
"Message",
|
|
49
|
+
"Receive",
|
|
50
|
+
"Scope",
|
|
51
|
+
"Send",
|
|
52
|
+
"UnsupportedScopeError",
|
|
53
|
+
"from_asgi",
|
|
54
|
+
"lifespan",
|
|
55
|
+
"to_asgi",
|
|
56
|
+
"to_asgi_with",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
publish(globals())
|
pyfect/http/asgi/_app.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""``to_asgi``: an app as an ASGI 3 application whose services a layer
|
|
2
|
+
builds, in a ``ManagedRuntime`` that lives as long as the server's
|
|
3
|
+
lifespan."""
|
|
4
|
+
# pyright: reportPrivateUsage=false
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from collections.abc import AsyncGenerator, Callable
|
|
9
|
+
from contextlib import asynccontextmanager
|
|
10
|
+
from typing import Any, Never, overload
|
|
11
|
+
|
|
12
|
+
from pyfect._context_effects import provide_context
|
|
13
|
+
from pyfect._core import Effect, _WithFiber
|
|
14
|
+
from pyfect._effect_args import require_effect
|
|
15
|
+
from pyfect._fiber import Fiber
|
|
16
|
+
from pyfect._layer_core import MemoMap, require_layer
|
|
17
|
+
from pyfect.context import Context, Tag
|
|
18
|
+
from pyfect.effect import succeed
|
|
19
|
+
from pyfect.http.asgi._serve import AsgiHandler
|
|
20
|
+
from pyfect.http.asgi._types import Receive, Scope, Send
|
|
21
|
+
from pyfect.http.http_effect import HttpMiddleware
|
|
22
|
+
from pyfect.http.server_request import HttpServerRequest
|
|
23
|
+
from pyfect.http.server_response import HttpServerResponse
|
|
24
|
+
from pyfect.layer import Layer, provide_merge
|
|
25
|
+
from pyfect.layer import effect as layer_effect
|
|
26
|
+
from pyfect.layer import empty as empty_layer
|
|
27
|
+
from pyfect.managed_runtime import ManagedRuntime
|
|
28
|
+
from pyfect.scope import Scope as ScopeTag
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AsgiApp:
|
|
32
|
+
"""An ASGI 3 application (``await app(scope, receive, send)``) serving
|
|
33
|
+
an HTTP app.
|
|
34
|
+
|
|
35
|
+
``runtime`` holds the layer's services: built by the ``lifespan``
|
|
36
|
+
scope's startup, or by the first request when the server sends none,
|
|
37
|
+
and released at its shutdown, which interrupts requests in flight
|
|
38
|
+
(a plain app is uninterruptible, as in Effect, so it is awaited; router
|
|
39
|
+
routes are interruptible). Each request runs on its own fiber, on the
|
|
40
|
+
server's loop."""
|
|
41
|
+
|
|
42
|
+
__slots__ = ("_handler", "runtime")
|
|
43
|
+
|
|
44
|
+
def __init__(
|
|
45
|
+
self,
|
|
46
|
+
app: Effect[HttpServerResponse, Any, Any],
|
|
47
|
+
runtime: ManagedRuntime[Any, Any],
|
|
48
|
+
middleware: HttpMiddleware | None,
|
|
49
|
+
) -> None:
|
|
50
|
+
self.runtime = runtime
|
|
51
|
+
self._handler = AsgiHandler(app, middleware, Context.empty(), self._fork)
|
|
52
|
+
|
|
53
|
+
def _fork(self, handled: Effect[None, Never, Any], context: Context[Any]) -> Fiber[None, Never]:
|
|
54
|
+
return self.runtime.run_fork(handled.pipe(provide_context(context)))
|
|
55
|
+
|
|
56
|
+
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
|
57
|
+
if scope["type"] == "lifespan":
|
|
58
|
+
await self._lifespan(receive, send)
|
|
59
|
+
else:
|
|
60
|
+
await self._handler(scope, receive, send)
|
|
61
|
+
|
|
62
|
+
async def _lifespan(self, receive: Receive, send: Send) -> None:
|
|
63
|
+
while True:
|
|
64
|
+
message = await receive()
|
|
65
|
+
if message["type"] == "lifespan.startup":
|
|
66
|
+
try:
|
|
67
|
+
await self.runtime.context()
|
|
68
|
+
except Exception as error:
|
|
69
|
+
await send({"type": "lifespan.startup.failed", "message": str(error)})
|
|
70
|
+
return
|
|
71
|
+
await send({"type": "lifespan.startup.complete"})
|
|
72
|
+
elif message["type"] == "lifespan.shutdown":
|
|
73
|
+
await self.runtime.dispose_async()
|
|
74
|
+
await send({"type": "lifespan.shutdown.complete"})
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
@asynccontextmanager
|
|
78
|
+
async def lifespan(self) -> AsyncGenerator[None]:
|
|
79
|
+
"""Build the services on enter and release them on exit: the
|
|
80
|
+
lifespan of a host app this one is mounted in (``FastAPI(lifespan=
|
|
81
|
+
lambda _: app.lifespan())``), whose server sends no lifespan to
|
|
82
|
+
mounted apps."""
|
|
83
|
+
await self.runtime.context()
|
|
84
|
+
try:
|
|
85
|
+
yield
|
|
86
|
+
finally:
|
|
87
|
+
await self.runtime.dispose_async()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
type _Served = HttpServerRequest | ScopeTag
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@overload
|
|
94
|
+
def to_asgi[E](
|
|
95
|
+
app: Effect[HttpServerResponse, E, _Served],
|
|
96
|
+
/,
|
|
97
|
+
*,
|
|
98
|
+
middleware: HttpMiddleware | None = None,
|
|
99
|
+
) -> AsgiApp: ...
|
|
100
|
+
@overload
|
|
101
|
+
def to_asgi[E, R, LE](
|
|
102
|
+
app: Effect[HttpServerResponse, E, R | _Served],
|
|
103
|
+
layer: Layer[R, LE],
|
|
104
|
+
/,
|
|
105
|
+
*,
|
|
106
|
+
middleware: HttpMiddleware | None = None,
|
|
107
|
+
memo_map: MemoMap | None = None,
|
|
108
|
+
) -> AsgiApp: ...
|
|
109
|
+
def to_asgi(
|
|
110
|
+
app: Effect[HttpServerResponse, Any, Any],
|
|
111
|
+
layer: Layer[Any, Any] | None = None,
|
|
112
|
+
/,
|
|
113
|
+
*,
|
|
114
|
+
middleware: HttpMiddleware | None = None,
|
|
115
|
+
memo_map: MemoMap | None = None,
|
|
116
|
+
) -> AsgiApp:
|
|
117
|
+
"""``app`` (through ``middleware``) as an ASGI 3 application for
|
|
118
|
+
uvicorn, hypercorn, granian or a host framework, with the services of
|
|
119
|
+
``layer``. ``HEAD`` responses have no body; request bodies are
|
|
120
|
+
streams; streamed responses are sent as they are produced; a client
|
|
121
|
+
disconnect interrupts the request; WebSocket requests are upgraded
|
|
122
|
+
through ``request.upgrade``."""
|
|
123
|
+
require_effect(app, "app")
|
|
124
|
+
if layer is not None:
|
|
125
|
+
require_layer(layer, "layer")
|
|
126
|
+
runtime = ManagedRuntime.make(empty_layer if layer is None else layer, memo_map=memo_map)
|
|
127
|
+
return AsgiApp(app, runtime, middleware)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class _ServedApp(Tag[Effect[HttpServerResponse, Any, Any]], key="pyfect/http/asgi/ServedApp"):
|
|
131
|
+
"""The app ``to_asgi_with`` made of the layer's services."""
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _served(fiber: Fiber[Any, Any]) -> Effect[HttpServerResponse, Any, Any]:
|
|
135
|
+
return fiber._context.get_unsafe(_ServedApp)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def to_asgi_with[LE](
|
|
139
|
+
layer: Layer[Any, LE],
|
|
140
|
+
to_app: Callable[[Context[Any]], Effect[HttpServerResponse, Any, Any]],
|
|
141
|
+
*,
|
|
142
|
+
middleware: HttpMiddleware | None = None,
|
|
143
|
+
memo_map: MemoMap | None = None,
|
|
144
|
+
) -> AsgiApp:
|
|
145
|
+
"""``to_asgi`` for the app ``to_app`` makes of ``layer``'s services once
|
|
146
|
+
they are built (what ``router.to_asgi`` serves routes with)."""
|
|
147
|
+
require_layer(layer, "layer")
|
|
148
|
+
|
|
149
|
+
def make(fiber: Fiber[Any, Any]) -> Effect[Effect[HttpServerResponse, Any, Any]]:
|
|
150
|
+
return succeed(to_app(fiber._context))
|
|
151
|
+
|
|
152
|
+
served = layer_effect(_ServedApp, _WithFiber(make)).pipe(provide_merge(layer))
|
|
153
|
+
runtime = ManagedRuntime.make(served, memo_map=memo_map)
|
|
154
|
+
app: Effect[HttpServerResponse, Any, Any] = _WithFiber(_served)
|
|
155
|
+
return AsgiApp(app, runtime, middleware)
|