generated from coulomb/repo-seed
Deliverables: - src/local_identity/gecos.py: /etc/passwd GECOS parsing, current_username() - src/local_identity/user.py: UserRecord dataclass, ProductionIdentity, make_test_user() - Pure test-user derivation: <user>N / +testN email alias / source_user tracking - src/local_identity/store.py: file store CRUD backed by LOCAL_IDENTITY_HOME - ~/.local-identity/ mode 700, user files mode 600 - All path lookups dynamic (env-var override enables clean test isolation) - src/local_identity/cli.py: init/list/show commands; email from flag > config > prompt - pyproject.toml + uv.lock: pyyaml dep, local-identity script entry point Tests (41 passing): - test_gecos.py: 9 tests — simple/comma/empty/non-ASCII/whitespace GECOS, fallback - test_user.py: 14 tests — test-user derivation, YAML roundtrip, non-ASCII, idempotency - test_store.py: 18 tests — dir creation, permissions (700/600), CRUD, list, config, idempotency (reinit with --force produces identical users) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
35 lines
921 B
Python
35 lines
921 B
Python
"""
|
|
Parse the operator's Linux identity from /etc/passwd and the environment.
|
|
|
|
GECOS format: "Full Name,Room Number,Work Phone,Home Phone,Other"
|
|
We only need the first field (full name).
|
|
"""
|
|
|
|
import os
|
|
import pwd
|
|
|
|
|
|
def current_username() -> str:
|
|
"""Return the current Linux username."""
|
|
return (
|
|
os.environ.get("USER")
|
|
or os.environ.get("LOGNAME")
|
|
or pwd.getpwuid(os.getuid()).pw_name
|
|
)
|
|
|
|
|
|
def get_gecos_fullname(username: str) -> str:
|
|
"""
|
|
Extract the full name from /etc/passwd GECOS for the given username.
|
|
Falls back to the username itself if GECOS is absent or unparseable.
|
|
"""
|
|
try:
|
|
entry = pwd.getpwnam(username)
|
|
# GECOS may be "Full Name,room,work,home,other" — take the first field
|
|
fullname = entry.pw_gecos.split(",")[0].strip()
|
|
if fullname:
|
|
return fullname
|
|
except KeyError:
|
|
pass
|
|
return username
|