initial commit
This commit is contained in:
93
readme.md
Normal file
93
readme.md
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
build a small python cli tool called `usajobs.py` for exploring usajobs results.
|
||||||
|
|
||||||
|
goal:
|
||||||
|
- query the official usajobs api
|
||||||
|
- apply strict local filters
|
||||||
|
- show results in a readable terminal table
|
||||||
|
- let me select rows to export into an org-mode file
|
||||||
|
|
||||||
|
stack:
|
||||||
|
- python 3.11+
|
||||||
|
- click for cli args
|
||||||
|
- requests for api
|
||||||
|
- rich for table + row selection prompt
|
||||||
|
- pathlib/json/csv stdlib only otherwise
|
||||||
|
|
||||||
|
env vars:
|
||||||
|
- USAJOBS_EMAIL
|
||||||
|
- USAJOBS_KEY
|
||||||
|
|
||||||
|
basic command:
|
||||||
|
`python jobs.py search --location "Washington, DC" --radius 25 --salary-min 150 --grade-min 15 --grade-max 15 --series 2210 --series 0340 --clearance 3 --clearance 4`
|
||||||
|
|
||||||
|
option behavior:
|
||||||
|
- --radius 25 means 25 miles
|
||||||
|
- --salary-min 150 means $150,000
|
||||||
|
- --grade-min/--grade-max filter locally against low/high grade
|
||||||
|
- --series may repeat; pass to api as semicolon list
|
||||||
|
- --clearance may repeat; pass to api as semicolon list
|
||||||
|
- --pay-plan may repeat, default gs and gg
|
||||||
|
- --limit defaults 100
|
||||||
|
- --out defaults jobs.org
|
||||||
|
- --cache-dir defaults .cache/usajobs
|
||||||
|
|
||||||
|
search behavior:
|
||||||
|
1. call https://data.usajobs.gov/api/search using official headers:
|
||||||
|
host: data.usajobs.gov
|
||||||
|
user-agent: $USAJOBS_EMAIL
|
||||||
|
authorization-key: $USAJOBS_KEY
|
||||||
|
2. request fields=full, resultsperpage=500, sortfield=opendate, sortdirection=desc
|
||||||
|
3. cache raw json response per query/page under .cache/usajobs
|
||||||
|
4. apply local filters after fetching:
|
||||||
|
- pay plan in allowed pay plans
|
||||||
|
- low_grade >= grade_min
|
||||||
|
- high_grade <= grade_max
|
||||||
|
- salary max >= salary_min, or salary min >= salary_min if max absent
|
||||||
|
- location string contains/near requested location as available
|
||||||
|
5. output table with columns:
|
||||||
|
idx, title, agency, grade, salary, location, close date, clearance match, url
|
||||||
|
6. selection/export:
|
||||||
|
- after displaying table, allow user to arrow/highlight and mark for export
|
||||||
|
- pick sensible defaults, eg x or m for mark, u for unmark, a for all, e for export
|
||||||
|
- export selected jobs to new file with short slug name + datetime stamp
|
||||||
|
- org output format:
|
||||||
|
```
|
||||||
|
** <shortened job title> [[url][link]]
|
||||||
|
:properties:
|
||||||
|
:agency: <agency>
|
||||||
|
:grade: <pay plan> <low>-<high>
|
||||||
|
:close_date: <date>
|
||||||
|
:end:
|
||||||
|
|
||||||
|
salary: <salary range>
|
||||||
|
location: <location>
|
||||||
|
travel: <travel percentage or unknown>
|
||||||
|
clearance: <clearance/security text or unknown>
|
||||||
|
|
||||||
|
*** posting
|
||||||
|
<raw posting text>
|
||||||
|
```
|
||||||
|
7. (stretch) Cache each query, allow arrow/scroll through them like a cli, recall, or save filters. could be too much.
|
||||||
|
|
||||||
|
implementation notes:
|
||||||
|
- write clean functional code:
|
||||||
|
- build_params()
|
||||||
|
- fetch_page()
|
||||||
|
- fetch_all()
|
||||||
|
- normalize_job()
|
||||||
|
- passes_filters()
|
||||||
|
- render_table()
|
||||||
|
- parse_selection()
|
||||||
|
- export_org()
|
||||||
|
- normalize both official api shape and frontend-ish shape if present:
|
||||||
|
- api jobs may use MatchedObjectDescriptor
|
||||||
|
- details may be under UserArea.Details
|
||||||
|
- raw posting text should combine title, summary, duties, requirements, qualifications, evaluations, other info, key requirements.
|
||||||
|
- shortened job title should be max 80 chars, strip all-caps screaming where reasonable, preserve meaning.
|
||||||
|
- include helpful errors if env vars missing.
|
||||||
|
- include a --offline flag that only reads cached json and does not call api.
|
||||||
|
- include a --debug flag that prints api params and counts before/after filtering.
|
||||||
|
|
||||||
|
acceptance test:
|
||||||
|
- running the command with `--salary-min 150 --grade-min 15 --grade-max 15 --radius 25` should not show gs/gg-13 jobs after local filtering.
|
||||||
|
- selecting `none` exits without writing.
|
||||||
Reference in New Issue
Block a user