hired.persistence.base#
Canonical data root, filesystem codecs, and the two-level candidate layout.
The canonical root is resolved by app_data_dir(), honoring (in order):
the
HIRED_DATA_DIRenvironment variable (used by tests and power users),$XDG_DATA_HOME/hired(the XDG Base Directory spec),~/.local/share/hired(the XDG default).
Storage v2 — two-level layout. Per-candidate data is split into *what is true about the candidate* (cross-JD, reusable) and work on a specific company’s role(s):
users/<user>/
user/ # the candidate — single source of truth
raw/ # raw sources the user provided (bytes; real filenames)
info/ # agent-maintained, operable knowledge (agent CRUDs here)
facts/ <id>.json
qa/ <id>.json
topics/ <topic>/... # per-subject dossiers (Phase 2)
synopsis.md # regenerated overview (singleton)
state.json # refresh bookkeeping (Phase 3)
jds/<jd_id>/ # one engagement = 1+ related JDs of the same company
meta.json
jobs/ reports/ report_history/ company/ interview_prep/ (<key>.json)
Codecs (the extension fix). Keys stay domain-oriented and extension-less on the
MutableMapping facade; file extensions live only on the filesystem side, applied by
dol key codecs, and values are dicts in Python / JSON on disk via value codecs:
json_store()—JsonFiles+ a.jsonkey codec: bare-id keys,<id>.jsonfiles, dict values.markdown_store()—TextFiles+ a.mdkey codec: bare keys,<key>.mdfiles,strvalues.bytes_store()—dol.Files: keys are real filenames (extension kept, as the extension is the meaningful domain key for an upload likecv.pdf).
The key codec uses only dol’s core wrap_kvs (not affix_key_codec/filt_iter,
which has a Windows-specific bug in dol 0.3.x) and normalizes path separators, so stores
behave identically on POSIX and Windows.
UserStore groups the user-level stores; JDStore groups one engagement’s
stores. Singletons (synopsis.md, state.json, meta.json) are single files —
their accessors carry the extension in the path, never in a store key.
Module Attributes
A store of JSON-able values (dicts in Python, JSON on disk), keyed by bare ids. |
|
A store of |
|
A store of raw |
Functions
|
Return the canonical hired data directory, joined with |
|
A |
|
A |
|
Engagement ids under |
|
A |
|
One-time copy of a legacy store into the canonical root. |
|
Read a JSON file, or return |
|
Read a text file, or return |
|
Filesystem base for a candidate: |
|
Write |
|
Write |
Classes
|
Per-engagement storage under |
|
Per-candidate cross-JD storage: raw sources + agent-maintained |
- hired.persistence.base.BytesStore#
A store of raw
bytes, keyed by real filenames.alias of
MutableMapping[str,bytes]
- class hired.persistence.base.JDStore(user, jd_id, *, root=None)[source]#
Bases:
objectPer-engagement storage under
users/<user>/jds/<jd_id>/.An engagement is one or a group of related JDs of the same company; it holds the parsed jobs, alignment reports (+ archived history), company research, and interview-prep briefings for that company’s role(s).
>>> import tempfile, os >>> os.environ['HIRED_DATA_DIR'] = tempfile.mkdtemp() >>> jd = JDStore('me', 'acme') >>> jd.reports['role-1'] = {'verdict': {'recommendation': 'apply'}} >>> jd.reports['role-1']['verdict']['recommendation'] 'apply' >>> jd.write_meta({'company': 'Acme'}) >>> jd.read_meta()['company'] 'Acme'
- hired.persistence.base.JsonStore#
A store of JSON-able values (dicts in Python, JSON on disk), keyed by bare ids.
alias of
MutableMapping[str,Any]
- hired.persistence.base.TextStore#
A store of
strvalues (e.g. markdown files), keyed by bare names.alias of
MutableMapping[str,str]
- class hired.persistence.base.UserStore(user='me', *, root=None)[source]#
Bases:
objectPer-candidate cross-JD storage: raw sources + agent-maintained
info.rawis a bytes store;factsandqaare json stores;synopsisis a single markdown file accessed viaread_synopsis()/write_synopsis().>>> import tempfile, os >>> os.environ['HIRED_DATA_DIR'] = tempfile.mkdtemp() >>> us = UserStore() # default user "me" >>> us.facts['f1'] = {'statement': 'knows Python'} >>> us.facts['f1'] {'statement': 'knows Python'} >>> us.raw['cv.pdf'] = b'%PDF-1.4' >>> us.raw['cv.pdf'] b'%PDF-1.4' >>> us.write_synopsis('# me') >>> us.read_synopsis() '# me'
- hired.persistence.base.app_data_dir(*subpaths, make=True)[source]#
Return the canonical hired data directory, joined with
subpaths.The directory is created when
makeis true (the default).- Return type:
>>> import os, tempfile >>> os.environ['HIRED_DATA_DIR'] = tempfile.mkdtemp() >>> root = app_data_dir() >>> os.path.isdir(root) True >>> app_data_dir('users', 'me').endswith(os.path.join('users', 'me')) True
- hired.persistence.base.bytes_store(rootdir)[source]#
A
MutableMappingof rawbytes; keys are real filenames (extension kept).- Return type:
- hired.persistence.base.json_store(rootdir)[source]#
A
MutableMappingof JSON-able values: bare-id keys,<id>.jsonfiles.Built on
JsonFiles(dict↔JSON value codec) + a.jsonkey codec. Missing intermediate directories are created on write, so nested keys (e.g."job/stamp") work transparently.- Return type:
- hired.persistence.base.list_jds(user='me', *, root=None)[source]#
Engagement ids under
users/<user>/jds/(sorted; empty if none).
- hired.persistence.base.markdown_store(rootdir)[source]#
A
MutableMappingofstrvalues: bare keys,<key>.mdfiles.- Return type:
- hired.persistence.base.migrate_legacy(legacy_path, target_path)[source]#
One-time copy of a legacy store into the canonical root.
If
target_pathdoes not yet exist butlegacy_pathdoes, copy it (file or directory) so historical data is preserved when storage roots are unified. No-op otherwise. Returns True iff a copy happened.- Return type:
- hired.persistence.base.read_json_file(path)[source]#
Read a JSON file, or return
Noneif it does not exist.- Return type:
- hired.persistence.base.read_text_file(path)[source]#
Read a text file, or return
Noneif it does not exist.
- hired.persistence.base.user_base(user='me', *, root=None)[source]#
Filesystem base for a candidate:
<root>or<data>/users/<user>.- Return type: