podpack-qrcode 0.2.1__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.
- podpack_qrcode-0.2.1/PKG-INFO +32 -0
- podpack_qrcode-0.2.1/README.md +20 -0
- podpack_qrcode-0.2.1/pyproject.toml +48 -0
- podpack_qrcode-0.2.1/src/podpack_qrcode/__init__.py +15 -0
- podpack_qrcode-0.2.1/src/podpack_qrcode/forms.py +7 -0
- podpack_qrcode-0.2.1/src/podpack_qrcode/templates/qrcode/form.html +32 -0
- podpack_qrcode-0.2.1/src/podpack_qrcode/views.py +30 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: podpack-qrcode
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: QR code generation for podpack sites
|
|
5
|
+
Author: Steve Holden
|
|
6
|
+
Author-email: Steve Holden <steve@holdenweb.com>
|
|
7
|
+
Requires-Dist: flask>=3.0
|
|
8
|
+
Requires-Dist: flask-wtf>=1.2.1
|
|
9
|
+
Requires-Dist: qrcode[pil]>=7.4.2
|
|
10
|
+
Requires-Python: >=3.12
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# podpack-qrcode
|
|
14
|
+
|
|
15
|
+
A podpack app that turns a piece of text into a QR code, delivered as a GIF.
|
|
16
|
+
|
|
17
|
+
The distribution is `podpack-qrcode`, the import name (for a site's `apps`
|
|
18
|
+
list) is `podpack_qrcode`, and the app answers to `qrcode` — its blueprint's
|
|
19
|
+
name, which keys `[site.mounts]` and its directories on disk.
|
|
20
|
+
|
|
21
|
+
## Routes
|
|
22
|
+
|
|
23
|
+
| Route | What it does |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| `/qrcode/` (GET) | the form |
|
|
26
|
+
| `/qrcode/` (POST) | the QR code, as `image/gif` |
|
|
27
|
+
|
|
28
|
+
## What it needs from the site
|
|
29
|
+
|
|
30
|
+
The form is CSRF-protected by flask-wtf, which uses the `SECRET_KEY` podpack
|
|
31
|
+
already requires — nothing to configure. There is no `[apps.qrcode]` section;
|
|
32
|
+
the app has no settings.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# podpack-qrcode
|
|
2
|
+
|
|
3
|
+
A podpack app that turns a piece of text into a QR code, delivered as a GIF.
|
|
4
|
+
|
|
5
|
+
The distribution is `podpack-qrcode`, the import name (for a site's `apps`
|
|
6
|
+
list) is `podpack_qrcode`, and the app answers to `qrcode` — its blueprint's
|
|
7
|
+
name, which keys `[site.mounts]` and its directories on disk.
|
|
8
|
+
|
|
9
|
+
## Routes
|
|
10
|
+
|
|
11
|
+
| Route | What it does |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| `/qrcode/` (GET) | the form |
|
|
14
|
+
| `/qrcode/` (POST) | the QR code, as `image/gif` |
|
|
15
|
+
|
|
16
|
+
## What it needs from the site
|
|
17
|
+
|
|
18
|
+
The form is CSRF-protected by flask-wtf, which uses the `SECRET_KEY` podpack
|
|
19
|
+
already requires — nothing to configure. There is no `[apps.qrcode]` section;
|
|
20
|
+
the app has no settings.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "podpack-qrcode"
|
|
3
|
+
version = "0.2.1"
|
|
4
|
+
description = "QR code generation for podpack sites"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"flask>=3.0",
|
|
9
|
+
"flask-wtf>=1.2.1",
|
|
10
|
+
"qrcode[pil]>=7.4.2",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[[project.authors]]
|
|
14
|
+
name = "Steve Holden"
|
|
15
|
+
email = "steve@holdenweb.com"
|
|
16
|
+
|
|
17
|
+
[build-system]
|
|
18
|
+
requires = ["uv_build>=0.8.4,<0.9.0"]
|
|
19
|
+
build-backend = "uv_build"
|
|
20
|
+
|
|
21
|
+
# podpack is deliberately absent from `dependencies`: a real dependency's
|
|
22
|
+
# [tool.uv.sources] entry travels with the distribution, so a site whose own
|
|
23
|
+
# podpack source differs could never lock. A dependency group is dev-only
|
|
24
|
+
# metadata and constrains nobody. See writing-an-app.md rule 1.
|
|
25
|
+
[dependency-groups]
|
|
26
|
+
dev = [
|
|
27
|
+
"podpack",
|
|
28
|
+
"pytest>=8.0",
|
|
29
|
+
"mypy>=1.11",
|
|
30
|
+
"types-qrcode>=8.2.0.20260518",
|
|
31
|
+
"types-wtforms>=3.2.1.20260518",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[tool.uv.sources]
|
|
35
|
+
# The published repository, not a path. An editable pointer at
|
|
36
|
+
# /Users/sholden/sites/podpack resolved on exactly one machine, put an absolute
|
|
37
|
+
# home directory into a committed lockfile, and made this package unlockable
|
|
38
|
+
# anywhere else. podpack is on GitHub, so a git source needs no checkout at all.
|
|
39
|
+
podpack = { git = "https://github.com/holdenweb/podpack.git" }
|
|
40
|
+
|
|
41
|
+
[tool.mypy]
|
|
42
|
+
files = ["src", "tests"]
|
|
43
|
+
|
|
44
|
+
# flask-wtf ships neither stubs nor a py.typed marker, and no types-* package
|
|
45
|
+
# exists for it. Suppressed for that one module rather than globally.
|
|
46
|
+
[[tool.mypy.overrides]]
|
|
47
|
+
module = "flask_wtf.*"
|
|
48
|
+
ignore_missing_imports = true
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""The qrcode app: turn a piece of text into a QR code image."""
|
|
2
|
+
|
|
3
|
+
from podpack import Section, SiteApp
|
|
4
|
+
|
|
5
|
+
from .views import blueprint
|
|
6
|
+
|
|
7
|
+
site_app = SiteApp(
|
|
8
|
+
blueprint=blueprint,
|
|
9
|
+
url_prefix="/qrcode",
|
|
10
|
+
# `qrcode.form`, not `podpack_qrcode.form`: nav names an *endpoint*, and
|
|
11
|
+
# endpoints carry the blueprint's name, which is this app's name (ADR-0003).
|
|
12
|
+
# `podpack_qrcode` is only the import name -- what a site's `apps` list
|
|
13
|
+
# carries -- and the two differ deliberately.
|
|
14
|
+
nav=(Section("QR codes", "qrcode.form"),),
|
|
15
|
+
)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block content %}
|
|
4
|
+
<div class="col-5">
|
|
5
|
+
<h1>QR Code Generator</h1>
|
|
6
|
+
<form class="form-horizontal" method="post" enctype="multipart/form-data">
|
|
7
|
+
<fieldset>
|
|
8
|
+
{{ form.hidden_tag() }}
|
|
9
|
+
|
|
10
|
+
<!-- Form Name -->
|
|
11
|
+
<legend>QR Code Generator</legend>
|
|
12
|
+
<p>Enter the text you want in the QR code
|
|
13
|
+
and it will be displayed as a GIF file.</p>
|
|
14
|
+
|
|
15
|
+
<!-- File Button -->
|
|
16
|
+
<div class="control-group">
|
|
17
|
+
<label class="control-label" for="qrcode_text">QR code text</label>
|
|
18
|
+
<div class="controls">
|
|
19
|
+
{{ form.qrcode_text(size=32) }}
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<!-- Button -->
|
|
24
|
+
<div class="control-group">
|
|
25
|
+
<label class="control-label" for="sbutton">Get QR Code</label>
|
|
26
|
+
<div class="controls">
|
|
27
|
+
{{ form.submit() }}
|
|
28
|
+
</div>
|
|
29
|
+
</fieldset>
|
|
30
|
+
</form>
|
|
31
|
+
</div>
|
|
32
|
+
{% endblock %}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""One form, one image: the QR code generator."""
|
|
2
|
+
|
|
3
|
+
import io
|
|
4
|
+
from logging import getLogger
|
|
5
|
+
|
|
6
|
+
import qrcode
|
|
7
|
+
from flask import Blueprint, Response, render_template, request
|
|
8
|
+
from flask.typing import ResponseReturnValue
|
|
9
|
+
from qrcode.image.pil import PilImage
|
|
10
|
+
|
|
11
|
+
from .forms import QRCodeForm
|
|
12
|
+
|
|
13
|
+
logger = getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
blueprint = Blueprint("qrcode", __name__, template_folder="templates")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@blueprint.route("/", methods=["GET", "POST"])
|
|
19
|
+
def form() -> ResponseReturnValue:
|
|
20
|
+
form = QRCodeForm()
|
|
21
|
+
if form.validate_on_submit():
|
|
22
|
+
text = request.form["qrcode_text"]
|
|
23
|
+
# The PIL factory named explicitly: qrcode falls back to a PyPNG-backed
|
|
24
|
+
# image without Pillow, whose save() cannot produce the GIF promised.
|
|
25
|
+
image = qrcode.make(text, image_factory=PilImage)
|
|
26
|
+
memfile = io.BytesIO()
|
|
27
|
+
image.save(memfile, format="GIF")
|
|
28
|
+
logger.info("generated a QR code of %d characters", len(text))
|
|
29
|
+
return Response(memfile.getvalue(), mimetype="image/gif")
|
|
30
|
+
return render_template("qrcode/form.html", form=form, title="QR Code Generator")
|