Codebase Knowledge Index

Overview

afwf_genpass is an Alfred workflow that ships three independent generators — secure passwords, YouTube-style short IDs, and UUID4s — each wired to its own Alfred keyword. Under the hood it is a thin layer on top of the afwf SDK: every Alfred keyword calls a Python function that returns an afwf.ScriptFilter object, which the CLI serializes to JSON for Alfred to render.

This page is the knowledge index for the codebase — a one-stop list of the files that define what the workflow does and where to look when you need to change something.

Top-level configuration files

The package metadata, dependencies (afwf, fire, diskcache), and the console-script entry point afwf-genpass = "afwf_genpass.cli:run" are declared in pyproject.toml. This is the binary that Alfred invokes — and the same binary you can reach from the shell via uvx --from afwf-genpass.

pyproject.toml
  1# ==============================================================================
  2# The [project] table defined by Official python.org
  3#
  4# Read: https://packaging.python.org/en/latest/guides/writing-pyproject-toml/
  5# ==============================================================================
  6[project]
  7name = "afwf_genpass"
  8# Increment version before each release - follow `semantic versioning <https://semver.org/>`_
  9# Currently, poetry 2.1.X doesn't support dynamic versioning
 10# (Read https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#version)
 11# So this value has to be aligned with the one in ``afwf_genpass/_version.py``
 12version = "0.1.2"
 13description = "Alfred Workflow for Random Password."
 14# Read https://dev-exp-share.readthedocs.io/en/latest/search.html?q=Pick+An+Open+Source+License+For+Python+Project&check_keywords=yes&area=default
 15# To pick a license and update the ``license``, ``classifier`` field in ``pyproject.toml``
 16# And also update the ``LICENSE.txt`` file in the git repo.
 17license = "MIT"
 18license-files = ["LICENSE.txt", "AUTHORS.rst"]
 19authors = [
 20    { name = "Sanhe Hu", email = "husanhe@email.com" },
 21]
 22maintainers = [
 23    { name = "Sanhe Hu", email = "husanhe@email.com" },
 24]
 25keywords = []
 26readme = "README.rst"
 27requires-python = ">=3.10,<4.0"
 28# Full list of classifiers: https://pypi.org/classifiers/
 29classifiers = [
 30    "Development Status :: 4 - Beta",
 31    "Intended Audience :: Developers",
 32    "Natural Language :: English",
 33    "Operating System :: Microsoft :: Windows",
 34    "Operating System :: MacOS",
 35    "Operating System :: Unix",
 36    "Programming Language :: Python :: 3",
 37    "Programming Language :: Python :: 3.10",
 38    "Programming Language :: Python :: 3.11",
 39    "Programming Language :: Python :: 3.12",
 40    "Programming Language :: Python :: 3.13",
 41    "Programming Language :: Python :: 3.14",
 42]
 43
 44# ------------------------------------------------------------------------------
 45# Core Dependencies
 46# ------------------------------------------------------------------------------
 47dependencies = [
 48    "afwf>=1.0.2,<2.0.0",
 49    "diskcache>=5.6.3,<6.0.0",
 50    "fire>=0.6.0,<1.0.0",
 51]
 52
 53# ------------------------------------------------------------------------------
 54# Optional dependency that can be used in ``pip install ${your_project_name}[${feature_name}]``
 55# Sometime this is also called "extras"
 56# Read: https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#dependencies-optional-dependencies
 57#
 58# IMPORTANT: all optional dependencies has to be compatible with the "requires-python" field
 59# ------------------------------------------------------------------------------
 60[project.optional-dependencies]
 61
 62# ------------------------------------------------------------------------------
 63# Local Development dependenceies
 64# ------------------------------------------------------------------------------
 65dev = [
 66    "rich>=13.8.1,<14.0.0", # pretty print
 67]
 68
 69# ------------------------------------------------------------------------------
 70# (Unit/Coverage/Integration/Load) Test dependenceies
 71# ------------------------------------------------------------------------------
 72test = [
 73    "pytest>=8.2.2,<9.0.0", # Testing framework
 74    "pytest-cov>=6.0.0,<7.0.0", # Coverage reporting
 75]
 76
 77# ------------------------------------------------------------------------------
 78# Documentation build dependenceies
 79# ------------------------------------------------------------------------------
 80doc = [
 81    "Sphinx>=7.4.7,<8.0.0",
 82    "sphinx-copybutton>=0.5.2,<1.0.0", # add copy button to code block
 83    "sphinx-design>=0.6.1,<1.0.0", # add additional design pattern to sphinx
 84    "sphinx-jinja>=2.0.2,<3.0.0", # enable jinja syntax in reStructuredText
 85    "furo==2024.8.6", # the furo sphinx theme
 86    "pygments>=2.18.0,<3.0.0", # syntax highlight
 87    "ipython>=8.18.1,<8.19.0", # interactive Python
 88    "nbsphinx>=0.8.12,<1.0.0", # add jupyter notebook in sphinx doc
 89    "rstobj==2.0.0", # generate reStructuredText from Python code
 90    "docfly==3.0.3", # automaticall generate .. toctree directives and API reference doc
 91]
 92
 93# ------------------------------------------------------------------------------
 94# Mise task runner dependencies
 95# ------------------------------------------------------------------------------
 96mise = [
 97    "PyGithub>=2.8.0,<3.0.0", # GitHub API client
 98    "httpx>=0.28.0,<1.0.0", # HTTP client for ReadTheDocs API
 99    "tomli>=2.0.0,<3.0.0; python_version < '3.11'", # TOML parser for Python 3.10
100]
101
102# Quick Links
103[project.urls]
104Homepage = "https://github.com/MacHu-GWU/afwf_genpass-project"
105Documentation = "https://afwf-genpass.readthedocs.io/en/latest/"
106Repository = "https://github.com/MacHu-GWU/afwf_genpass-project"
107Issues = "https://github.com/MacHu-GWU/afwf_genpass-project/issues"
108Changelog = "https://github.com/MacHu-GWU/afwf_genpass-project/blob/main/release-history.rst"
109Download = "https://pypi.org/pypi/afwf-genpass#files"
110
111# For command line interface, read: https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#creating-executable-scripts
112[project.scripts]
113afwf-genpass = "afwf_genpass.cli:run"
114
115[tool.setuptools.packages.find]
116where = ["."]
117include = [
118    "afwf_genpass*"
119]
120exclude = [
121    "afwf_genpass.tests",
122    "afwf_genpass.tests.*",
123    "afwf_genpass.docs",
124    "afwf_genpass.docs.*",
125]
126
127[build-system]
128requires = ["setuptools>=61.0", "wheel"]
129build-backend = "setuptools.build_meta"

The Alfred workflow definition lives in info.plist. It contains three Script Filter nodes — genpass, genid, genuuid4 — each of which calls ~/.local/bin/uvx --from "afwf-genpass==X.Y.Z" afwf-genpass <subcommand>. Keep this file in the repo as the source of truth; the installed copy in Alfred is a snapshot taken at release time.

info.plist
  1<?xml version="1.0" encoding="UTF-8"?>
  2<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3<plist version="1.0">
  4<dict>
  5	<key>bundleid</key>
  6	<string>MacHu-GWU.generate-secure-password</string>
  7	<key>connections</key>
  8	<dict>
  9		<key>C9643FA2-6BC2-4020-A2D4-4099AF6D58DE</key>
 10		<array/>
 11	</dict>
 12	<key>createdby</key>
 13	<string>Sanhe Hu</string>
 14	<key>description</key>
 15	<string>Generate a Secure Password made easy</string>
 16	<key>disabled</key>
 17	<false/>
 18	<key>name</key>
 19	<string>afwf_genpass</string>
 20	<key>objects</key>
 21	<array>
 22		<dict>
 23			<key>config</key>
 24			<dict>
 25				<key>alfredfiltersresults</key>
 26				<false/>
 27				<key>alfredfiltersresultsmatchmode</key>
 28				<integer>0</integer>
 29				<key>argumenttreatemptyqueryasnil</key>
 30				<false/>
 31				<key>argumenttrimmode</key>
 32				<integer>0</integer>
 33				<key>argumenttype</key>
 34				<integer>1</integer>
 35				<key>escaping</key>
 36				<integer>68</integer>
 37				<key>keyword</key>
 38				<string>genpass</string>
 39				<key>queuedelaycustom</key>
 40				<integer>3</integer>
 41				<key>queuedelayimmediatelyinitially</key>
 42				<true/>
 43				<key>queuedelaymode</key>
 44				<integer>1</integer>
 45				<key>queuemode</key>
 46				<integer>1</integer>
 47				<key>runningsubtext</key>
 48				<string>please wait ...</string>
 49				<key>script</key>
 50				<string>~/.local/bin/uvx --from "afwf-genpass==0.1.2" afwf-genpass genpass --query '{query}'
 51# ~/Documents/GitHub/afwf_genpass-project/.venv/bin/afwf-genpass genpass --query '{query}'</string>
 52				<key>scriptargtype</key>
 53				<integer>0</integer>
 54				<key>scriptfile</key>
 55				<string></string>
 56				<key>subtext</key>
 57				<string>Generate a secure password</string>
 58				<key>title</key>
 59				<string>genpass</string>
 60				<key>type</key>
 61				<integer>0</integer>
 62				<key>withspace</key>
 63				<true/>
 64			</dict>
 65			<key>type</key>
 66			<string>alfred.workflow.input.scriptfilter</string>
 67			<key>uid</key>
 68			<string>C9643FA2-6BC2-4020-A2D4-4099AF6D58DE</string>
 69			<key>version</key>
 70			<integer>3</integer>
 71		</dict>
 72		<dict>
 73			<key>config</key>
 74			<dict>
 75				<key>alfredfiltersresults</key>
 76				<false/>
 77				<key>alfredfiltersresultsmatchmode</key>
 78				<integer>0</integer>
 79				<key>argumenttreatemptyqueryasnil</key>
 80				<false/>
 81				<key>argumenttrimmode</key>
 82				<integer>0</integer>
 83				<key>argumenttype</key>
 84				<integer>1</integer>
 85				<key>escaping</key>
 86				<integer>68</integer>
 87				<key>keyword</key>
 88				<string>genid</string>
 89				<key>queuedelaycustom</key>
 90				<integer>3</integer>
 91				<key>queuedelayimmediatelyinitially</key>
 92				<true/>
 93				<key>queuedelaymode</key>
 94				<integer>1</integer>
 95				<key>queuemode</key>
 96				<integer>1</integer>
 97				<key>runningsubtext</key>
 98				<string>please wait ...</string>
 99				<key>script</key>
