Skip to content

Commit 16a80cb

Browse files
authored
Clean up repository now that Python 3.14 is out. (#16)
1 parent 077f3e1 commit 16a80cb

File tree

10 files changed

+162
-423
lines changed

10 files changed

+162
-423
lines changed

.devcontainer/Dockerfile

Lines changed: 0 additions & 20 deletions
This file was deleted.

.devcontainer/devcontainer.json

Lines changed: 0 additions & 44 deletions
This file was deleted.

.github/workflows/test.yml

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,23 @@ name: Test
66
on:
77
push:
88
branches:
9-
- '*'
10-
workflow_dispatch: # Allows manual triggering of the workflow
11-
9+
- "*"
10+
workflow_dispatch: # Allows manual triggering of the workflow
1211

1312
jobs:
14-
test:
15-
runs-on: ubuntu-latest
16-
steps:
17-
- name: Checkout repository
18-
uses: actions/checkout@v4
19-
# TODO: fix this stuff -- no longer working for some reason. -Dave
20-
# - name: Build Docker image
21-
# run: docker build -t pep750-docker -f .devcontainer/Dockerfile .
22-
# - name: Check sort order
23-
# run: docker run -v $(pwd):/app -w /app pep750-docker /bin/bash -c "pip install -r requirements.txt && isort --check pep"
24-
# - name: Check formatting
25-
# run: docker run -v $(pwd):/app -w /app pep750-docker /bin/bash -c "pip install -r requirements.txt && black --check pep"
26-
# - name: Run tests
27-
# run: docker run -v $(pwd):/app -w /app pep750-docker /bin/bash -c "pip install -r requirements.txt && pytest"
13+
test:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout repository
17+
uses: actions/checkout@v5
18+
19+
- name: Set up Python 3.14
20+
uses: actions/setup-python@v6
21+
with:
22+
python-version: "3.14"
23+
24+
- name: Install uv
25+
uses: astral-sh/setup-uv@v6
2826

27+
- name: Run tests
28+
run: uv run pytest

.pre-commit-config.yaml

Lines changed: 0 additions & 13 deletions
This file was deleted.

.vscode/settings.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"python.testing.pytestArgs": [
3-
"pep"
4-
],
5-
"python.testing.unittestEnabled": false,
6-
"python.testing.pytestEnabled": true
2+
"python.testing.pytestArgs": ["pep"],
3+
"python.testing.unittestEnabled": false,
4+
"python.testing.pytestEnabled": true,
5+
"python.terminal.activateEnvInCurrentTerminal": false,
6+
"python.terminal.activateEnvironment": false
77
}

README.md

Lines changed: 6 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,11 @@ This repository contains full implementations of the code examples described in
44

55
## Running This Code
66

7-
This repo has a [devcontainer](https://containers.dev) definition that makes it easy to run the examples. The devcontainer includes a [fork of cpython 3.14a7+](https://github.com/lysnikolaou/cpython/tree/tstrings) that provides a prototype implementation of PEP 750.
7+
You'll need [Python 3.14](https://www.python.org/downloads/release/python-3140/), which was released in October 2025, and includes support for t-strings.
88

9-
It's easy to run this code yourself:
9+
If you have [Astral's `uv`](https://docs.astral.sh/uv/) installed, you can run 3.14 in an isolated environment with `uv run --python 3.14 python`.
1010

11-
1. Make sure you have Docker installed
12-
2. Clone this repository and open it with `vscode`
13-
3. When asked, say that you want to re-open _inside_ the devcontainer
14-
15-
After the container is initialized, make sure that everything works by opening up a terminal in vscode. This will open in the running docker instance. Then:
16-
17-
```
18-
/workspaces/pep750-examples# python --version
19-
Python 3.14.0a7+
20-
/workspaces/pep750-examples# pytest
21-
... (hopefully, all tests pass!) ...
22-
```
23-
24-
Congrats; you're good to go!
25-
26-
## A Word About the Code
27-
28-
This repository builds on top of the @lysnikolaou's [cpython branch implementing t-strings](https://github.com/lysnikolaou/cpython/tree/tstrings).
29-
30-
### Linting, formatting, etc.
31-
32-
The included devcontainer loads my [fork of black with t-string support](https://github.com/davepeck/black/tree/pep750-support).
33-
34-
`isort` is used.
35-
36-
Tools like `mypy` and friends can't type check t-strings yet, hence the many extra `: Template` annotations sprinkled throughout the code.
11+
You can run tests on this repository `uv run pytest`.
3712

3813
## Examples
3914

@@ -48,6 +23,7 @@ templated = t"Hello {name!r}, value: {value:.2f}"
4823
formatted = f"Hello {name!r}, value: {value:.2f}"
4924
assert f(templated) == formatted
5025
```
26+
5127
See also [the tests](./pep/test_fstring.py).
5228

5329
This [example is described in detail](https://peps.python.org/pep-0750/#example-implementing-f-strings-with-t-strings) in PEP 750.
@@ -85,7 +61,6 @@ See the tests in [`test_logging.py`](./pep/test_logging.py).
8561

8662
This [example is described in detail](https://peps.python.org/pep-0750/#example-structured-logging) in PEP 750.
8763

88-
8964
### Working with old-style format strings
9065

9166
The code in [`format.py`](./pep/format.py) shows how to convert old-style format
@@ -101,133 +76,12 @@ assert f(as_template) == "Thank you Alice for spending $42.00."
10176

10277
The `from_format()` function supports essentially all the features of old-style format strings, including positional and keyword arguments, automatic and manual field numbering, index and dot interpolation notation, nested format specifiers, and more.
10378

104-
10579
### HTML Templating
10680

10781
There are several short "HTML templating" examples in [PEP 750](https://peps.python.org/pep-0750/).
10882

10983
They all use a hypothetical `html()` function that parses template strings to an intermediate type, `Element`, and supports context-dependent processing of interpolations.
11084

111-
A real working implementation of `html()` is found in this repository's [`web.py`](./pep/web.py). Corresponding tests are found in [`test_web.py`](./pep/test_web.py).
112-
113-
Building a full robust HTML templating package on top of template strings is both a noble goal _and_ beyond the scope of this example code. Instead, our goal is to hint at some interesting uses of template strings in the HTML context, and to provide an early roadmap (warts and all) for how a more robust package might be built.
114-
115-
The `Element` class is a simple representation of an HTML element:
116-
117-
```python
118-
119-
from dataclasses import dataclass
120-
121-
@dataclass(frozen=True)
122-
class Element:
123-
"""A simple representation of an HTML element."""
124-
125-
tag: str # An empty string indicates a fragment
126-
attributes: Mapping[str, str | None]
127-
children: Sequence[str | Element]
128-
129-
def __str__(self) -> str:
130-
...
131-
```
132-
133-
Elements can be converted to strings:
134-
135-
```python
136-
element = Element(tag="p", attributes={}, children=["hello"])
137-
assert str(element) == "<p>hello</p>"
138-
139-
element2 = Element(tag="div", attributes={"id": "main"}, children=[element])
140-
assert str(element2) == '<div id="main"><p>hello</p></div>'
141-
```
142-
143-
The `html()` function parses PEP 750 template strings to an `Element`:
144-
145-
```python
146-
def html(template: Template) -> Element:
147-
...
148-
149-
assert html(t"<p>hello</p>") == Element(tag="p", attributes={}, children=["hello"])
150-
```
151-
152-
The `html()` function supports several features that decide how interpolations are processed based both on their type _and_ their position in the HTML syntax.
153-
154-
Content can be interpolated into the body of an element:
155-
156-
```python
157-
text = "Hello, World!"
158-
element = html(t"<p>{text}</p>")
159-
assert str(element) == "<p>Hello, World!</p>"
160-
```
161-
162-
When content is interpolated, it is also automatically escaped:
163-
164-
```python
165-
evil = "<script>alert('evil')</script>"
166-
element = html(t"<p>{evil}</p>")
167-
assert str(element) == "<p>&lt;script&gt;alert('evil')&lt;/script&gt;</p>"
168-
```
169-
170-
Attribute values can be interpolated:
171-
172-
```python
173-
src = "shrubbery.jpg"
174-
element = html(t'<img src={src} />')
175-
assert str(element) == '<img src="shrubbery.jpg" />'
176-
```
177-
178-
Multiple attributes can be interpolated at once:
179-
180-
```python
181-
attributes = {"src": "shrubbery.jpg", "alt": "A shrubbery"}
182-
element = html(t'<img {attributes} />')
183-
assert str(element) == '<img src="shrubbery.jpg" alt="A shrubbery" />'
184-
```
185-
186-
Boolean attributes are also supported:
187-
188-
```python
189-
attributes = {"type": "text", "required": True}
190-
element = html(t'<input {attributes} />')
191-
assert str(element) == '<input type="text" required />'
192-
```
193-
194-
HTML `Element` instances can be nested:
195-
196-
```python
197-
item1 = html(t"<li>Item 1</li>")
198-
item2 = html(t"<li>Item 2</li>")
199-
element = html(t"<ul>{item1}{item2}</ul>")
200-
assert str(element) == "<ul><li>Item 1</li><li>Item 2</li></ul>"
201-
```
202-
203-
As a convenience, `html()` also supports a simplification for nesting: if an interpolation's value is a `Template`, it is automatically converted to an `Element`:
204-
205-
```python
206-
item1 = t"<li>Item 1</li>"
207-
item2 = t"<li>Item 2</li>"
208-
element = html(t"<ul>{item1}{item2}</ul>")
209-
assert str(element) == "<ul><li>Item 1</li><li>Item 2</li></ul>"
210-
```
211-
212-
Tag names can also be interpolated:
213-
214-
```python
215-
tag = "h1"
216-
element = html(t"<{tag}>Hello, World!</{tag}>")
217-
assert str(element) == "<h1>Hello, World!</h1>"
218-
```
219-
220-
Tag name interpolation allows us to support a simple form of "components". For instance, we can define a `Magic()` function that alters both the attributes and children of an element:
221-
222-
```python
223-
def Magic(attributes: Mapping[str, str | None], children: Sequence[str | Element]) -> Element:
224-
"""A simple, but extremely magical, component."""
225-
magic_attributes = {**attributes, "data-magic": "yes"}
226-
magic_children = [*children, "Magic!"]
227-
return Element("div", magic_attributes, magic_children)
228-
229-
element = html(t'<{Magic} id="wow"><b>FUN!</b></{Magic}>')
230-
assert str(element) == '<div id="wow" data-magic="yes"><b>FUN!</b>Magic!</div>'
231-
```
85+
This repository _used_ to contain a real working implementation of `html()`, but it was for demonstration purposes only. We have since built a much more [robust HTML templating package, `tdom`](https://github.com/t-strings/tdom), which is based on the same ideas but is much more fully featured. We hope that, in addition to being a useful package in its own right, `tdom` will also serve as a more complete reference implementation of the ideas described in PEP 750.
23286

233-
The `html()` template processing code sees that `{Magic}` is an interpolation, that it occurs in the tag position, and that its value is a `Callable`. As a result, `html()` calls `Magic()` with the interpolated children and attributes and uses the result returned _by_ `Magic()` as the final `Element`.
87+
(You can find the older HTML templating examples in the commit history, in case you still want to see them.)

0 commit comments

Comments
 (0)