pyfr-cli 0.11.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,573 @@
1
+ Metadata-Version: 2.5
2
+ Name: pyfr-cli
3
+ Version: 0.11.0
4
+ Summary: PyFr β€” a cookiecutter template for production-ready Python microservices, and the tool that keeps a generated project up to date with it
5
+ License: Mozilla Public License Version 2.0
6
+ ==================================
7
+
8
+ 1. Definitions
9
+ --------------
10
+
11
+ 1.1. "Contributor"
12
+ means each individual or legal entity that creates, contributes to
13
+ the creation of, or owns Covered Software.
14
+
15
+ 1.2. "Contributor Version"
16
+ means the combination of the Contributions of others (if any) used
17
+ by a Contributor and that particular Contributor's Contribution.
18
+
19
+ 1.3. "Contribution"
20
+ means Covered Software of a particular Contributor.
21
+
22
+ 1.4. "Covered Software"
23
+ means Source Code Form to which the initial Contributor has attached
24
+ the notice in Exhibit A, the Executable Form of such Source Code
25
+ Form, and Modifications of such Source Code Form, in each case
26
+ including portions thereof.
27
+
28
+ 1.5. "Incompatible With Secondary Licenses"
29
+ means
30
+
31
+ (a) that the initial Contributor has attached the notice described
32
+ in Exhibit B to the Covered Software; or
33
+
34
+ (b) that the Covered Software was made available under the terms of
35
+ version 1.1 or earlier of the License, but not also under the
36
+ terms of a Secondary License.
37
+
38
+ 1.6. "Executable Form"
39
+ means any form of the work other than Source Code Form.
40
+
41
+ 1.7. "Larger Work"
42
+ means a work that combines Covered Software with other material, in
43
+ a separate file or files, that is not Covered Software.
44
+
45
+ 1.8. "License"
46
+ means this document.
47
+
48
+ 1.9. "Licensable"
49
+ means having the right to grant, to the maximum extent possible,
50
+ whether at the time of the initial grant or subsequently, any and
51
+ all of the rights conveyed by this License.
52
+
53
+ 1.10. "Modifications"
54
+ means any of the following:
55
+
56
+ (a) any file in Source Code Form that results from an addition to,
57
+ deletion from, or modification of the contents of Covered
58
+ Software; or
59
+
60
+ (b) any new file in Source Code Form that contains any Covered
61
+ Software.
62
+
63
+ 1.11. "Patent Claims" of a Contributor
64
+ means any patent claim(s), including without limitation, method,
65
+ process, and apparatus claims, in any patent Licensable by such
66
+ Contributor that would be infringed, but for the grant of the
67
+ License, by the making, using, selling, offering for sale, having
68
+ made, import, or transfer of either its Contributions or its
69
+ Contributor Version.
70
+
71
+ 1.12. "Secondary License"
72
+ means either the GNU General Public License, Version 2.0, the GNU
73
+ Lesser General Public License, Version 2.1, the GNU Affero General
74
+ Public License, Version 3.0, or any later versions of those
75
+ licenses.
76
+
77
+ 1.13. "Source Code Form"
78
+ means the form of the work preferred for making modifications.
79
+
80
+ 1.14. "You" (or "Your")
81
+ means an individual or a legal entity exercising rights under this
82
+ License. For legal entities, "You" includes any entity that
83
+ controls, is controlled by, or is under common control with You. For
84
+ purposes of this definition, "control" means (a) the power, direct
85
+ or indirect, to cause the direction or management of such entity,
86
+ whether by contract or otherwise, or (b) ownership of more than
87
+ fifty percent (50%) of the outstanding shares or beneficial
88
+ ownership of such entity.
89
+
90
+ 2. License Grants and Conditions
91
+ --------------------------------
92
+
93
+ 2.1. Grants
94
+
95
+ Each Contributor hereby grants You a world-wide, royalty-free,
96
+ non-exclusive license:
97
+
98
+ (a) under intellectual property rights (other than patent or trademark)
99
+ Licensable by such Contributor to use, reproduce, make available,
100
+ modify, display, perform, distribute, and otherwise exploit its
101
+ Contributions, either on an unmodified basis, with Modifications, or
102
+ as part of a Larger Work; and
103
+
104
+ (b) under Patent Claims of such Contributor to make, use, sell, offer
105
+ for sale, have made, import, and otherwise transfer either its
106
+ Contributions or its Contributor Version.
107
+
108
+ 2.2. Effective Date
109
+
110
+ The licenses granted in Section 2.1 with respect to any Contribution
111
+ become effective for each Contribution on the date the Contributor first
112
+ distributes such Contribution.
113
+
114
+ 2.3. Limitations on Grant Scope
115
+
116
+ The licenses granted in this Section 2 are the only rights granted under
117
+ this License. No additional rights or licenses will be implied from the
118
+ distribution or licensing of Covered Software under this License.
119
+ Notwithstanding Section 2.1(b) above, no patent license is granted by a
120
+ Contributor:
121
+
122
+ (a) for any code that a Contributor has removed from Covered Software;
123
+ or
124
+
125
+ (b) for infringements caused by: (i) Your and any other third party's
126
+ modifications of Covered Software, or (ii) the combination of its
127
+ Contributions with other software (except as part of its Contributor
128
+ Version); or
129
+
130
+ (c) under Patent Claims infringed by Covered Software in the absence of
131
+ its Contributions.
132
+
133
+ This License does not grant any rights in the trademarks, service marks,
134
+ or logos of any Contributor (except as may be necessary to comply with
135
+ the notice requirements in Section 3.4).
136
+
137
+ 2.4. Subsequent Licenses
138
+
139
+ No Contributor makes additional grants as a result of Your choice to
140
+ distribute the Covered Software under a subsequent version of this
141
+ License (see Section 10.2) or under the terms of a Secondary License (if
142
+ permitted under the terms of Section 3.3).
143
+
144
+ 2.5. Representation
145
+
146
+ Each Contributor represents that the Contributor believes its
147
+ Contributions are its original creation(s) or it has sufficient rights
148
+ to grant the rights to its Contributions conveyed by this License.
149
+
150
+ 2.6. Fair Use
151
+
152
+ This License is not intended to limit any rights You have under
153
+ applicable copyright doctrines of fair use, fair dealing, or other
154
+ equivalents.
155
+
156
+ 2.7. Conditions
157
+
158
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
159
+ in Section 2.1.
160
+
161
+ 3. Responsibilities
162
+ -------------------
163
+
164
+ 3.1. Distribution of Source Form
165
+
166
+ All distribution of Covered Software in Source Code Form, including any
167
+ Modifications that You create or to which You contribute, must be under
168
+ the terms of this License. You must inform recipients that the Source
169
+ Code Form of the Covered Software is governed by the terms of this
170
+ License, and how they can obtain a copy of this License. You may not
171
+ attempt to alter or restrict the recipients' rights in the Source Code
172
+ Form.
173
+
174
+ 3.2. Distribution of Executable Form
175
+
176
+ If You distribute Covered Software in Executable Form then:
177
+
178
+ (a) such Covered Software must also be made available in Source Code
179
+ Form, as described in Section 3.1, and You must inform recipients of
180
+ the Executable Form how they can obtain a copy of such Source Code
181
+ Form by reasonable means in a timely manner, at a charge no more
182
+ than the cost of distribution to the recipient; and
183
+
184
+ (b) You may distribute such Executable Form under the terms of this
185
+ License, or sublicense it under different terms, provided that the
186
+ license for the Executable Form does not attempt to limit or alter
187
+ the recipients' rights in the Source Code Form under this License.
188
+
189
+ 3.3. Distribution of a Larger Work
190
+
191
+ You may create and distribute a Larger Work under terms of Your choice,
192
+ provided that You also comply with the requirements of this License for
193
+ the Covered Software. If the Larger Work is a combination of Covered
194
+ Software with a work governed by one or more Secondary Licenses, and the
195
+ Covered Software is not Incompatible With Secondary Licenses, this
196
+ License permits You to additionally distribute such Covered Software
197
+ under the terms of such Secondary License(s), so that the recipient of
198
+ the Larger Work may, at their option, further distribute the Covered
199
+ Software under the terms of either this License or such Secondary
200
+ License(s).
201
+
202
+ 3.4. Notices
203
+
204
+ You may not remove or alter the substance of any license notices
205
+ (including copyright notices, patent notices, disclaimers of warranty,
206
+ or limitations of liability) contained within the Source Code Form of
207
+ the Covered Software, except that You may alter any license notices to
208
+ the extent required to remedy known factual inaccuracies.
209
+
210
+ 3.5. Application of Additional Terms
211
+
212
+ You may choose to offer, and to charge a fee for, warranty, support,
213
+ indemnity or liability obligations to one or more recipients of Covered
214
+ Software. However, You may do so only on Your own behalf, and not on
215
+ behalf of any Contributor. You must make it absolutely clear that any
216
+ such warranty, support, indemnity, or liability obligation is offered by
217
+ You alone, and You hereby agree to indemnify every Contributor for any
218
+ liability incurred by such Contributor as a result of warranty, support,
219
+ indemnity or liability terms You offer. You may include additional
220
+ disclaimers of warranty and limitations of liability specific to any
221
+ jurisdiction.
222
+
223
+ 4. Inability to Comply Due to Statute or Regulation
224
+ ---------------------------------------------------
225
+
226
+ If it is impossible for You to comply with any of the terms of this
227
+ License with respect to some or all of the Covered Software due to
228
+ statute, judicial order, or regulation then You must: (a) comply with
229
+ the terms of this License to the maximum extent possible; and (b)
230
+ describe the limitations and the code they affect. Such description must
231
+ be placed in a text file included with all distributions of the Covered
232
+ Software under this License. Except to the extent prohibited by statute
233
+ or regulation, such description must be sufficiently detailed for a
234
+ recipient of ordinary skill to be able to understand it.
235
+
236
+ 5. Termination
237
+ --------------
238
+
239
+ 5.1. The rights granted under this License will terminate automatically
240
+ if You fail to comply with any of its terms. However, if You become
241
+ compliant, then the rights granted under this License from a particular
242
+ Contributor are reinstated (a) provisionally, unless and until such
243
+ Contributor explicitly and finally terminates Your grants, and (b) on an
244
+ ongoing basis, if such Contributor fails to notify You of the
245
+ non-compliance by some reasonable means prior to 60 days after You have
246
+ come back into compliance. Moreover, Your grants from a particular
247
+ Contributor are reinstated on an ongoing basis if such Contributor
248
+ notifies You of the non-compliance by some reasonable means, this is the
249
+ first time You have received notice of non-compliance with this License
250
+ from such Contributor, and You become compliant prior to 30 days after
251
+ Your receipt of the notice.
252
+
253
+ 5.2. If You initiate litigation against any entity by asserting a patent
254
+ infringement claim (excluding declaratory judgment actions,
255
+ counter-claims, and cross-claims) alleging that a Contributor Version
256
+ directly or indirectly infringes any patent, then the rights granted to
257
+ You by any and all Contributors for the Covered Software under Section
258
+ 2.1 of this License shall terminate.
259
+
260
+ 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
261
+ end user license agreements (excluding distributors and resellers) which
262
+ have been validly granted by You or Your distributors under this License
263
+ prior to termination shall survive termination.
264
+
265
+ ************************************************************************
266
+ * *
267
+ * 6. Disclaimer of Warranty *
268
+ * ------------------------- *
269
+ * *
270
+ * Covered Software is provided under this License on an "as is" *
271
+ * basis, without warranty of any kind, either expressed, implied, or *
272
+ * statutory, including, without limitation, warranties that the *
273
+ * Covered Software is free of defects, merchantable, fit for a *
274
+ * particular purpose or non-infringing. The entire risk as to the *
275
+ * quality and performance of the Covered Software is with You. *
276
+ * Should any Covered Software prove defective in any respect, You *
277
+ * (not any Contributor) assume the cost of any necessary servicing, *
278
+ * repair, or correction. This disclaimer of warranty constitutes an *
279
+ * essential part of this License. No use of any Covered Software is *
280
+ * authorized under this License except under this disclaimer. *
281
+ * *
282
+ ************************************************************************
283
+
284
+ ************************************************************************
285
+ * *
286
+ * 7. Limitation of Liability *
287
+ * -------------------------- *
288
+ * *
289
+ * Under no circumstances and under no legal theory, whether tort *
290
+ * (including negligence), contract, or otherwise, shall any *
291
+ * Contributor, or anyone who distributes Covered Software as *
292
+ * permitted above, be liable to You for any direct, indirect, *
293
+ * special, incidental, or consequential damages of any character *
294
+ * including, without limitation, damages for lost profits, loss of *
295
+ * goodwill, work stoppage, computer failure or malfunction, or any *
296
+ * and all other commercial damages or losses, even if such party *
297
+ * shall have been informed of the possibility of such damages. This *
298
+ * limitation of liability shall not apply to liability for death or *
299
+ * personal injury resulting from such party's negligence to the *
300
+ * extent applicable law prohibits such limitation. Some *
301
+ * jurisdictions do not allow the exclusion or limitation of *
302
+ * incidental or consequential damages, so this exclusion and *
303
+ * limitation may not apply to You. *
304
+ * *
305
+ ************************************************************************
306
+
307
+ 8. Litigation
308
+ -------------
309
+
310
+ Any litigation relating to this License may be brought only in the
311
+ courts of a jurisdiction where the defendant maintains its principal
312
+ place of business and such litigation shall be governed by laws of that
313
+ jurisdiction, without reference to its conflict-of-law provisions.
314
+ Nothing in this Section shall prevent a party's ability to bring
315
+ cross-claims or counter-claims.
316
+
317
+ 9. Miscellaneous
318
+ ----------------
319
+
320
+ This License represents the complete agreement concerning the subject
321
+ matter hereof. If any provision of this License is held to be
322
+ unenforceable, such provision shall be reformed only to the extent
323
+ necessary to make it enforceable. Any law or regulation which provides
324
+ that the language of a contract shall be construed against the drafter
325
+ shall not be used to construe this License against a Contributor.
326
+
327
+ 10. Versions of the License
328
+ ---------------------------
329
+
330
+ 10.1. New Versions
331
+
332
+ Mozilla Foundation is the license steward. Except as provided in Section
333
+ 10.3, no one other than the license steward has the right to modify or
334
+ publish new versions of this License. Each version will be given a
335
+ distinguishing version number.
336
+
337
+ 10.2. Effect of New Versions
338
+
339
+ You may distribute the Covered Software under the terms of the version
340
+ of the License under which You originally received the Covered Software,
341
+ or under the terms of any subsequent version published by the license
342
+ steward.
343
+
344
+ 10.3. Modified Versions
345
+
346
+ If you create software not governed by this License, and you want to
347
+ create a new license for such software, you may create and use a
348
+ modified version of this License if you rename the license and remove
349
+ any references to the name of the license steward (except to note that
350
+ such modified license differs from this License).
351
+
352
+ 10.4. Distributing Source Code Form that is Incompatible With Secondary
353
+ Licenses
354
+
355
+ If You choose to distribute Source Code Form that is Incompatible With
356
+ Secondary Licenses under the terms of this version of the License, the
357
+ notice described in Exhibit B of this License must be attached.
358
+
359
+ Exhibit A - Source Code Form License Notice
360
+ -------------------------------------------
361
+
362
+ This Source Code Form is subject to the terms of the Mozilla Public
363
+ License, v. 2.0. If a copy of the MPL was not distributed with this
364
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
365
+
366
+ If it is not possible or desirable to put the notice in a particular
367
+ file, then You may include the notice in a location (such as a LICENSE
368
+ file in a relevant directory) where a recipient would be likely to look
369
+ for such a notice.
370
+
371
+ You may add additional accurate notices of copyright ownership.
372
+
373
+ Exhibit B - "Incompatible With Secondary Licenses" Notice
374
+ ---------------------------------------------------------
375
+
376
+ This Source Code Form is "Incompatible With Secondary Licenses", as
377
+ defined by the Mozilla Public License, v. 2.0.
378
+ License-File: LICENSE
379
+ Requires-Python: >=3.13
380
+ Requires-Dist: cookiecutter<3,>=2.6
381
+ Requires-Dist: pathspec>=0.12
382
+ Requires-Dist: pyyaml>=6.0
383
+ Description-Content-Type: text/markdown
384
+
385
+ <div align="center">
386
+
387
+ # 🐍 PyFr
388
+
389
+ **A cookiecutter template for production-ready Python microservices.**
390
+
391
+ *Answer a few prompts. Get a service that runs, is tested, is observable, and is documented.*
392
+
393
+ [![CI](https://github.com/EmadMokhtar/pyfr/actions/workflows/ci.yml/badge.svg)](https://github.com/EmadMokhtar/pyfr/actions/workflows/ci.yml)
394
+ [![Full suite](https://github.com/EmadMokhtar/pyfr/actions/workflows/full-suite.yml/badge.svg)](https://github.com/EmadMokhtar/pyfr/actions/workflows/full-suite.yml)
395
+ [![Docs](https://img.shields.io/badge/docs-pyfr-blue)](https://emadmokhtar.github.io/pyfr/)
396
+ [![Python](https://img.shields.io/badge/python-3.13%2B-blue)](https://www.python.org/)
397
+ [![License: MPL 2.0](https://img.shields.io/badge/license-MPL--2.0-brightgreen)](LICENSE)
398
+ [![Status: usable template](https://img.shields.io/badge/status-usable%20template-brightgreen)](https://emadmokhtar.github.io/pyfr/roadmap/)
399
+
400
+ πŸ“– **[Read the documentation β†’](https://emadmokhtar.github.io/pyfr/)**
401
+
402
+ </div>
403
+
404
+ ---
405
+
406
+ ## πŸ‘‹ Welcome
407
+
408
+ Every team starts a new Python service the same way: wiring up logging, health
409
+ checks, configuration, error formats, a container image. It takes two to four
410
+ weeks, and every team's result is a little different.
411
+
412
+ PyFr aims to make that a ten-minute step instead β€” and to make the result the
413
+ same good one every time.
414
+
415
+ **The generated code is yours.** 🎁 Nothing is published to a package index, and
416
+ a generated service imports no PyFr package. There is no framework to upgrade,
417
+ no runtime dependency on us, and nothing to lock you in. From M8, a generated
418
+ project will still be able to pull later template fixes into itself through an
419
+ ordinary `git merge`.
420
+
421
+ ## βœ… Status: M0–M7 done, M8 to go
422
+
423
+ **The template is usable** β€” `uvx cookiecutter gh:EmadMokhtar/pyfr`
424
+ generates a project whose `just check` passes: three combinations are
425
+ rendered for real and run through their own `just check-all` on every merge
426
+ to `main` and every night, and all eight are rendered and lint-checked on
427
+ every pull request and merge. M7, the conversion into a template, is complete: the template
428
+ renders from twelve prompts, prunes the backends you do not choose, gives
429
+ a generated project its own workflows and its own documentation site
430
+ about itself, and records the template version it came from. See the
431
+ [roadmap](https://emadmokhtar.github.io/pyfr/roadmap/) for what each
432
+ milestone delivered.
433
+ The [**reference service**](examples/reference-service/) is rendered from
434
+ that template; it is the complete, running service you can run, read, and
435
+ copy from right now.
436
+
437
+ PyFr is built in three phases:
438
+
439
+ | Phase | Milestones | What happens |
440
+ | --- | --- | --- |
441
+ | **A** | M0–M6 | Build the reference service as ordinary Python β€” no template placeholders anywhere |
442
+ | **B** | M7 | Convert it into the cookiecutter template ✨ |
443
+ | **C** | M8+ | Keep the two in step, forever |
444
+
445
+ The rule behind that order: never debug Jinja and Python at the same time. πŸ™‚
446
+
447
+ **M0 through M7 β€” the reference service and its conversion into a
448
+ template β€” are complete. M8, template updates for generated projects, is
449
+ next.** See the [roadmap](https://emadmokhtar.github.io/pyfr/roadmap/)
450
+ for what ships when.
451
+
452
+ ## πŸš€ Try it in one command
453
+
454
+ ```bash
455
+ uvx cookiecutter gh:EmadMokhtar/pyfr
456
+ ```
457
+
458
+ cookiecutter asks twelve questions β€” the project's name, its author, which
459
+ of PostgreSQL, Redis and S3 it gets, its port, its licence β€” and every one
460
+ has a default. The hook then prunes what you did not choose, runs `git
461
+ init`, `uv sync` and `pre-commit install`, and makes the first commit, each
462
+ step best effort, so an offline laptop still gets a whole project.
463
+
464
+ Then `cd` into it, `just up`, and open <http://localhost:8000/docs>. πŸ‘‹
465
+
466
+ The [getting started guide](https://emadmokhtar.github.io/pyfr/getting-started/)
467
+ explains each prompt and what the hook does; the generated project's own
468
+ site takes it from there.
469
+
470
+ ## πŸ“¦ What's in the box
471
+
472
+ Every item below already runs in the reference service today β€” nothing here is
473
+ a promise:
474
+
475
+ - ⚑ **FastAPI**, with an application factory and a lifespan.
476
+ - 🧱 **Four layers** β€” domain, services, infrastructure, api β€” with the
477
+ dependency rule enforced by a build check, not by code review.
478
+ - βœ… **Configuration validated at startup.** A bad value stops the process
479
+ with a readable message and exit code 78, instead of causing a 500 an hour
480
+ later.
481
+ - πŸ“‹ **Structured logging** β€” one JSON object per line on standard output,
482
+ with third-party records passing through the same chain.
483
+ - πŸ’š **Three health endpoints** answering three different questions. Liveness
484
+ never checks a dependency, so a database hiccup cannot restart every
485
+ instance at once.
486
+ - 🚨 **RFC 9457 Problem Details** error responses.
487
+ - πŸ”— **Correlation identifiers** binding one value to every log line a single
488
+ request produced.
489
+ - πŸ›‘ **Graceful shutdown**, so a rolling deployment does not drop live
490
+ requests.
491
+ - πŸ”’ **A hardened container image**: non-root, no build tools, no shell
492
+ utilities in the final layer, and reproducible installs from a lock file.
493
+ - πŸ“– **Its own documentation site**, built from its own `docs/` and
494
+ deployed to GitHub Pages by its own workflow β€” the
495
+ [reference service's site](https://emadmokhtar.github.io/pyfr/reference-service/)
496
+ is the worked example.
497
+
498
+ M1–M6 have since added persistence, OpenTelemetry, contract testing, cache and
499
+ object storage, release automation, and supply-chain auditing, scanning and
500
+ publishing β€” the [roadmap](https://emadmokhtar.github.io/pyfr/roadmap/) lists
501
+ what each one delivered.
502
+
503
+ ## πŸ“š Documentation
504
+
505
+ Two sites, deployed together. **[PyFr's site](https://emadmokhtar.github.io/pyfr/)**
506
+ is about the template: generating a project, how the template is built and
507
+ tested, and why it is a template rather than a framework. **[The reference
508
+ service's site](https://emadmokhtar.github.io/pyfr/reference-service/)** is
509
+ about the service: it is the documentation every generated project ships
510
+ about itself, rendered here for the reference answers.
511
+
512
+ | Page | What it covers |
513
+ | --- | --- |
514
+ | 🏁 [Getting started](https://emadmokhtar.github.io/pyfr/getting-started/) | Generate a project: the twelve prompts, the hook, the first `just up` |
515
+ | πŸ—ΊοΈ [Roadmap](https://emadmokhtar.github.io/pyfr/roadmap/) | What ships when |
516
+ | 🀝 [Contributing](https://emadmokhtar.github.io/pyfr/contributing/) | Working on PyFr itself: the template body, the golden diff, pruning, the two sites |
517
+ | 🏁 [Run the service](https://emadmokhtar.github.io/pyfr/reference-service/getting-started/) | Place an order and read each response |
518
+ | πŸ”¨ [Add an endpoint](https://emadmokhtar.github.io/pyfr/reference-service/guides/add-an-endpoint/) | Build a feature through all four layers |
519
+ | πŸ›οΈ [Architecture](https://emadmokhtar.github.io/pyfr/reference-service/explanation/architecture/) | How the pieces fit, and why |
520
+ | βš™οΈ [Configuration](https://emadmokhtar.github.io/pyfr/reference-service/reference/configuration/) | Every environment variable |
521
+
522
+ The design specification and milestone plans live in
523
+ [`docs/superpowers/`](docs/superpowers/). They contain the reasoning behind
524
+ the decisions the site describes, and are deliberately not published.
525
+
526
+ ## πŸ› οΈ Development
527
+
528
+ The repository root and the reference service are two separate Python
529
+ projects, each with its own `pyproject.toml`. They are never synced together.
530
+ The template body, `{{cookiecutter.project_slug}}/`, is the source of truth:
531
+ edit it, run `just regen`, and the reference service is rendered from it β€”
532
+ never edit `examples/reference-service/` by hand.
533
+
534
+ ```bash
535
+ # The template and its tests: both sites build, the root suite, the golden diff
536
+ uv sync --group dev --group docs && just check
537
+ ```
538
+
539
+ ```bash
540
+ # The reference service
541
+ cd examples/reference-service && uv sync && just check
542
+ ```
543
+
544
+ ```bash
545
+ # PyFr's documentation site, with a live preview
546
+ just docs-install && just docs
547
+ ```
548
+
549
+ The [contributing guide](https://emadmokhtar.github.io/pyfr/contributing/)
550
+ has the whole loop: the regeneration and golden diff, backends and pruning,
551
+ the two documentation sites and every root `just` recipe.
552
+
553
+ ## 🀝 Contributing
554
+
555
+ Issues, questions, and pull requests are all welcome β€” including "I read this
556
+ and it didn't make sense," which is one of the most useful things you can send
557
+ while the project is this young.
558
+
559
+ Commit messages and pull request titles must follow
560
+ [Conventional Commits](https://www.conventionalcommits.org/). The
561
+ [contributing guide](https://emadmokhtar.github.io/pyfr/contributing/) has the
562
+ rest.
563
+
564
+ ## πŸ™ Credits
565
+
566
+ PyFr's architecture is influenced by [GoFr](https://gofr.dev), the Go
567
+ microservice framework β€” the context-driven layering and the emphasis on
568
+ developer experience, adapted to Python's ecosystem and to a template rather
569
+ than a library.
570
+
571
+ ## βš–οΈ License
572
+
573
+ [Mozilla Public License 2.0](LICENSE).
@@ -0,0 +1,18 @@
1
+ pyfr_cli/__init__.py,sha256=tOCilatyZKtbv6nDFuwxZgYEG9o_M0YghuMSJl4eito,573
2
+ pyfr_cli/__main__.py,sha256=GOj-eUMVL_0i3TGoM3QNj3g6sYlTfuChLVlULyrdJAc,2800
3
+ pyfr_cli/answers.py,sha256=TqOotwM8n2QJEBrbSndIdrL1WN-raaYsOCEXGJ7WfRw,4274
4
+ pyfr_cli/changelog.py,sha256=rNsQFk_I0fM8swpM5X1RJG-eTnCnWZdwYF7yIvRsORU,2771
5
+ pyfr_cli/errors.py,sha256=bT8iSNJ830e3s0JZrOdAUHDWOZbl6LvyO7Lbd_yA764,354
6
+ pyfr_cli/git.py,sha256=bktsmAxak8PVzqvJmpXJy1kSrDgfwuJZRChwqa4unr4,3666
7
+ pyfr_cli/ignore.py,sha256=yg1VAfeN9CfYQ3XWacgC7tLfcKFGIVRcjOsxNSwgFUw,3292
8
+ pyfr_cli/migrate.py,sha256=3LqLaNyAbenJWSytMRK5X9PZ4cPM47BirTWw27YB8uI,3557
9
+ pyfr_cli/render.py,sha256=Vnl0_7hUtiUiXfVG-cZ1IU9oiRCWXZpcs8wRoXRBmZg,4442
10
+ pyfr_cli/state.py,sha256=YL9cog1WLg_httA-sFs40EZ98AuKZ2P97LGeFkAloi4,2016
11
+ pyfr_cli/update.py,sha256=SfCXJkPalLKEBZ7ubVWZYRNGm0kqgXXqpHdYTJlev6I,18694
12
+ pyfr_cli/vendor.py,sha256=qilBVpcpMa6-duiFD1r-wbIFmrWhjX1cxojcLBn1POw,15546
13
+ pyfr_cli/versions.py,sha256=UNu7DyJlhZxF5ygPNhacKiNro9QXnmojK3NO8_Px6Zs,3586
14
+ pyfr_cli-0.11.0.dist-info/METADATA,sha256=2PVRyI44kDFf4sfcC3HdrRL1ysx4mR8hRmpw9kPWIdk,28990
15
+ pyfr_cli-0.11.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
16
+ pyfr_cli-0.11.0.dist-info/entry_points.txt,sha256=Ota_6MPmx-IFOwi0Nhi4Zfdj0ylEMNy1nLlFvn9Gwhk,48
17
+ pyfr_cli-0.11.0.dist-info/licenses/LICENSE,sha256=Pz2eACSxkhsGfW9_iN60pgy-enjnbGTj8df8O3ebnQQ,16726
18
+ pyfr_cli-0.11.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pyfr = pyfr_cli.__main__:main