pj
Three methods to create, sync, and release projects:
Project.new()Create repo on GitHub + local clone. Ifnbdev: add theme toggle, set GH Pages branch.Project.sync()(opt.nbdev_prepare) →commit→pull --rebase→push.Project.ship()Version bump →tag→ GitHub release. IfPyPI=True: build → upload.
Works with any repo to handle lifecycle with Git, GitHub, and PyPI.
Notebook-friendly, whether Jupyter,1 nbdev, or SolveIT! 📚💙
Built with fastgit (git operations), ghapi (GitHub API), and fastcore (utilities).
Install
This has only been tested in SolveIT, with the nbs/00_core dialog. You may either:
- clone this repo and open
nbs/00_core(or usepj/core.py) - download
nbs/00_coreor view the shared dialog, and import it to your SolveIT instance.
More coming very soon.
# [coming soon] pip install pj-pyUsage
Select Project > sync to commit+push > release.
0. API setup
Authenticate once. All Project instances share the connection.
# imports not required if you run it from the 00_core dialog in SolveIT.
# Otherwise:
#from pj import Project, set_api
#from ghapi.all import GhApi
set_api(GhApi())Check that it’s fine:
get_api()1. Target project
Create a new project (A), or select an existing repo (B).
A. Create new
p = Project.new("mylib")
# = Project.new("mylib", path=None, org=None, desc=None, private=True, nbdev=False, verbose=False)Creates a private GitHub repo under your user, clones it locally, installs nbdev hooks. org takes the GH handle.
B. Select existing repo
p = Project("path/to/repo")Auto-detects pj type and owner (settings.ini for nbdev, otherwise pyproject.toml, or other if none).
2. Sync changes
p.sync()
# = p.sync(msg="sync")Stages all, commits with message “sync”, pulls with rebase, pushes.
3. Release
p.ship()
# = p.ship(part=2, dry_run=False, force=False, pypi=False, quiet=False)Bumps patch version (0.0.X), tags, creates GitHub release. No PyPI upload by default.
Utilities
Project. public methods:
ls()to list files in the project’s repo.setup_pages()configures GitHub Pages manually.dark_theme()applies dark mode to nbdev docs.- Any unknown method forwards to git.
Troubleshooting
Path errors
Reassign p = Project("correct/path") to fix the current working directory (cwd).
Restart kernel first if it still fails.
Rebase conflicts
p.g('rebase', '--abort') to start over, or resolve and continue.
API Summary
Create:
p = Project.new("mylib") # Private repop = Project.new(
"mylib",
org="myorg", # GH Organization
desc="Cool lib" # About
private=False, # Public repository
nbdev=True # nbdev/Quarto GH Pages w. light/dark toggle
)Existing:
p = Project('mylib') # [cwd/]'relative/path' or '/absolute/path'Sync:
p.sync() # Commit all, rebase, push
p.sync("Fix bug #42") # Commit message (default: 'sync')Release:
p.ship() # Bump patch, tag, GitHub release
p.ship(part=1) # Bump minor
p.ship(pypi=True) # Include PyPI upload
p.ship(dry_run=True) # Preview without doing anythingUtilities:
p.ls() # List files (takes regex str)
p.ls('nbs') # List notebooks ('py' for Python files)
p.setup_pages() # Configure GitHub Pages manually
p.dark_theme() # Enable Quarto dark mode w. toggle button (nbdev docs)
p.status() # Git methods forward to p.g (thus fastgit.Git)Footnotes
Jupyter+Quarto specific QoL to come soon™↩︎