Skip to content

FUCs

A collection of frequently used commands related to this project. I actually need this.

Bandit#

Tool designed to find common security issues in Python code.

  • Scan: uv run bandit -r -c bandit.yaml .

bandit.yaml:

exclude_dirs: [.venv]

Links:

MkDocs#

Project documentation with Markdown.

  • Serve (with .env): uv run --env-file .env mkdocs serve
  • Build (with .env): uv run --env-file .env mkdocs build
  • Deploy to Github Pages (with .env): uv run --env-file .env mkdocs gh-deploy

mkdocs.yaml:

site_name: Scaffold Kit
site_description: >
  Command-line tools for project setup, structure creation, file tracking, and
  directory trees.
copyright: © 2025 Dirk Sidney Jansen. All Rights Reserved.
repo_name: sidisinsane/scaffold-kit
site_url: https://sidisinsane.github.io/scaffold-kit
repo_url: https://github.com/sidisinsane/scaffold-kit
docs_dir: docs
site_dir: site
dev_addr: 127.0.0.1:8888
edit_uri: edit/main/docs/
use_directory_urls: true

draft_docs: |
  draft.*.md

plugins:
  - mkdocs-nav-weight:
      section_renamed: true
      index_weight: -10
      warning: true
      reverse: false
      headless_included: false
  - offline
  - search
  - autorefs
  - mkdocstrings

validation:
  omitted_files: warn
  absolute_links: warn
  unrecognized_links: warn

theme:
  name: material
  language: en
  favicon: assets/images/favicon.ico
  logo: assets/images/logo-dark-theme.svg
  icon:
    repo: fontawesome/brands/git-alt

  features:
    - announce.dismiss
    - content.code.annotate
    - content.code.copy
    - content.tooltips
    - header.autohide
    - navigation.footer
    - navigation.indexes
    - navigation.sections
    - navigation.tracking
    - navigation.top
    - search.highlight
    - search.suggest
    - toc.follow
    - toc.integrate

  palette:
    - media: "(prefers-color-scheme: light)"
      scheme: default
      primary: deep-purple
      accent: yellow
      toggle:
        icon: material/toggle-switch
        name: Switch to dark mode
    - media: "(prefers-color-scheme: dark)"
      scheme: slate
      primary: black
      accent: yellow
      toggle:
        icon: material/toggle-switch-off-outline
        name: Switch to light mode

markdown_extensions:
  - attr_list
  - admonition
  - footnotes
  - pymdownx.arithmatex:
      generic: true
  - pymdownx.highlight:
      anchor_linenums: true
  - pymdownx.details
  - pymdownx.inlinehilite
  - pymdownx.magiclink
  - pymdownx.snippets:
      check_paths: true
  - pymdownx.tasklist:
      custom_checkbox: true
  - sane_lists
  - smarty:
      smart_dashes: true
      smart_quotes: true
      smart_angled_quotes: true
      smart_ellipses: true
  - toc:
      permalink: "#"

extra_javascript:
  - assets/javascripts/mathjax.js
  - https://polyfill.io/v3/polyfill.min.js?features=es6
  - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js

extra:
  social:
    - icon: fontawesome/brands/github
      link: https://github.com/sidisinsane

Kill running server on port 8888

  1. Get PID (e.g. 14765): $ lsof -n -i4TCP:8888

  2. Kill PID: $ kill -9 14765

Links:

MyPy#

Static type checker for Python.

  • Check: uv run mypy .

Broken

TODO: Fix “There are no .py[i] files in…”

mypy.ini:

# Global options
[mypy]
exclude             = [.venv]
python_version      = 3.12
warn_return_any     = True
warn_unused_configs = True

# Per-module options
[mypy-tests.*]
ignore_errors = True

Links:

Ruff#

Python linter and code formatter.

  • Lint (and fix): uv run ruff check [--fix]
  • Format: uv run ruff format

ruff.toml:

line-length = 80

exclude = [
  ".bzr",
  ".direnv",
  ".eggs",
  ".git",
  ".git-rewrite",
  ".hg",
  ".mypy_cache",
  ".nox",
  ".pants.d",
  ".pytype",
  ".ruff_cache",
  ".svn",
  ".tox",
  ".venv",
  "__pypackages__",
  "_build",
  "buck-out",
  "dist",
  "node_modules",
  "venv",
  "uv.lock",
  "docs",
  "reports",
  "public",
]

