Skip to content

Commit

Permalink
fix: pass import path instead of callable in 'screenshot_apps'
Browse files Browse the repository at this point in the history
  • Loading branch information
azmeuk committed Dec 25, 2024
1 parent 4f1fa8d commit db07c66
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 138 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,10 @@ jobs:
run: playwright install
- name: Run unittest
run: pytest
- name: Upload failed image artifact
if: failure()
uses: actions/upload-artifact@v4
with:
name: failed-images-${{ matrix.os }}-${{ matrix.python-version }}
# https://docs.pytest.org/en/stable/how-to/tmp_path.html#temporary-directory-location-and-retention
path: /tmp/pytest-of-*/pytest-*/*/*/*.obtained.png
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,25 +65,28 @@ It also generates a PDF file when `pdf` option is given, which might be useful w
## Local WSGI application

`sphinxcontrib-screenshot` can launch your local WSGI applications and take screenshot of thems.
Define them in the `screenshot_apps` dict. The key must be a name you choose for your applications, and the value must be a callable that creates a WSGI app:
Define them in the `screenshot_apps` dict.
The key must be a name you choose for your applications, and the value must be a callable that creates a WSGI app:

```python
from flask import Flask

def create_app():
def create_app(sphinx_app):
app = Flask(__name__)

@app.route("/hello")
def hello():
return "Hello, world!"

return app
```


```
screenshot_apps = {
"example": create_app,
"example": "my_module.my_app:create_app",
}
```
Note that you might manually add your application module in `sys.path`.

Then you can use a Sphinx substitution with your application name to refer to its temporary URL:

Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ dev =
mypy
Pillow
pytest
pytest-regressions
pytest-regressions[image]
sphinx[test]
toml
twine
Expand Down
17 changes: 13 additions & 4 deletions sphinxcontrib/screenshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.

import hashlib
import importlib
import os
import threading
import typing
Expand Down Expand Up @@ -208,20 +209,28 @@ def run(self) -> typing.List[nodes.Node]:
app_threads = {}


def resolve_wsgi_app_import(app: Sphinx, app_path: str):
module_path, app_attribute = app_path.split(":")
module = importlib.import_module(module_path)
app_attr = getattr(module, app_attribute)
wsgi_app = app_attr(app) if callable(app_attr) else app_attr
return wsgi_app


def setup_apps(app: Sphinx, config: Config):
"""Start the WSGI application threads.
A new replacement is created for each WSGI app."""
for app_name, app_builder in config.screenshot_apps.items():
for wsgi_app_name, wsgi_app_path in config.screenshot_apps.items():
port = pick_unused_port()
config.rst_prolog = (
config.rst_prolog or
"") + f".. |{app_name}| replace:: http://localhost:{port}\n"
wsgi_app = app_builder()
"") + f"\n.. |{wsgi_app_name}| replace:: http://localhost:{port}\n"
wsgi_app = resolve_wsgi_app_import(app, wsgi_app_path)
httpd = wsgiref.simple_server.make_server("localhost", port, wsgi_app)
thread = threading.Thread(target=httpd.serve_forever)
thread.start()
app_threads[app_name] = (httpd, thread)
app_threads[wsgi_app_name] = (httpd, thread)


def teardown_apps(app: Sphinx, exception: typing.Optional[Exception]):
Expand Down
Empty file.
9 changes: 4 additions & 5 deletions tests/roots/test-wsgi-apps/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
def hello_world_app(environ, start_response):
headers = [('Content-type', 'text/plain; charset=utf-8')]
start_response('200 OK', headers)
return [b'Hello, World!']
import pathlib
import sys

sys.path.insert(0, str(pathlib.Path(__file__).parent.resolve()))

extensions = ['sphinxcontrib.screenshot']
screenshot_apps = {"example": lambda: hello_world_app}
screenshot_apps = {"example": "example_app:create_app"}
25 changes: 25 additions & 0 deletions tests/roots/test-wsgi-apps/example_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
def create_app(sphinx_app):

def hello_world_app(environ, start_response):
headers = [('Content-type', 'text/html; charset=utf-8')]
start_response('200 OK', headers)
style = b"font-family: arial; font-size: 10px; margin: 0; padding: 0"
return [
b"<html>" + b'<body style="' + style + b'">' + b"Hello, World!" +
b"</body>" + b"</html>"
]

return hello_world_app
2 changes: 2 additions & 0 deletions tests/roots/test-wsgi-apps/index.rst
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
.. screenshot:: |example|
:width: 800
:height: 600
4 changes: 2 additions & 2 deletions tests/test_wsgi_apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

@pytest.mark.sphinx('html', testroot="wsgi-apps")
def test_default(app: SphinxTestApp, status: StringIO, warning: StringIO,
data_regression) -> None:
image_regression) -> None:
app.build()
out_html = app.outdir / "index.html"

Expand All @@ -29,4 +29,4 @@ def test_default(app: SphinxTestApp, status: StringIO, warning: StringIO,

img_path = app.outdir / imgs[0]['src']
with open(img_path, "rb") as fd:
data_regression.check(fd.read())
image_regression.check(fd.read())
Binary file added tests/test_wsgi_apps/test_default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
122 changes: 0 additions & 122 deletions tests/test_wsgi_apps/test_default.yml

This file was deleted.

0 comments on commit db07c66

Please sign in to comment.