atsfill 0.0.4.dev66__tar.gz → 0.0.4.dev68__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.dev66 → atsfill-0.0.4.dev68}/PKG-INFO +1 -1
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/pyproject.toml +1 -1
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/pyproject.toml.orig +1 -1
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/workable.py +9 -5
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/LICENSE +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/README.md +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/__init__.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/__init__.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/ashby.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/bamboohr.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/breezy.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/dayforce.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/greenhouse.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/hireology.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/jazzhr.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/lever.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/manatal.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/oracle.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/paycor.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/paylocity.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/phenom.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/recruitee.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/smartrecruiters.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/teamtailor.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/adapters/wttj.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/cli.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/core/__init__.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/core/accounts.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/core/adapter.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/core/attempts.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/core/browser.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/core/commands.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/core/matching.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/core/paths.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/core/registry.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/core/results.py +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/src/atsfill/py.typed +0 -0
- {atsfill-0.0.4.dev66 → atsfill-0.0.4.dev68}/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.dev68
|
|
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
|
|
@@ -25,6 +25,7 @@ API = "https://apply.workable.com/api/v1/jobs/{code}/form"
|
|
|
25
25
|
APPLIED = re.compile(r"/api/v1/jobs/[0-9A-F]{10}/apply$")
|
|
26
26
|
FORM = "form[data-ui=application-form]"
|
|
27
27
|
COOKIES = "[data-ui=cookie-consent-decline]"
|
|
28
|
+
UPLOADED = "[data-action=delete]" # an uploading file shows its name and an abort button
|
|
28
29
|
FORM_TIMEOUT_MS = 30_000
|
|
29
30
|
COOKIE_TIMEOUT_MS = 5_000
|
|
30
31
|
OPTIONS_TIMEOUT_MS = 5_000
|
|
@@ -101,7 +102,7 @@ _READ = """form => {
|
|
|
101
102
|
return found;
|
|
102
103
|
}"""
|
|
103
104
|
|
|
104
|
-
# What each field shows: a choice its checked option's label, a file its
|
|
105
|
+
# What each field shows: a choice its checked option's label, a file its uploaded name (a photo
|
|
105
106
|
# its preview's alt), the phone its country's dial code then its number.
|
|
106
107
|
_READ_BACK = """(form, kinds) => {
|
|
107
108
|
const text = el => el ? el.textContent.replace(/\\s+/g, " ").trim() : null;
|
|
@@ -114,7 +115,9 @@ _READ_BACK = """(form, kinds) => {
|
|
|
114
115
|
if (kind === "file") {
|
|
115
116
|
const zone = el.closest("[data-role=dropzone]");
|
|
116
117
|
const preview = zone?.querySelector("[data-role=preview] img"); // a photo, named by its alt
|
|
117
|
-
|
|
118
|
+
const uploaded = zone?.querySelector("[data-action=delete]"); // not while it uploads
|
|
119
|
+
out[id] = !uploaded ? null
|
|
120
|
+
: preview ? preview.alt : text(zone.querySelector("[data-id=filename]"));
|
|
118
121
|
} else if (kind === "phone") {
|
|
119
122
|
const dial = (el.querySelector("button[aria-label]")?.getAttribute("aria-label") || "")
|
|
120
123
|
.match(/\\((\\+\\d+)\\)/);
|
|
@@ -201,13 +204,14 @@ class Workable:
|
|
|
201
204
|
field.set_input_files(values[0])
|
|
202
205
|
zone = field.locator("xpath=ancestor::*[@data-role='dropzone']")
|
|
203
206
|
crop = page.locator("button[data-ui=crop-image]")
|
|
207
|
+
# attaching another file while one uploads empties it, so each waits
|
|
208
|
+
uploaded = zone.locator(UPLOADED)
|
|
204
209
|
with suppress(Timeout):
|
|
205
|
-
|
|
206
|
-
timeout=UPLOAD_TIMEOUT_MS
|
|
207
|
-
)
|
|
210
|
+
uploaded.or_(crop).first.wait_for(timeout=UPLOAD_TIMEOUT_MS)
|
|
208
211
|
if crop.is_visible():
|
|
209
212
|
crop.click()
|
|
210
213
|
crop.wait_for(state="hidden", timeout=UPLOAD_TIMEOUT_MS)
|
|
214
|
+
uploaded.wait_for(timeout=UPLOAD_TIMEOUT_MS)
|
|
211
215
|
case "phone": # the number's dial code picks the country
|
|
212
216
|
number = field.locator("input[type=tel]")
|
|
213
217
|
number.fill("")
|
|
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
|