[format]
docstring-code-format      = false
docstring-code-line-length = 80

[lint]
select = [
  "I",
  "E501", # line-too-long
  "W505", # doc-line-too-long
]

[lint.per-file-ignores]
"**/scripts/*" = [
  "I002",   # from __future__ import annotations
  "INP001",
  "T201",
]

"**/tests/**/*" = [ "PLC1901", "PLR2004", "PLR6301", "S", "TID252" ]

[lint.flake8-tidy-imports]
ban-relative-imports = "all"

[lint.isort]
known-first-party = [  ]
case-sensitive = true
length-sort-straight = true
lines-after-imports = 2
lines-between-types = 1
order-by-type = true
required-imports = [ "from __future__ import annotations" ]
section-order = [
  "future",
  "standard-library",
  "third-party",
  "first-party",
  "local-folder",
]

[lint.flake8-pytest-style]
fixture-parentheses = false
mark-parentheses    = false

[lint.pydocstyle]
convention = "google"

[lint.pycodestyle]
max-doc-length = 80

Links:

Sphinx#

Generates documentation automatically from docstrings.

  • Generate .rst stubs: uv run sphinx-apidoc -o docs_sphinx src --force --module-first --no-toc
  • Build HTML: uv run sphinx-build -b html docs_sphinx reference
API Reference
=============

Add your content using ``reStructuredText`` syntax. See the
`reStructuredText <https://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html>`_
documentation for details.

.. toctree::
   :maxdepth: 4
   :caption: Contents:

   modules

Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

Links:

docs_sphinx/index.rst:

UV#

Python package and project manager.

  • Add dependency: uv add <package>
  • Add optional dependency: uv add <package> --optional <name>
  • Remove optional dependency: uv remove <package> --optional <name>
  • Update the project’s environment: uv sync
  • Include all optional dependencies: uv sync --all-extras
  • Include optional dependency: uv sync --extras <name>

pyproject.toml:

[build-system]
requires      = [ "hatchling", "hatch-vcs" ]
build-backend = "hatchling.build"

[project]
name = "scaffold-kit"
dynamic = [ "version" ] # Version comes from Git tags
description = "Command-line tools for project setup, structure creation, file tracking, and directory trees."
readme = "README.md"
license = "MIT"
authors = [
  { name = "Dirk Sidney Jansen", email = "sidisinsane@users.noreply.github.com" },
]
requires-python = ">=3.12"
keywords = [
  "scaffold",
  "productivity",
  "generator",
  "project-structure",
  "cli",
  "cli-tool",
  "command-line",
  "command-line-tool",
  "tree",
  "file-tree",
  "directory-tree",
]
classifiers = [
  "Development Status :: 4 - Beta",
  "Intended Audience :: Developers",
  "License :: OSI Approved :: MIT License",
  "Operating System :: OS Independent",
  "Programming Language :: Python :: 3",
  "Programming Language :: Python :: 3.12",
  "Programming Language :: Python :: 3.13",
  "Topic :: Software Development :: Code Generators",
  "Topic :: System :: Filesystems",
  "Topic :: Utilities",
]

dependencies = [
  "pyyaml~=6.0.2",
]

[project.urls]
Homepage        = "https://github.com/sidisinsane/scaffold-kit"
Documentation   = "https://sidisinsane.github.io/scaffold-kit/"
"API Reference" = "https://sidisinsane.github.io/scaffold-kit/reference/"
Repository      = "https://github.com/sidisinsane/scaffold-kit.git"
"Bug Tracker"   = "https://github.com/sidisinsane/scaffold-kit/issues"

[project.optional-dependencies]
build = [ "python-semantic-release~=10.3.1" ]

dev = [
  "ruff~=0.12.10",
  "mypy~=1.17.0",
  "bandit~=1.8.6",
  "pre-commit~=4.3.0",
  "yamllint~=1.37.1",
  "taplo~=0.9.3",
  "pylint~=3.3.8",
  "pytest~=8.4.1",
  "pytest-cov~=6.2.1",
  "coverage~=7.10.1",
]

