pubkit 0.1.0__tar.gz → 0.1.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.
- {pubkit-0.1.0 → pubkit-0.1.1}/CHANGELOG.md +17 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/PKG-INFO +23 -1
- {pubkit-0.1.0 → pubkit-0.1.1}/README.md +22 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/pyproject.toml +1 -1
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/__init__.py +1 -1
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/scaffold.py +27 -7
- {pubkit-0.1.0 → pubkit-0.1.1}/tests/test_core.py +16 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/.gitignore +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/LICENSE +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/NOTICE +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/docs/ADAPTERS.md +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/docs/ARCHITECTURE.md +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/docs/FAILURE-MODES.md +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/docs/QUICKSTART.md +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part1-01-model-sizes.png +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part1-02-cpu-vs-gpu-ANIMATED.gif +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part1-03-starving-cores-ANIMATED.gif +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part1-04-gpu-comparison.png +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-01-one-token-one-read-ANIMATED.gif +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-02-decode-ceilings.png +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-03-prefill-vs-decode.png +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-04-kv-cache-cost.png +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-05-batching-ANIMATED.gif +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-06-vram-budget.png +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-07-throughput-latency.png +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part3-01-interconnect.png +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part3-02-llmd-request-path.png +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part3-03-llmd-objects.png +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part3-04-slos.png +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/part-1.md +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/part-2.md +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/part-3.md +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/__main__.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/adapters/__init__.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/adapters/api_base.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/adapters/devto.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/adapters/medium.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/adapters/substack.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/adapters/x.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/browserctl.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/cli.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/__init__.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/adapter.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/anchors.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/auth.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/browser.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/capabilities.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/checks.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/ir.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/loader.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/runner.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/state.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/transport.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/py.typed +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/registry.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/render/__init__.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/render/html.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/workflows/__init__.py +0 -0
- {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/workflows/airflow.py +0 -0
|
@@ -4,6 +4,23 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
4
4
|
Versioning is [semantic](https://semver.org/); adapters may change behaviour on
|
|
5
5
|
a minor bump when a platform changes underneath them.
|
|
6
6
|
|
|
7
|
+
## [0.1.1] — 2026-09-11
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Docker image on the Playwright base (`ghcr.io/arunsingh/pubkit`), so browser
|
|
12
|
+
adapters work in CI without hand-installing Chromium's system libraries.
|
|
13
|
+
- `action.yml` — the repository is now a reusable GitHub Action.
|
|
14
|
+
- `CITATION.cff`, and a Homebrew formula template under `packaging/`.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- `pubkit doctor` ignored `PLAYWRIGHT_BROWSERS_PATH` and reported Chromium as
|
|
19
|
+
missing on managed images (CI runners, devcontainers, the Playwright Docker
|
|
20
|
+
image) where it was in fact installed — sending people off to fix a problem
|
|
21
|
+
they did not have. Found by running the published package in exactly such an
|
|
22
|
+
environment.
|
|
23
|
+
|
|
7
24
|
## [0.1.0] — 2026-09-11
|
|
8
25
|
|
|
9
26
|
First release. Extracted from a real, painful publishing run: a 15,000-word
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pubkit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Publish one source to many platforms, safely. Medium, Substack, X, Dev.to, Hashnode.
|
|
5
5
|
Project-URL: Homepage, https://github.com/arunsingh/pubkit
|
|
6
6
|
Project-URL: Issues, https://github.com/arunsingh/pubkit/issues
|
|
@@ -229,6 +229,28 @@ ghost = "my_pubkit_ghost:GhostAdapter"
|
|
|
229
229
|
Five extension points, all first-class: `pubkit.adapters`, `pubkit.renderers`,
|
|
230
230
|
`pubkit.checks`, `pubkit.hooks`, and per-platform `transforms:` in config.
|
|
231
231
|
|
|
232
|
+
## Install it however you like
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
pip install "pubkit[all]" # the normal way
|
|
236
|
+
pipx install "pubkit[all]" # isolated CLI
|
|
237
|
+
uv tool install "pubkit[all]" # same, faster
|
|
238
|
+
docker run --rm -v "$PWD:/work" ghcr.io/arunsingh/pubkit validate content/
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
The Docker image ships Chromium and its system libraries, which is the part
|
|
242
|
+
nobody wants to install on a CI runner by hand.
|
|
243
|
+
|
|
244
|
+
As a GitHub Action, no install step at all:
|
|
245
|
+
|
|
246
|
+
```yaml
|
|
247
|
+
- uses: arunsingh/pubkit@v1
|
|
248
|
+
with:
|
|
249
|
+
command: plan
|
|
250
|
+
path: content/
|
|
251
|
+
platforms: medium,devto
|
|
252
|
+
```
|
|
253
|
+
|
|
232
254
|
## Fit it into a workflow
|
|
233
255
|
|
|
234
256
|
**GitHub Actions** — plan on every PR, publish on merge:
|
|
@@ -179,6 +179,28 @@ ghost = "my_pubkit_ghost:GhostAdapter"
|
|
|
179
179
|
Five extension points, all first-class: `pubkit.adapters`, `pubkit.renderers`,
|
|
180
180
|
`pubkit.checks`, `pubkit.hooks`, and per-platform `transforms:` in config.
|
|
181
181
|
|
|
182
|
+
## Install it however you like
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
pip install "pubkit[all]" # the normal way
|
|
186
|
+
pipx install "pubkit[all]" # isolated CLI
|
|
187
|
+
uv tool install "pubkit[all]" # same, faster
|
|
188
|
+
docker run --rm -v "$PWD:/work" ghcr.io/arunsingh/pubkit validate content/
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The Docker image ships Chromium and its system libraries, which is the part
|
|
192
|
+
nobody wants to install on a CI runner by hand.
|
|
193
|
+
|
|
194
|
+
As a GitHub Action, no install step at all:
|
|
195
|
+
|
|
196
|
+
```yaml
|
|
197
|
+
- uses: arunsingh/pubkit@v1
|
|
198
|
+
with:
|
|
199
|
+
command: plan
|
|
200
|
+
path: content/
|
|
201
|
+
platforms: medium,devto
|
|
202
|
+
```
|
|
203
|
+
|
|
182
204
|
## Fit it into a workflow
|
|
183
205
|
|
|
184
206
|
**GitHub Actions** — plan on every PR, publish on merge:
|
|
@@ -6,7 +6,7 @@ from .core.loader import load_document, load_series # noqa: F401
|
|
|
6
6
|
from .core.runner import Pipeline, RunReport # noqa: F401
|
|
7
7
|
from .registry import build_adapter, list_adapters, register # noqa: F401
|
|
8
8
|
|
|
9
|
-
__version__ = "0.1.
|
|
9
|
+
__version__ = "0.1.1"
|
|
10
10
|
__all__ = [
|
|
11
11
|
"Document", "Series", "Asset", "Figure", "Table", "Heading", "Paragraph", "Code",
|
|
12
12
|
"Pipeline", "RunReport", "load_document", "load_series",
|
|
@@ -212,14 +212,34 @@ def diagnose() -> list[Finding]:
|
|
|
212
212
|
)
|
|
213
213
|
|
|
214
214
|
if _has("playwright"):
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
)
|
|
220
|
-
|
|
215
|
+
# Honour PLAYWRIGHT_BROWSERS_PATH. Managed images (CI runners, devcontainers,
|
|
216
|
+
# the Playwright Docker image) put browsers somewhere else entirely, and
|
|
217
|
+
# reporting "not downloaded" when they are right there sends people off to
|
|
218
|
+
# fix a problem they do not have.
|
|
219
|
+
override = os.environ.get("PLAYWRIGHT_BROWSERS_PATH")
|
|
220
|
+
if override and override != "0":
|
|
221
|
+
roots = [Path(override)]
|
|
222
|
+
where = override
|
|
223
|
+
else:
|
|
224
|
+
roots = [
|
|
225
|
+
Path.home()
|
|
226
|
+
/ (
|
|
227
|
+
"Library/Caches/ms-playwright"
|
|
228
|
+
if platform.system() == "Darwin"
|
|
229
|
+
else "AppData/Local/ms-playwright"
|
|
230
|
+
if platform.system() == "Windows"
|
|
231
|
+
else ".cache/ms-playwright"
|
|
232
|
+
)
|
|
233
|
+
]
|
|
234
|
+
where = "the default cache"
|
|
235
|
+
found = [d for r in roots if r.exists() for d in r.glob("chromium*")]
|
|
221
236
|
out.append(
|
|
222
|
-
Finding(
|
|
237
|
+
Finding(
|
|
238
|
+
bool(found),
|
|
239
|
+
"chromium",
|
|
240
|
+
f"{len(found)} build(s) in {where}" if found else f"none in {where}",
|
|
241
|
+
"playwright install chromium",
|
|
242
|
+
)
|
|
223
243
|
)
|
|
224
244
|
|
|
225
245
|
out.append(
|
|
@@ -421,3 +421,19 @@ async def test_transient_errors_are_retried():
|
|
|
421
421
|
|
|
422
422
|
assert await with_retry(fn, attempts=4, base=0.001) == "ok"
|
|
423
423
|
assert calls == 3
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
def test_doctor_honours_playwright_browsers_path(tmp_path, monkeypatch):
|
|
427
|
+
"""Managed images put browsers outside the default cache.
|
|
428
|
+
|
|
429
|
+
Reporting "not downloaded" when Chromium is sitting right there sends
|
|
430
|
+
someone off to fix a problem they do not have.
|
|
431
|
+
"""
|
|
432
|
+
from pubkit.scaffold import diagnose
|
|
433
|
+
|
|
434
|
+
(tmp_path / "chromium-1194").mkdir()
|
|
435
|
+
monkeypatch.setenv("PLAYWRIGHT_BROWSERS_PATH", str(tmp_path))
|
|
436
|
+
findings = {f.label: f for f in diagnose()}
|
|
437
|
+
if "chromium" in findings: # only present when playwright is installed
|
|
438
|
+
assert findings["chromium"].ok
|
|
439
|
+
assert str(tmp_path) in findings["chromium"].detail
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part1-03-starving-cores-ANIMATED.gif
RENAMED
|
File without changes
|
|
File without changes
|
{pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-01-one-token-one-read-ANIMATED.gif
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|