Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to geoip2 5.0.1 and minor cleanup #162

Merged
merged 7 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# This file is execfile()d with the current directory set to its containing dir.
#
Expand All @@ -9,8 +8,8 @@
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys
import os
import sys

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
Expand Down
7 changes: 3 additions & 4 deletions minfraud/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@

# flake8: noqa: F401
from .errors import (
MinFraudError,
AuthenticationError,
HTTPError,
InvalidRequestError,
InsufficientFundsError,
InvalidRequestError,
MinFraudError,
)

from .webservice import AsyncClient, Client
from .version import __version__
from .webservice import AsyncClient, Client

__author__ = "Gregory Oschwald"
142 changes: 75 additions & 67 deletions minfraud/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,27 @@
"""

# pylint:disable=too-many-lines,too-many-instance-attributes,too-many-locals
from typing import Dict, List, Optional, Sequence
from collections.abc import Sequence
from typing import Optional

from geoip2.mixins import SimpleEquality
import geoip2.models
import geoip2.records


class _Serializable(SimpleEquality):
def to_dict(self):
"""Returns a dict of the object suitable for serialization"""
class _Serializable:
def __eq__(self, other: object) -> bool:
return isinstance(other, self.__class__) and self.to_dict() == other.to_dict()

def __ne__(self, other: object) -> bool:
return not self.__eq__(other)

def to_dict(self) -> dict:
"""Returns a dict of the object suitable for serialization."""
result = {}
for key, value in self.__dict__.items():
if hasattr(value, "to_dict") and callable(value.to_dict):
if d := value.to_dict():
result[key] = d
elif hasattr(value, "raw"):
# geoip2 uses "raw" for historical reasons
if d := value.raw:
result[key] = d
elif isinstance(value, list):
ls = []
for e in value:
Expand Down Expand Up @@ -82,7 +84,9 @@ class IPRiskReason(_Serializable):
code: Optional[str]
reason: Optional[str]

def __init__(self, code: Optional[str] = None, reason: Optional[str] = None):
def __init__(
self, code: Optional[str] = None, reason: Optional[str] = None
) -> None:
self.code = code
self.reason = reason

Expand Down Expand Up @@ -112,7 +116,7 @@ class GeoIP2Location(geoip2.records.Location):
local_time: Optional[str]

def __init__(self, *args, **kwargs) -> None:
self.local_time = kwargs.get("local_time", None)
self.local_time = kwargs.get("local_time")
super().__init__(*args, **kwargs)


Expand Down Expand Up @@ -196,16 +200,16 @@ class IPAddress(geoip2.models.Insights):

location: GeoIP2Location
risk: Optional[float]
risk_reasons: List[IPRiskReason]
risk_reasons: list[IPRiskReason]

def __init__(
self,
locales: Optional[Sequence[str]],
*,
country: Optional[Dict] = None,
location: Optional[Dict] = None,
country: Optional[dict] = None,
location: Optional[dict] = None,
risk: Optional[float] = None,
risk_reasons: Optional[List[Dict]] = None,
risk_reasons: Optional[list[dict]] = None,
**kwargs,
) -> None:
# For raw attribute
Expand All @@ -218,7 +222,7 @@ def __init__(
if risk_reasons is not None:
kwargs["risk_reasons"] = risk_reasons

super().__init__(kwargs, locales=list(locales or []))
super().__init__(locales, **kwargs)
self.location = GeoIP2Location(**(location or {}))
self.risk = risk
self.risk_reasons = [IPRiskReason(**x) for x in risk_reasons or []]
Expand All @@ -237,7 +241,7 @@ class ScoreIPAddress(_Serializable):

risk: Optional[float]

def __init__(self, *, risk: Optional[float] = None, **_):
def __init__(self, *, risk: Optional[float] = None, **_) -> None:
self.risk = risk


Expand Down Expand Up @@ -292,7 +296,7 @@ def __init__(
phone_number: Optional[str] = None,
matches_provided_phone_number: Optional[bool] = None,
**_,
):
) -> None:
self.name = name
self.matches_provided_name = matches_provided_name
self.phone_number = phone_number
Expand Down Expand Up @@ -352,7 +356,7 @@ def __init__(
last_seen: Optional[str] = None,
local_time: Optional[str] = None,
**_,
):
) -> None:
self.confidence = confidence
self.id = id
self.last_seen = last_seen
Expand Down Expand Up @@ -402,7 +406,7 @@ def __init__(
reason: Optional[str] = None,
rule_label: Optional[str] = None,
**_,
):
) -> None:
self.action = action
self.reason = reason
self.rule_label = rule_label
Expand All @@ -423,7 +427,7 @@ class EmailDomain(_Serializable):

first_seen: Optional[str]

def __init__(self, *, first_seen: Optional[str] = None, **_):
def __init__(self, *, first_seen: Optional[str] = None, **_) -> None:
self.first_seen = first_seen


Expand Down Expand Up @@ -477,12 +481,12 @@ class Email(_Serializable):

def __init__(
self,
domain: Optional[Dict] = None,
domain: Optional[dict] = None,
first_seen: Optional[str] = None,
is_disposable: Optional[bool] = None,
is_free: Optional[bool] = None,
is_high_risk: Optional[bool] = None,
):
) -> None:
self.domain = EmailDomain(**(domain or {}))
self.first_seen = first_seen
self.is_disposable = is_disposable
Expand Down Expand Up @@ -564,7 +568,7 @@ class CreditCard(_Serializable):

def __init__(
self,
issuer: Optional[Dict] = None,
issuer: Optional[dict] = None,
country: Optional[str] = None,
brand: Optional[str] = None,
is_business: Optional[bool] = None,
Expand All @@ -573,7 +577,7 @@ def __init__(
is_virtual: Optional[bool] = None,
# pylint:disable=redefined-builtin
type: Optional[str] = None,
):
) -> None:
self.issuer = Issuer(**(issuer or {}))
self.country = country
self.brand = brand
Expand Down Expand Up @@ -642,7 +646,7 @@ def __init__(
distance_to_ip_location: Optional[int] = None,
is_in_ip_country: Optional[bool] = None,
**_,
):
) -> None:
self.is_postal_in_city = is_postal_in_city
self.latitude = latitude
self.longitude = longitude
Expand Down Expand Up @@ -729,7 +733,7 @@ def __init__(
is_high_risk: Optional[bool] = None,
distance_to_billing_address: Optional[int] = None,
**_,
):
) -> None:
self.is_postal_in_city = is_postal_in_city
self.latitude = latitude
self.longitude = longitude
Expand Down Expand Up @@ -789,7 +793,7 @@ def __init__(
network_operator: Optional[str] = None,
number_type: Optional[str] = None,
**_,
):
) -> None:
self.country = country
self.is_voip = is_voip
self.network_operator = network_operator
Expand Down Expand Up @@ -837,7 +841,7 @@ def __init__(
warning: Optional[str] = None,
input_pointer: Optional[str] = None,
**_,
):
) -> None:
self.code = code
self.warning = warning
self.input_pointer = input_pointer
Expand Down Expand Up @@ -1060,7 +1064,7 @@ def __init__(
shipping_address_distance_to_ip_location: Optional[float] = None,
time_of_day: Optional[float] = None,
**_,
):
) -> None:
self.avs_result = avs_result
self.billing_address = billing_address
self.billing_address_distance_to_ip_location = (
Expand Down Expand Up @@ -1174,8 +1178,12 @@ class Reason(_Serializable):
reason: Optional[str]

def __init__(
self, *, code: Optional[str] = None, reason: Optional[str] = None, **_
):
self,
*,
code: Optional[str] = None,
reason: Optional[str] = None,
**_,
) -> None:
self.code = code
self.reason = reason

Expand All @@ -1202,15 +1210,15 @@ class RiskScoreReason(_Serializable):
"""

