atsfill 0.0.4.dev95__tar.gz → 0.0.4.dev98__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.4.dev95 → atsfill-0.0.4.dev98}/PKG-INFO +4 -2
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/README.md +1 -1
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/pyproject.toml +3 -1
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/pyproject.toml.orig +3 -1
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/core/browser.py +12 -16
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/core/paths.py +3 -3
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/LICENSE +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/__init__.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/__init__.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/ashby.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/bamboohr.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/breezy.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/dayforce.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/eightfold.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/greenhouse.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/hireology.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/hiringthing.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/jazzhr.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/lever.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/manatal.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/oracle.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/paycor.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/paylocity.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/personio.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/phenom.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/pinpoint.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/recruitee.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/rippling.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/smartrecruiters.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/teamtailor.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/workable.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/workday.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/wttj.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/adapters/zohorecruit.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/cli.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/core/__init__.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/core/accounts.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/core/adapter.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/core/attempts.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/core/commands.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/core/conditions.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/core/matching.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/core/passwords.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/core/registry.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/core/results.py +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/py.typed +0 -0
- {atsfill-0.0.4.dev95 → atsfill-0.0.4.dev98}/src/atsfill/registry.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: atsfill
|
|
3
|
-
Version: 0.0.4.
|
|
3
|
+
Version: 0.0.4.dev98
|
|
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
|
|
@@ -10,12 +10,14 @@ Classifier: Development Status :: 3 - Alpha
|
|
|
10
10
|
Classifier: Environment :: Console
|
|
11
11
|
Classifier: Intended Audience :: End Users/Desktop
|
|
12
12
|
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
13
14
|
Classifier: Operating System :: POSIX :: Linux
|
|
14
15
|
Classifier: Programming Language :: Python :: 3
|
|
15
16
|
Classifier: Programming Language :: Python :: 3.14
|
|
16
17
|
Classifier: Topic :: Office/Business
|
|
17
18
|
Classifier: Typing :: Typed
|
|
18
19
|
Requires-Dist: camoufox==0.5.8
|
|
20
|
+
Requires-Dist: filelock==4.1.1
|
|
19
21
|
Requires-Dist: keyring==25.7.0
|
|
20
22
|
Requires-Dist: packaging==26.3
|
|
21
23
|
Requires-Python: >=3.14
|
|
@@ -82,7 +84,7 @@ atsfill moves the quirks into one adapter per system and makes the check code: a
|
|
|
82
84
|
|
|
83
85
|
## Install
|
|
84
86
|
|
|
85
|
-
atsfill runs on Linux and
|
|
87
|
+
atsfill runs on Linux, macOS and Windows with Python 3.14, which `uvx` fetches if needed.
|
|
86
88
|
|
|
87
89
|
```sh
|
|
88
90
|
uvx atsfill install-browser
|
|
@@ -56,7 +56,7 @@ atsfill moves the quirks into one adapter per system and makes the check code: a
|
|
|
56
56
|
|
|
57
57
|
## Install
|
|
58
58
|
|
|
59
|
-
atsfill runs on Linux and
|
|
59
|
+
atsfill runs on Linux, macOS and Windows with Python 3.14, which `uvx` fetches if needed.
|
|
60
60
|
|
|
61
61
|
```sh
|
|
62
62
|
uvx atsfill install-browser
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "atsfill"
|
|
3
|
-
version = "0.0.4.
|
|
3
|
+
version = "0.0.4.dev98"
|
|
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"
|
|
@@ -20,6 +20,7 @@ classifiers = [
|
|
|
20
20
|
"Environment :: Console",
|
|
21
21
|
"Intended Audience :: End Users/Desktop",
|
|
22
22
|
"Operating System :: MacOS",
|
|
23
|
+
"Operating System :: Microsoft :: Windows",
|
|
23
24
|
"Operating System :: POSIX :: Linux",
|
|
24
25
|
"Programming Language :: Python :: 3",
|
|
25
26
|
"Programming Language :: Python :: 3.14",
|
|
@@ -28,6 +29,7 @@ classifiers = [
|
|
|
28
29
|
]
|
|
29
30
|
dependencies = [
|
|
30
31
|
"camoufox==0.5.8",
|
|
32
|
+
"filelock==4.1.1",
|
|
31
33
|
"keyring==25.7.0",
|
|
32
34
|
"packaging==26.3",
|
|
33
35
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "atsfill"
|
|
3
|
-
version = "0.0.4.
|
|
3
|
+
version = "0.0.4.dev98"
|
|
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"
|
|
@@ -13,6 +13,7 @@ classifiers = [
|
|
|
13
13
|
"Environment :: Console",
|
|
14
14
|
"Intended Audience :: End Users/Desktop",
|
|
15
15
|
"Operating System :: MacOS",
|
|
16
|
+
"Operating System :: Microsoft :: Windows",
|
|
16
17
|
"Operating System :: POSIX :: Linux",
|
|
17
18
|
"Programming Language :: Python :: 3",
|
|
18
19
|
"Programming Language :: Python :: 3.14",
|
|
@@ -21,6 +22,7 @@ classifiers = [
|
|
|
21
22
|
]
|
|
22
23
|
dependencies = [
|
|
23
24
|
"camoufox==0.5.8",
|
|
25
|
+
"filelock==4.1.1",
|
|
24
26
|
"keyring==25.7.0",
|
|
25
27
|
"packaging==26.3",
|
|
26
28
|
]
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""The browser launcher, the only module that imports camoufox and playwright (ADR 0002)."""
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
-
import fcntl
|
|
5
4
|
import json
|
|
6
5
|
import locale
|
|
7
6
|
import platform
|
|
@@ -24,6 +23,8 @@ from camoufox.exceptions import CamoufoxNotInstalled
|
|
|
24
23
|
from camoufox.fingerprints import Screen, generate_fingerprint
|
|
25
24
|
from camoufox.pkgman import installed_verstr
|
|
26
25
|
from camoufox.sync_api import Camoufox
|
|
26
|
+
from filelock import FileLock
|
|
27
|
+
from filelock import Timeout as LockTimeout
|
|
27
28
|
from playwright.sync_api import APIRequestContext as Request
|
|
28
29
|
from playwright.sync_api import Browser, Locator, Page, Response, sync_playwright
|
|
29
30
|
from playwright.sync_api import Error as BrowserError
|
|
@@ -107,8 +108,7 @@ def _build_blocker() -> None:
|
|
|
107
108
|
from disk: fetched by each launch, they would hold its first page for seconds, and each
|
|
108
109
|
list on is compiled by each launch before the blocker starts."""
|
|
109
110
|
ADDONS_DIR.mkdir(parents=True, exist_ok=True)
|
|
110
|
-
with (ADDONS_DIR / f"{BLOCKER.name}.lock")
|
|
111
|
-
fcntl.flock(f, fcntl.LOCK_EX)
|
|
111
|
+
with FileLock(ADDONS_DIR / f"{BLOCKER.name}.lock"):
|
|
112
112
|
build = BLOCKER.with_name(f"{BLOCKER.name}.build")
|
|
113
113
|
shutil.rmtree(build, ignore_errors=True)
|
|
114
114
|
shutil.copytree(get_addon_path(DefaultAddons.UBO.name), build)
|
|
@@ -171,19 +171,15 @@ def machine_locale() -> str | None:
|
|
|
171
171
|
@contextmanager
|
|
172
172
|
def lock(data_dir: Path, deadline: float) -> Generator[None]:
|
|
173
173
|
"""Holds the data directory; a second command waits here until its deadline."""
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
try:
|
|
184
|
-
yield
|
|
185
|
-
finally:
|
|
186
|
-
fcntl.flock(f, fcntl.LOCK_UN)
|
|
174
|
+
held = FileLock(data_dir / "lock", poll_interval=LOCK_POLL_S)
|
|
175
|
+
try:
|
|
176
|
+
held.acquire(timeout=max(0.0, deadline - time.monotonic()))
|
|
177
|
+
except LockTimeout:
|
|
178
|
+
raise OutOfTime("time budget ran out waiting for another command") from None
|
|
179
|
+
try:
|
|
180
|
+
yield
|
|
181
|
+
finally:
|
|
182
|
+
held.release()
|
|
187
183
|
|
|
188
184
|
|
|
189
185
|
@contextmanager
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import fcntl
|
|
2
1
|
import os
|
|
3
2
|
import platform
|
|
4
3
|
import re
|
|
5
4
|
import tomllib
|
|
6
5
|
from pathlib import Path
|
|
7
6
|
|
|
7
|
+
from filelock import FileLock
|
|
8
|
+
|
|
8
9
|
LINUX = platform.system() == "Linux"
|
|
9
10
|
DEFAULT_USER = "default"
|
|
10
11
|
TEST_USER = "test"
|
|
@@ -50,8 +51,7 @@ def _move_to_default(data: Path) -> None:
|
|
|
50
51
|
user, once, under the lock."""
|
|
51
52
|
if not any((data / name).exists() for name in MOVED):
|
|
52
53
|
return
|
|
53
|
-
with (data / "lock")
|
|
54
|
-
fcntl.flock(lock, fcntl.LOCK_EX)
|
|
54
|
+
with FileLock(data / "lock"):
|
|
55
55
|
default = data / "users" / DEFAULT_USER
|
|
56
56
|
default.mkdir(mode=0o700, parents=True, exist_ok=True)
|
|
57
57
|
for name in MOVED:
|
|
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
|