100				<string>~/.local/bin/uvx --from "afwf-genpass==0.1.2" afwf-genpass genid --query '{query}'
101# ~/Documents/GitHub/afwf_genpass-project/.venv/bin/afwf-genpass genid --query '{query}'</string>
102				<key>scriptargtype</key>
103				<integer>0</integer>
104				<key>scriptfile</key>
105				<string></string>
106				<key>subtext</key>
107				<string>Generate Random ID</string>
108				<key>title</key>
109				<string>genid</string>
110				<key>type</key>
111				<integer>0</integer>
112				<key>withspace</key>
113				<true/>
114			</dict>
115			<key>type</key>
116			<string>alfred.workflow.input.scriptfilter</string>
117			<key>uid</key>
118			<string>D5C6FAF4-8EC7-4F6E-842A-50587EDA22A9</string>
119			<key>version</key>
120			<integer>3</integer>
121		</dict>
122		<dict>
123			<key>config</key>
124			<dict>
125				<key>alfredfiltersresults</key>
126				<false/>
127				<key>alfredfiltersresultsmatchmode</key>
128				<integer>0</integer>
129				<key>argumenttreatemptyqueryasnil</key>
130				<false/>
131				<key>argumenttrimmode</key>
132				<integer>0</integer>
133				<key>argumenttype</key>
134				<integer>2</integer>
135				<key>escaping</key>
136				<integer>68</integer>
137				<key>keyword</key>
138				<string>genuuid4</string>
139				<key>queuedelaycustom</key>
140				<integer>3</integer>
141				<key>queuedelayimmediatelyinitially</key>
142				<true/>
143				<key>queuedelaymode</key>
144				<integer>1</integer>
145				<key>queuemode</key>
146				<integer>1</integer>
147				<key>runningsubtext</key>
148				<string>please wait ...</string>
149				<key>script</key>
150				<string>~/.local/bin/uvx --from "afwf-genpass==0.1.2" afwf-genpass genuuid4
151# ~/Documents/GitHub/afwf_genpass-project/.venv/bin/afwf-genpass genuuid4</string>
152				<key>scriptargtype</key>
153				<integer>0</integer>
154				<key>scriptfile</key>
155				<string></string>
156				<key>subtext</key>
157				<string>Generate Random UUID 4</string>
158				<key>title</key>
159				<string>genuuid4</string>
160				<key>type</key>
161				<integer>0</integer>
162				<key>withspace</key>
163				<false/>
164			</dict>
165			<key>type</key>
166			<string>alfred.workflow.input.scriptfilter</string>
167			<key>uid</key>
168			<string>7CF84DAD-33A9-408A-8DA3-107AF4FCC927</string>
169			<key>version</key>
170			<integer>3</integer>
171		</dict>
172	</array>
173	<key>readme</key>
174	<string>This workflow can generate secure password that:
175
176- length is between 8, 32 (you can define it)
177- has at least one lowercase letter
178- has at least one upper letter
179- has at least one digital letter
180- has at least one special character
181- avoid characters like ``1lIoO0`` that is hard to distinguish
182
183Dependencies:
184
185- OS Intel / Arm
186- Python3.7+</string>
187	<key>uidata</key>
188	<dict>
189		<key>7CF84DAD-33A9-408A-8DA3-107AF4FCC927</key>
190		<dict>
191			<key>xpos</key>
192			<real>40</real>
193			<key>ypos</key>
194			<real>240</real>
195		</dict>
196		<key>C9643FA2-6BC2-4020-A2D4-4099AF6D58DE</key>
197		<dict>
198			<key>xpos</key>
199			<real>40</real>
200			<key>ypos</key>
201			<real>30</real>
202		</dict>
203		<key>D5C6FAF4-8EC7-4F6E-842A-50587EDA22A9</key>
204		<dict>
205			<key>xpos</key>
206			<real>40</real>
207			<key>ypos</key>
208			<real>135</real>
209		</dict>
210	</dict>
211	<key>userconfigurationconfig</key>
212	<array/>
213	<key>variablesdontexport</key>
214	<array/>
215	<key>version</key>
216	<string>0.1.1</string>
217	<key>webaddress</key>
218	<string>https://github.com/MacHu-GWU/afwf_genpass-project</string>
219</dict>
220</plist>

