atsfill 0.0.5.dev187__tar.gz → 0.0.5.dev188__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/PKG-INFO +1 -1
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/pyproject.toml +1 -1
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/pyproject.toml.orig +1 -1
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/phenom.py +22 -2
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/paths.py +8 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/LICENSE +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/README.md +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/__init__.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/__init__.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/adp.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/adpmyjobs.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/ashby.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/bamboohr.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/breezy.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/dayforce.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/eightfold.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/greenhouse.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/gupy.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/hireology.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/hiringthing.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/hrmdirect.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/isolvedhire.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/jazzhr.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/jobaffinity.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/jobstreet.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/join.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/lever.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/manatal.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/oracle.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/paycor.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/paylocity.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/personio.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/pinpoint.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/recruitee.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/recruiterflow.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/rippling.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/smartrecruiters.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/successfactors.js +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/successfactors.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/taleo.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/teamtailor.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/ukg.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/welcomekit.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/workable.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/workatastartup.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/workday.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/wttj.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/adapters/zohorecruit.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/cli.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/__init__.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/accounts.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/adapter.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/attempts.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/browser.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/commands.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/conditions.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/html.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/matching.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/otp.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/passwords.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/registry.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/results.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/snapshot.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/core/telemetry.py +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/py.typed +0 -0
- {atsfill-0.0.5.dev187 → atsfill-0.0.5.dev188}/src/atsfill/registry.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: atsfill
|
|
3
|
-
Version: 0.0.5.
|
|
3
|
+
Version: 0.0.5.dev188
|
|
4
4
|
Summary: Read, dry-run and submit job application forms on hiring systems: Ashby, Greenhouse, Teamtailor, Welcome to the Jungle.
|
|
5
5
|
Keywords: job-applications,ats,ashby,greenhouse,teamtailor,ai-agents,cli
|
|
6
6
|
Author: shbernal
|
|
@@ -8,6 +8,7 @@ fields, dependent lists): a request read or a browser read interprets them witho
|
|
|
8
8
|
step. Filling walks the wizard on a fresh session, each step's answers read back before Next.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
+
import hashlib
|
|
11
12
|
import http.cookiejar
|
|
12
13
|
import json
|
|
13
14
|
import re
|
|
@@ -23,7 +24,7 @@ from pathlib import PurePath
|
|
|
23
24
|
from typing import Any
|
|
24
25
|
from urllib.parse import parse_qs, urlsplit
|
|
25
26
|
|
|
26
|
-
from atsfill.core import browser, matching
|
|
27
|
+
from atsfill.core import browser, matching, paths
|
|
27
28
|
from atsfill.core.adapter import Gap, NotTaken, Unsupported, known_gap
|
|
28
29
|
from atsfill.core.browser import HTTP_TIMEOUT_S, BrowserError, Locator, Overlaid, Page, Timeout
|
|
29
30
|
from atsfill.core.results import (
|
|
@@ -67,6 +68,7 @@ PICK_TRIES = 3
|
|
|
67
68
|
MAX_STEPS = 12
|
|
68
69
|
OPTIONS_TIMEOUT_S = 8
|
|
69
70
|
LOADERS_AT_ONCE = 8 # a loader request a country: 245 on one site
|
|
71
|
+
COUNTRIES_KEPT_S = 24 * 3600 # a site's country fields, kept between reads
|
|
70
72
|
YES_NO = ["Yes", "No"]
|
|
71
73
|
NO_YES = ["No", "Yes"]
|
|
72
74
|
MONTH = " (MM/YYYY)"
|
|
@@ -1005,7 +1007,7 @@ class _Config:
|
|
|
1005
1007
|
values, texts = self.listed.get(path) or ([], [])
|
|
1006
1008
|
held, _ = self.prefilled(path)
|
|
1007
1009
|
codes = sorted(values, key=lambda c: c != held)
|
|
1008
|
-
parts = self.
|
|
1010
|
+
parts = self.country_parts(payload, codes)
|
|
1009
1011
|
by_id: dict[str, dict[Any, dict[str, Any]]] = {}
|
|
1010
1012
|
for code, part in zip(codes, parts, strict=True):
|
|
1011
1013
|
part = get(part, "applyGetReferences.data")
|
|
@@ -1017,6 +1019,24 @@ class _Config:
|
|
|
1017
1019
|
shown = dict(zip(values, texts, strict=False))
|
|
1018
1020
|
return [_by_country(path, rows, codes, shown) for rows in by_id.values()]
|
|
1019
1021
|
|
|
1022
|
+
def country_parts(self, payload: str, codes: list[Any]) -> list[Any]:
|
|
1023
|
+
"""Each country's loader answer, kept a day for the site: a read posts one a country,
|
|
1024
|
+
and two reads in a row get `/applySubmit` refused (403) on one site."""
|
|
1025
|
+
key = hashlib.sha1(f"{self.ph.get('locale')} {payload}".encode()).hexdigest()[:12]
|
|
1026
|
+
path = paths.cache_dir() / "phenom" / f"{self.ph.get('refNum')}-{key}.json"
|
|
1027
|
+
kept: dict[str, Any] = {}
|
|
1028
|
+
with suppress(OSError, ValueError):
|
|
1029
|
+
if time.time() - path.stat().st_mtime < COUNTRIES_KEPT_S:
|
|
1030
|
+
kept = json.loads(path.read_text())
|
|
1031
|
+
missing = [c for c in codes if str(c) not in kept]
|
|
1032
|
+
if missing:
|
|
1033
|
+
parts = self.calls(payload, [{"countryCode": c} for c in missing])
|
|
1034
|
+
kept |= {str(c): p for c, p in zip(missing, parts, strict=True) if p is not None}
|
|
1035
|
+
with suppress(OSError):
|
|
1036
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
1037
|
+
path.write_text(json.dumps(kept))
|
|
1038
|
+
return [kept.get(str(c)) for c in codes]
|
|
1039
|
+
|
|
1020
1040
|
def date_range(
|
|
1021
1041
|
self, p: dict, u: dict, path: str, nav: Any, when: Condition | None
|
|
1022
1042
|
) -> list[dict[str, Any]]:
|
|
@@ -60,6 +60,14 @@ def _move_to_default(data: Path) -> None:
|
|
|
60
60
|
(data / name).rename(default / name)
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
def cache_dir() -> Path:
|
|
64
|
+
"""Public data atsfill can fetch again, kept to spare a hiring system the requests:
|
|
65
|
+
`$XDG_CACHE_HOME/atsfill` on Linux (`~/.cache/atsfill`), `~/.atsfill/cache` elsewhere."""
|
|
66
|
+
if xdg := os.environ.get("XDG_CACHE_HOME"):
|
|
67
|
+
return Path(xdg) / "atsfill"
|
|
68
|
+
return Path.home() / (".cache/atsfill" if LINUX else ".atsfill/cache")
|
|
69
|
+
|
|
70
|
+
|
|
63
71
|
def config_file() -> Path:
|
|
64
72
|
if xdg := os.environ.get("XDG_CONFIG_HOME"):
|
|
65
73
|
return Path(xdg) / "atsfill/config.toml"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|