atsfill 0.0.4.dev87__tar.gz → 0.0.4.dev88__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.
Files changed (45) hide show
  1. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/PKG-INFO +1 -1
  2. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/pyproject.toml +1 -1
  3. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/pyproject.toml.orig +1 -1
  4. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/oracle.py +10 -10
  5. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/LICENSE +0 -0
  6. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/README.md +0 -0
  7. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/__init__.py +0 -0
  8. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/__init__.py +0 -0
  9. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/ashby.py +0 -0
  10. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/bamboohr.py +0 -0
  11. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/breezy.py +0 -0
  12. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/dayforce.py +0 -0
  13. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/eightfold.py +0 -0
  14. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/greenhouse.py +0 -0
  15. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/hireology.py +0 -0
  16. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/hiringthing.py +0 -0
  17. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/jazzhr.py +0 -0
  18. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/lever.py +0 -0
  19. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/manatal.py +0 -0
  20. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/paycor.py +0 -0
  21. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/paylocity.py +0 -0
  22. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/personio.py +0 -0
  23. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/phenom.py +0 -0
  24. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/pinpoint.py +0 -0
  25. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/recruitee.py +0 -0
  26. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/rippling.py +0 -0
  27. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/smartrecruiters.py +0 -0
  28. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/teamtailor.py +0 -0
  29. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/workable.py +0 -0
  30. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/wttj.py +0 -0
  31. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/adapters/zohorecruit.py +0 -0
  32. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/cli.py +0 -0
  33. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/core/__init__.py +0 -0
  34. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/core/accounts.py +0 -0
  35. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/core/adapter.py +0 -0
  36. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/core/attempts.py +0 -0
  37. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/core/browser.py +0 -0
  38. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/core/commands.py +0 -0
  39. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/core/matching.py +0 -0
  40. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/core/passwords.py +0 -0
  41. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/core/paths.py +0 -0
  42. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/core/registry.py +0 -0
  43. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/core/results.py +0 -0
  44. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/src/atsfill/py.typed +0 -0
  45. {atsfill-0.0.4.dev87 → atsfill-0.0.4.dev88}/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.dev87
3
+ Version: 0.0.4.dev88
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "atsfill"
3
- version = "0.0.4.dev87"
3
+ version = "0.0.4.dev88"
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"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "atsfill"
3
- version = "0.0.4.dev87"
3
+ version = "0.0.4.dev88"
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"
@@ -255,7 +255,6 @@ class Oracle:
255
255
  self._picked: dict[str, str] = {} # a geography field's id: the item picked in it
256
256
  self._months: list[str] = []
257
257
  self._job = ""
258
- self._uploads: dict[str, str] = {}
259
258
 
260
259
  def detect(self, url: str, page: Page | None) -> bool:
261
260
  return JOB.search(urlsplit(url).path) is not None
@@ -311,14 +310,14 @@ class Oracle:
311
310
  if COUNTRY in on_page: # the address below it follows the country's format
312
311
  self._fill(page, COUNTRY, answers[COUNTRY])
313
312
  _settle(page)
314
- for field_id in [i for i in on_page if i != COUNTRY]:
313
+ # Files go last: a click while one attaches can be lost, and once attached its
314
+ # label takes the focus back from a field typed after it.
315
+ files = [i for i in on_page if self._kinds[i] == "file"]
316
+ for field_id in [i for i in on_page if i not in (COUNTRY, *files)] + files:
315
317
  self._fill(page, field_id, answers[field_id])
316
- self._uploads = {
317
- i: PurePath(a).name
318
- for i, a in answers.items()
319
- if self._fields[i].type is FieldType.FILE and isinstance(a, str)
320
- }
321
- self._wait_for_uploads(page)
318
+ self._wait_for_uploads(
319
+ page, {i: PurePath(a).name for i in files if isinstance(a := answers[i], str)}
320
+ )
322
321
 
323
322
  def read_back(self, page: Page) -> dict[str, Answer]:
324
323
  values: dict[str, Any] = page.evaluate(_READ_BACK, self._kinds)
@@ -490,8 +489,9 @@ class Oracle:
490
489
  def _file_input(self, page: Page, field_id: str) -> Locator:
491
490
  return page.locator(f"{_upload(field_id)} input[type=file]").first
492
491
 
493
- def _wait_for_uploads(self, page: Page) -> None:
494
- for field_id, name in self._uploads.items():
492
+ def _wait_for_uploads(self, page: Page, uploads: dict[str, str]) -> None:
493
+ """Waits for each file (by field id: its name) to show attached."""
494
+ for field_id, name in uploads.items():
495
495
  selector = f"{_upload(field_id)} :is({ATTACHED})"
496
496
  done = page.locator(selector, has_text=name)
497
497
  try:
File without changes
File without changes