From ff346673623b964114af5e53bdfb3a066b057ec2 Mon Sep 17 00:00:00 2001 From: Eric Wolf Date: Fri, 1 Oct 2021 10:24:49 +0200 Subject: [PATCH] increment version to 3.1 This includes README and debian/changelog updates --- README.md | 112 +++++++++++++++++++++++++++++------- debian/changelog | 17 ++++++ pyhp/__init__.py | 2 +- pyhp/wsgi/interfaces/php.py | 1 + 4 files changed, 110 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 88709e9..462fbf8 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,12 @@ A script is called either by the configuration of the web server or a shebang an - unlike PHP, each code section of code must have a valid syntax of its own - if-Statements or loops can not span multiple code sections + ### Runtime + - module level constants are set and allow for source introspection if the backend supports it + - `exit` and [`sys.exit`](https://docs.python.org/3/library/sys.html#sys.exit) terminate the script, not the whole server + - [`atexit`](https://docs.python.org/3/library/atexit.html) registered functions dont get called until server shutdown in WSGI mode + - since try statements can't span multiple code sections cleanup actions should be executed by [`register_shutdown_function`](#php-interface) + ### Usage - can be used for - CLI scripts with the `pyhp-cli` command @@ -38,34 +44,35 @@ A script is called either by the configuration of the web server or a shebang an ### PHP Interface - the following PHP features are available: - - `$_SERVER` as `SERVER` - - `$_REQUEST` as `REQUEST` - - `$_GET` as `GET` - - `$_POST` as `POST` - - `$_COOKIE` as `COOKIE` - - `$_FILES` as `FILES` - - `http_response_code` - - `header` - - `headers_list` - - `header_remove` - - `headers_sent` - - `header_register_callback` with an additional `replace` keyword argument to register multiple callbacks - - `setcookie` with an additional `samesite` keyword argument - - `setrawcookie` also with an additional `samesite` keyword argument - - `opcache_compile_file` which raises Exceptions instead of returning `False` when compilation fails - - `opcache_invalidate` - - `opcache_is_script_cached` - - `opcache_reset` + - [`$_SERVER`](https://www.php.net/manual/en/reserved.variables.server.php) as `SERVER` + - [`$_REQUEST`](https://www.php.net/manual/en/reserved.variables.request.php) as `REQUEST` + - [`$_GET`](https://www.php.net/manual/en/reserved.variables.get.php) as `GET` + - [`$_POST`](https://www.php.net/manual/en/reserved.variables.post.php) as `POST` + - [`$_COOKIE`](https://www.php.net/manual/en/reserved.variables.cookies.php) as `COOKIE` + - [`$_FILES`](https://www.php.net/manual/en/reserved.variables.files.php) as `FILES` + - [`http_response_code`](https://www.php.net/manual/en/function.http-response-code) + - [`header`](https://www.php.net/manual/en/function.header.php) + - [`headers_list`](https://www.php.net/manual/en/function.headers-list.php) + - [`header_remove`](https://www.php.net/manual/en/function.header-remove.php) + - [`headers_sent`](https://www.php.net/manual/en/function.headers-sent.php) + - [`header_register_callback`](https://www.php.net/manual/en/function.header-register-callback.php) with an additional `replace` keyword argument to register multiple callbacks + - [`setcookie`](https://www.php.net/manual/en/function.setcookie.php) with an additional `samesite` keyword argument + - [`setrawcookie`](https://www.php.net/manual/en/function.setrawcookie.php) also with an additional `samesite` keyword argument + - [`register_shutdown_function`](https://www.php.net/manual/en/function.register-shutdown-function) with reversed callback execution order (LIFO) + - [`opcache_compile_file`](https://www.php.net/manual/en/function.opcache-compile-file) which raises Exceptions instead of returning `False` when compilation fails + - [`opcache_invalidate`](https://www.php.net/manual/en/function.opcache-invalidate.php) + - [`opcache_is_script_cached`](https://www.php.net/manual/en/function.opcache-is-script-cached.php) + - [`opcache_reset`](https://www.php.net/manual/en/function.opcache-reset.php) ### Config file - - is valid toml + - is valid [toml](https://toml.io) - is looked for in these locations (no merging takes place, the first file wins): - the path given by the `-c` or `--config` cli argument - the path pointed to by the `PYHPCONFIG` environment variable - `~/.config/pyhp.toml` - `/etc/pyhp.toml` - - raises a `RuntimeError` if not found + - raises a [`RuntimeError`](https://docs.python.org/3/library/exceptions.html#RuntimeError) if not found ### Backends @@ -90,7 +97,7 @@ A script is called either by the configuration of the web server or a shebang an 1. execute `debian/build_deb.sh` in the root directory of the project. 2. Done! You can now install the debian package with `sudo dpkg -i python3-pyhp-core_{version}-1_all.deb` - - Optional: check if the recommended packages `python3-toml` and `python3-werkzeug` are installed to use the CLI commands + - Optional: check if the recommended packages [`python3-toml`](https://packages.debian.org/search?keywords=python3-toml) and [`python3-werkzeug`](https://packages.debian.org/search?keywords=python3-werkzeug) are installed to use the CLI commands - Important: `pyhp-backend clear` will be executed on uninstall or upgrade if the backend is a cache, remember this when using paths containing `~` for the file cache ### Manually @@ -98,3 +105,66 @@ A script is called either by the configuration of the web server or a shebang an 2. set the `PYHPCONFIG` environ variable or copy *pyhp.toml* to one of the config file locations 3. Done! You can now use the `pyhp-*` commands + ## WSGI Example + + ### Manually + + ```python + import sys + import re + import tempfile + from wsgiref.simple_server import make_server + from pyhp.compiler import parsers, util, generic + from pyhp.backends.files import Directory + from pyhp.wsgi.apps import ConcurrentWSGIApp + from pyhp.wsgi.proxys import LocalStackProxy + from pyhp.wsgi.interfaces.php import PHPWSGIInterfaceFactory + from pyhp.wsgi.interfaces.phputils import UploadStreamFactory + + + compiler = util.Compiler( + parsers.RegexParser( + re.compile(r"<\?pyhp\s"), + re.compile(r"\s\?>") + ), + util.Dedenter( + generic.GenericCodeBuilder(-1) + ) + ) + + interface_factory = PHPWSGIInterfaceFactory( + 200, + [("Content-type", "text/html; charset=\"UTF-8\"")], + None, + ("GET", "POST", "COOKIE"), + 8000000, + UploadStreamFactory( + tempfile.gettempdir(), + 20 + ) + ) + + sys.stdout = proxy = LocalStackProxy(sys.stdout) + + with Directory(".", compiler) as backend: + with ConcurrentWSGIApp("tests/embedding/syntax.pyhp", backend, proxy, interface_factory) as app: + with make_server("", 8000, app) as httpd: + httpd.serve_forever() + + ``` + + ### From a config file + + ```python + from wsgiref.simple_server import make_server + import toml + from pyhp.wsgi.util import ConcurrentWSGIAppFactory + + + config = toml.load("pyhp.toml") + + with ConcurrentWSGIAppFactory.from_config(config) as factory: + with factory.app("tests/embedding/syntax.pyhp") as app: + with make_server("", 8000, app) as httpd: + httpd.serve_forever() + ``` diff --git a/debian/changelog b/debian/changelog index a137c4c..296f69a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,20 @@ +python3-pyhp-core (3.1-1) stable; urgency=low + + * eighth release + * add pyhp-backend command + * add backends.main submodule + * add script to clear the cache on debian uninstall + * add PHP opcache functions to PHPWSGIInterface + * add TimestampedCodeSource methods to FileCacheSource and MemoryCacheSource + * move code from wsgi.utils to [Compiler|RegexParser].from_config + * move load_config from main to seperate config submodule + * move FileSource constructor logic to .from_path and .with_inferred_spec + * fix CacheSourceContainer.gc and .clear not closing sources + * fix warnings on debian uninstall + * fix errors in ConcurrentWSGIApp.commit_removals if requesting a code source fails + + -- Eric Wolf Thu, 30 Sep 2021 18:59:00 +0100 + python3-pyhp-core (3.0-1) stable; urgency=low * seventh release diff --git a/pyhp/__init__.py b/pyhp/__init__.py index 6217d20..4913b66 100644 --- a/pyhp/__init__.py +++ b/pyhp/__init__.py @@ -13,7 +13,7 @@ # package metadata # needs to be defined before .main is imported -__version__ = "3.0" +__version__ = "3.1" __author__ = "Eric Wolf" __maintainer__ = "Eric Wolf" __license__ = "GPLv3" diff --git a/pyhp/wsgi/interfaces/php.py b/pyhp/wsgi/interfaces/php.py index 8136e79..2318ee8 100644 --- a/pyhp/wsgi/interfaces/php.py +++ b/pyhp/wsgi/interfaces/php.py @@ -355,6 +355,7 @@ def http_response_code(self, response_code: Optional[int] = None) -> int: def register_shutdown_function(self, callback: Callable[..., None], *args: Any, **kwargs: Any) -> None: """register a callback to be called on shutdown""" + # execute in lifo order to prevent calling low level callbacks before high level ones self.shutdown_callbacks.appendleft((callback, args, kwargs)) def opcache_compile_file(self, filename: str) -> bool: