papyrium 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,288 @@
1
+ Metadata-Version: 2.4
2
+ Name: papyrium
3
+ Version: 0.1.0
4
+ Summary: A virtual vintage printer: the papyrium command with every printer model.
5
+ Author-email: Robert Smallshire <robert@smallshire.org.uk>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/rob-smallshire/papyrium
8
+ Project-URL: Repository, https://github.com/rob-smallshire/papyrium
9
+ Project-URL: Issues, https://github.com/rob-smallshire/papyrium/issues
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: End Users/Desktop
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Printing
20
+ Classifier: Topic :: System :: Emulators
21
+ Requires-Python: >=3.12
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: papyrium-cli>=0.1.0
25
+ Requires-Dist: papyrium-model-epson-fx80>=0.1.0
26
+ Requires-Dist: papyrium-model-brother-m1109>=0.1.0
27
+ Dynamic: license-file
28
+
29
+ <!-- Generated by scripts/render_readme.py from a template; edit the template, not this file. -->
30
+ # Papyrium
31
+
32
+ [![CI](https://github.com/rob-smallshire/papyrium/actions/workflows/ci.yml/badge.svg)](https://github.com/rob-smallshire/papyrium/actions/workflows/ci.yml)
33
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/rob-smallshire/papyrium/blob/master/LICENSE)
34
+
35
+ Papyrium is a virtual vintage printer. It runs as a headless service,
36
+ receives the bytes a computer sends to its printer, interprets them as a
37
+ chosen period printer would, lays the result out on emulated paper, and
38
+ writes the pages as PNG images and PDF documents, dot for dot.
39
+
40
+ <p>
41
+ <img src="https://raw.githubusercontent.com/rob-smallshire/papyrium/master/docs/images/ledger.png" alt="A condensed ledger report printed by the Epson FX-80 on green-bar listing paper" width="100%">
42
+ </p>
43
+ <p>
44
+ <img src="https://raw.githubusercontent.com/rob-smallshire/papyrium/master/docs/images/letter.png" alt="A letter printed by the Brother M-1109 in near letter quality" width="100%">
45
+ </p>
46
+
47
+ The printers are 9-pin dot-matrix printers of the 1980s, the Epson FX-80
48
+ and the Brother M-1109, speaking Epson's ESC/P. The first client is
49
+ Beebium, the BBC Micro emulator, but Papyrium knows nothing about the
50
+ computer on the other end: any emulator, or real hardware behind a
51
+ network adapter, can drive it.
52
+
53
+ ## Quick start
54
+
55
+ With [uv](https://docs.astral.sh/uv/), run it straight from PyPI:
56
+
57
+ ```sh
58
+ uvx papyrium serve
59
+ ```
60
+
61
+ or install the `papyrium` command for good with `uv tool install papyrium`
62
+ (or `pipx install papyrium`, or `pip install papyrium`). The `papyrium`
63
+ distribution brings the command and every printer model; `papyrium-cli`
64
+ alone brings the command with no printer model, to which you add the
65
+ `papyrium-model-...` packages you want.
66
+
67
+ From a checkout:
68
+
69
+ ```sh
70
+ git clone https://github.com/rob-smallshire/papyrium.git
71
+ cd papyrium
72
+ uv sync
73
+ uv run papyrium serve
74
+ ```
75
+
76
+ This listens on `localhost:9100` (raw TCP, the JetDirect convention) as an
77
+ Epson FX-80, and writes each job into `papyrium-jobs/job-NNNN/`:
78
+
79
+ | File | Contents |
80
+ |---|---|
81
+ | `capture.prn` | Every byte received, exactly as sent |
82
+ | `job.json` | When the job started and ended, why it ended, and the printer setup |
83
+ | `page-0001.png`, ... | Each page, written as the paper is ejected |
84
+ | `job.pdf` | The whole job, written when the job ends |
85
+
86
+ Print something to it:
87
+
88
+ ```sh
89
+ printf 'HELLO FROM PAPYRIUM\r\n\x0c' | nc localhost 9100
90
+ ```
91
+
92
+ A job ends after five seconds without bytes (`--idle-timeout`), or when
93
+ the service stops. A disconnect never ends a job: an emulator may hold one
94
+ connection open for its whole life.
95
+
96
+ ## Printers, paper and fonts
97
+
98
+ ```
99
+ $ papyrium list-models
100
+ Models
101
+ ┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
102
+ ┃ Name ┃ Description ┃
103
+ ┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
104
+ │ brother-m1109 │ Brother M-1109: an 80-column, 9-pin dot-matrix printer in │
105
+ │ │ its Mode I. │
106
+ │ epson-fx80 │ Epson FX-80: an 80-column, 9-pin dot-matrix printer speaking │
107
+ │ │ ESC/P. │
108
+ └───────────────┴──────────────────────────────────────────────────────────────┘
109
+
110
+ $ papyrium list-fonts
111
+ Fonts
112
+ ┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
113
+ ┃ Name ┃ Description ┃
114
+ ┡━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
115
+ │ draft-9 │ An original 9-pin draft font in the style of 1980s dot-matrix │
116
+ │ │ printers. │
117
+ │ m1109-draft │ The Brother M-1109's draft font, reconstructed from printed │
118
+ │ │ output. │
119
+ │ m1109-nlq │ The Brother M-1109's NLQ font, reconstructed from printed │
120
+ │ │ output. │
121
+ └─────────────┴────────────────────────────────────────────────────────────────┘
122
+ ```
123
+
124
+ Choose a printer with `--model` and set its options with `-M KEY=VALUE`;
125
+ `papyrium describe-model NAME` describes a model and its options, which
126
+ set its DIP switches and its paper. For example, an M-1109 printing near
127
+ letter quality from power on, on blue-bar listing paper:
128
+
129
+ ```sh
130
+ uv run papyrium serve --model brother-m1109 -M near-letter-quality=yes -M stationery=blue-bar
131
+ ```
132
+
133
+ The paper can be a plain `sheet`, continuous `fanfold` with its tear-off
134
+ strips and feed holes, or listing paper: `green-bar`, `blue-bar` or
135
+ `music-ruled`. A font stands in for each printer's character ROM, which is
136
+ never copied: `draft-9` is an original design, and the M-1109's fonts are
137
+ reconstructed from its printed output. Any font can be replaced by a dot
138
+ font file, with `-M font=PATH`.
139
+
140
+ ## Printing from a BBC Micro in Beebium
141
+
142
+ ```sh
143
+ uv run papyrium serve
144
+ /path/to/beebium/build/src/server/beebium-model-b --tcp-printer host=localhost:port=9100
145
+ ```
146
+
147
+ On the BBC:
148
+
149
+ ```
150
+ *FX6,0
151
+ *FX5,1
152
+ VDU 2
153
+ PRINT "HELLO"
154
+ VDU 1,12
155
+ VDU 3
156
+ ```
157
+
158
+ `*FX5,1` selects the parallel printer. The BBC normally suppresses line
159
+ feeds to the printer and sends CR alone; `*FX6,0` lets them through. If you
160
+ would rather leave the BBC at its defaults, switch on the printer's auto
161
+ line feed DIP switch instead:
162
+
163
+ ```sh
164
+ uv run papyrium serve -M auto-line-feed=yes
165
+ ```
166
+
167
+ Escape sequences go to the printer with `VDU 1`, so `VDU 1,27,1,69` turns
168
+ on emphasized printing (`ESC E`).
169
+
170
+ ## Finding Papyrium on the network
171
+
172
+ `--advertise` announces the printer on the local network with multicast
173
+ DNS, as Bonjour and Avahi announce network printers, so that a sender,
174
+ such as a bridge from a real computer's printer port, can find it without
175
+ being given an address:
176
+
177
+ ```sh
178
+ uv run papyrium serve --model brother-m1109 --advertise --name "Desk M-1109"
179
+ ```
180
+
181
+ It appears as a raw TCP printer, a `_pdl-datastream._tcp` service. Its TXT
182
+ record names it a Papyrium printer (`note=Papyrium virtual printer`, and
183
+ `ty=Brother M-1109 (Papyrium)`), so a client can tell it from a real
184
+ printer, and carries the printer's `uuid`, which stays the same across
185
+ restarts and renames. The UUID is kept in `printer.json` in the output
186
+ directory; `--name` defaults to the model's name with "(Papyrium)".
187
+
188
+ Advertising makes the printer listen on every interface unless a host is
189
+ given with `-T host=`. Anyone on the network can then send it jobs, as with
190
+ any network printer. A printer only this machine can reach is not
191
+ advertised, and says so. A desktop that adds the printer from its printer
192
+ dialog must print to it in ESC/P, not PostScript or PCL.
193
+
194
+ ## Commands
195
+
196
+ | Command | Purpose |
197
+ |---|---|
198
+ | `papyrium serve` | Run a printer until interrupted |
199
+ | `papyrium render JOB_OR_CAPTURE` | Print a captured job again, from a job directory or a `.prn` file |
200
+ | `papyrium list-jobs` | List captured jobs |
201
+ | `papyrium list-models`, `describe-model NAME` | The printer models installed, and their options |
202
+ | `papyrium list-transports`, `list-languages`, `list-fonts`, `list-outputs`, `list-advertisers` | The other plug-ins installed |
203
+
204
+ Options are passed as `KEY=VALUE`: `-T` for the transport (`-T port=9101`),
205
+ `-M` for the printer model (`-M character-set=uk`), and
206
+ `-O OUTPUT.KEY=VALUE` for an output (`-O png.dpi=300`). Choose outputs with
207
+ `-o png -o pdf`. Reports such as `list-jobs` print as a table, or as TSV or
208
+ JSON with `--as tsv` or `--as json`.
209
+
210
+ Replaying a capture with the same printer setup always gives identical
211
+ pages; `render` on a job directory uses the setup recorded in its
212
+ `job.json`. `serve --capture-only` captures jobs without printing
213
+ them, and needs no printer model installed: each job records the model and
214
+ options asked for, so it can be printed later on a machine that has it.
215
+
216
+ ## How it is built
217
+
218
+ Papyrium is a framework of independent, pluggable axes. Each is an
219
+ entry-point extension point, so a separately distributed `papyrium-*`
220
+ package can add to it:
221
+
222
+ | Axis | Plug-in | Description | Package |
223
+ |---|---|---|---|
224
+ | Transports deliver bytes | `raw-tcp` | Raw TCP printing, by default on port 9100 | [`papyrium-transport-raw-tcp`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-transport-raw-tcp/) |
225
+ | Languages interpret them | `escp` | Epson ESC/P, as spoken by 9-pin dot-matrix printers such as the FX-80 | [`papyrium-language-escp`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-language-escp/) |
226
+ | Printer models are what the user chooses | `brother-m1109` | Brother M-1109: an 80-column, 9-pin dot-matrix printer in its Mode I | [`papyrium-model-brother-m1109`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-model-brother-m1109/) |
227
+ | | `epson-fx80` | Epson FX-80: an 80-column, 9-pin dot-matrix printer speaking ESC/P | [`papyrium-model-epson-fx80`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-model-epson-fx80/) |
228
+ | Fonts stand in for character ROMs | `draft-9` | An original 9-pin draft font in the style of 1980s dot-matrix printers | [`papyrium-font-draft-9`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-font-draft-9/) |
229
+ | | `m1109-draft` | The Brother M-1109's draft font, reconstructed from printed output | [`papyrium-font-m1109-draft`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-font-m1109-draft/) |
230
+ | | `m1109-nlq` | The Brother M-1109's NLQ font, reconstructed from printed output | [`papyrium-font-m1109-nlq`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-font-m1109-nlq/) |
231
+ | Outputs write pages | `pdf` | One PDF per job, one page per printed page, every dot a vector dot | [`papyrium-output-pdf`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-output-pdf/) |
232
+ | | `png` | PNG images, one per page, with each struck dot drawn as a dot | [`papyrium-output-png`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-output-png/) |
233
+ | Advertisers announce printers | `mdns` | Announces printers with multicast DNS, as Bonjour and Avahi do | [`papyrium-advertiser-mdns`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-advertiser-mdns/) |
234
+
235
+ The packages live under `packages/`, in a [uv](https://docs.astral.sh/uv/)
236
+ workspace, and share the `papyrium` namespace:
237
+
238
+ | Package | Contents |
239
+ |---|---|
240
+ | [`papyrium-exception`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-exception/) | Categorised exceptions and the CLI error-reporting boundary shared by Papyrium |
241
+ | [`papyrium-extension`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-extension/) | Entry-point plug-in framework shared by every extensible axis of Papyrium |
242
+ | [`papyrium-core`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-core/) | Papyrium's extension axes, conformance suites, spooler and job captures |
243
+ | [`papyrium-transport-raw-tcp`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-transport-raw-tcp/) | Raw TCP (port 9100, JetDirect style) transport for Papyrium |
244
+ | [`papyrium-language-escp`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-language-escp/) | The Epson ESC/P printer language for Papyrium's 9-pin dot-matrix models |
245
+ | [`papyrium-model-epson-fx80`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-model-epson-fx80/) | The Epson FX-80 9-pin dot-matrix printer, emulated for Papyrium |
246
+ | [`papyrium-model-brother-m1109`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-model-brother-m1109/) | The Brother M-1109 9-pin dot-matrix printer, emulated for Papyrium |
247
+ | [`papyrium-font-draft-9`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-font-draft-9/) | draft-9, a 9-pin dot-matrix font in the style of 1980s printers, designed for Papyrium |
248
+ | [`papyrium-font-m1109-draft`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-font-m1109-draft/) | m1109-draft, the Brother M-1109's draft characters, reconstructed for Papyrium |
249
+ | [`papyrium-font-m1109-nlq`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-font-m1109-nlq/) | m1109-nlq, the Brother M-1109's near letter quality characters, reconstructed for Papyrium |
250
+ | [`papyrium-output-png`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-output-png/) | PNG output for Papyrium: one raster image per page, dots drawn as dots |
251
+ | [`papyrium-output-pdf`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-output-pdf/) | PDF output for Papyrium: one document per job, dots as vector dots |
252
+ | [`papyrium-advertiser-mdns`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-advertiser-mdns/) | Announces Papyrium printers on the local network with multicast DNS (Bonjour, Avahi) |
253
+ | [`papyrium-cli`](https://github.com/rob-smallshire/papyrium/blob/master/packages/papyrium-cli/) | The papyrium command: run a virtual vintage printer, replay its jobs and inspect them |
254
+
255
+ `docs/specification.md` is the design as handed over from Beebium.
256
+ `docs/epson-fx80.md` and `docs/brother-m1109.md` record the behaviour
257
+ Papyrium follows, from the manufacturers' manuals, and `CLAUDE.md` records
258
+ the working practices.
259
+
260
+ ## Development
261
+
262
+ ```sh
263
+ uv sync
264
+ uv run pytest
265
+ uv run pre-commit install
266
+ ```
267
+
268
+ The golden tests replay the captures in each printer model's
269
+ `tests/golden/` and compare every page with a pinned image. The end-to-end
270
+ tests that drive a real Beebium BBC Micro are in `integration/beebium/`;
271
+ their module docstring gives the command to run them. `oracles/` compares
272
+ Papyrium with independent interpreters run as separate programs:
273
+ `uv run pytest oracles/escapy`.
274
+
275
+ This README and the printer models' READMEs are generated by
276
+ `scripts/render_readme.py` from the templates in
277
+ `scripts/readme-templates/` and `packages/*/readme/`, running the examples
278
+ in `scripts/readme-examples/` against the workspace's own code. The
279
+ pre-commit hook regenerates them, so edit the templates, not the READMEs.
280
+
281
+ ## Licence
282
+
283
+ Papyrium is released under the MIT licence; see [`LICENSE`](https://github.com/rob-smallshire/papyrium/blob/master/LICENSE). Each
284
+ package carries its own copy.
285
+
286
+ Epson, Brother and the other printer and computer names in this project
287
+ are trademarks of their owners, used only to identify the printers that
288
+ Papyrium emulates. Papyrium is not affiliated with or endorsed by them.
@@ -0,0 +1,6 @@
1
+ papyrium-0.1.0.dist-info/licenses/LICENSE,sha256=L_Uw2MQC3xsCy2nOzWmY_DYRQMHC-Yu2_zTvUTadNAY,1074
2
+ papyrium-0.1.0.dist-info/METADATA,sha256=3cBarZWXpMkMW53uFQugxdw0KZU-hYpcv8_FMDFdhlg,17050
3
+ papyrium-0.1.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
4
+ papyrium-0.1.0.dist-info/entry_points.txt,sha256=1tgV0x_b5KzgkI7Iydvt8H22iBUzb3c05PSXHhY06SU,46
5
+ papyrium-0.1.0.dist-info/top_level.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
6
+ papyrium-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ papyrium = papyrium.cli:cli
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Robert Smallshire
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+