xcookie.main module

This is a Python script to apply the xcookie template to either create a new repo or update an existing one with the latest standards.

Todo

Port logic from ~/misc/make_new_python_package_repo.sh

CommandLine

~/code/xcookie/xcookie/main.py

python -m xcookie.main
ExampleUsage:

# Update my repos python -m xcookie.main –repodir=$HOME/code/pyflann_ibeis –tags=”erotemic,github,binpy”

python -m xcookie.main –repodir=$HOME/code/whodat –tags=”kitware,gitlab,purepy,cv2,gdal” python -m xcookie.main –repodir=$HOME/code/whatdat –tags=”kitware,gitlab,purepy,cv2,gdal” python -m xcookie.main –repodir=$HOME/code/whendat –tags=”kitware,gitlab,purepy,cv2,gdal” python -m xcookie.main –repodir=$HOME/code/whydat –tags=”kitware,gitlab,purepy,cv2,gdal” python -m xcookie.main –repodir=$HOME/code/howdat –tags=”kitware,gitlab,purepy,cv2,gdal”

python -m xcookie.main –repodir=$HOME/code/kwconf –tags=”kitware,gitlab,erotemic,github,purepy”

# Create this repo python -m xcookie.main –repo_name=xcookie –repodir=$HOME/code/xcookie –tags=”erotemic,github,purepy”

# Create a new python repo python -m xcookie.main –repo_name=cookiecutter_purepy –repodir=$HOME/code/cookiecutter_purepy –tags=”github,purepy”

# Create a new binary repo python -m xcookie.main –repo_name=cookiecutter_binpy –repodir=$HOME/code/cookiecutter_binpy –tags=”github,binpy,gdal”

# Create a new binary gitlab kitware repo python -m xcookie.main –repo_name=kwimage_ext –repodir=$HOME/code/kwimage_ext –tags=”kitware,gitlab,binpy” python -m xcookie.main –repo_name=balanced_sampler –repodir=$HOME/code/balanced_sampler –tags=”kitware,gitlab,binpy”

python -m xcookie.main –repo_name=kwcoco_dataloader –repodir=$HOME/code/kwcoco_dataloader –tags=”kitware,gitlab,purepy,gdal,cv2”

# Create a new binary github repo python -m xcookie.main –repodir=$HOME/code/networkx_algo_common_subtree –tags=”github,erotemic,binpy”

# Create a new purepy github repo python -m xcookie.main –repodir=$HOME/code/googledoc –tags=”github,erotemic,purepy”

python -m xcookie.main –repodir=$HOME/code/networkx_algo_common_subtree_cython –tags=”github,erotemic,binpy”

python -m xcookie.main –repo_name=delayed_image –repodir=$HOME/code/delayed_image –tags=”kitware,gitlab,purepy,cv2,gdal”

HOST=https://gitlab.kitware.com export PRIVATE_GITLAB_TOKEN=$(git_token_for “$HOST”) python -m xcookie.main –repo_name=kwutil –repodir=$HOME/code/kwutil –tags=”kitware,gitlab,purepy”

python -m xcookie.main –repo_name=geowatch –repodir=$HOME/code/geowatch –tags=”kitware,gitlab,purepy,cv2,gdal”

python -m xcookie.main –repo_name=stdx –repodir=$HOME/code/stdx –tags=”github,purepy,erotemic”

python -m xcookie.main –repo_name=ustd –repodir=$HOME/code/ustd –tags=”github,purepy,erotemic”

load_secrets export PRIVATE_GITLAB_TOKEN=$(git_token_for “https://gitlab.kitware.com”) python -m xcookie.main –repo_name=simple_dvc –repodir=$HOME/code/simple_dvc –tags=”gitlab,kitware,purepy,erotemic”

python -m xcookie.main –repo_name=audio_restore –repodir=$HOME/code/audio_restore –tags=”github,erotemic,purepy” –use_pyproject_requirements=True –use_setup_py=False

exception xcookie.main.SkipFile[source]

Bases: Exception

class xcookie.main.XCookieConfig(*args: Any, **kwargs: Any)[source]

Bases: Config

The XCookie CLI

Valid options: []

Parameters:
  • *args – positional arguments mapped onto declared fields.

  • **kwargs – keyword arguments for any declared field.

property _description

Argparse description, separate from project metadata.

_load_pyproject_config()[source]
_load_xcookie_pyproject_settings()[source]
_infer_project_authors(disk_config)[source]
_infer_xcookie_settings_from_pyproject(disk_config)[source]

Helper to populate the xcookie main settings from more standard pyproject schemas.

confirm(msg: str, default: bool = True) → bool[source]
Parameters:
  • msg (str) – display to the user

  • default (bool) – default value if non-interactive

Return type:

bool

prompt(msg: str, choices: list[str], default: str | bool = True) → str | bool[source]
Parameters:
  • msg (str) – display to the user

  • default (bool) – default value if non-interactive

Return type:

bool

classmethod load_from_cli_and_pyproject(argv: int | bool | str | Sequence[str] | None = False, strict: bool = True, autocomplete: bool | str = 'auto', **kwargs: Any) → XCookieConfig[source]
classmethod main(argv: int | bool | str | Sequence[str] | None = False, strict: bool = True, autocomplete: bool | str = 'auto', **kwargs: Any) → TemplateApplier[source]

Main entry point

Example

repodir = ub.Path.appdir(‘pypkg/demo/my_new_repo’) import sys, ubelt sys.path.append(ubelt.expandpath(‘~/code/xcookie’)) from xcookie.main import * # NOQA kwargs = {

‘repodir’: repodir,

} argv = 0

