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.
Files changed (59) hide show
  1. {pubkit-0.1.0 → pubkit-0.1.1}/CHANGELOG.md +17 -0
  2. {pubkit-0.1.0 → pubkit-0.1.1}/PKG-INFO +23 -1
  3. {pubkit-0.1.0 → pubkit-0.1.1}/README.md +22 -0
  4. {pubkit-0.1.0 → pubkit-0.1.1}/pyproject.toml +1 -1
  5. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/__init__.py +1 -1
  6. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/scaffold.py +27 -7
  7. {pubkit-0.1.0 → pubkit-0.1.1}/tests/test_core.py +16 -0
  8. {pubkit-0.1.0 → pubkit-0.1.1}/.gitignore +0 -0
  9. {pubkit-0.1.0 → pubkit-0.1.1}/LICENSE +0 -0
  10. {pubkit-0.1.0 → pubkit-0.1.1}/NOTICE +0 -0
  11. {pubkit-0.1.0 → pubkit-0.1.1}/docs/ADAPTERS.md +0 -0
  12. {pubkit-0.1.0 → pubkit-0.1.1}/docs/ARCHITECTURE.md +0 -0
  13. {pubkit-0.1.0 → pubkit-0.1.1}/docs/FAILURE-MODES.md +0 -0
  14. {pubkit-0.1.0 → pubkit-0.1.1}/docs/QUICKSTART.md +0 -0
  15. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part1-01-model-sizes.png +0 -0
  16. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part1-02-cpu-vs-gpu-ANIMATED.gif +0 -0
  17. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part1-03-starving-cores-ANIMATED.gif +0 -0
  18. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part1-04-gpu-comparison.png +0 -0
  19. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-01-one-token-one-read-ANIMATED.gif +0 -0
  20. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-02-decode-ceilings.png +0 -0
  21. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-03-prefill-vs-decode.png +0 -0
  22. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-04-kv-cache-cost.png +0 -0
  23. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-05-batching-ANIMATED.gif +0 -0
  24. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-06-vram-budget.png +0 -0
  25. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part2-07-throughput-latency.png +0 -0
  26. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part3-01-interconnect.png +0 -0
  27. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part3-02-llmd-request-path.png +0 -0
  28. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part3-03-llmd-objects.png +0 -0
  29. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/img/part3-04-slos.png +0 -0
  30. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/part-1.md +0 -0
  31. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/part-2.md +0 -0
  32. {pubkit-0.1.0 → pubkit-0.1.1}/examples/inside-ai-infra/part-3.md +0 -0
  33. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/__main__.py +0 -0
  34. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/adapters/__init__.py +0 -0
  35. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/adapters/api_base.py +0 -0
  36. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/adapters/devto.py +0 -0
  37. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/adapters/medium.py +0 -0
  38. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/adapters/substack.py +0 -0
  39. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/adapters/x.py +0 -0
  40. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/browserctl.py +0 -0
  41. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/cli.py +0 -0
  42. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/__init__.py +0 -0
  43. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/adapter.py +0 -0
  44. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/anchors.py +0 -0
  45. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/auth.py +0 -0
  46. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/browser.py +0 -0
  47. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/capabilities.py +0 -0
  48. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/checks.py +0 -0
  49. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/ir.py +0 -0
  50. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/loader.py +0 -0
  51. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/runner.py +0 -0
  52. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/state.py +0 -0
  53. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/core/transport.py +0 -0
  54. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/py.typed +0 -0
  55. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/registry.py +0 -0
  56. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/render/__init__.py +0 -0
  57. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/render/html.py +0 -0
  58. {pubkit-0.1.0 → pubkit-0.1.1}/src/pubkit/workflows/__init__.py +0 -0
  59. {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.0
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:
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "pubkit"
7
- version = "0.1.0"
7
+ version = "0.1.1"
8
8
  description = "Publish one source to many platforms, safely. Medium, Substack, X, Dev.to, Hashnode."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -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.0"
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
- from pathlib import Path as _P
216
-
217
- cache = _P.home() / (
218
- "Library/Caches/ms-playwright" if platform.system() == "Darwin" else ".cache/ms-playwright"
219
- )
220
- found = cache.exists() and any(cache.glob("chromium*"))
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(found, "chromium", "downloaded" if found else "not downloaded", "playwright install chromium")
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
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