atsfill 0.0.5.dev169__tar.gz → 0.0.5.dev171__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 (65) hide show
  1. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/PKG-INFO +1 -1
  2. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/pyproject.toml +1 -1
  3. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/pyproject.toml.orig +1 -1
  4. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/jobstreet.py +4 -2
  5. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/accounts.py +4 -2
  6. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/adapter.py +3 -2
  7. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/results.py +1 -1
  8. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/LICENSE +0 -0
  9. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/README.md +0 -0
  10. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/__init__.py +0 -0
  11. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/__init__.py +0 -0
  12. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/adpmyjobs.py +0 -0
  13. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/ashby.py +0 -0
  14. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/bamboohr.py +0 -0
  15. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/breezy.py +0 -0
  16. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/dayforce.py +0 -0
  17. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/eightfold.py +0 -0
  18. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/greenhouse.py +0 -0
  19. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/gupy.py +0 -0
  20. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/hireology.py +0 -0
  21. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/hiringthing.py +0 -0
  22. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/hrmdirect.py +0 -0
  23. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/isolvedhire.py +0 -0
  24. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/jazzhr.py +0 -0
  25. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/jobaffinity.py +0 -0
  26. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/join.py +0 -0
  27. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/lever.py +0 -0
  28. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/manatal.py +0 -0
  29. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/oracle.py +0 -0
  30. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/paycor.py +0 -0
  31. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/paylocity.py +0 -0
  32. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/personio.py +0 -0
  33. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/phenom.py +0 -0
  34. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/pinpoint.py +0 -0
  35. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/recruitee.py +0 -0
  36. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/recruiterflow.py +0 -0
  37. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/rippling.py +0 -0
  38. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/smartrecruiters.py +0 -0
  39. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/successfactors.js +0 -0
  40. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/successfactors.py +0 -0
  41. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/taleo.py +0 -0
  42. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/teamtailor.py +0 -0
  43. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/ukg.py +0 -0
  44. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/welcomekit.py +0 -0
  45. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/workable.py +0 -0
  46. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/workatastartup.py +0 -0
  47. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/workday.py +0 -0
  48. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/wttj.py +0 -0
  49. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/adapters/zohorecruit.py +0 -0
  50. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/cli.py +0 -0
  51. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/__init__.py +0 -0
  52. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/attempts.py +0 -0
  53. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/browser.py +0 -0
  54. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/commands.py +0 -0
  55. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/conditions.py +0 -0
  56. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/html.py +0 -0
  57. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/matching.py +0 -0
  58. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/otp.py +0 -0
  59. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/passwords.py +0 -0
  60. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/paths.py +0 -0
  61. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/registry.py +0 -0
  62. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/snapshot.py +0 -0
  63. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/core/telemetry.py +0 -0
  64. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/src/atsfill/py.typed +0 -0
  65. {atsfill-0.0.5.dev169 → atsfill-0.0.5.dev171}/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.dev169
3
+ Version: 0.0.5.dev171
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.5.dev169"
3
+ version = "0.0.5.dev171"
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.5.dev169"
3
+ version = "0.0.5.dev171"
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"
@@ -119,10 +119,12 @@ class Jobstreet:
119
119
  def login_url(self, scope: str | None) -> str:
120
120
  return f"https://{scope}/oauth/login?returnUrl=%2F"
121
121
 
122
- def signed_in(self, request: Request, scope: str | None) -> bool:
122
+ def signed_in(self, request: Request, scope: str | None) -> bool | None:
123
123
  """The site's `/profile` redirects an account to `/profile/me` and shows a visitor its
124
- page. Cloudflare answers 403 outside the browser, so a session there reads signed out."""
124
+ page. Cloudflare can answer 403 outside the browser, which tells neither."""
125
125
  response = request.get(f"https://{scope}/profile", max_redirects=0)
126
+ if response.status == 403 or response.headers.get("cf-mitigated") == "challenge":
127
+ return None
126
128
  return response.status in (302, 307) and response.headers.get("location", "").endswith(
127
129
  "/profile/me"
128
130
  )
@@ -111,11 +111,13 @@ def redacted(error: Exception, password: str) -> Exception:
111
111
 
112
112
 
113
113
  def state(adapter: NeedsAccount, session: Path, scope: str | None) -> str:
114
- """`signed_in` or `signed_out` from the system itself, `missing` with no session stored."""
114
+ """`signed_in` or `signed_out` from the system itself, `unknown` when its answer cannot
115
+ tell, `missing` with no session stored."""
115
116
  if not session.exists():
116
117
  return "missing"
117
118
  with browser.session_request(session) as request:
118
- return "signed_in" if adapter.signed_in(request, scope) else "signed_out"
119
+ signed_in = adapter.signed_in(request, scope)
120
+ return {True: "signed_in", False: "signed_out", None: "unknown"}[signed_in]
119
121
 
120
122
 
121
123
  def wait_for_person(
@@ -122,8 +122,9 @@ class NeedsAccount(Protocol):
122
122
 
123
123
  def login_url(self, scope: str | None) -> str: ...
124
124
 
125
- def signed_in(self, request: Request, scope: str | None) -> bool:
126
- """Whether the cookies `request` carries are signed in, from one request to the system."""
125
+ def signed_in(self, request: Request, scope: str | None) -> bool | None:
126
+ """Whether the cookies `request` carries are signed in, from one request to the system;
127
+ None when its answer cannot tell, such as a bot protection's challenge."""
127
128
  ...
128
129
 
129
130
 
@@ -120,7 +120,7 @@ class SessionReport:
120
120
  user: str
121
121
  adapter: str
122
122
  scope: str | None # the account scope, None for an account that covers the whole system
123
- session: str # signed_in | signed_out | missing
123
+ session: str # signed_in | signed_out | unknown | missing
124
124
  path: Path
125
125
  status: str | None = None # a login's outcome: signed_in | refused | blocked | unsupported
126
126
  reason: str | None = None # why a login stored nothing, `code` or `code: detail`
File without changes
File without changes