atsfill 0.0.7.dev211__tar.gz → 0.0.7.dev212__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.7.dev211 → atsfill-0.0.7.dev212}/PKG-INFO +2 -2
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/pyproject.toml +2 -2
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/pyproject.toml.orig +2 -2
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/browser.py +12 -20
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/LICENSE +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/README.md +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/__init__.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/__init__.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/adp.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/adpmyjobs.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/ashby.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/bamboohr.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/breezy.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/dayforce.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/eightfold.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/greenhouse.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/gupy.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/hireology.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/hiringthing.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/hrmdirect.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/isolvedhire.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/jazzhr.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/jobaffinity.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/jobstreet.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/join.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/lever.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/manatal.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/oracle.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/paycor.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/paylocity.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/personio.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/phenom.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/pinpoint.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/recruitee.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/recruiterflow.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/rippling.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/smartrecruiters.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/successfactors.js +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/successfactors.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/taleo.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/teamtailor.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/ukg.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/welcomekit.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/wellfound.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/werecruit.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/workable.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/workatastartup.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/workday.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/wttj.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/adapters/zohorecruit.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/cli.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/__init__.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/accounts.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/adapter.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/attempts.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/commands.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/conditions.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/countries.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/html.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/matching.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/otp.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/passwords.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/paths.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/registry.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/results.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/snapshot.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/core/telemetry.py +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/py.typed +0 -0
- {atsfill-0.0.7.dev211 → atsfill-0.0.7.dev212}/src/atsfill/registry.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: atsfill
|
|
3
|
-
Version: 0.0.7.
|
|
3
|
+
Version: 0.0.7.dev212
|
|
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
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.14
|
|
17
17
|
Classifier: Topic :: Office/Business
|
|
18
18
|
Classifier: Typing :: Typed
|
|
19
|
-
Requires-Dist: camoufox==0.5.
|
|
19
|
+
Requires-Dist: camoufox==0.5.9b6
|
|
20
20
|
Requires-Dist: filelock==4.1.1
|
|
21
21
|
Requires-Dist: keyring==25.7.0
|
|
22
22
|
Requires-Dist: packaging==26.3
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "atsfill"
|
|
3
|
-
version = "0.0.7.
|
|
3
|
+
version = "0.0.7.dev212"
|
|
4
4
|
description = "Read, dry-run and submit job application forms on hiring systems: Ashby, Greenhouse, Teamtailor, Welcome to the Jungle."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -28,7 +28,7 @@ classifiers = [
|
|
|
28
28
|
"Typing :: Typed",
|
|
29
29
|
]
|
|
30
30
|
dependencies = [
|
|
31
|
-
"camoufox==0.5.
|
|
31
|
+
"camoufox==0.5.9b6",
|
|
32
32
|
"filelock==4.1.1",
|
|
33
33
|
"keyring==25.7.0",
|
|
34
34
|
"packaging==26.3",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "atsfill"
|
|
3
|
-
version = "0.0.7.
|
|
3
|
+
version = "0.0.7.dev212"
|
|
4
4
|
description = "Read, dry-run and submit job application forms on hiring systems: Ashby, Greenhouse, Teamtailor, Welcome to the Jungle."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -21,7 +21,7 @@ classifiers = [
|
|
|
21
21
|
"Typing :: Typed",
|
|
22
22
|
]
|
|
23
23
|
dependencies = [
|
|
24
|
-
"camoufox==0.5.
|
|
24
|
+
"camoufox==0.5.9b6",
|
|
25
25
|
"filelock==4.1.1",
|
|
26
26
|
"keyring==25.7.0",
|
|
27
27
|
"packaging==26.3",
|
|
@@ -18,10 +18,10 @@ from urllib.parse import urljoin
|
|
|
18
18
|
from urllib.request import Request as HttpRequest
|
|
19
19
|
from urllib.request import urlopen
|
|
20
20
|
|
|
21
|
-
from camoufox.addons import
|
|
21
|
+
from camoufox.addons import DefaultAddons, get_addon_path
|
|
22
22
|
from camoufox.exceptions import CamoufoxNotInstalled
|
|
23
23
|
from camoufox.fingerprints import Screen, generate_fingerprint
|
|
24
|
-
from camoufox.pkgman import installed_verstr
|
|
24
|
+
from camoufox.pkgman import INSTALL_DIR, installed_verstr, launch_path
|
|
25
25
|
from camoufox.sync_api import Camoufox
|
|
26
26
|
from filelock import FileLock
|
|
27
27
|
from filelock import Timeout as LockTimeout
|
|
@@ -58,11 +58,9 @@ BUDGET = 180.0 # seconds per command, lock wait included
|
|
|
58
58
|
PROFILE_BUDGET = 300.0 # seconds for a `profile` run, which may save every profile step
|
|
59
59
|
LOCK_POLL_S = 0.1
|
|
60
60
|
HTTP_TIMEOUT_S = 20 # per request to a hiring system's API
|
|
61
|
-
BUILD = "
|
|
62
|
-
BLOCKER =
|
|
61
|
+
BUILD = "158.0.1-beta.41" # the Camoufox browser build, pinned so results compare across machines
|
|
62
|
+
BLOCKER = INSTALL_DIR / "atsfill" / f"UBO-{BUILD}" # the build's uBlock Origin, annoyance lists on
|
|
63
63
|
BLOCKER_LISTS = "annoyances" # the group of uBlock Origin lists: cookie banners, pop-ups, widgets
|
|
64
|
-
# On, its first update, 37s into a launch, leaves the blocker hiding nothing for the rest of it.
|
|
65
|
-
BLOCKER_AUTO_UPDATE = "autoUpdate: true,"
|
|
66
64
|
# The adapters' filters for the banners the lists miss: a list of the blocker's, on like them.
|
|
67
65
|
FILTERS = "assets/atsfill/filters.txt"
|
|
68
66
|
INCLUDE = re.compile(r"^!#include (\S+)$", re.M)
|
|
@@ -90,14 +88,13 @@ def version() -> str:
|
|
|
90
88
|
|
|
91
89
|
|
|
92
90
|
def install() -> int:
|
|
93
|
-
"""Fetches the pinned browser build unless it is installed, then the
|
|
94
|
-
loads, so that browsers started side by side do not each
|
|
91
|
+
"""Fetches the pinned browser build unless it is installed, then builds the blocker every
|
|
92
|
+
launch loads, so that browsers started side by side do not each build it."""
|
|
95
93
|
if version() != BUILD:
|
|
96
|
-
subprocess.call([sys.executable, "-m", "camoufox", "fetch"
|
|
94
|
+
subprocess.call([sys.executable, "-m", "camoufox", "fetch"]) # the package's paired build
|
|
97
95
|
if version() != BUILD: # `camoufox fetch` exits 0 when it fails
|
|
98
96
|
print(f"the Camoufox build {BUILD} is not installed", file=sys.stderr)
|
|
99
97
|
return 1
|
|
100
|
-
maybe_download_addons(list(DefaultAddons))
|
|
101
98
|
try:
|
|
102
99
|
_build_blocker()
|
|
103
100
|
except OSError as e:
|
|
@@ -109,13 +106,13 @@ def install() -> int:
|
|
|
109
106
|
def _build_blocker() -> None:
|
|
110
107
|
"""Copies Camoufox's uBlock Origin to `BLOCKER` with only its annoyance lists on, read
|
|
111
108
|
from disk: fetched by each launch, they would hold its first page for seconds, and each
|
|
112
|
-
list on is compiled by each launch before the blocker starts.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
with FileLock(
|
|
109
|
+
list on is compiled by each launch before the blocker starts. Camoufox's policy keeps it
|
|
110
|
+
from updating them: its first update, 37s into a launch, left it hiding nothing."""
|
|
111
|
+
BLOCKER.parent.mkdir(parents=True, exist_ok=True)
|
|
112
|
+
with FileLock(BLOCKER.with_name(f"{BLOCKER.name}.lock")):
|
|
116
113
|
build = BLOCKER.with_name(f"{BLOCKER.name}.build")
|
|
117
114
|
shutil.rmtree(build, ignore_errors=True)
|
|
118
|
-
shutil.copytree(get_addon_path(DefaultAddons.UBO.name), build)
|
|
115
|
+
shutil.copytree(get_addon_path(DefaultAddons.UBO.name, launch_path()), build)
|
|
119
116
|
assets = build / "assets" / "assets.json"
|
|
120
117
|
entries = json.loads(assets.read_text())
|
|
121
118
|
for key, entry in entries.items():
|
|
@@ -135,10 +132,6 @@ def _build_blocker() -> None:
|
|
|
135
132
|
(build / FILTERS).parent.mkdir()
|
|
136
133
|
(build / FILTERS).touch()
|
|
137
134
|
assets.write_text(json.dumps(entries))
|
|
138
|
-
settings = build / "js" / "background.js"
|
|
139
|
-
defaults = settings.read_text()
|
|
140
|
-
assert BLOCKER_AUTO_UPDATE in defaults # gone from a new uBlock Origin: find its new form
|
|
141
|
-
settings.write_text(defaults.replace(BLOCKER_AUTO_UPDATE, "autoUpdate: false,"))
|
|
142
135
|
shutil.rmtree(BLOCKER, ignore_errors=True)
|
|
143
136
|
build.rename(BLOCKER)
|
|
144
137
|
|
|
@@ -193,7 +186,6 @@ def lock(data_dir: Path, deadline: float) -> Generator[None]:
|
|
|
193
186
|
@contextmanager
|
|
194
187
|
def _launch(data_dir: Path, headless: bool) -> Generator[Browser]:
|
|
195
188
|
if not (BLOCKER / FILTERS).exists(): # installed before the blocker, or its filters, were
|
|
196
|
-
maybe_download_addons(list(DefaultAddons))
|
|
197
189
|
_build_blocker()
|
|
198
190
|
_write_filters()
|
|
199
191
|
with Camoufox(
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|