palfrey 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- palfrey-0.1.0/.gitignore +32 -0
- palfrey-0.1.0/LICENSE +11 -0
- palfrey-0.1.0/PKG-INFO +220 -0
- palfrey-0.1.0/README.md +155 -0
- palfrey-0.1.0/benchmarks/__init__.py +1 -0
- palfrey-0.1.0/benchmarks/apps.py +39 -0
- palfrey-0.1.0/benchmarks/run.py +546 -0
- palfrey-0.1.0/docs/en/docs/concepts/asgi.md +86 -0
- palfrey-0.1.0/docs/en/docs/concepts/event-loop.md +43 -0
- palfrey-0.1.0/docs/en/docs/concepts/http.md +60 -0
- palfrey-0.1.0/docs/en/docs/concepts/lifespan.md +49 -0
- palfrey-0.1.0/docs/en/docs/concepts/middleware.md +36 -0
- palfrey-0.1.0/docs/en/docs/concepts/server-behavior.md +49 -0
- palfrey-0.1.0/docs/en/docs/concepts/terms-and-mental-models.md +140 -0
- palfrey-0.1.0/docs/en/docs/concepts/websockets.md +64 -0
- palfrey-0.1.0/docs/en/docs/contributing.md +97 -0
- palfrey-0.1.0/docs/en/docs/getting-started/installation.md +136 -0
- palfrey-0.1.0/docs/en/docs/getting-started/quickstart.md +136 -0
- palfrey-0.1.0/docs/en/docs/guides/faq.md +44 -0
- palfrey-0.1.0/docs/en/docs/guides/from-zero-to-production.md +94 -0
- palfrey-0.1.0/docs/en/docs/guides/https-tls.md +54 -0
- palfrey-0.1.0/docs/en/docs/guides/reverse-proxy-nginx.md +66 -0
- palfrey-0.1.0/docs/en/docs/guides/security-hardening.md +43 -0
- palfrey-0.1.0/docs/en/docs/guides/troubleshooting.md +96 -0
- palfrey-0.1.0/docs/en/docs/index.md +139 -0
- palfrey-0.1.0/docs/en/docs/operations/benchmarks.md +58 -0
- palfrey-0.1.0/docs/en/docs/operations/capacity-planning.md +40 -0
- palfrey-0.1.0/docs/en/docs/operations/deployment.md +94 -0
- palfrey-0.1.0/docs/en/docs/operations/docker.md +57 -0
- palfrey-0.1.0/docs/en/docs/operations/observability.md +44 -0
- palfrey-0.1.0/docs/en/docs/operations/platform-notes.md +32 -0
- palfrey-0.1.0/docs/en/docs/operations/release-process.md +44 -0
- palfrey-0.1.0/docs/en/docs/operations/reload.md +52 -0
- palfrey-0.1.0/docs/en/docs/operations/workers.md +76 -0
- palfrey-0.1.0/docs/en/docs/reference/cli.md +163 -0
- palfrey-0.1.0/docs/en/docs/reference/configuration.md +122 -0
- palfrey-0.1.0/docs/en/docs/reference/environment-variables.md +61 -0
- palfrey-0.1.0/docs/en/docs/reference/error-catalog.md +104 -0
- palfrey-0.1.0/docs/en/docs/reference/logging.md +60 -0
- palfrey-0.1.0/docs/en/docs/reference/protocols.md +90 -0
- palfrey-0.1.0/docs/en/docs/release-notes.md +69 -0
- palfrey-0.1.0/docs/en/docs/sponsorship.md +28 -0
- palfrey-0.1.0/docs/en/docs/stylesheets/extra.css +29 -0
- palfrey-0.1.0/docs/en/mkdocs.yml +117 -0
- palfrey-0.1.0/docs/language_names.yml +183 -0
- palfrey-0.1.0/docs/missing-translation.md.yml +4 -0
- palfrey-0.1.0/docs_src/cli/basic_commands.py +11 -0
- palfrey-0.1.0/docs_src/concepts/asgi_minimal.py +16 -0
- palfrey-0.1.0/docs_src/concepts/asgi_scope_inspector.py +32 -0
- palfrey-0.1.0/docs_src/concepts/http_read_body.py +32 -0
- palfrey-0.1.0/docs_src/concepts/http_streaming.py +23 -0
- palfrey-0.1.0/docs_src/concepts/lifespan_state.py +32 -0
- palfrey-0.1.0/docs_src/concepts/proxy_headers_middleware.py +26 -0
- palfrey-0.1.0/docs_src/concepts/websocket_auth_gate.py +25 -0
- palfrey-0.1.0/docs_src/concepts/websocket_chat_room.py +34 -0
- palfrey-0.1.0/docs_src/concepts/websocket_echo.py +18 -0
- palfrey-0.1.0/docs_src/config/example.py +21 -0
- palfrey-0.1.0/docs_src/getting_started/factory_app.py +24 -0
- palfrey-0.1.0/docs_src/getting_started/hello_world.py +20 -0
- palfrey-0.1.0/docs_src/getting_started/json_api.py +29 -0
- palfrey-0.1.0/docs_src/guides/https_run.py +11 -0
- palfrey-0.1.0/docs_src/guides/nginx_reverse_proxy_app.py +20 -0
- palfrey-0.1.0/docs_src/guides/troubleshooting_healthcheck.py +34 -0
- palfrey-0.1.0/docs_src/lifespan/lifespan_app.py +26 -0
- palfrey-0.1.0/docs_src/logging/logging_json.py +2 -0
- palfrey-0.1.0/docs_src/middleware/proxy_headers.py +19 -0
- palfrey-0.1.0/docs_src/operations/benchmark_plan.py +19 -0
- palfrey-0.1.0/docs_src/operations/docker_healthcheck.py +34 -0
- palfrey-0.1.0/docs_src/operations/graceful_shutdown.py +23 -0
- palfrey-0.1.0/docs_src/operations/gunicorn_conf.py +16 -0
- palfrey-0.1.0/docs_src/operations/reload_dev.py +13 -0
- palfrey-0.1.0/docs_src/operations/systemd_app.py +20 -0
- palfrey-0.1.0/docs_src/operations/workers_cpu_bound.py +13 -0
- palfrey-0.1.0/docs_src/protocols/websocket_echo.py +16 -0
- palfrey-0.1.0/docs_src/reference/custom_headers.py +11 -0
- palfrey-0.1.0/docs_src/reference/env_runtime.py +17 -0
- palfrey-0.1.0/docs_src/reference/logging_json.py +18 -0
- palfrey-0.1.0/docs_src/reference/programmatic_config.py +16 -0
- palfrey-0.1.0/docs_src/reference/programmatic_run.py +23 -0
- palfrey-0.1.0/docs_src/reload/reload_cli.py +5 -0
- palfrey-0.1.0/docs_src/ssl/ssl_cli.py +5 -0
- palfrey-0.1.0/docs_src/workers/workers_cli.py +5 -0
- palfrey-0.1.0/palfrey/__init__.py +14 -0
- palfrey-0.1.0/palfrey/__main__.py +6 -0
- palfrey-0.1.0/palfrey/acceleration.py +191 -0
- palfrey-0.1.0/palfrey/adapters.py +230 -0
- palfrey-0.1.0/palfrey/cli.py +579 -0
- palfrey-0.1.0/palfrey/config.py +808 -0
- palfrey-0.1.0/palfrey/env.py +55 -0
- palfrey-0.1.0/palfrey/http_date.py +50 -0
- palfrey-0.1.0/palfrey/importer.py +213 -0
- palfrey-0.1.0/palfrey/lifespan.py +187 -0
- palfrey-0.1.0/palfrey/logging_config.py +248 -0
- palfrey-0.1.0/palfrey/loops/__init__.py +58 -0
- palfrey-0.1.0/palfrey/loops/asyncio.py +21 -0
- palfrey-0.1.0/palfrey/loops/auto.py +25 -0
- palfrey-0.1.0/palfrey/loops/none.py +23 -0
- palfrey-0.1.0/palfrey/loops/uvloop.py +29 -0
- palfrey-0.1.0/palfrey/main.py +52 -0
- palfrey-0.1.0/palfrey/middleware/__init__.py +6 -0
- palfrey-0.1.0/palfrey/middleware/message_logger.py +144 -0
- palfrey-0.1.0/palfrey/middleware/proxy_headers.py +186 -0
- palfrey-0.1.0/palfrey/protocols/__init__.py +0 -0
- palfrey-0.1.0/palfrey/protocols/http.py +822 -0
- palfrey-0.1.0/palfrey/protocols/http2.py +265 -0
- palfrey-0.1.0/palfrey/protocols/http3.py +301 -0
- palfrey-0.1.0/palfrey/protocols/utils.py +139 -0
- palfrey-0.1.0/palfrey/protocols/websocket.py +1862 -0
- palfrey-0.1.0/palfrey/py.typed +0 -0
- palfrey-0.1.0/palfrey/runtime.py +352 -0
- palfrey-0.1.0/palfrey/server.py +1171 -0
- palfrey-0.1.0/palfrey/supervisors/reload.py +231 -0
- palfrey-0.1.0/palfrey/supervisors/workers.py +404 -0
- palfrey-0.1.0/palfrey/types.py +66 -0
- palfrey-0.1.0/palfrey/workers.py +235 -0
- palfrey-0.1.0/pyproject.toml +182 -0
- palfrey-0.1.0/rust/palfrey_rust/Cargo.toml +13 -0
- palfrey-0.1.0/rust/palfrey_rust/src/lib.rs +102 -0
- palfrey-0.1.0/scripts/build-rust-extension +5 -0
- palfrey-0.1.0/scripts/clean +29 -0
- palfrey-0.1.0/scripts/docs.py +334 -0
- palfrey-0.1.0/scripts/hooks.py +254 -0
- palfrey-0.1.0/scripts/install +20 -0
- palfrey-0.1.0/scripts/publish +25 -0
- palfrey-0.1.0/tests/__init__.py +0 -0
- palfrey-0.1.0/tests/adapters/__init__.py +0 -0
- palfrey-0.1.0/tests/adapters/test_adapters.py +230 -0
- palfrey-0.1.0/tests/adapters/test_adapters_compat_extra.py +63 -0
- palfrey-0.1.0/tests/benchmarks/__init__.py +0 -0
- palfrey-0.1.0/tests/benchmarks/test_run_script.py +148 -0
- palfrey-0.1.0/tests/cli/__init__.py +0 -0
- palfrey-0.1.0/tests/cli/test_cli_compat.py +281 -0
- palfrey-0.1.0/tests/cli/test_cli_runtime_mode_compat.py +84 -0
- palfrey-0.1.0/tests/cli/test_cli_surface.py +101 -0
- palfrey-0.1.0/tests/config/__init__.py +0 -0
- palfrey-0.1.0/tests/config/custom_protocol_classes.py +11 -0
- palfrey-0.1.0/tests/config/test_config.py +99 -0
- palfrey-0.1.0/tests/config/test_config_bind_socket_compat.py +168 -0
- palfrey-0.1.0/tests/config/test_config_compat.py +122 -0
- palfrey-0.1.0/tests/config/test_config_load_compat.py +198 -0
- palfrey-0.1.0/tests/config/test_config_loop_factory_compat.py +54 -0
- palfrey-0.1.0/tests/config/test_config_runtime_modes_compat.py +118 -0
- palfrey-0.1.0/tests/config/test_config_uvicorn_compat_extra.py +45 -0
- palfrey-0.1.0/tests/fixtures/__init__.py +0 -0
- palfrey-0.1.0/tests/fixtures/apps.py +194 -0
- palfrey-0.1.0/tests/helpers.py +15 -0
- palfrey-0.1.0/tests/importer/__init__.py +0 -0
- palfrey-0.1.0/tests/importer/circular_import_a.py +1 -0
- palfrey-0.1.0/tests/importer/circular_import_b.py +1 -0
- palfrey-0.1.0/tests/importer/raise_import_error.py +3 -0
- palfrey-0.1.0/tests/importer/test_importer.py +172 -0
- palfrey-0.1.0/tests/importer/test_importer_compat.py +81 -0
- palfrey-0.1.0/tests/integration/__init__.py +0 -0
- palfrey-0.1.0/tests/integration/test_http_headers_integration.py +109 -0
- palfrey-0.1.0/tests/integration/test_http_integration.py +58 -0
- palfrey-0.1.0/tests/integration/test_uvicorn_differential_compat.py +706 -0
- palfrey-0.1.0/tests/integration/test_websocket_integration.py +114 -0
- palfrey-0.1.0/tests/loops/__init__.py +0 -0
- palfrey-0.1.0/tests/loops/custom_loop_class.py +7 -0
- palfrey-0.1.0/tests/loops/custom_loop_factory.py +8 -0
- palfrey-0.1.0/tests/loops/test_custom_loop_compat.py +37 -0
- palfrey-0.1.0/tests/loops/test_loops.py +60 -0
- palfrey-0.1.0/tests/middleware/__init__.py +0 -0
- palfrey-0.1.0/tests/middleware/test_message_logger.py +34 -0
- palfrey-0.1.0/tests/middleware/test_message_logger_compat_extra.py +79 -0
- palfrey-0.1.0/tests/middleware/test_message_logger_lifecycle_compat.py +51 -0
- palfrey-0.1.0/tests/middleware/test_proxy_headers.py +97 -0
- palfrey-0.1.0/tests/middleware/test_proxy_headers_compat_extra.py +149 -0
- palfrey-0.1.0/tests/middleware/test_proxy_headers_host_matrix_compat.py +79 -0
- palfrey-0.1.0/tests/protocols/__init__.py +0 -0
- palfrey-0.1.0/tests/protocols/test_http2_protocol.py +328 -0
- palfrey-0.1.0/tests/protocols/test_http3_protocol.py +285 -0
- palfrey-0.1.0/tests/protocols/test_http_asgi.py +252 -0
- palfrey-0.1.0/tests/protocols/test_http_behavior_compat.py +186 -0
- palfrey-0.1.0/tests/protocols/test_http_headers_compat_extra.py +114 -0
- palfrey-0.1.0/tests/protocols/test_http_parser.py +125 -0
- palfrey-0.1.0/tests/protocols/test_http_response.py +125 -0
- palfrey-0.1.0/tests/protocols/test_utils.py +116 -0
- palfrey-0.1.0/tests/protocols/test_websocket_behavior_compat.py +776 -0
- palfrey-0.1.0/tests/protocols/test_websocket_coverage_extra.py +996 -0
- palfrey-0.1.0/tests/protocols/test_websocket_protocol.py +2663 -0
- palfrey-0.1.0/tests/runtime/__init__.py +0 -0
- palfrey-0.1.0/tests/runtime/test_coverage_edges.py +112 -0
- palfrey-0.1.0/tests/runtime/test_env.py +42 -0
- palfrey-0.1.0/tests/runtime/test_env_dotenv_compat.py +28 -0
- palfrey-0.1.0/tests/runtime/test_gunicorn_workers_compat.py +214 -0
- palfrey-0.1.0/tests/runtime/test_lifespan.py +71 -0
- palfrey-0.1.0/tests/runtime/test_logging_config.py +135 -0
- palfrey-0.1.0/tests/runtime/test_logging_config_compat.py +218 -0
- palfrey-0.1.0/tests/runtime/test_main_module_compat.py +20 -0
- palfrey-0.1.0/tests/runtime/test_public_api_compat.py +14 -0
- palfrey-0.1.0/tests/runtime/test_runtime.py +224 -0
- palfrey-0.1.0/tests/runtime/test_runtime_api_compat.py +205 -0
- palfrey-0.1.0/tests/runtime/test_runtime_behavior_compat.py +157 -0
- palfrey-0.1.0/tests/runtime/test_runtime_main_compat.py +44 -0
- palfrey-0.1.0/tests/server/__init__.py +0 -0
- palfrey-0.1.0/tests/server/test_server_behavior_compat.py +561 -0
- palfrey-0.1.0/tests/server/test_server_http_next.py +248 -0
- palfrey-0.1.0/tests/server/test_server_internal.py +528 -0
- palfrey-0.1.0/tests/server/test_server_serve_compat_extra.py +453 -0
- palfrey-0.1.0/tests/supervisors/__init__.py +0 -0
- palfrey-0.1.0/tests/supervisors/test_reload.py +294 -0
- palfrey-0.1.0/tests/supervisors/test_reload_behavior_compat.py +122 -0
- palfrey-0.1.0/tests/supervisors/test_workers.py +238 -0
- palfrey-0.1.0/tests/supervisors/test_workers_behavior_compat.py +144 -0
- palfrey-0.1.0/tests/unit/__init__.py +0 -0
- palfrey-0.1.0/tests/unit/test_acceleration.py +51 -0
- palfrey-0.1.0/tests/unit/test_acceleration_compat_extra.py +50 -0
- palfrey-0.1.0/tests/unit/test_cli.py +16 -0
- palfrey-0.1.0/tests/unit/test_config.py +13 -0
- palfrey-0.1.0/tests/unit/test_http_protocol.py +29 -0
- palfrey-0.1.0/tests/unit/test_importer.py +27 -0
- palfrey-0.1.0/tests/unit/test_websocket_protocol.py +17 -0
palfrey-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# folders
|
|
2
|
+
*.egg-info/
|
|
3
|
+
.hypothesis/
|
|
4
|
+
.idea/
|
|
5
|
+
.mypy_cache/
|
|
6
|
+
.pytest_cache/
|
|
7
|
+
.scannerwork/
|
|
8
|
+
.tox/
|
|
9
|
+
.venv/
|
|
10
|
+
.vscode/
|
|
11
|
+
__pycache__/
|
|
12
|
+
virtualenv/
|
|
13
|
+
build/
|
|
14
|
+
dist/
|
|
15
|
+
node_modules/
|
|
16
|
+
results/
|
|
17
|
+
site/
|
|
18
|
+
site_lang/
|
|
19
|
+
target/
|
|
20
|
+
|
|
21
|
+
# files
|
|
22
|
+
par.md
|
|
23
|
+
**/*.so
|
|
24
|
+
**/*.sqlite
|
|
25
|
+
*.iml
|
|
26
|
+
**/*_test*
|
|
27
|
+
.DS_Store
|
|
28
|
+
.coverage
|
|
29
|
+
.coverage.*
|
|
30
|
+
.python-version
|
|
31
|
+
coverage.*
|
|
32
|
+
example.sqlite
|
palfrey-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Copyright © 2025, Dymmond Ltd. All rights reserved.
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
4
|
+
|
|
5
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
6
|
+
|
|
7
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
8
|
+
|
|
9
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
10
|
+
|
|
11
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
palfrey-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: palfrey
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A clean-room ASGI server with Uvicorn-compatible CLI and behavior mapping.
|
|
5
|
+
Project-URL: Homepage, https://github.com/dymmond/palfrey
|
|
6
|
+
Project-URL: Documentation, https://palfrey.dymmond.com
|
|
7
|
+
Project-URL: Source, https://github.com/dymmond/palfrey
|
|
8
|
+
Project-URL: Changelog, https://github.com/dymmond/palfrey/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: Tiago Silva <tarsil@tarsild.io>
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: asgi,click,server,websocket
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Web Environment
|
|
15
|
+
Classifier: Framework :: AsyncIO
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
27
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
28
|
+
Classifier: Typing :: Typed
|
|
29
|
+
Requires-Python: >=3.10
|
|
30
|
+
Requires-Dist: click<9.0.0,>=8.1.7
|
|
31
|
+
Requires-Dist: h11>=0.8
|
|
32
|
+
Provides-Extra: benchmark
|
|
33
|
+
Requires-Dist: uvicorn[standard]<1.0.0,>=0.34.0; extra == 'benchmark'
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: maturin<2.0.0,>=1.9.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: ruff<1.0.0,>=0.11.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: ty>=0.0.1a16; extra == 'dev'
|
|
38
|
+
Provides-Extra: docs
|
|
39
|
+
Requires-Dist: griffe-typingdoc<1.0,>=0.2.2; extra == 'docs'
|
|
40
|
+
Requires-Dist: mdx-include>=1.4.2; extra == 'docs'
|
|
41
|
+
Requires-Dist: mkdocs-macros-plugin>=0.4.0; extra == 'docs'
|
|
42
|
+
Requires-Dist: mkdocs-material>=9.4.4; extra == 'docs'
|
|
43
|
+
Requires-Dist: mkdocs-meta-descriptions-plugin>=2.3.0; extra == 'docs'
|
|
44
|
+
Requires-Dist: mkdocs<2.0.0,>=1.1.2; extra == 'docs'
|
|
45
|
+
Requires-Dist: mkdocstrings[python]>=0.23.0; extra == 'docs'
|
|
46
|
+
Requires-Dist: pyyaml<7.0.0,>=6.0; extra == 'docs'
|
|
47
|
+
Requires-Dist: sayer>=0.7.4; extra == 'docs'
|
|
48
|
+
Requires-Dist: typing-extensions>=3.10.0; extra == 'docs'
|
|
49
|
+
Provides-Extra: http2
|
|
50
|
+
Requires-Dist: h2>=4.1.0; extra == 'http2'
|
|
51
|
+
Provides-Extra: http3
|
|
52
|
+
Requires-Dist: aioquic>=1.2.0; extra == 'http3'
|
|
53
|
+
Provides-Extra: standard
|
|
54
|
+
Requires-Dist: colorama>=0.4; (sys_platform == 'win32') and extra == 'standard'
|
|
55
|
+
Requires-Dist: httptools>=0.6.3; extra == 'standard'
|
|
56
|
+
Requires-Dist: python-dotenv>=0.13; extra == 'standard'
|
|
57
|
+
Requires-Dist: pyyaml>=5.1; extra == 'standard'
|
|
58
|
+
Requires-Dist: uvloop>=0.15.1; (sys_platform != 'win32' and (sys_platform != 'cygwin' and platform_python_implementation != 'PyPy')) and extra == 'standard'
|
|
59
|
+
Requires-Dist: watchfiles>=0.20; extra == 'standard'
|
|
60
|
+
Requires-Dist: websockets>=10.4; extra == 'standard'
|
|
61
|
+
Provides-Extra: testing
|
|
62
|
+
Requires-Dist: pytest-cov<7.0.0,>=5.0.0; extra == 'testing'
|
|
63
|
+
Requires-Dist: pytest<9.0.0,>=8.3.0; extra == 'testing'
|
|
64
|
+
Description-Content-Type: text/markdown
|
|
65
|
+
|
|
66
|
+
# Palfrey
|
|
67
|
+
|
|
68
|
+
<p align="center">
|
|
69
|
+
<a href="https://palfrey.dymmond.com"><img src="https://res.cloudinary.com/dymmond/image/upload/v1771522360/Palfrey/Logo/logo_ocxyty.png" alt='Palfrey'></a>
|
|
70
|
+
</p>
|
|
71
|
+
|
|
72
|
+
<p align="center">
|
|
73
|
+
<em>Palfrey is a clean-room, high-performance Python ASGI server with source-traceable parity mapping.</em>
|
|
74
|
+
</p>
|
|
75
|
+
|
|
76
|
+
<p align="center">
|
|
77
|
+
<a href="https://github.com/dymmond/palfrey/actions/workflows/ci.yml/badge.svg?event=push&branch=main" target="_blank">
|
|
78
|
+
<img src="https://github.com/dymmond/palfrey/actions/workflows/ci.yml/badge.svg?event=push&branch=main" alt="Test Suite">
|
|
79
|
+
</a>
|
|
80
|
+
|
|
81
|
+
<a href="https://pypi.org/project/palfrey" target="_blank">
|
|
82
|
+
<img src="https://img.shields.io/pypi/v/palfrey?color=%2334D058&label=pypi%20package" alt="Package version">
|
|
83
|
+
</a>
|
|
84
|
+
|
|
85
|
+
<a href="https://pypi.org/project/palfrey" target="_blank">
|
|
86
|
+
<img src="https://img.shields.io/pypi/pyversions/palfrey.svg?color=%2334D058" alt="Supported Python versions">
|
|
87
|
+
</a>
|
|
88
|
+
</p>
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
**Documentation**: [https://palfrey.dev](https://palfrey.dev) 📚
|
|
93
|
+
|
|
94
|
+
**Source Code**: [https://github.com/dymmond/palfrey](https://github.com/dymmond/palfrey)
|
|
95
|
+
|
|
96
|
+
**The official supported version is always the latest released**.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
Palfrey is a clean-room ASGI server focused on three things:
|
|
101
|
+
|
|
102
|
+
- behavior you can reason about
|
|
103
|
+
- deployment controls you can operate safely
|
|
104
|
+
- performance you can reproduce and verify
|
|
105
|
+
|
|
106
|
+
Protocol runtime modes include HTTP/1.1 backends plus opt-in HTTP/2 (`--http h2`) and HTTP/3 (`--http h3`) paths.
|
|
107
|
+
|
|
108
|
+
This documentation is written for both technical and non-technical readers.
|
|
109
|
+
|
|
110
|
+
- Engineers can use the protocol details, option tables, and runbooks.
|
|
111
|
+
- Product, support, and operations teams can use the plain-language summaries and checklists.
|
|
112
|
+
|
|
113
|
+
## What Palfrey Does
|
|
114
|
+
|
|
115
|
+
At runtime, Palfrey sits between clients and your ASGI application.
|
|
116
|
+
|
|
117
|
+
1. accepts TCP or UNIX socket connections
|
|
118
|
+
2. parses protocol bytes into ASGI events
|
|
119
|
+
3. calls your app with `scope`, `receive`, `send`
|
|
120
|
+
4. writes responses back to clients
|
|
121
|
+
5. manages process behavior (reload, workers, graceful shutdown)
|
|
122
|
+
|
|
123
|
+
## Who Should Start Where
|
|
124
|
+
|
|
125
|
+
## If you are new to ASGI
|
|
126
|
+
|
|
127
|
+
1. [Installation](getting-started/installation.md)
|
|
128
|
+
2. [Quickstart](getting-started/quickstart.md)
|
|
129
|
+
3. [Terms and Mental Models](concepts/terms-and-mental-models.md)
|
|
130
|
+
4. [Server Behavior](concepts/server-behavior.md)
|
|
131
|
+
|
|
132
|
+
## If you operate production services
|
|
133
|
+
|
|
134
|
+
1. [Deployment](operations/deployment.md)
|
|
135
|
+
2. [Workers](operations/workers.md)
|
|
136
|
+
3. [Observability](operations/observability.md)
|
|
137
|
+
4. [Troubleshooting](guides/troubleshooting.md)
|
|
138
|
+
5. [Release Process](operations/release-process.md)
|
|
139
|
+
|
|
140
|
+
## First 60 Seconds
|
|
141
|
+
|
|
142
|
+
Create `main.py`:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
async def app(scope, receive, send):
|
|
146
|
+
"""Return a plain-text greeting for HTTP requests."""
|
|
147
|
+
if scope["type"] != "http":
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
body = b"Hello from Palfrey"
|
|
151
|
+
await send(
|
|
152
|
+
{
|
|
153
|
+
"type": "http.response.start",
|
|
154
|
+
"status": 200,
|
|
155
|
+
"headers": [
|
|
156
|
+
(b"content-type", b"text/plain; charset=utf-8"),
|
|
157
|
+
(b"content-length", str(len(body)).encode("ascii")),
|
|
158
|
+
],
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
await send({"type": "http.response.body", "body": body})
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Run Palfrey:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
palfrey main:app --host 127.0.0.1 --port 8000
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Check it:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
curl http://127.0.0.1:8000
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Gunicorn + Palfrey worker:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
gunicorn main:app -k palfrey.workers.PalfreyWorker -w 4 -b 0.0.0.0:8000
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Documentation Structure
|
|
183
|
+
|
|
184
|
+
## Getting Started
|
|
185
|
+
|
|
186
|
+
- install, verify, and run your first app
|
|
187
|
+
- move from a minimal app to real startup patterns
|
|
188
|
+
|
|
189
|
+
## Concepts
|
|
190
|
+
|
|
191
|
+
- what ASGI is, and how Palfrey applies it
|
|
192
|
+
- how HTTP, WebSocket, and lifespan flows behave
|
|
193
|
+
- how server internals affect user-visible outcomes
|
|
194
|
+
|
|
195
|
+
## Reference
|
|
196
|
+
|
|
197
|
+
- full CLI and config surface
|
|
198
|
+
- protocol and logging behavior
|
|
199
|
+
- env var model and common errors
|
|
200
|
+
|
|
201
|
+
## Guides
|
|
202
|
+
|
|
203
|
+
- migration, security hardening, production rollout
|
|
204
|
+
- practical troubleshooting and FAQ
|
|
205
|
+
|
|
206
|
+
## Operations
|
|
207
|
+
|
|
208
|
+
- deployment shapes, workers, reload model
|
|
209
|
+
- capacity planning, observability, benchmark method
|
|
210
|
+
- platform-specific notes and release process
|
|
211
|
+
|
|
212
|
+
## Plain-Language Summary
|
|
213
|
+
|
|
214
|
+
If your application is the business logic, Palfrey is the runtime control layer around it.
|
|
215
|
+
A good runtime control layer gives teams:
|
|
216
|
+
|
|
217
|
+
- predictable startup and shutdown
|
|
218
|
+
- fewer surprises under traffic spikes
|
|
219
|
+
- clearer incident response paths
|
|
220
|
+
- safer, repeatable deployments
|
palfrey-0.1.0/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Palfrey
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://palfrey.dymmond.com"><img src="https://res.cloudinary.com/dymmond/image/upload/v1771522360/Palfrey/Logo/logo_ocxyty.png" alt='Palfrey'></a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<em>Palfrey is a clean-room, high-performance Python ASGI server with source-traceable parity mapping.</em>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://github.com/dymmond/palfrey/actions/workflows/ci.yml/badge.svg?event=push&branch=main" target="_blank">
|
|
13
|
+
<img src="https://github.com/dymmond/palfrey/actions/workflows/ci.yml/badge.svg?event=push&branch=main" alt="Test Suite">
|
|
14
|
+
</a>
|
|
15
|
+
|
|
16
|
+
<a href="https://pypi.org/project/palfrey" target="_blank">
|
|
17
|
+
<img src="https://img.shields.io/pypi/v/palfrey?color=%2334D058&label=pypi%20package" alt="Package version">
|
|
18
|
+
</a>
|
|
19
|
+
|
|
20
|
+
<a href="https://pypi.org/project/palfrey" target="_blank">
|
|
21
|
+
<img src="https://img.shields.io/pypi/pyversions/palfrey.svg?color=%2334D058" alt="Supported Python versions">
|
|
22
|
+
</a>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
**Documentation**: [https://palfrey.dev](https://palfrey.dev) 📚
|
|
28
|
+
|
|
29
|
+
**Source Code**: [https://github.com/dymmond/palfrey](https://github.com/dymmond/palfrey)
|
|
30
|
+
|
|
31
|
+
**The official supported version is always the latest released**.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
Palfrey is a clean-room ASGI server focused on three things:
|
|
36
|
+
|
|
37
|
+
- behavior you can reason about
|
|
38
|
+
- deployment controls you can operate safely
|
|
39
|
+
- performance you can reproduce and verify
|
|
40
|
+
|
|
41
|
+
Protocol runtime modes include HTTP/1.1 backends plus opt-in HTTP/2 (`--http h2`) and HTTP/3 (`--http h3`) paths.
|
|
42
|
+
|
|
43
|
+
This documentation is written for both technical and non-technical readers.
|
|
44
|
+
|
|
45
|
+
- Engineers can use the protocol details, option tables, and runbooks.
|
|
46
|
+
- Product, support, and operations teams can use the plain-language summaries and checklists.
|
|
47
|
+
|
|
48
|
+
## What Palfrey Does
|
|
49
|
+
|
|
50
|
+
At runtime, Palfrey sits between clients and your ASGI application.
|
|
51
|
+
|
|
52
|
+
1. accepts TCP or UNIX socket connections
|
|
53
|
+
2. parses protocol bytes into ASGI events
|
|
54
|
+
3. calls your app with `scope`, `receive`, `send`
|
|
55
|
+
4. writes responses back to clients
|
|
56
|
+
5. manages process behavior (reload, workers, graceful shutdown)
|
|
57
|
+
|
|
58
|
+
## Who Should Start Where
|
|
59
|
+
|
|
60
|
+
## If you are new to ASGI
|
|
61
|
+
|
|
62
|
+
1. [Installation](getting-started/installation.md)
|
|
63
|
+
2. [Quickstart](getting-started/quickstart.md)
|
|
64
|
+
3. [Terms and Mental Models](concepts/terms-and-mental-models.md)
|
|
65
|
+
4. [Server Behavior](concepts/server-behavior.md)
|
|
66
|
+
|
|
67
|
+
## If you operate production services
|
|
68
|
+
|
|
69
|
+
1. [Deployment](operations/deployment.md)
|
|
70
|
+
2. [Workers](operations/workers.md)
|
|
71
|
+
3. [Observability](operations/observability.md)
|
|
72
|
+
4. [Troubleshooting](guides/troubleshooting.md)
|
|
73
|
+
5. [Release Process](operations/release-process.md)
|
|
74
|
+
|
|
75
|
+
## First 60 Seconds
|
|
76
|
+
|
|
77
|
+
Create `main.py`:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
async def app(scope, receive, send):
|
|
81
|
+
"""Return a plain-text greeting for HTTP requests."""
|
|
82
|
+
if scope["type"] != "http":
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
body = b"Hello from Palfrey"
|
|
86
|
+
await send(
|
|
87
|
+
{
|
|
88
|
+
"type": "http.response.start",
|
|
89
|
+
"status": 200,
|
|
90
|
+
"headers": [
|
|
91
|
+
(b"content-type", b"text/plain; charset=utf-8"),
|
|
92
|
+
(b"content-length", str(len(body)).encode("ascii")),
|
|
93
|
+
],
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
await send({"type": "http.response.body", "body": body})
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Run Palfrey:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
palfrey main:app --host 127.0.0.1 --port 8000
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Check it:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
curl http://127.0.0.1:8000
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Gunicorn + Palfrey worker:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
gunicorn main:app -k palfrey.workers.PalfreyWorker -w 4 -b 0.0.0.0:8000
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Documentation Structure
|
|
118
|
+
|
|
119
|
+
## Getting Started
|
|
120
|
+
|
|
121
|
+
- install, verify, and run your first app
|
|
122
|
+
- move from a minimal app to real startup patterns
|
|
123
|
+
|
|
124
|
+
## Concepts
|
|
125
|
+
|
|
126
|
+
- what ASGI is, and how Palfrey applies it
|
|
127
|
+
- how HTTP, WebSocket, and lifespan flows behave
|
|
128
|
+
- how server internals affect user-visible outcomes
|
|
129
|
+
|
|
130
|
+
## Reference
|
|
131
|
+
|
|
132
|
+
- full CLI and config surface
|
|
133
|
+
- protocol and logging behavior
|
|
134
|
+
- env var model and common errors
|
|
135
|
+
|
|
136
|
+
## Guides
|
|
137
|
+
|
|
138
|
+
- migration, security hardening, production rollout
|
|
139
|
+
- practical troubleshooting and FAQ
|
|
140
|
+
|
|
141
|
+
## Operations
|
|
142
|
+
|
|
143
|
+
- deployment shapes, workers, reload model
|
|
144
|
+
- capacity planning, observability, benchmark method
|
|
145
|
+
- platform-specific notes and release process
|
|
146
|
+
|
|
147
|
+
## Plain-Language Summary
|
|
148
|
+
|
|
149
|
+
If your application is the business logic, Palfrey is the runtime control layer around it.
|
|
150
|
+
A good runtime control layer gives teams:
|
|
151
|
+
|
|
152
|
+
- predictable startup and shutdown
|
|
153
|
+
- fewer surprises under traffic spikes
|
|
154
|
+
- clearer incident response paths
|
|
155
|
+
- safer, repeatable deployments
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Benchmark package for Palfrey performance comparisons."""
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Benchmark ASGI application targets."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
async def app(scope, receive, send):
|
|
7
|
+
"""Serve HTTP and WebSocket echo paths for benchmark workloads."""
|
|
8
|
+
|
|
9
|
+
if scope["type"] == "lifespan":
|
|
10
|
+
while True:
|
|
11
|
+
message = await receive()
|
|
12
|
+
if message["type"] == "lifespan.startup":
|
|
13
|
+
await send({"type": "lifespan.startup.complete"})
|
|
14
|
+
elif message["type"] == "lifespan.shutdown":
|
|
15
|
+
await send({"type": "lifespan.shutdown.complete"})
|
|
16
|
+
return
|
|
17
|
+
|
|
18
|
+
if scope["type"] == "http":
|
|
19
|
+
await send(
|
|
20
|
+
{
|
|
21
|
+
"type": "http.response.start",
|
|
22
|
+
"status": 200,
|
|
23
|
+
"headers": [(b"content-type", b"text/plain")],
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
await send({"type": "http.response.body", "body": b"pong"})
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
if scope["type"] == "websocket":
|
|
30
|
+
await send({"type": "websocket.accept"})
|
|
31
|
+
while True:
|
|
32
|
+
message = await receive()
|
|
33
|
+
if message["type"] == "websocket.disconnect":
|
|
34
|
+
return
|
|
35
|
+
if message["type"] == "websocket.receive":
|
|
36
|
+
if "text" in message:
|
|
37
|
+
await send({"type": "websocket.send", "text": message["text"]})
|
|
38
|
+
else:
|
|
39
|
+
await send({"type": "websocket.send", "bytes": message.get("bytes", b"")})
|