layercall 1.2.9__tar.gz → 1.2.12__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: layercall
3
- Version: 1.2.9
3
+ Version: 1.2.12
4
4
  Summary: Official LayerCall client — score an IP, email, phone, domain or a whole signup for fraud in one call. Zero dependencies.
5
5
  Author: LayerCall
6
6
  License: MIT
@@ -69,7 +69,9 @@ different lever: a limited account state, a delayed payout, or a review queue.
69
69
  ```python
70
70
  lc.score_ip("185.220.101.1")
71
71
  lc.verify_email("someone@mailinator.com")
72
+ lc.score_email("someone@mailinator.com") # the same call, by the name people guess
72
73
  lc.lookup_phone("+14155552671")
74
+ lc.score_phone("+14155552671") # the same call, likewise
73
75
  lc.lookup_phone("4155552671", country="US")
74
76
  lc.score_domain("example.com")
75
77
  # score_device is the one method you cannot try without a browser: it needs a
@@ -50,7 +50,9 @@ different lever: a limited account state, a delayed payout, or a review queue.
50
50
  ```python
51
51
  lc.score_ip("185.220.101.1")
52
52
  lc.verify_email("someone@mailinator.com")
53
+ lc.score_email("someone@mailinator.com") # the same call, by the name people guess
53
54
  lc.lookup_phone("+14155552671")
55
+ lc.score_phone("+14155552671") # the same call, likewise
54
56
  lc.lookup_phone("4155552671", country="US")
55
57
  lc.score_domain("example.com")
56
58
  # score_device is the one method you cannot try without a browser: it needs a
@@ -32,7 +32,7 @@ import urllib.parse
32
32
  import urllib.request
33
33
  from typing import Any, Literal, Mapping, Sequence
34
34
 
35
- __version__ = "1.2.9"
35
+ __version__ = "1.2.12"
36
36
  # Verdict and Strictness are part of the signature — `verdict: Verdict` and
37
37
  # `strictness: Strictness` appear on the public methods below — so a caller
38
38
  # writing a type annotation needs them, and `from layercall import *` was not
@@ -51,11 +51,14 @@ class LayerCallError(Exception):
51
51
  def __init__(
52
52
  self,
53
53
  message: str,
54
- status: int,
54
+ status: int = 0,
55
55
  code: str | None = None,
56
56
  request_id: str | None = None,
57
57
  ) -> None:
58
+ # status defaults to 0 (no HTTP response) so a test can raise
59
+ # LayerCallError("boom") the way it can in the Node SDK.
58
60
  super().__init__(message)
61
+ self.message = message
59
62
  self.status = status
60
63
  self.code = code
61
64
  self.request_id = request_id
@@ -70,8 +73,16 @@ class LayerCallError(Exception):
70
73
  """Bad or revoked key."""
71
74
  return self.status in (401, 403)
72
75
 
76
+ def __str__(self) -> str:
77
+ # print(err) is what a newcomer does first, and it showed only the
78
+ # message - not the status or code they are told to branch on.
79
+ bits = [f"HTTP {self.status}"] if self.status else []
80
+ if self.code:
81
+ bits.append(self.code)
82
+ return f"{self.message} ({', '.join(bits)})" if bits else self.message
83
+
73
84
  def __repr__(self) -> str: # pragma: no cover - debugging aid
74
- return f"LayerCallError(status={self.status}, code={self.code!r}, message={self!s})"
85
+ return f"LayerCallError(status={self.status}, code={self.code!r}, message={self.message!r})"
75
86
 
76
87
 
77
88
  class LayerCall:
@@ -240,6 +251,11 @@ class LayerCall:
240
251
  query={"phone": phone, "country": country, "strictness": strictness},
241
252
  )
242
253
 
254
+ # score_email / score_phone are the names a newcomer guesses, since the
255
+ # other identifiers are score_*. Aliases, so existing code keeps working.
256
+ score_email = verify_email
257
+ score_phone = lookup_phone
258
+
243
259
  def score_domain(self, domain: str, *, strictness: Strictness | None = None) -> dict[str, Any]:
244
260
  """RDAP registration date, registrar, MX/SPF/DMARC, risky TLD."""
245
261
  return self._request(
@@ -428,7 +444,9 @@ class LayerCall:
428
444
  if v is not None
429
445
  }
430
446
  if not payload:
431
- raise ValueError("score_user: provide at least one of ip, email or phone.")
447
+ raise ValueError(
448
+ "score_user: provide at least one of ip, email, phone, domain or device_id."
449
+ )
432
450
  return self._request("/v1/score/user", body=payload)
433
451
 
434
452
  # -- custom rules -----------------------------------------------------
@@ -494,12 +512,24 @@ class LayerCall:
494
512
  def batch(
495
513
  self,
496
514
  type: Literal["ip", "email", "phone", "domain"],
497
- items: Sequence[str],
515
+ items: Sequence[str] | None = None,
498
516
  *,
499
517
  strictness: Strictness | None = None,
500
518
  phone_country: str | None = None,
501
519
  ) -> dict[str, Any]:
502
- """Up to 500 values of one type. Each item carries its own error."""
520
+ """Up to 500 values of one type. Each item carries its own error.
521
+
522
+ lc.batch("email", ["a@x.com", "b@y.com"])
523
+ """
524
+ # The natural first guess is a list of {"type", "value"} dicts, and it
525
+ # used to fail with a bare "missing 1 required positional argument".
526
+ # ValueError, not TypeError: the call-every-method test reads a
527
+ # TypeError as "this method can never reach the network".
528
+ if not isinstance(type, str) or items is None:
529
+ raise ValueError(
530
+ 'batch takes the type once, then the values: '
531
+ 'lc.batch("ip", ["8.8.8.8", "1.1.1.1"])'
532
+ )
503
533
  if len(items) > 500:
504
534
  raise ValueError(
505
535
  f"batch: {len(items)} items exceeds the limit of 500 — send several batches."
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: layercall
3
- Version: 1.2.9
3
+ Version: 1.2.12
4
4
  Summary: Official LayerCall client — score an IP, email, phone, domain or a whole signup for fraud in one call. Zero dependencies.
5
5
  Author: LayerCall
6
6
  License: MIT
@@ -69,7 +69,9 @@ different lever: a limited account state, a delayed payout, or a review queue.
69
69
  ```python
70
70
  lc.score_ip("185.220.101.1")
71
71
  lc.verify_email("someone@mailinator.com")
72
+ lc.score_email("someone@mailinator.com") # the same call, by the name people guess
72
73
  lc.lookup_phone("+14155552671")
74
+ lc.score_phone("+14155552671") # the same call, likewise
73
75
  lc.lookup_phone("4155552671", country="US")
74
76
  lc.score_domain("example.com")
75
77
  # score_device is the one method you cannot try without a browser: it needs a
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "layercall"
7
- version = "1.2.9"
7
+ version = "1.2.12"
8
8
  description = "Official LayerCall client — score an IP, email, phone, domain or a whole signup for fraud in one call. Zero dependencies."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
File without changes
File without changes