Skip to content

Commit f5fc08e

Browse files
committed
Add missing type hints and fix minor issues
1 parent 1e1e6a0 commit f5fc08e

File tree

6 files changed

+167
-152
lines changed

6 files changed

+167
-152
lines changed

minfraud/models.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717

1818
class _Serializable(SimpleEquality):
19-
def to_dict(self):
19+
def to_dict(self) -> dict:
2020
"""Returns a dict of the object suitable for serialization."""
2121
result = {}
2222
for key, value in self.__dict__.items():

minfraud/request.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import re
1010
import unicodedata
1111
import warnings
12-
from typing import Any
12+
from typing import Any, Optional
1313

1414
from voluptuous import MultipleInvalid
1515

@@ -339,7 +339,7 @@ def maybe_hash_email(transaction) -> None:
339339
email["address"] = hashlib.md5(address.encode("UTF-8")).hexdigest()
340340

341341

342-
def _clean_domain(domain):
342+
def _clean_domain(domain: str) -> str:
343343
domain = domain.strip().rstrip(".").encode("idna").decode("ASCII")
344344

345345
domain = re.sub(r"(?:\.com){2,}$", ".com", domain)
@@ -348,14 +348,14 @@ def _clean_domain(domain):
348348
idx = domain.rfind(".")
349349
if idx != -1:
350350
tld = domain[idx + 1:]
351-
if tld in _TYPO_TLDS:
352-
domain = domain[:idx] + "." + _TYPO_TLDS.get(tld)
351+
if typo_tld := _TYPO_TLDS.get(tld):
352+
domain = domain[:idx] + "." + typo_tld
353353

354354
domain = _TYPO_DOMAINS.get(domain, domain)
355355
return _EQUIVALENT_DOMAINS.get(domain, domain)
356356

357357

358-
def _clean_email(address):
358+
def _clean_email(address: str) -> tuple[Optional[str], Optional[str]]:
359359
address = address.lower().strip()
360360

361361
at_idx = address.rfind("@")

tests/test_models.py

+32-31
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,29 @@
11
import unittest
2+
from typing import Any, Union
23

34
from minfraud.models import *
45

56

67
class TestModels(unittest.TestCase):
7-
def setUp(self):
8+
def setUp(self) -> None:
89
self.maxDiff = 20_000
910

10-
def test_billing_address(self):
11-
address = BillingAddress(**self.address_dict)
11+
def test_billing_address(self) -> None:
12+
address = BillingAddress(**self.address_dict) # type: ignore[arg-type]
1213
self.check_address(address)
1314

14-
def test_shipping_address(self):
15+
def test_shipping_address(self) -> None:
1516
address_dict = self.address_dict
1617
address_dict["is_high_risk"] = False
1718
address_dict["distance_to_billing_address"] = 200
1819

19-
address = ShippingAddress(**address_dict)
20+
address = ShippingAddress(**address_dict) # type:ignore[arg-type]
2021
self.check_address(address)
2122
self.assertEqual(False, address.is_high_risk)
2223
self.assertEqual(200, address.distance_to_billing_address)
2324

2425
@property
25-
def address_dict(self):
26+
def address_dict(self) -> dict[str, Union[bool, float]]:
2627
return {
2728
"is_in_ip_country": True,
2829
"latitude": 43.1,
@@ -31,14 +32,14 @@ def address_dict(self):
3132
"is_postal_in_city": True,
3233
}
3334

34-
def check_address(self, address):
35+
def check_address(self, address) -> None:
3536
self.assertEqual(True, address.is_in_ip_country)
3637
self.assertEqual(True, address.is_postal_in_city)
3738
self.assertEqual(100, address.distance_to_ip_location)
3839
self.assertEqual(32.1, address.longitude)
3940
self.assertEqual(43.1, address.latitude)
4041