docs = [
  "mkdocs~=1.6.1",
  "mkdocstrings[python]~=0.30.0",
  "mkdocs-gen-files~=0.5.0",
  "mkdocs-material~=9.6.16",
  "mkdocs-nav-weight~=0.2.0",
  "mkdocs-section-index~=0.3.10",
  "pymdown-extensions~=10.16.1",
  "sphinx~=8.2.3",
  "sphinx-favicon~=1.0.1",
]

test = [
  "pytest~=8.4.1",
  "pytest-cov~=6.2.1",
  "coverage~=7.10.1",
]

[project.scripts]
scaffold-kit = "scaffold_kit.main:main"

[tool.hatch.version]
source = "vcs"

[tool.hatch.build]
exclude = [ "uv.lock", ".tool-versions", ".github", ".venv" ]

[tool.hatch.build.targets.wheel]
packages = [ "src/scaffold_kit" ]

[tool.hatch.build.hooks.vcs]
version-file = "src/scaffold_kit/__version__.py"
version-scheme = "guess-next-dev"
local-scheme = "no-local-version"
fallback-version = "0.1.0"
template = '''"""Package version information.

Automatic version file generated by hatch-vcs. Do not change, do not track!
"""

from __future__ import annotations


__version__ = {version!r}
__version_tuple__ = {version_tuple!r}

'''

[tool.semantic_release]
build_command = """
  uv lock --upgrade-package "$PACKAGE_NAME"
  uv build
"""
commit_message = "chore(release): {version}"
commit_author = "semantic-release <semantic-release>"
commit_parser = "conventional"
tag_format = "{version}"

[tool.semantic_release.branches.main]
match      = "(main|master)"
prerelease = false

[tool.semantic_release.changelog]
mode = "update"
insertion_flag = "<!-- version list -->"
exclude_commit_patterns = [
  '''chore(?:\([^)]*?\))?: .+''',
  '''ci(?:\([^)]*?\))?: .+''',
  '''refactor(?:\([^)]*?\))?: .+''',
  '''style(?:\([^)]*?\))?: .+''',
  '''test(?:\([^)]*?\))?: .+''',
  '''build\((?!deps\): .+)''',
  '''Initial [Cc]ommit.*''',
  '''First [Cc]ommit.*''',
]

[tool.semantic_release.changelog.default_templates]
changelog_file = "CHANGELOG.md"
output_format  = "md"

[tool.semantic_release.changelog.environment]
block_start_string    = "{%"
block_end_string      = "%}"
variable_start_string = "{{"
variable_end_string   = "}}"
comment_start_string  = "{#"
comment_end_string    = "#}"
trim_blocks           = false
lstrip_blocks         = false
newline_sequence      = "\n"
keep_trailing_newline = false
extensions            = [  ]
autoescape            = false

[tool.semantic_release.commit_parser_options]
minor_tags = [ "feat" ]
patch_tags = [ "fix", "perf" ]
other_allowed_tags = [
  "build",
  "chore",
  "ci",
  "docs",
  "refactor",
  "release",
  "style",
  "test",
]
allowed_tags = [
  "feat",
  "fix",
  "perf",
  "build",
  "chore",
  "ci",
  "docs",
  "refactor",
  "release",
  "style",
  "test",
]
default_bump_level = 0
parse_squash_commits = true
ignore_merge_commits = true

[tool.semantic_release.publish]
dist_glob_patterns    = [ "dist/*" ]
upload_to_vcs_release = true

Links:

Yamllint#

A linter for YAML files.

  • Lint: uv run yamllint --strict -c .yamllint.yaml .

.yamllint.yaml:

extends: default

yaml-files:
  - "*.yaml"
  - "*.yml"

ignore:
  - .git
  - .mypy_cache
  - .pytest_cache
  - .ruff_cache
  - .venv

rules:
  braces:
    forbid: true
    level: warning
  brackets:
    forbid: false
  comments:
    require-starting-space: true
    ignore-shebangs: true
    min-spaces-from-content: 1
  document-end:
    present: false
    level: warning
  document-start:
    present: false
    level: warning
  indentation:
    spaces: 2
  line-length:
    max: 80
    allow-non-breakable-words: true
    allow-non-breakable-inline-mappings: false
    level: warning
    ignore:
      - .github/workflows/*.yml
  new-line-at-end-of-file: enable
  new-lines:
    type: unix
  quoted-strings:
    quote-type: double
    required: only-when-needed
  trailing-spaces:
    level: warning
  truthy:
    ignore:
      - .github/workflows/*.yml

Links: