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,151 @@
|
|
|
1
|
+
"""``Stream`` methods that feed the stream to a ``Sink``: ``run``,
|
|
2
|
+
``transduce``, ``aggregate``, ``aggregate_within``, ``grouped_within``,
|
|
3
|
+
``pipe_through``, ``tap_sink`` and ``peel``. The work is in
|
|
4
|
+
``pyfect.stream._sinking``."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Never, overload
|
|
9
|
+
|
|
10
|
+
from pyfect.stream._base import A_co, E_co, R_co, StreamBase
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from pyfect._core import Effect
|
|
14
|
+
from pyfect.duration import Duration
|
|
15
|
+
from pyfect.option import Option
|
|
16
|
+
from pyfect.schedule import Schedule
|
|
17
|
+
from pyfect.scope import Scope
|
|
18
|
+
from pyfect.sink import Sink
|
|
19
|
+
from pyfect.stream._stream import Stream
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _require_sink(sink: object) -> None:
|
|
23
|
+
from pyfect.sink._sink import require_sink
|
|
24
|
+
|
|
25
|
+
require_sink(sink, "sink")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SinkMethods(StreamBase[A_co, E_co, R_co]):
|
|
29
|
+
__slots__ = ()
|
|
30
|
+
|
|
31
|
+
def run[B, L, E2 = Never, R2 = Never](
|
|
32
|
+
self, sink: Sink[B, A_co, L, E2, R2]
|
|
33
|
+
) -> Effect[B, E_co | E2, R_co | R2]:
|
|
34
|
+
"""Run the stream into ``sink`` and succeed with the sink's value.
|
|
35
|
+
The stream's failures pass by the sink's error handlers."""
|
|
36
|
+
from pyfect.stream import _sinking
|
|
37
|
+
|
|
38
|
+
_require_sink(sink)
|
|
39
|
+
return _sinking.run(self, sink)
|
|
40
|
+
|
|
41
|
+
# A stream of ``Never`` has no items to leave over, so it takes any
|
|
42
|
+
# sink; the overload keeps pyright from reading ``A`` as ``Never``.
|
|
43
|
+
@overload
|
|
44
|
+
def transduce[B, E, R, E2 = Never, R2 = Never](
|
|
45
|
+
self: SinkMethods[Never, E, R], sink: Sink[B, Never, object, E2, R2]
|
|
46
|
+
) -> Stream[B, E | E2, R | R2]: ...
|
|
47
|
+
@overload
|
|
48
|
+
def transduce[A, E, R, B, E2 = Never, R2 = Never](
|
|
49
|
+
self: SinkMethods[A, E, R], sink: Sink[B, A, A, E2, R2]
|
|
50
|
+
) -> Stream[B, E | E2, R | R2]: ...
|
|
51
|
+
def transduce(self, sink: Sink[Any, Any, Any, Any, Any]) -> Stream[Any, Any, Any]:
|
|
52
|
+
"""Run ``sink`` again and again on the stream, writing each value it
|
|
53
|
+
ends with; its leftovers start the next run. A stream failure ends
|
|
54
|
+
the current run first."""
|
|
55
|
+
from pyfect.stream import _sinking
|
|
56
|
+
|
|
57
|
+
_require_sink(sink)
|
|
58
|
+
return _sinking.transduce(self, sink)
|
|
59
|
+
|
|
60
|
+
@overload
|
|
61
|
+
def aggregate[B, E, R, E2 = Never, R2 = Never](
|
|
62
|
+
self: SinkMethods[Never, E, R], sink: Sink[B, Never, object, E2, R2]
|
|
63
|
+
) -> Stream[B, E | E2, R | R2]: ...
|
|
64
|
+
@overload
|
|
65
|
+
def aggregate[A, E, R, B, E2 = Never, R2 = Never](
|
|
66
|
+
self: SinkMethods[A, E, R], sink: Sink[B, A, A, E2, R2]
|
|
67
|
+
) -> Stream[B, E | E2, R | R2]: ...
|
|
68
|
+
def aggregate(self, sink: Sink[Any, Any, Any, Any, Any]) -> Stream[Any, Any, Any]:
|
|
69
|
+
"""``transduce`` while the stream keeps running: a fiber pulls the
|
|
70
|
+
stream as ``sink`` asks for input, and each run of the sink ends
|
|
71
|
+
when the sink is done."""
|
|
72
|
+
from pyfect import schedule
|
|
73
|
+
from pyfect.stream import _sinking
|
|
74
|
+
|
|
75
|
+
_require_sink(sink)
|
|
76
|
+
return _sinking.aggregate_within(self, sink, schedule.forever)
|
|
77
|
+
|
|
78
|
+
@overload
|
|
79
|
+
def aggregate_within[B, E, R, EE = Never, RR = Never](
|
|
80
|
+
self: SinkMethods[Never, E, R],
|
|
81
|
+
sink: Sink[B, Never, object, EE, RR],
|
|
82
|
+
schedule: Schedule[object, Option[B], EE, RR],
|
|
83
|
+
) -> Stream[B, E | EE, R | RR]: ...
|
|
84
|
+
@overload
|
|
85
|
+
def aggregate_within[A, E, R, B, EE = Never, RR = Never](
|
|
86
|
+
self: SinkMethods[A, E, R],
|
|
87
|
+
sink: Sink[B, A, A, EE, RR],
|
|
88
|
+
schedule: Schedule[object, Option[B], EE, RR],
|
|
89
|
+
) -> Stream[B, E | EE, R | RR]: ...
|
|
90
|
+
def aggregate_within(
|
|
91
|
+
self,
|
|
92
|
+
sink: Sink[Any, Any, Any, Any, Any],
|
|
93
|
+
schedule: Schedule[Any, Any, Any, Any],
|
|
94
|
+
) -> Stream[Any, Any, Any]:
|
|
95
|
+
"""``aggregate``, also ending each run of ``sink`` when ``schedule``
|
|
96
|
+
says so. The schedule steps once input arrives (with the last value
|
|
97
|
+
written) and its clock leaves out the time between runs; a schedule
|
|
98
|
+
that stops ends the stream once the sink has drained its
|
|
99
|
+
leftovers."""
|
|
100
|
+
from pyfect.stream import _sinking
|
|
101
|
+
|
|
102
|
+
_require_sink(sink)
|
|
103
|
+
return _sinking.aggregate_within(self, sink, schedule)
|
|
104
|
+
|
|
105
|
+
def grouped_within(self, chunk_size: int, duration: Duration) -> Stream[list[A_co], E_co, R_co]:
|
|
106
|
+
"""Group the items in lists of up to ``chunk_size`` (at least 1),
|
|
107
|
+
ending a group early once ``duration`` has passed since its first
|
|
108
|
+
item."""
|
|
109
|
+
from pyfect import schedule
|
|
110
|
+
from pyfect.sink import take
|
|
111
|
+
from pyfect.stream import _sinking
|
|
112
|
+
|
|
113
|
+
return _sinking.aggregate_within(self, take(max(chunk_size, 1)), schedule.spaced(duration))
|
|
114
|
+
|
|
115
|
+
def pipe_through[B, L, E2 = Never, R2 = Never](
|
|
116
|
+
self, sink: Sink[B, A_co, L, E2, R2]
|
|
117
|
+
) -> Stream[L, E_co | E2, R_co | R2]:
|
|
118
|
+
"""Run the stream into ``sink`` and write the sink's leftovers. The
|
|
119
|
+
stream's failures pass by the sink's error handlers."""
|
|
120
|
+
from pyfect.stream import _sinking
|
|
121
|
+
|
|
122
|
+
_require_sink(sink)
|
|
123
|
+
return _sinking.pipe_through(self, sink)
|
|
124
|
+
|
|
125
|
+
def tap_sink[E2 = Never, R2 = Never](
|
|
126
|
+
self, sink: Sink[object, A_co, object, E2, R2]
|
|
127
|
+
) -> Stream[A_co, E_co | E2, R_co | R2]:
|
|
128
|
+
"""Send each chunk to ``sink`` too, as it is written. The stream
|
|
129
|
+
waits for the sink to take each chunk; once the sink is done it
|
|
130
|
+
goes on alone, and a sink failure fails the stream."""
|
|
131
|
+
from pyfect.stream import _sinking
|
|
132
|
+
|
|
133
|
+
_require_sink(sink)
|
|
134
|
+
return _sinking.tap_sink(self, sink)
|
|
135
|
+
|
|
136
|
+
@overload
|
|
137
|
+
def peel[B, E, R, E2 = Never, R2 = Never](
|
|
138
|
+
self: SinkMethods[Never, E, R], sink: Sink[B, Never, object, E2, R2]
|
|
139
|
+
) -> Effect[tuple[B, Stream[Never, E]], E | E2, Scope | R | R2]: ...
|
|
140
|
+
@overload
|
|
141
|
+
def peel[A, E, R, B, E2 = Never, R2 = Never](
|
|
142
|
+
self: SinkMethods[A, E, R], sink: Sink[B, A, A, E2, R2]
|
|
143
|
+
) -> Effect[tuple[B, Stream[A, E]], E | E2, Scope | R | R2]: ...
|
|
144
|
+
def peel(self, sink: Sink[Any, Any, Any, Any, Any]) -> Effect[Any, Any, Any]:
|
|
145
|
+
"""Run ``sink`` on the start of the stream and succeed with its value
|
|
146
|
+
and the rest of the stream (the sink's leftovers first). The rest
|
|
147
|
+
reads the stream's pull, which lives in the current ``Scope``."""
|
|
148
|
+
from pyfect.stream import _sinking
|
|
149
|
+
|
|
150
|
+
_require_sink(sink)
|
|
151
|
+
return _sinking.peel(self, sink)
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"""The work behind ``Stream``'s sink methods: ``run``, ``transduce``,
|
|
2
|
+
``pipe_through``, ``tap_sink``, ``peel`` and ``aggregate_within``.
|
|
3
|
+
|
|
4
|
+
A stream's own failures reach a sink as hidden defects and are restored
|
|
5
|
+
once the sink has exited (``run_sink``), so no sink error handler sees
|
|
6
|
+
them.
|
|
7
|
+
"""
|
|
8
|
+
# pyright: reportPrivateUsage=false
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from collections.abc import Generator
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from pyfect import channel
|
|
16
|
+
from pyfect._core import Effect, _FailCause, _Gen, _Succeed, _Suspend
|
|
17
|
+
from pyfect.cause import Cause, fail
|
|
18
|
+
from pyfect.channel._upstream import restore_upstream_failure, upstream_failure_to_defect
|
|
19
|
+
from pyfect.clock import Clock, ClockService, sleep
|
|
20
|
+
from pyfect.duration import from_nanos
|
|
21
|
+
from pyfect.effect import never
|
|
22
|
+
from pyfect.exit import Exit, Failure
|
|
23
|
+
from pyfect.latch import Latch
|
|
24
|
+
from pyfect.option import Option, Some
|
|
25
|
+
from pyfect.pull import catch_done
|
|
26
|
+
from pyfect.queue import Queue
|
|
27
|
+
from pyfect.queue import _state as queue_state
|
|
28
|
+
from pyfect.schedule import Schedule
|
|
29
|
+
from pyfect.schedule._model import Continue, to_step
|
|
30
|
+
from pyfect.scope import CloseableScope, fork_in, scoped_with
|
|
31
|
+
from pyfect.sink._sink import AnySink, End
|
|
32
|
+
from pyfect.sink._steps import ENDED
|
|
33
|
+
from pyfect.stream._base import AnyStream
|
|
34
|
+
from pyfect.stream._stream import Stream, transform_pull, transform_pull_bracket
|
|
35
|
+
|
|
36
|
+
type AnyEffect = Effect[Any, Any, Any]
|
|
37
|
+
type Chunk = tuple[Any, ...]
|
|
38
|
+
type AnyStream_ = Stream[Any, Any, Any]
|
|
39
|
+
type AnyEnd = End[Any, Any]
|
|
40
|
+
type Channel_ = channel.Channel[Any, Any, Any, Any, Any, Any, Any]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def run_sink(sink: AnySink, upstream: AnyEffect, scope: CloseableScope) -> AnyEffect:
|
|
44
|
+
"""Run ``sink`` on ``upstream``; upstream failures bypass the sink's
|
|
45
|
+
error handlers and are restored once the sink has exited."""
|
|
46
|
+
return restore_upstream_failure(sink._transform(upstream_failure_to_defect(upstream), scope))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def run(self: AnyStream, sink: AnySink) -> AnyEffect:
|
|
50
|
+
def consume(scope: CloseableScope) -> AnyEffect:
|
|
51
|
+
built = self._channel.to_pull_scoped(scope)
|
|
52
|
+
return built.flat_map(lambda pull: run_sink(sink, pull, scope)).map(_value)
|
|
53
|
+
|
|
54
|
+
return scoped_with(consume)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _value(end: AnyEnd) -> Any:
|
|
58
|
+
return end[0]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def transduce(self: AnyStream, sink: AnySink) -> AnyStream_:
|
|
62
|
+
def build(upstream: AnyEffect, scope: CloseableScope) -> AnyEffect:
|
|
63
|
+
stopped: AnyEffect | None = None
|
|
64
|
+
leftover: Chunk | None = None
|
|
65
|
+
|
|
66
|
+
def next_chunk() -> AnyEffect:
|
|
67
|
+
nonlocal leftover
|
|
68
|
+
if leftover is not None:
|
|
69
|
+
chunk, leftover = leftover, None
|
|
70
|
+
return _Succeed(chunk)
|
|
71
|
+
return upstream
|
|
72
|
+
|
|
73
|
+
def stop(error: object) -> AnyEffect:
|
|
74
|
+
nonlocal stopped
|
|
75
|
+
stopped = _FailCause(fail(error))
|
|
76
|
+
return ENDED
|
|
77
|
+
|
|
78
|
+
fed = _Suspend(next_chunk).catch_all(stop)
|
|
79
|
+
|
|
80
|
+
def emit(end: AnyEnd) -> Chunk:
|
|
81
|
+
nonlocal leftover
|
|
82
|
+
leftover = end[1]
|
|
83
|
+
return (end[0],)
|
|
84
|
+
|
|
85
|
+
pull = _Suspend(lambda: sink._transform(fed, scope)).map(emit)
|
|
86
|
+
return _Succeed(_Suspend(lambda: pull if stopped is None else stopped))
|
|
87
|
+
|
|
88
|
+
return transform_pull(self, build)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def pipe_through(self: AnyStream, sink: AnySink) -> AnyStream_:
|
|
92
|
+
from pyfect.sink import to_channel
|
|
93
|
+
|
|
94
|
+
def leftovers(end: AnyEnd) -> Any:
|
|
95
|
+
return channel.empty if end[1] is None else channel.succeed(end[1])
|
|
96
|
+
|
|
97
|
+
piped: Any = self._channel.pipe_to_or_fail(to_channel(sink)).concat_with(leftovers)
|
|
98
|
+
return Stream(piped)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def tap_sink(self: AnyStream, sink: AnySink) -> AnyStream_:
|
|
102
|
+
def build(pull: AnyEffect, _scope: CloseableScope, forked: CloseableScope) -> AnyEffect:
|
|
103
|
+
upstream_latch = Latch()
|
|
104
|
+
sink_latch = Latch()
|
|
105
|
+
chunk: Chunk | None = None
|
|
106
|
+
sink_cause: Cause[Any] | None = None
|
|
107
|
+
sink_done = False
|
|
108
|
+
stream_done = False
|
|
109
|
+
|
|
110
|
+
def hand_over() -> AnyEffect:
|
|
111
|
+
nonlocal chunk
|
|
112
|
+
if chunk is None:
|
|
113
|
+
return ENDED
|
|
114
|
+
taken, chunk = chunk, None
|
|
115
|
+
if not stream_done:
|
|
116
|
+
upstream_latch.close_unsafe()
|
|
117
|
+
return sink_latch.open().as_(taken)
|
|
118
|
+
|
|
119
|
+
sink_upstream = upstream_latch.when_open(_Suspend(hand_over))
|
|
120
|
+
|
|
121
|
+
def sink_exited(ex: Exit[Any, Any]) -> AnyEffect:
|
|
122
|
+
nonlocal sink_done, sink_cause
|
|
123
|
+
sink_done = True
|
|
124
|
+
if isinstance(ex, Failure):
|
|
125
|
+
sink_cause = ex.cause
|
|
126
|
+
return sink_latch.open()
|
|
127
|
+
|
|
128
|
+
running = _Suspend(lambda: sink._transform(sink_upstream, forked)).on_exit(sink_exited)
|
|
129
|
+
|
|
130
|
+
def offer(next_chunk: Chunk) -> AnyEffect:
|
|
131
|
+
nonlocal chunk
|
|
132
|
+
if sink_cause is not None:
|
|
133
|
+
return _FailCause(sink_cause)
|
|
134
|
+
if sink_done:
|
|
135
|
+
return _Succeed(next_chunk)
|
|
136
|
+
chunk = next_chunk
|
|
137
|
+
sink_latch.close_unsafe()
|
|
138
|
+
upstream_latch.open_unsafe()
|
|
139
|
+
return sink_latch.wait().as_(next_chunk)
|
|
140
|
+
|
|
141
|
+
def stream_ended(_: object) -> AnyEffect:
|
|
142
|
+
nonlocal stream_done
|
|
143
|
+
if sink_cause is not None:
|
|
144
|
+
return _FailCause(sink_cause)
|
|
145
|
+
if sink_done:
|
|
146
|
+
return ENDED
|
|
147
|
+
stream_done = True
|
|
148
|
+
sink_latch.close_unsafe()
|
|
149
|
+
upstream_latch.open_unsafe()
|
|
150
|
+
return sink_latch.wait().and_then(
|
|
151
|
+
_Suspend(lambda: ENDED if sink_cause is None else _FailCause(sink_cause))
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
pull_and_offer = catch_done(pull.flat_map(offer), stream_ended)
|
|
155
|
+
|
|
156
|
+
def next_pull() -> AnyEffect:
|
|
157
|
+
if sink_cause is not None:
|
|
158
|
+
return _FailCause(sink_cause)
|
|
159
|
+
return pull if sink_done else pull_and_offer
|
|
160
|
+
|
|
161
|
+
return fork_in(running, forked).as_(_Suspend(next_pull))
|
|
162
|
+
|
|
163
|
+
return transform_pull_bracket(self, build)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def peel(self: AnyStream, sink: AnySink) -> AnyEffect:
|
|
167
|
+
from pyfect.stream._constructors import empty, from_iterable
|
|
168
|
+
from pyfect.stream._stream import from_pull
|
|
169
|
+
|
|
170
|
+
def body() -> Generator[AnyEffect, Any, tuple[Any, AnyStream_]]:
|
|
171
|
+
failed = False
|
|
172
|
+
original = yield self._channel.to_pull()
|
|
173
|
+
|
|
174
|
+
def mark(cause: Cause[Any]) -> AnyEffect:
|
|
175
|
+
nonlocal failed
|
|
176
|
+
failed = True
|
|
177
|
+
return _FailCause(cause)
|
|
178
|
+
|
|
179
|
+
pull = original.catch_cause(mark)
|
|
180
|
+
value, leftover = yield scoped_with(lambda scope: run_sink(sink, pull, scope))
|
|
181
|
+
rest: AnyStream_ = empty if failed else from_pull(_Succeed(original))
|
|
182
|
+
if leftover is not None:
|
|
183
|
+
rest = from_iterable(leftover).concat(rest)
|
|
184
|
+
return (value, rest)
|
|
185
|
+
|
|
186
|
+
return _Gen(body)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
_SCHEDULE_STEP = object()
|
|
190
|
+
"""What the schedule puts in the buffer to end the current aggregation."""
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def aggregate_within(
|
|
194
|
+
self: AnyStream, sink: AnySink, policy: Schedule[Any, Any, Any, Any]
|
|
195
|
+
) -> AnyStream_:
|
|
196
|
+
def transform(_upstream: Any, scope: CloseableScope, forked: CloseableScope) -> AnyEffect:
|
|
197
|
+
def body() -> Generator[AnyEffect, Any, AnyEffect]:
|
|
198
|
+
pull = yield self._channel.to_pull_scoped(scope)
|
|
199
|
+
pull_latch = Latch()
|
|
200
|
+
buffer: Queue[Any, Any] = Queue(0)
|
|
201
|
+
|
|
202
|
+
def offer(chunk: Chunk) -> AnyEffect:
|
|
203
|
+
pull_latch.close_unsafe()
|
|
204
|
+
return buffer.offer(chunk)
|
|
205
|
+
|
|
206
|
+
producer = pull_latch.when_open(pull).flat_map(offer).forever()
|
|
207
|
+
yield fork_in(producer.catch_cause(buffer.fail_cause), forked)
|
|
208
|
+
|
|
209
|
+
# The schedule's clock leaves out the time between aggregations.
|
|
210
|
+
clock: ClockService = yield Clock()
|
|
211
|
+
step = yield to_step(policy)
|
|
212
|
+
has_input = Latch()
|
|
213
|
+
schedule_time = clock.now_nanos_unsafe()
|
|
214
|
+
opened_at = 0
|
|
215
|
+
last_output: Option[Any] = None
|
|
216
|
+
leftover: Chunk | None = None
|
|
217
|
+
|
|
218
|
+
def on_input(chunk: Chunk) -> AnyEffect:
|
|
219
|
+
nonlocal opened_at
|
|
220
|
+
if has_input.open_unsafe():
|
|
221
|
+
opened_at = clock.now_nanos_unsafe()
|
|
222
|
+
return _Succeed(chunk)
|
|
223
|
+
|
|
224
|
+
def decided(decision: object) -> AnyEffect:
|
|
225
|
+
if isinstance(decision, Continue):
|
|
226
|
+
return sleep(decision.delay).and_then(buffer.offer(_SCHEDULE_STEP))
|
|
227
|
+
# End input so the sink drains its leftovers without pulling
|
|
228
|
+
# more upstream.
|
|
229
|
+
return buffer.end()
|
|
230
|
+
|
|
231
|
+
step_to_buffer = (
|
|
232
|
+
has_input.wait()
|
|
233
|
+
.flat_map(lambda _: step(from_nanos(schedule_time), last_output))
|
|
234
|
+
.flat_map(decided)
|
|
235
|
+
.and_then(never)
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
def take_input(item: Any) -> AnyEffect:
|
|
239
|
+
return ENDED if item is _SCHEDULE_STEP else on_input(item)
|
|
240
|
+
|
|
241
|
+
def next_input() -> AnyEffect:
|
|
242
|
+
nonlocal leftover
|
|
243
|
+
if leftover is not None:
|
|
244
|
+
chunk, leftover = leftover, None
|
|
245
|
+
return on_input(chunk)
|
|
246
|
+
if isinstance(buffer._state, queue_state.Open):
|
|
247
|
+
pull_latch.open_unsafe()
|
|
248
|
+
return buffer.take().flat_map(take_input)
|
|
249
|
+
|
|
250
|
+
sink_upstream = _Suspend(next_input)
|
|
251
|
+
|
|
252
|
+
def emit(end: AnyEnd) -> AnyEffect:
|
|
253
|
+
nonlocal schedule_time, last_output, leftover
|
|
254
|
+
if has_input.is_open():
|
|
255
|
+
schedule_time += clock.now_nanos_unsafe() - opened_at
|
|
256
|
+
elif isinstance(buffer._state, queue_state.Done):
|
|
257
|
+
return ENDED
|
|
258
|
+
last_output = Some(end[0])
|
|
259
|
+
leftover = end[1]
|
|
260
|
+
return _Succeed((end[0],))
|
|
261
|
+
|
|
262
|
+
def next_pull() -> AnyEffect:
|
|
263
|
+
state = buffer._state
|
|
264
|
+
if isinstance(state, queue_state.Done) and leftover is None:
|
|
265
|
+
return _FailCause(state.cause)
|
|
266
|
+
has_input.close_unsafe()
|
|
267
|
+
aggregated = _Suspend(lambda: run_sink(sink, sink_upstream, scope)).flat_map(emit)
|
|
268
|
+
if isinstance(state, queue_state.Open):
|
|
269
|
+
return aggregated.race_first(step_to_buffer)
|
|
270
|
+
return aggregated
|
|
271
|
+
|
|
272
|
+
return _Suspend(next_pull)
|
|
273
|
+
|
|
274
|
+
return _Gen(body)
|
|
275
|
+
|
|
276
|
+
built: Channel_ = channel.from_transform_bracket(transform)
|
|
277
|
+
return Stream(built)
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""Streams fed from outside: callbacks offering to a queue, queues,
|
|
2
|
+
pubsubs, schedules, ticks and async iterables."""
|
|
3
|
+
# pyright: reportPrivateUsage=false
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from collections.abc import AsyncIterable, Callable
|
|
8
|
+
from typing import Any, Never, overload
|
|
9
|
+
|
|
10
|
+
from pyfect import channel
|
|
11
|
+
from pyfect._core import Effect, _Succeed, _Suspend, _Sync
|
|
12
|
+
from pyfect.channel._base import end_with
|
|
13
|
+
from pyfect.duration import Duration, to_seconds
|
|
14
|
+
from pyfect.errors import Done
|
|
15
|
+
from pyfect.pubsub import PubSub, Subscription
|
|
16
|
+
from pyfect.queue import Dequeue, Queue, Strategy
|
|
17
|
+
from pyfect.schedule import Schedule
|
|
18
|
+
from pyfect.schedule._model import Metadata, Stop, to_step_with_metadata
|
|
19
|
+
from pyfect.scope import Scope
|
|
20
|
+
from pyfect.stream._stream import Stream, from_pull
|
|
21
|
+
from pyfect.take import Take
|
|
22
|
+
|
|
23
|
+
type AnyPull = Effect[Any, Any, Any]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@overload
|
|
27
|
+
def callback[A, E = Never](
|
|
28
|
+
f: Callable[[Queue[A, E | Done]], Effect[object, E, Scope]],
|
|
29
|
+
*,
|
|
30
|
+
buffer_size: int | None = None,
|
|
31
|
+
strategy: Strategy = "suspend",
|
|
32
|
+
) -> Stream[A, E]: ...
|
|
33
|
+
@overload
|
|
34
|
+
def callback[A, E = Never, R = Never](
|
|
35
|
+
f: Callable[[Queue[A, E | Done]], Effect[object, E, R | Scope]],
|
|
36
|
+
*,
|
|
37
|
+
buffer_size: int | None = None,
|
|
38
|
+
strategy: Strategy = "suspend",
|
|
39
|
+
) -> Stream[A, E, R]: ...
|
|
40
|
+
def callback(
|
|
41
|
+
f: Callable[[Queue[Any, Any]], Effect[object, Any, Any]],
|
|
42
|
+
*,
|
|
43
|
+
buffer_size: int | None = None,
|
|
44
|
+
strategy: Strategy = "suspend",
|
|
45
|
+
) -> Stream[Any, Any, Any]:
|
|
46
|
+
"""A stream of what ``f`` offers to a queue. ``f`` runs on a fiber, with
|
|
47
|
+
the stream's ``Scope``, when the stream starts; the stream ends when the
|
|
48
|
+
queue ends and fails with ``f``'s failure or the queue's. With a
|
|
49
|
+
``buffer_size`` the queue is bounded and ``strategy`` says what a full
|
|
50
|
+
one does (``"suspend"`` waits: backpressure)."""
|
|
51
|
+
chunks: Any = channel.callback_array(f, buffer_size=buffer_size, strategy=strategy)
|
|
52
|
+
return Stream(chunks)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@overload
|
|
56
|
+
def from_queue[A](queue: Dequeue[A, Done]) -> Stream[A]: ...
|
|
57
|
+
@overload
|
|
58
|
+
def from_queue[A, E](queue: Dequeue[A, E | Done]) -> Stream[A, E]: ...
|
|
59
|
+
def from_queue(queue: Dequeue[Any, Any]) -> Stream[Any, Any]:
|
|
60
|
+
"""A stream taking everything waiting in ``queue`` at each pull, until
|
|
61
|
+
it ends (or fails)."""
|
|
62
|
+
return Stream(channel.from_queue_array(queue))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def from_subscription[A](subscription: Subscription[A]) -> Stream[A]:
|
|
66
|
+
"""A stream of the messages of ``subscription``; it ends when the
|
|
67
|
+
pubsub shuts down."""
|
|
68
|
+
return Stream(channel.from_subscription_array(subscription))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def from_pubsub[A](pubsub: PubSub[A]) -> Stream[A]:
|
|
72
|
+
"""A stream of what is published to ``pubsub`` after the stream starts
|
|
73
|
+
(and what it replays); it ends when the pubsub shuts down."""
|
|
74
|
+
return Stream(channel.from_pubsub_array(pubsub))
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def from_pubsub_take[A, E](pubsub: PubSub[Take[A, E, None]]) -> Stream[A, E]:
|
|
78
|
+
"""A stream replaying the ``Take`` values published to ``pubsub``: the
|
|
79
|
+
chunks, then the failure or the end."""
|
|
80
|
+
return Stream(channel.from_pubsub_take(pubsub))
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def from_schedule[O, E = Never, R = Never](schedule: Schedule[O, object, E, R]) -> Stream[O, E, R]:
|
|
84
|
+
"""A stream of the outputs of ``schedule``, each after its delay; it
|
|
85
|
+
ends when the schedule stops."""
|
|
86
|
+
|
|
87
|
+
def with_step(step: Callable[[None], Effect[Metadata[O, Any] | Stop[O], E, R]]) -> AnyPull:
|
|
88
|
+
def written(decision: Metadata[O, Any] | Stop[O]) -> AnyPull:
|
|
89
|
+
return end_with(None) if isinstance(decision, Stop) else _Succeed((decision.output,))
|
|
90
|
+
|
|
91
|
+
return step(None).flat_map(written)
|
|
92
|
+
|
|
93
|
+
return from_pull(to_step_with_metadata(schedule).map(with_step))
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def tick(interval: Duration) -> Stream[None]:
|
|
97
|
+
"""An endless stream of ``None``: the first at once, then one after
|
|
98
|
+
each ``interval``."""
|
|
99
|
+
seconds = to_seconds(interval)
|
|
100
|
+
tock: Effect[tuple[None]] = _Succeed((None,))
|
|
101
|
+
|
|
102
|
+
def make_pull() -> AnyPull:
|
|
103
|
+
delayed = tock.delay(seconds)
|
|
104
|
+
first = True
|
|
105
|
+
|
|
106
|
+
def pull() -> AnyPull:
|
|
107
|
+
nonlocal first
|
|
108
|
+
if first:
|
|
109
|
+
first = False
|
|
110
|
+
return tock
|
|
111
|
+
return delayed
|
|
112
|
+
|
|
113
|
+
return _Suspend(pull)
|
|
114
|
+
|
|
115
|
+
return from_pull(_Sync(make_pull))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def from_async_iterable[A, E](
|
|
119
|
+
iterable: AsyncIterable[A], on_error: Callable[[Exception], E]
|
|
120
|
+
) -> Stream[A, E]:
|
|
121
|
+
"""A stream of what ``iterable`` yields, failing with
|
|
122
|
+
``on_error(exception)`` if it raises. The iterator is closed when the
|
|
123
|
+
run ends. Needs an asyncio loop (``run_async``)."""
|
|
124
|
+
return Stream(channel.from_async_iterable_array(iterable, on_error))
|