41-
def test_credit_card(self):
42+
def test_credit_card(self) -> None:
4243
cc = CreditCard(
4344
issuer={"name": "Bank"},
4445
brand="Visa",
@@ -59,7 +60,7 @@ def test_credit_card(self):
5960
self.assertEqual(True, cc.is_issued_in_billing_address_country)
6061
self.assertEqual("credit", cc.type)
6162

62-
def test_device(self):
63+
def test_device(self) -> None:
6364
id = "b643d445-18b2-4b9d-bad4-c9c4366e402a"
6465
last_seen = "2016-06-08T14:16:38Z"
6566
local_time = "2016-06-10T14:19:10-08:00"
@@ -75,7 +76,7 @@ def test_device(self):
7576
self.assertEqual(last_seen, device.last_seen)
7677
self.assertEqual(local_time, device.local_time)
7778

78-
def test_disposition(self):
79+
def test_disposition(self) -> None:
7980
disposition = Disposition(
8081
action="accept",
8182
reason="default",
@@ -86,7 +87,7 @@ def test_disposition(self):
8687
self.assertEqual("default", disposition.reason)
8788
self.assertEqual("custom rule label", disposition.rule_label)
8889

89-
def test_email(self):
90+
def test_email(self) -> None:
9091
first_seen = "2016-01-01"
9192
email = Email(
9293
first_seen=first_seen,
@@ -100,21 +101,21 @@ def test_email(self):
100101
self.assertEqual(True, email.is_free)
101102
self.assertEqual(False, email.is_high_risk)
102103

103-
def test_email_domain(self):
104+
def test_email_domain(self) -> None:
104105
first_seen = "2016-01-01"
105106
domain = EmailDomain(
106107
first_seen=first_seen,
107108
)
108109

109110
self.assertEqual(first_seen, domain.first_seen)
110111

111-
def test_geoip2_location(self):
112+
def test_geoip2_location(self) -> None:
112113
time = "2015-04-19T12:59:23-01:00"
113114
location = GeoIP2Location(local_time=time, latitude=5)
114115
self.assertEqual(time, location.local_time)
115116
self.assertEqual(5, location.latitude)
116117

117-
def test_ip_address(self):
118+
def test_ip_address(self) -> None:
118119
time = "2015-04-19T12:59:23-01:00"
119120
address = IPAddress(
120121
["en"],
@@ -175,15 +176,15 @@ def test_ip_address(self):
175176
address.risk_reasons[1].reason,
176177
)
177178

178-
def test_empty_address(self):
179+
def test_empty_address(self) -> None:
179180
address = IPAddress([])
180181
self.assertEqual([], address.risk_reasons)
181182

182-
def test_score_ip_address(self):
183+
def test_score_ip_address(self) -> None:
183184
address = ScoreIPAddress(risk=99)
184185
self.assertEqual(99, address.risk)
185186

186-
def test_ip_address_locales(self):
187+
def test_ip_address_locales(self) -> None:
187188
loc = IPAddress(
188189
["fr"],
189190
country={"names": {"fr": "Country"}},
@@ -193,7 +194,7 @@ def test_ip_address_locales(self):
193194
self.assertEqual("City", loc.city.name)
194195
self.assertEqual("Country", loc.country.name)
195196

196-
def test_issuer(self):
197+
def test_issuer(self) -> None:
197198
phone = "132-342-2131"
198199

199200
issuer = Issuer(
@@ -208,7 +209,7 @@ def test_issuer(self):
208209
self.assertEqual(phone, issuer.phone_number)
209210
self.assertEqual(True, issuer.matches_provided_phone_number)
210211

211-
def test_phone(self):
212+
def test_phone(self) -> None:
212213
phone = Phone(
213214
country="US",
214215
is_voip=True,
@@ -221,7 +222,7 @@ def test_phone(self):
221222
self.assertEqual("Verizon/1", phone.network_operator)
222223
self.assertEqual("fixed", phone.number_type)
223224

224-
def test_warning(self):
225+
def test_warning(self) -> None:
225226
code = "INVALID_INPUT"
226227
msg = "Input invalid"
227228

@@ -231,7 +232,7 @@ def test_warning(self):
231232
self.assertEqual(msg, warning.warning)
232233
self.assertEqual("/first/second", warning.input_pointer)
233234

234-
def test_reason(self):
235+
def test_reason(self) -> None:
235236
code = "EMAIL_ADDRESS_NEW"
236237
msg = "Riskiness of newly-sighted email address"
237238

@@ -240,7 +241,7 @@ def test_reason(self):
240241
self.assertEqual(code, reason.code)
241242
self.assertEqual(msg, reason.reason)
242243

243-
def test_risk_score_reason(self):
244+
def test_risk_score_reason(self) -> None:
244245
multiplier = 0.34
245246
code = "EMAIL_ADDRESS_NEW"
246247
msg = "Riskiness of newly-sighted email address"
@@ -254,7 +255,7 @@ def test_risk_score_reason(self):
254255
self.assertEqual(code, reason.reasons[0].code)
255256
self.assertEqual(msg, reason.reasons[0].reason)
256257

257-
def test_score(self):
258+
def test_score(self) -> None:
258259
id = "b643d445-18b2-4b9d-bad4-c9c4366e402a"
259260
response = {
260261
"id": id,
@@ -264,7 +265,7 @@ def test_score(self):
264265
"ip_address": {"risk": 99},
265266
"warnings": [{"code": "INVALID_INPUT"}],
266267
}
267-
score = Score(**response)
268+
score = Score(**response) # type: ignore[arg-type]
268269

269270
self.assertEqual(id, score.id)
270271
self.assertEqual(10.01, score.funds_remaining)
@@ -275,17 +276,17 @@ def test_score(self):
275276

276277
self.assertEqual(response, score.to_dict())
277278

278-
def test_insights(self):
279+
def test_insights(self) -> None:
279280
response = self.factors_response()
280281
del response["risk_score_reasons"]
281282
del response["subscores"]
282-
insights = Insights(None, **response)
283+
insights = Insights(None, **response) # type: ignore[arg-type]
283284
self.check_insights_data(insights, response["id"])
284285
self.assertEqual(response, insights.to_dict())
285286

286-
def test_factors(self):
287+
def test_factors(self) -> None:
287288
response = self.factors_response()
288-
factors = Factors(None, **response)
289+
factors = Factors(None, **response) # type: ignore[arg-type]
289290
self.check_insights_data(factors, response["id"])
290291
self.check_risk_score_reasons_data(factors.risk_score_reasons)
291292
self.assertEqual(0.01, factors.subscores.avs_result)
@@ -317,7 +318,7 @@ def test_factors(self):
317318

318319
self.assertEqual(response, factors.to_dict())
319320

320-
def factors_response(self):
321+
def factors_response(self) -> dict[str, Any]:
321322
return {
322323
"id": "b643d445-18b2-4b9d-bad4-c9c4366e402a",
323324
"disposition": {"action": "reject"},
@@ -373,7 +374,7 @@ def factors_response(self):
373374
],
374375
}
375376

376-
def check_insights_data(self, insights, uuid):
377+
def check_insights_data(self, insights, uuid) -> None:
377378
self.assertEqual("US", insights.ip_address.country.iso_code)
378379
self.assertEqual(False, insights.ip_address.country.is_in_european_union)
379380
self.assertEqual(True, insights.credit_card.is_business)
@@ -395,7 +396,7 @@ def check_insights_data(self, insights, uuid):
395396
self.assertEqual("INVALID_INPUT", insights.warnings[0].code)
396397
self.assertIsInstance(insights.warnings, list, "warnings is a list")
397398

398-
def check_risk_score_reasons_data(self, reasons):
399+
def check_risk_score_reasons_data(self, reasons) -> None:
399400
self.assertEqual(1, len(reasons))
400401
self.assertEqual(45, reasons[0].multiplier)
401402
self.assertEqual(1, len(reasons[0].reasons))

tests/test_request.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99

1010
class TestRequest(unittest.TestCase):
11-
def test_maybe_hash_email(self):
11+
def test_maybe_hash_email(self) -> None:
1212
tests = [
1313
{
1414
"name": "no email",
@@ -171,7 +171,7 @@ def test_maybe_hash_email(self):
171171

172172
self.assertEqual(test["expected"], transaction)
173173

174-
def test_clean_credit_card(self):
174+
def test_clean_credit_card(self) -> None:
175175
tests = [
176176
{
177177
"name": "deprecated last_4_digits is cleaned to last_digits",
@@ -217,7 +217,7 @@ def test_clean_credit_card(self):
217217
self.assertEqual(test["expected"], transaction)
218218

219219

220-
def test_clean_email():
220+
def test_clean_email() -> None:
221221
tests = [
222222
{"input": "", "output": None},
223223
{"input": "fasfs", "output": None},
@@ -256,5 +256,5 @@ def test_clean_email():
256256
]
257257

258258
for test in tests:
259-
got, _ = _clean_email(test["input"])
260-
assert test["output"] == got
259+
got, _ = _clean_email(test["input"]) # type: ignore
260+
assert test["output"] == got # type: ignore

0 commit comments

Comments
 (0)