multiplier: float
reasons: List[Reason]
reasons: list[Reason]

def __init__(
self,
*,
multiplier: float,
reasons: Optional[List] = None,
reasons: Optional[list] = None,
**_,
):
) -> None:
self.multiplier = multiplier
self.reasons = [Reason(**x) for x in reasons or []]

Expand Down Expand Up @@ -1357,32 +1365,32 @@ class Factors(_Serializable):
shipping_address: ShippingAddress
shipping_phone: Phone
subscores: Subscores
warnings: List[ServiceWarning]
risk_score_reasons: List[RiskScoreReason]
warnings: list[ServiceWarning]
risk_score_reasons: list[RiskScoreReason]

def __init__(
self,
locales: Sequence[str],
*,
billing_address: Optional[Dict] = None,
billing_phone: Optional[Dict] = None,
credit_card: Optional[Dict] = None,
disposition: Optional[Dict] = None,
billing_address: Optional[dict] = None,
billing_phone: Optional[dict] = None,
credit_card: Optional[dict] = None,
disposition: Optional[dict] = None,
funds_remaining: float,
device: Optional[Dict] = None,
email: Optional[Dict] = None,
device: Optional[dict] = None,
email: Optional[dict] = None,
# pylint:disable=redefined-builtin
id: str,
ip_address: Optional[Dict] = None,
ip_address: Optional[dict] = None,
queries_remaining: int,
risk_score: float,
shipping_address: Optional[Dict] = None,
shipping_phone: Optional[Dict] = None,
subscores: Optional[Dict] = None,
warnings: Optional[List[Dict]] = None,
risk_score_reasons: Optional[List[Dict]] = None,
shipping_address: Optional[dict] = None,
shipping_phone: Optional[dict] = None,
subscores: Optional[dict] = None,
warnings: Optional[list[dict]] = None,
risk_score_reasons: Optional[list[dict]] = None,
**_,
):
) -> None:
self.billing_address = BillingAddress(**(billing_address or {}))
self.billing_phone = Phone(**(billing_phone or {}))
self.credit_card = CreditCard(**(credit_card or {}))
Expand Down Expand Up @@ -1524,29 +1532,29 @@ class Insights(_Serializable):
risk_score: float
shipping_address: ShippingAddress
shipping_phone: Phone
warnings: List[ServiceWarning]
warnings: list[ServiceWarning]

def __init__(
self,
locales: Sequence[str],
*,
billing_address: Optional[Dict] = None,
billing_phone: Optional[Dict] = None,
credit_card: Optional[Dict] = None,
device: Optional[Dict] = None,
disposition: Optional[Dict] = None,
email: Optional[Dict] = None,
billing_address: Optional[dict] = None,
billing_phone: Optional[dict] = None,
credit_card: Optional[dict] = None,
device: Optional[dict] = None,
disposition: Optional[dict] = None,
email: Optional[dict] = None,
funds_remaining: float,
# pylint:disable=redefined-builtin
id: str,
ip_address: Optional[Dict] = None,
ip_address: Optional[dict] = None,
queries_remaining: int,
risk_score: float,
shipping_address: Optional[Dict] = None,
shipping_phone: Optional[Dict] = None,
warnings: Optional[List[Dict]] = None,
shipping_address: Optional[dict] = None,
shipping_phone: Optional[dict] = None,
warnings: Optional[list[dict]] = None,
**_,
):
) -> None:
self.billing_address = BillingAddress(**(billing_address or {}))
self.billing_phone = Phone(**(billing_phone or {}))
self.credit_card = CreditCard(**(credit_card or {}))
Expand Down Expand Up @@ -1627,21 +1635,21 @@ class Score(_Serializable):
ip_address: ScoreIPAddress
queries_remaining: int
risk_score: float
warnings: List[ServiceWarning]
warnings: list[ServiceWarning]

def __init__(
self,
*,
disposition: Optional[Dict] = None,
disposition: Optional[dict] = None,
funds_remaining: float,
# pylint:disable=redefined-builtin
id: str,
ip_address: Optional[Dict] = None,
ip_address: Optional[dict] = None,
queries_remaining: int,
risk_score: float,
warnings: Optional[List[Dict]] = None,
warnings: Optional[list[dict]] = None,
**_,
):
) -> None:
self.disposition = Disposition(**(disposition or {}))
self.funds_remaining = funds_remaining
self.id = id
Expand Down
Loading
Loading