Python library Builder with CLI
Project description
pylibup
Personal and Opinionated Pylib Builder with CLI
Motivation
Since I've been on a recent building spree, I've been trying to adopt the DRY methodology. Mostly releasing smaller modules that aren't mono-repos. But copying and pasting templates got boring. So this sets to solve a few things that I use in particular, and likely won't be useful if your use case doesn't fit as well.
The end goal is that the structure should almost be pip install
-able as is.
Tasks:
-
Setup a sane
setup.py
-
Create some base module files in the correct structure
-
Adds
.gitignores
by default to prevent my default working files to be added -
Creates
CI/CD
github workflows for:-
Autopublish to Pypi
-
Docker Image releases (if part of an app)
-
-
Sets up repo
secrets
for dependentCI/CD
workflows
Why should you use this over other ones such as cookie-cutter
? I dont know, you probably shouldn't.
Quickstart
pip install --upgrade pylibup
Usage
cd ~/path/to/github
mkdir newlib && cd newlib
## This will generate a metadata.yaml in the cwd. You can then edit that file.
pylibup repo init
## Options & Args
# - name: Optional[str] = Argument(None) = name of python library
# - project_dir: Optional[str] = Argument(get_cwd()) = where the project should go
# - repo_user: Optional[str] = Argument(None) = your github username, or optionally, an org repo
# - github_token: Optional[str] = Option("", envvar="GITHUB_TOKEN") = auth token for github
# - private: bool = Option(True, "--public") = whether the repo should be published publicly, private by default.
# - overwrite: bool = Option(False) = overwrite existing files that were created
# - overwrite_state: bool = Option(False) = overwrite existing local state
## This will construct the library according to the metadata.yaml specs
pylibup repo build
## Options & Args
# config_file: Optional[str] = Argument(get_cwd('metadata.yaml')) = where your metadata.yaml should be located
# name: Optional[str] = Argument(None)
# project_dir: Optional[str] = Argument(get_cwd()),
# github_token: Optional[str] = Option("", envvar="GITHUB_TOKEN"),
# pypirc_path: Optional[str] = Option("~/.pypirc", envvar="PYPIRC_PATH"),
# commit_msg: Optional[str] = Option("Initialize"),
# auto_publish: bool = Option(False), # If auto_publish == True, then will automatically push to github
# overwrite: bool = Option(False),
# overwrite_state: bool = Option(False),
## Used whenever you didnt specify auto_publish = True
pylibup repo publish
## Options & Args
# config_file: Optional[str] = Argument(get_cwd('metadata.yaml')),
# github_token: Optional[str] = Option("", envvar="GITHUB_TOKEN"),
# pypirc_path: Optional[str] = Option("~/.pypirc", envvar="PYPIRC_PATH"),
# commit_msg: Optional[str] = Option("Initialize"),
# overwrite_state: bool = Option(False),
## Additionally you can utilize the build.sh script
sh build.sh dist # releases to main pypi
sh build.sh # will deploy to testpypi
Statefulness
CLI Apps tend to have bad statefulness. Two statefiles
are created:
-
local
: the current project folder -
global
: where the lib is installed
You can set certain configs like github_token
to where it will always load, rather than having to set it each time.
The global
state is loaded first, and overridden by local
state values.
Note: if you reinstall this library, the global state will likely be erased.
pylibup state set github_token=ghp_xtyz anothervalue=1234
## Options and Args
# states: List[str] where a state is "x=y"
# --global-state: will write to global state versus local state
# --overwrite-state: will overwrite current values, true by default
"""
[pylib] app.set_state Setting github_token -> ghp_xtyz. Previous: None
"""
Metadata Templating
Below is the base configuration for the metadata that is autogenerated
# These will automatically be added to .gitignore
gitignores:
- cache*
- '*.DS_Store'
- tests*
- __pycache__*
- '*logs'
- '*dist'
- '*build'
- '**build.sh'
- '*test.py'
- '*.egg-info*'
- '*.vscode'
- '**.ipynb'
- '**meta.yaml'
- '**metadata.yaml' # avoids adding this metadata file
- '**state.yaml'
# Some optional configs
options:
default_branch: main # sets to the default branch of the repo
include_app: true # creates an app/ which is intended to use if containerizing
include_buildscript: true # includes a build.sh, allowing you to quickly publish to pypi
include_dockerfile: true # includes a Dockerfile [using fastapi]
include_init: true # includes an __init__.py file in your module root that adds all the modules
include_reqtext: true # includes a requirements.txt in the repo root
private: true # sets the repo to public or private
project_description: '' # metadata used for description text
readme_text: '' #will be merged into the README.md
# optionally use annotation such as
# readme_text: |
# ## My Readme
# this is the readme
repo: trisongz/pylibup # the full name of your repo
secrets: # Optional secrets that will be automatically added to your repo.
AWS_ACCESS_KEY_ID: # as this is a dict, the key AWS_ACCESS_KEY_ID will be set as the secret key
from: AWS_ACCESS_KEY_ID_SVC_ACCOUNT # but `from` is the key that is used to get env value
AWS_REGION: us-east-1 # as this is a string, it will use this value directly.
AWS_SECRET_ACCESS_KEY: # as this is empty (null), will use the `key` to get the env value
# Additionally, you can set any other values following the same pattern as above.
# if no value is found, then it will not attempt to set the value.
setup:
author: null # will attempt to gather from github user profile
cli_cmds: [] # cli cmds to be added where an item = `pylibup = pylibup.cli:baseCli`
email: ts@growthengineai.com # will attempt to gather from github user profile
git_repo: trisongz/pylibup
kwargs: {} # additional setup keyword dict values to add to main setup function
lib_name: pylibup # if you intend for your `import x` to be different than the repo name
pkg_name: pylibup # the intended repo name
pkg_version: 0.0.0a # app version
require_py3: true # forces a check prior to installation
require_py3_version: 3.7 # no value = no check
requirements: # individual library requirements
- lazycls
- pylogz
- yourreq>1.5
structure: # will create these under yourapp/
modules: # so in this example, the following are created
- classes # yourapp/classes.py
- client # yourapp/client.py
- config # yourapp/config.py
- utils # yourapp/utils.py
workflows: # automatically create github workflows
docker_build: false # a quick docker-build.yaml targeting the Dockerfile when new pushes are made
docker_build_options: # specific build options for docker-build.yaml
# so the image handle will be img_repo/app_name
app_name: '' # the image name you want to publish under
docker_options:
img_repo: ''
ecr_options:
img_repo: ''
require_ecr: true # will create specific templating for ecr
pypi_publish: true # will create a workflow for pypi publish on push of setup.py and releases. Will also attempt to set PYPI_API_TOKEN if pypi_path is found to enable automagic.
Libraries & Dependencies
-
typer
: used for CLI -
PyGithub
: Used as Github API interface -
GitPython
: Used for git interface -
Jinja2
: Used for templating -
pyyaml
: Used for loading/saving statefiles -
pylogz
: Used for logging -
requests
: Used for calling the github API directly.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.