_abc_impl = <_abc._abc_data object>
class xcookie.main.TemplateApplier(config: XCookieConfig | dict[str, Any])[source]

Bases: object

The primary xcookie autogeneration class.

Note

this does not write any files unless you call setup (which just writes to a temporary directory) or apply (which can destructively clobber things).

template_infos: list[TemplateInfo]
close() → None[source]

Remove the temporary staging directory owned by this applier.

apply()[source]

Does the actual modification of the target repo.

Has special logic to handle building new respos versus updating repos.

autostage()[source]
property rel_mod_dpath: Path
property mod_dpath: Path
property mod_name: str
property pkg_name: str
property pkg_fname_prefix: str
_readme_fpath() → Path[source]

Prefer an existing README.md over README.rst, otherwise default to README.rst for newly generated repos.

_readme_content_type() → str[source]
_build_template_registry()[source]

Build the active template inventory.

property tags
_project_classifiers()[source]
_presetup()[source]

Resolve repository hosting metadata before staging templates.

setup()[source]

Finalizes a few variables and writes the “clean” template to the staging directory.

copy_staged_files()[source]
vcs_checks()[source]

Initialize Git and hosting state for a newly generated repository.

property template_context: TemplateContext
_stage_file(info)[source]

Write a single file to the staging directory based on its template info.

Parameters:

info (TemplateInfo | dict) – a template record that defines how to construct a file

Returns:

enriched information. A side effect of this function is writing the data to temporary storage.

Return type:

TemplateInfo

Example

>>> from xcookie.main import *  # NOQA
>>> dpath = ub.Path.appdir('xcookie/tests/test-stage').delete().ensuredir()
>>> kwargs = {
>>>     'repodir': dpath / 'testrepo',
>>>     'tags': ['gitlab', 'kitware', 'purepy', 'cv2'],
>>>     'is_new': False,
>>>     'interactive': False,
>>> }
>>> config = XCookieConfig.cli(argv=0, data=kwargs)
>>> print('config = {}'.format(ub.urepr(dict(config), nl=1)))
>>> self = TemplateApplier(config)
>>> self._build_template_registry()
>>> info = [d for d in self.template_infos if d['fname'] == '.gitlab-ci.yml'][0]
>>> self._stage_file(info)
_apply_xcookie_directives(stage_fpath)[source]
stage_files()[source]
gather_tasks() → PatchPlan[source]
render_patch_plan(plan: PatchPlan) → None[source]
build_requirements_txt()[source]
build_readthedocs()[source]
Returns:

templated code

Return type:

str

build_setup()[source]
Returns:

templated code

Return type:

str

build_pyproject()[source]
Returns:

templated code

Return type:

str

format_code(text, filename='snippet.py')[source]

Format Python code using the project’s pyproject.toml ruff settings.

Reads ruff configuration from [tool.ruff] and [tool.ruff.format] sections of the project’s pyproject.toml and uses those as defaults for formatting.

Parameters:
  • text (str) – Python code to format

  • filename (str) – Virtual filename for the formatter (default: ‘snippet.py’)

Returns:

Formatted code

Return type:

str

_setup_pip_commands()[source]
build_github_actions()[source]
build_github_actions_tests()[source]
build_github_actions_release()[source]
build_gitlab_ci()[source]
build_refresh_locks_sh()[source]

Build dev/refresh_locks.sh.

The script regenerates uv.lock from pyproject.toml and re-exports the requirements/locks/<extras>.txt files referenced by the strict CI variants in the active CI plan. Generated content is deterministic: one uv export invocation per unique extras combo.

build_run_linter()[source]
build_readme()[source]
build_docs_index()[source]
build_docs_conf()[source]
build_docs_requirements()[source]
build_optional_requirements()[source]
build_runtime_requirements()[source]
build_tests_requirements()[source]
_build_special_requirements(variant, version_defaults, header_lines)[source]

Example

>>> from xcookie.main import *  # NOQA
>>> dpath = ub.Path.appdir('xcookie/tests/test-stage').delete().ensuredir()
>>> kwargs = {
>>>     'repodir': dpath / 'testrepo',
>>>     'tags': ['gitlab', 'kitware', 'purepy', 'cv2'],
>>>     'is_new': False,
>>>     'min_python': '3.9',
>>>     'max_python': '3.12',
>>>     'interactive': False,
>>> }
>>> config = XCookieConfig.cli(argv=0, data=kwargs)
>>> print('config = {}'.format(ub.urepr(dict(config), nl=1)))
>>> self = TemplateApplier(config)
>>> print(chr(10) + 'headless.txt')
>>> print(self.build_cv2_headless_requirements_txt())
>>> print(chr(10) + 'gdal.txt')
>>> print(self.build_gdal_requirements_txt())
_build_cv2_requirements(variant)[source]
build_cv2_headless_requirements_txt()[source]
build_cv2_graphics_requirements_txt()[source]
_gdal_requirement_parts()[source]
build_gdal_requirements_txt()[source]
build_run_doctests()[source]
xcookie.main._parse_remote_url(url)[source]

Legacy remote URL parser retained for import compatibility.

xcookie.main.find_git_root(dpath)[source]

Find the nearest ancestor containing .git.

xcookie.main.main()[source]