End-user documentation — what each keyword does, allowed length ranges, default values, banned visually-confusing characters, and install instructions — lives in README.rst.

README.rst
 1.. image:: https://readthedocs.org/projects/afwf-genpass/badge/?version=latest
 2    :target: https://afwf-genpass.readthedocs.io/en/latest/
 3    :alt: Documentation Status
 4
 5.. image:: https://github.com/MacHu-GWU/afwf_genpass-project/actions/workflows/main.yml/badge.svg
 6    :target: https://github.com/MacHu-GWU/afwf_genpass-project/actions?query=workflow:CI
 7
 8.. image:: https://codecov.io/gh/MacHu-GWU/afwf_genpass-project/branch/main/graph/badge.svg
 9    :target: https://codecov.io/gh/MacHu-GWU/afwf_genpass-project
10
11.. image:: https://img.shields.io/pypi/v/afwf-genpass.svg
12    :target: https://pypi.python.org/pypi/afwf-genpass
13
14.. image:: https://img.shields.io/pypi/l/afwf-genpass.svg
15    :target: https://pypi.python.org/pypi/afwf-genpass
16
17.. image:: https://img.shields.io/pypi/pyversions/afwf-genpass.svg
18    :target: https://pypi.python.org/pypi/afwf-genpass
19
20.. image:: https://img.shields.io/badge/✍️_Release_History!--None.svg?style=social&logo=github
21    :target: https://github.com/MacHu-GWU/afwf_genpass-project/blob/main/release-history.rst
22
23.. image:: https://img.shields.io/badge/⭐_Star_me_on_GitHub!--None.svg?style=social&logo=github
24    :target: https://github.com/MacHu-GWU/afwf_genpass-project
25
26------
27
28.. image:: https://img.shields.io/badge/Link-API-blue.svg
29    :target: https://afwf-genpass.readthedocs.io/en/latest/py-modindex.html
30
31.. image:: https://img.shields.io/badge/Link-Install-blue.svg
32    :target: `Installation`_
33
34.. image:: https://img.shields.io/badge/Link-GitHub-blue.svg
35    :target: https://github.com/MacHu-GWU/afwf_genpass-project
36
37.. image:: https://img.shields.io/badge/Link-Submit_Issue-blue.svg
38    :target: https://github.com/MacHu-GWU/afwf_genpass-project/issues
39
40.. image:: https://img.shields.io/badge/Link-Request_Feature-blue.svg
41    :target: https://github.com/MacHu-GWU/afwf_genpass-project/issues
42
43.. image:: https://img.shields.io/badge/Link-Download-blue.svg
44    :target: https://pypi.org/pypi/afwf-genpass#files
45
46
47Welcome to ``afwf_genpass`` Documentation
48==============================================================================
49.. image:: https://afwf-genpass.readthedocs.io/en/latest/_static/afwf_genpass-logo.png
50    :target: https://afwf-genpass.readthedocs.io/en/latest/
51
52Use Case
53------------------------------------------------------------------------------
54This Alfred workflow exposes three independent Script Filters, each bound to its own keyword: ``genpass``, ``genid``, and ``genuuid4``.
55
56``genpass`` — Generate Secure Password
57------------------------------------------------------------------------------
58Type ``genpass <length>`` in Alfred to get 8 random passwords of the given ``<length>``. Each password is guaranteed to contain at least one lowercase letter, one uppercase letter, one digit and one symbol (from ``!%@#&^*``), and always starts with a letter.
59
60Allowed length is ``8`` to ``32``; default is ``12`` (just hit Enter on ``genpass``). Tab autocompletes to the default length. Hit ⌘C on any item to copy the password to your clipboard. Visually-confusing characters ``1``, ``l``, ``I``, ``O``, ``0`` are excluded for readability.
61
62``genid`` — Generate Short ID
63------------------------------------------------------------------------------
64Type ``genid <length>`` in Alfred to get 8 random YouTube-style short IDs of the given ``<length>``. Backed by ``secrets.choice`` (cryptographically strong) over a 57-character URL-safe charset, suitable for use as opaque identifiers in URLs, filenames, blog slugs, etc.
65
66Allowed length is ``6`` to ``32``; default is ``16`` (just hit Enter on ``genid``). Tab autocompletes to the default length. Hit ⌘C on any item to copy the ID to your clipboard. Visually-confusing characters ``0``, ``1``, ``l``, ``O``, ``o`` are excluded for readability.
67
68``genuuid4`` — Generate UUID4
69------------------------------------------------------------------------------
70Just type ``genuuid4`` in Alfred to get 8 freshly generated standard RFC 4122 UUID4s, formatted as ``8-4-4-4-12`` lowercase hex (e.g. ``550e8400-e29b-41d4-a716-446655440000``). No parameters — UUID4 has a fixed format. Hit ⌘C on any item to copy the UUID to your clipboard.
71
72For the length-based keywords (``genpass`` / ``genid``), if the value you type is not a valid integer in the allowed range, the workflow shows an inline error item instead of producing garbage results.
73
74Installation
75------------------------------------------------------------------------------
76Go to https://github.com/MacHu-GWU/afwf_genpass-project/releases, download the latest ``afwf-genpass-X.Y.Z.alfredworkflow`` file, double click to install.

Source package — afwf_genpass/

  • afwf_genpass.cli — the fire-based command-line entry point exposed as the afwf-genpass console script. Two flavours per generator:

    • gen* — Alfred Script Filter entry, emits JSON via afwf and routes uncaught errors to a rotating log file at ~/.alfred-afwf/afwf_genpass/error.log.

    • gen*-one — plain stdout, prints exactly one value. Independent of Alfred; handy in shell pipelines (e.g. export TOKEN=$(afwf-genpass genid-one)).

  • afwf_genpass.constants — single source of truth for all configuration knobs: character sets, banned characters, length bounds, default lengths, item-count constants, and the human-readable UI messages shown in Alfred. Change a default length or a banned character here and the rest of the codebase picks it up.

  • afwf_genpass.genpass — secure password generator. Detailed in Section 03.

  • afwf_genpass.genid — YouTube-style short-ID generator. Detailed in Section 04.

  • afwf_genpass.genuuid4 — UUID4 generator. Detailed in Section 05.

  • afwf_genpass.paths — centralized PathEnum of all project paths (project home, cache directory, error log, docs, virtualenv, etc.). All file paths used elsewhere in the codebase should be resolved through path_enum rather than hard-coded.

Tests — tests/

  • tests.test_genpass

  • tests.test_genid

  • tests.test_genuuid4

  • tests.test_cli

Pytest-based unit tests covering both the pure main() functions and the Command class in afwf_genpass.cli (including the _one stdout variants). Each file can be run standalone — the if __name__ == "__main__": block invokes pytest with coverage for the matching module.

Reading order

If you are new to the codebase, read in this order:

  1. README.rst — what the workflow does from a user’s perspective

  2. afwf_genpass.constants — every tunable parameter in the project

  3. afwf_genpass.genpass / afwf_genpass.genid / afwf_genpass.genuuid4 — the three generators

  4. afwf_genpass.cli — how the generators are exposed to Alfred and the shell

  5. info.plist — how Alfred binds keywords to CLI subcommands