followthemoney 4.0.3__py3-none-any.whl → 4.1.0__py3-none-any.whl
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.
- followthemoney/__init__.py +1 -1
- followthemoney/compare.py +6 -2
- followthemoney/dataset/util.py +2 -2
- followthemoney/namespace.py +5 -3
- followthemoney/proxy.py +1 -1
- followthemoney/types/address.py +7 -5
- followthemoney/types/common.py +3 -2
- followthemoney/types/email.py +46 -30
- followthemoney/types/name.py +4 -2
- followthemoney/util.py +2 -4
- {followthemoney-4.0.3.dist-info → followthemoney-4.1.0.dist-info}/METADATA +3 -3
- {followthemoney-4.0.3.dist-info → followthemoney-4.1.0.dist-info}/RECORD +15 -15
- {followthemoney-4.0.3.dist-info → followthemoney-4.1.0.dist-info}/WHEEL +0 -0
- {followthemoney-4.0.3.dist-info → followthemoney-4.1.0.dist-info}/entry_points.txt +0 -0
- {followthemoney-4.0.3.dist-info → followthemoney-4.1.0.dist-info}/licenses/LICENSE +0 -0
followthemoney/__init__.py
CHANGED
|
@@ -9,7 +9,7 @@ from followthemoney.statement import Statement, StatementEntity, SE
|
|
|
9
9
|
from followthemoney.dataset import Dataset, DefaultDataset, DS
|
|
10
10
|
from followthemoney.util import set_model_locale
|
|
11
11
|
|
|
12
|
-
__version__ = "4.0
|
|
12
|
+
__version__ = "4.1.0"
|
|
13
13
|
|
|
14
14
|
# Data model singleton
|
|
15
15
|
model = Model.instance()
|
followthemoney/compare.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import math
|
|
2
2
|
from itertools import islice, product
|
|
3
3
|
from typing import Dict, Generator, Iterable, List, Optional
|
|
4
|
-
from normality import
|
|
4
|
+
from normality import ascii_text
|
|
5
|
+
from rigour.text.scripts import can_latinize
|
|
5
6
|
from rigour.names import tokenize_name, remove_person_prefixes
|
|
6
7
|
from rigour.names import replace_org_types_compare
|
|
7
8
|
from followthemoney.exc import InvalidData
|
|
@@ -91,7 +92,7 @@ def _normalize_names(
|
|
|
91
92
|
can_person = schema.is_a("LegalEntity") and not schema.is_a("Organization")
|
|
92
93
|
can_org = schema.is_a("LegalEntity") and not schema.is_a("Person")
|
|
93
94
|
for name in names:
|
|
94
|
-
plain =
|
|
95
|
+
plain = name.lower().strip()
|
|
95
96
|
if plain is not None and plain not in seen:
|
|
96
97
|
seen.add(plain)
|
|
97
98
|
yield plain
|
|
@@ -102,6 +103,9 @@ def _normalize_names(
|
|
|
102
103
|
if can_org:
|
|
103
104
|
name = replace_org_types_compare(name)
|
|
104
105
|
tokens = tokenize_name(name.lower())
|
|
106
|
+
for token in tokens:
|
|
107
|
+
if can_latinize(token):
|
|
108
|
+
token = ascii_text(token) or token
|
|
105
109
|
fp = " ".join(sorted(tokens))
|
|
106
110
|
if fp is not None and len(fp) > 6 and fp not in seen:
|
|
107
111
|
seen.add(fp)
|
followthemoney/dataset/util.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
|
-
from normality import
|
|
2
|
+
from normality import slugify_text
|
|
3
3
|
from typing import Annotated, Any
|
|
4
4
|
from rigour.time import datetime_iso
|
|
5
5
|
from pydantic import AfterValidator, BeforeValidator, HttpUrl, PlainSerializer
|
|
@@ -11,7 +11,7 @@ def dataset_name_check(value: str) -> str:
|
|
|
11
11
|
"""Check that the given value is a valid dataset name. This doesn't convert
|
|
12
12
|
or clean invalid names, but raises an error if they are not compliant to
|
|
13
13
|
force the user to fix an invalid name"""
|
|
14
|
-
if
|
|
14
|
+
if slugify_text(value, sep="_") != value:
|
|
15
15
|
raise ValueError("Invalid %s: %r" % ("dataset name", value))
|
|
16
16
|
return value
|
|
17
17
|
|
followthemoney/namespace.py
CHANGED
|
@@ -26,9 +26,9 @@ the server without compromising isolation.
|
|
|
26
26
|
import hmac
|
|
27
27
|
from typing import Any, Optional, Tuple, Union
|
|
28
28
|
|
|
29
|
-
from followthemoney.types import registry
|
|
30
29
|
from followthemoney.proxy import E
|
|
31
|
-
from followthemoney.
|
|
30
|
+
from followthemoney.types import registry
|
|
31
|
+
from followthemoney.util import get_entity_id, key_bytes
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class Namespace(object):
|
|
@@ -69,9 +69,11 @@ class Namespace(object):
|
|
|
69
69
|
digest.update(key_bytes(entity_id))
|
|
70
70
|
return digest.hexdigest()
|
|
71
71
|
|
|
72
|
-
def sign(self, entity_id: str) -> Optional[str]:
|
|
72
|
+
def sign(self, entity_id: Optional[str]) -> Optional[str]:
|
|
73
73
|
"""Apply a namespace signature to an entity ID, removing any
|
|
74
74
|
previous namespace marker."""
|
|
75
|
+
if entity_id is None:
|
|
76
|
+
return None
|
|
75
77
|
parsed_id, _ = self.parse(entity_id)
|
|
76
78
|
if not len(self.bname):
|
|
77
79
|
return parsed_id
|
followthemoney/proxy.py
CHANGED
|
@@ -57,7 +57,7 @@ class EntityProxy(object):
|
|
|
57
57
|
#: A unique identifier for this entity, usually a hashed natural key,
|
|
58
58
|
#: a UUID, or a very simple slug. Can be signed using a
|
|
59
59
|
#: :class:`~followthemoney.namespace.Namespace`.
|
|
60
|
-
self.id = str(data["id"]) if "id"
|
|
60
|
+
self.id = str(data["id"]) if data.get("id") else None
|
|
61
61
|
if not cleaned:
|
|
62
62
|
self.id = sanitize_text(self.id)
|
|
63
63
|
|
followthemoney/types/address.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import re
|
|
2
2
|
from typing import Optional, TYPE_CHECKING
|
|
3
|
-
from normality import
|
|
4
|
-
from normality.cleaning import collapse_spaces
|
|
3
|
+
from normality import slugify_text, collapse_spaces
|
|
5
4
|
from rigour.addresses import normalize_address
|
|
6
5
|
from rigour.text.distance import levenshtein_similarity
|
|
7
6
|
|
|
@@ -39,7 +38,7 @@ class AddressType(PropertyType):
|
|
|
39
38
|
address = self.LINE_BREAKS.sub(", ", text)
|
|
40
39
|
address = self.COMMATA.sub(", ", address)
|
|
41
40
|
collapsed = collapse_spaces(address)
|
|
42
|
-
if collapsed is None
|
|
41
|
+
if collapsed is None:
|
|
43
42
|
return None
|
|
44
43
|
return collapsed
|
|
45
44
|
|
|
@@ -54,7 +53,10 @@ class AddressType(PropertyType):
|
|
|
54
53
|
return dampen(10, 60, value)
|
|
55
54
|
|
|
56
55
|
def node_id(self, value: str) -> Optional[str]:
|
|
57
|
-
|
|
56
|
+
normalized = normalize_address(value)
|
|
57
|
+
if normalized is None:
|
|
58
|
+
return None
|
|
59
|
+
slug = slugify_text(normalized)
|
|
58
60
|
if slug is None:
|
|
59
61
|
return None
|
|
60
|
-
return f"addr:{
|
|
62
|
+
return f"addr:{slug}"
|
followthemoney/types/common.py
CHANGED
|
@@ -204,9 +204,10 @@ class PropertyType(object):
|
|
|
204
204
|
return data
|
|
205
205
|
|
|
206
206
|
def __eq__(self, other: Any) -> bool:
|
|
207
|
-
|
|
207
|
+
try:
|
|
208
|
+
return self.name == other.name # type: ignore
|
|
209
|
+
except AttributeError:
|
|
208
210
|
return False
|
|
209
|
-
return self.name == other.name
|
|
210
211
|
|
|
211
212
|
def __hash__(self) -> int:
|
|
212
213
|
return hash(self.name)
|
followthemoney/types/email.py
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import re
|
|
2
2
|
import logging
|
|
3
3
|
from typing import Optional, TYPE_CHECKING
|
|
4
|
-
from
|
|
5
|
-
from normality.cleaning import strip_quotes
|
|
4
|
+
from rigour.env import ENCODING
|
|
6
5
|
|
|
7
6
|
from followthemoney.types.common import PropertyType
|
|
8
|
-
from followthemoney.util import
|
|
7
|
+
from followthemoney.util import defer as _
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# Regex to filter out invalid emails from a CSV file:
|
|
11
|
+
# csvgrep -c value -r '^(?![a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)' contrib/statements_emails.csv > contrib/test_invalid_emails.csv
|
|
9
12
|
|
|
10
13
|
log = logging.getLogger(__name__)
|
|
11
14
|
|
|
@@ -17,8 +20,9 @@ class EmailType(PropertyType):
|
|
|
17
20
|
"""Internet mail address (e.g. user@example.com). These are notoriously hard
|
|
18
21
|
to validate, but we use an irresponsibly simple rule and hope for the best."""
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
DOMAIN_RE = re.compile(r"^(?!-)(?:[a-z0-9-]{1,63}(?<!-)\.)+[a-z0-9-]{2,}$", re.U)
|
|
24
|
+
LOCAL_RE = re.compile(r"^[^<>()\[\]\,;:\?\s@\"]{1,64}$", re.U)
|
|
25
|
+
|
|
22
26
|
name = "email"
|
|
23
27
|
group = "emails"
|
|
24
28
|
label = _("E-Mail Address")
|
|
@@ -35,18 +39,29 @@ class EmailType(PropertyType):
|
|
|
35
39
|
# except:
|
|
36
40
|
# return False
|
|
37
41
|
|
|
42
|
+
def clean_domain_part(self, domain: str) -> Optional[str]:
|
|
43
|
+
"""Clean and normalize the domain part of the email."""
|
|
44
|
+
domain = domain.rstrip(".").lower()
|
|
45
|
+
try:
|
|
46
|
+
# Convert domain to IDNA encoding if it contains non-ASCII characters. This should
|
|
47
|
+
# be idempotent for domains that are already IDNA-encoded.
|
|
48
|
+
domain = domain.encode("idna").decode(ENCODING)
|
|
49
|
+
|
|
50
|
+
# Check if the domain matches the regex pattern, which requires labels to be
|
|
51
|
+
# alphanumeric and hyphenated, and the TLD to be at least two characters long.
|
|
52
|
+
if self.DOMAIN_RE.match(domain) is None:
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
domain = domain.encode(ENCODING).decode("idna")
|
|
56
|
+
return domain
|
|
57
|
+
except UnicodeError:
|
|
58
|
+
return None
|
|
59
|
+
|
|
38
60
|
def validate(
|
|
39
61
|
self, value: str, fuzzy: bool = False, format: Optional[str] = None
|
|
40
62
|
) -> bool:
|
|
41
63
|
"""Check to see if this is a valid email address."""
|
|
42
|
-
|
|
43
|
-
email = sanitize_text(value)
|
|
44
|
-
if email is None or not self.REGEX.match(email):
|
|
45
|
-
return False
|
|
46
|
-
_, domain = email.rsplit("@", 1)
|
|
47
|
-
if len(domain) < 4 or "." not in domain:
|
|
48
|
-
return False
|
|
49
|
-
return True
|
|
64
|
+
return self.clean_text(value, fuzzy=fuzzy, format=format) is not None
|
|
50
65
|
|
|
51
66
|
def clean_text(
|
|
52
67
|
self,
|
|
@@ -59,23 +74,24 @@ class EmailType(PropertyType):
|
|
|
59
74
|
|
|
60
75
|
Returns None if this is not an email address.
|
|
61
76
|
"""
|
|
62
|
-
email = strip_quotes(text)
|
|
63
|
-
if email is None or not self.REGEX.match(email):
|
|
64
|
-
return None
|
|
65
|
-
mailbox, domain = email.rsplit("@", 1)
|
|
66
77
|
# TODO: https://pypi.python.org/pypi/publicsuffix/
|
|
67
|
-
# handle URLs by extracting the domain
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
# handle URLs by extracting the domain names
|
|
79
|
+
# or TODO: adopt email.utils.parseaddr
|
|
80
|
+
|
|
81
|
+
# Remove mailto: prefix if present
|
|
82
|
+
email = text.strip()
|
|
83
|
+
if email.startswith("mailto:"):
|
|
84
|
+
email = email[7:]
|
|
85
|
+
|
|
72
86
|
try:
|
|
73
|
-
domain =
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return "@".join((mailbox, domain))
|
|
78
|
-
return None
|
|
87
|
+
local, domain = email.rsplit("@", 1)
|
|
88
|
+
"""Clean and validate the local part of the email."""
|
|
89
|
+
if self.LOCAL_RE.match(local) is None:
|
|
90
|
+
return None
|
|
79
91
|
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
domain_clean = self.clean_domain_part(domain)
|
|
93
|
+
if domain_clean is None:
|
|
94
|
+
return None
|
|
95
|
+
return f"{local}@{domain_clean}"
|
|
96
|
+
except ValueError:
|
|
97
|
+
return None
|
followthemoney/types/name.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, Optional, Sequence
|
|
2
|
-
from normality import
|
|
2
|
+
from normality import slugify_text
|
|
3
3
|
from normality.cleaning import collapse_spaces, strip_quotes
|
|
4
4
|
from rigour.env import MAX_NAME_LENGTH
|
|
5
5
|
from rigour.names import pick_name, tokenize_name
|
|
@@ -38,6 +38,8 @@ class NameType(PropertyType):
|
|
|
38
38
|
) -> Optional[str]:
|
|
39
39
|
"""Basic clean-up."""
|
|
40
40
|
name = strip_quotes(text)
|
|
41
|
+
if name is None:
|
|
42
|
+
return None
|
|
41
43
|
return collapse_spaces(name)
|
|
42
44
|
|
|
43
45
|
def pick(self, values: Sequence[str]) -> Optional[str]:
|
|
@@ -61,7 +63,7 @@ class NameType(PropertyType):
|
|
|
61
63
|
)
|
|
62
64
|
|
|
63
65
|
def node_id(self, value: str) -> Optional[str]:
|
|
64
|
-
slug =
|
|
66
|
+
slug = slugify_text(value)
|
|
65
67
|
if slug is None:
|
|
66
68
|
return None
|
|
67
69
|
return f"name:{slug}"
|
followthemoney/util.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
3
|
import logging
|
|
4
|
+
import unicodedata
|
|
4
5
|
from hashlib import sha1
|
|
5
6
|
from babel import Locale
|
|
6
7
|
from gettext import translation
|
|
@@ -8,7 +9,6 @@ from gettext import translation
|
|
|
8
9
|
from threading import local
|
|
9
10
|
from typing import cast, Dict, Any, List, Optional, TypeVar, Union
|
|
10
11
|
from normality import stringify
|
|
11
|
-
from normality.cleaning import compose_nfc
|
|
12
12
|
from normality.cleaning import remove_unsafe_chars
|
|
13
13
|
from normality.encoding import DEFAULT_ENCODING
|
|
14
14
|
from banal import is_mapping, unique_list, ensure_list
|
|
@@ -69,9 +69,7 @@ def sanitize_text(value: Any, encoding: str = DEFAULT_ENCODING) -> Optional[str]
|
|
|
69
69
|
if text is None:
|
|
70
70
|
return None
|
|
71
71
|
try:
|
|
72
|
-
text =
|
|
73
|
-
if text is None:
|
|
74
|
-
return None
|
|
72
|
+
text = unicodedata.normalize("NFC", text)
|
|
75
73
|
except (SystemError, Exception) as ex:
|
|
76
74
|
log.warning("Cannot NFC text: %s", ex)
|
|
77
75
|
return None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: followthemoney
|
|
3
|
-
Version: 4.0
|
|
3
|
+
Version: 4.1.0
|
|
4
4
|
Summary: A data model for anti corruption data modeling and analysis.
|
|
5
5
|
Project-URL: Documentation, https://followthemoney.tech/
|
|
6
6
|
Project-URL: Repository, https://github.com/opensanctions/followthemoney.git
|
|
@@ -41,7 +41,7 @@ Requires-Dist: banal<1.1.0,>=1.0.6
|
|
|
41
41
|
Requires-Dist: click<9.0.0,>=8.0
|
|
42
42
|
Requires-Dist: countrynames<2.0.0,>=1.13.0
|
|
43
43
|
Requires-Dist: networkx<3.5,>=2.5
|
|
44
|
-
Requires-Dist: normality<
|
|
44
|
+
Requires-Dist: normality<4.0.0,>=3.0.0
|
|
45
45
|
Requires-Dist: openpyxl<4.0.0,>=3.0.5
|
|
46
46
|
Requires-Dist: orjson<4.0,>=3.10.18
|
|
47
47
|
Requires-Dist: phonenumbers<10.0.0,>=8.12.22
|
|
@@ -51,7 +51,7 @@ Requires-Dist: pytz>=2021.1
|
|
|
51
51
|
Requires-Dist: pyyaml<7.0.0,>=5.0.0
|
|
52
52
|
Requires-Dist: rdflib<7.2.0,>=6.2.0
|
|
53
53
|
Requires-Dist: requests<3.0.0,>=2.21.0
|
|
54
|
-
Requires-Dist: rigour<2.0.0,>=1.
|
|
54
|
+
Requires-Dist: rigour<2.0.0,>=1.1.0
|
|
55
55
|
Requires-Dist: sqlalchemy[mypy]<3.0.0,>=2.0.0
|
|
56
56
|
Provides-Extra: dev
|
|
57
57
|
Requires-Dist: build; extra == 'dev'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
followthemoney/__init__.py,sha256=
|
|
2
|
-
followthemoney/compare.py,sha256=
|
|
1
|
+
followthemoney/__init__.py,sha256=XG3sMmmgBvV0kMOTtFP0JSqRQnlTSqtDEwtQ4MFxkSs,856
|
|
2
|
+
followthemoney/compare.py,sha256=bZlnj2VMoe67q4Lyq_VwS1a-EJnEK1kC8prbs8jyL9E,5774
|
|
3
3
|
followthemoney/entity.py,sha256=9wLKE3iFapxRQWOs_OAMzK3wtklf2HXaHaMYydIInWE,3045
|
|
4
4
|
followthemoney/exc.py,sha256=GyMgwY4QVm87hLevDfV7gM1MJsDqfNCi_UQw7F_A8X8,858
|
|
5
5
|
followthemoney/graph.py,sha256=7X1CGHGvmktS2LSZqld2iXWzG7B831eCNYyBqamqEJ8,10921
|
|
@@ -7,13 +7,13 @@ followthemoney/helpers.py,sha256=Btb6BlHg_c-qCXZo-NP_LURKG-qu-QD3Fj1ev_c7Xic,795
|
|
|
7
7
|
followthemoney/messages.py,sha256=zUEa9CFecU8nRafIzhN6TKCh1kEihiIyIS1qr8PxY4g,806
|
|
8
8
|
followthemoney/model.py,sha256=bWFVNa-DhYzc8BdSXBZdG2ev6Nh9uHx6i4tin8DvEEU,7374
|
|
9
9
|
followthemoney/names.py,sha256=LODQqExKEHdH4z6Mmbhlm0KeKRzGcptaSWzYXZ7lONI,1120
|
|
10
|
-
followthemoney/namespace.py,sha256=
|
|
10
|
+
followthemoney/namespace.py,sha256=utggu9IGA8bhgEYom3OUB1KxkAJR_TrMNbY5MUF_db8,4536
|
|
11
11
|
followthemoney/ontology.py,sha256=WWY_PYQGl5Ket4zZBuZglzQxD2Bh9UqHok6GJNNX7GA,3001
|
|
12
12
|
followthemoney/property.py,sha256=RDTzTXJeeLFLptQL1_gr1S1T-vdDe-8MGMwsRaGQh0I,7665
|
|
13
|
-
followthemoney/proxy.py,sha256=
|
|
13
|
+
followthemoney/proxy.py,sha256=LD4K1oPABXMX212UZxwLu7XOHRDyVBwTlqudTUsUZRQ,19619
|
|
14
14
|
followthemoney/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
followthemoney/schema.py,sha256=WYnPE4Lego0pJHlojECEv0aO9Miw_YIvEb35HoDo4Zk,18087
|
|
16
|
-
followthemoney/util.py,sha256=
|
|
16
|
+
followthemoney/util.py,sha256=QeNZI0rJPI2KcK2JQ-ka3rk_IobMkFSVN0jk-JJhAWI,4391
|
|
17
17
|
followthemoney/value.py,sha256=BJ4Sj5Tg2kMrslR6FjQUr96d8Kt75U7ny9NgzVGT0ZE,2335
|
|
18
18
|
followthemoney/cli/__init__.py,sha256=0mmz84uhXRp2qUn3syKnDXofU3MMAAe291s7htqX0Bg,187
|
|
19
19
|
followthemoney/cli/aggregate.py,sha256=xQTFpU3cVVj7fplpX4OJVrRlTVpn6b9kBr_Vb87pKfg,2164
|
|
@@ -29,7 +29,7 @@ followthemoney/dataset/coverage.py,sha256=rBnKs7VngCtIuaDqrF5D0ygCHg8NAMkYbmtl73
|
|
|
29
29
|
followthemoney/dataset/dataset.py,sha256=wWUzWsdzDW9qXLy8lS6Bpy08WMcaNU30oiMXU8jfo14,4724
|
|
30
30
|
followthemoney/dataset/publisher.py,sha256=nexZe9XexV8WI5Id999vf5OH_DPUmiKQ_GT3c59eF44,893
|
|
31
31
|
followthemoney/dataset/resource.py,sha256=S_-tNjMwHQ8LcSOsZO_xhXD-vLK90wyxtIRBbyCJ0Xo,1164
|
|
32
|
-
followthemoney/dataset/util.py,sha256=
|
|
32
|
+
followthemoney/dataset/util.py,sha256=mfVTXdbNnWly6cXo4SjNzHuJK1c1uNBwULYOVg1gK5I,1617
|
|
33
33
|
followthemoney/export/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
34
|
followthemoney/export/common.py,sha256=5b-Qlu3MaA0kSzzMAP93FAWncpgiioENnCnHikWYxhs,1021
|
|
35
35
|
followthemoney/export/csv.py,sha256=reWq1jYIv7sY2PEI4JwIxahYNNqnSiPfMCS3kQX4RZ8,2652
|
|
@@ -141,12 +141,12 @@ followthemoney/translations/ru/LC_MESSAGES/followthemoney.po,sha256=7SQWytOTvoAQ
|
|
|
141
141
|
followthemoney/translations/tr/LC_MESSAGES/followthemoney.mo,sha256=SC84e_ZF_oFJG1NKdyZY_W6Kb6POORZB6wdeAcEWmnE,487
|
|
142
142
|
followthemoney/translations/tr/LC_MESSAGES/followthemoney.po,sha256=AZC3marhtVVq8Ck1FOgnt4sbDMz548nX48O9GDwImbQ,89826
|
|
143
143
|
followthemoney/types/__init__.py,sha256=rWwQeiuMh2BNIuvhpMfJ4bPADDvt9Axu1eedvNFi0qY,3350
|
|
144
|
-
followthemoney/types/address.py,sha256=
|
|
144
|
+
followthemoney/types/address.py,sha256=8qapsxfAPFml9MyAcRxN5m_YkmkZYUUJyBXAiAAYUoE,2133
|
|
145
145
|
followthemoney/types/checksum.py,sha256=zZrU8WX4CY3Vta_vOyfgDNzIwbmtje7AaDv3O1fBMnk,823
|
|
146
|
-
followthemoney/types/common.py,sha256=
|
|
146
|
+
followthemoney/types/common.py,sha256=4ks7zPT8rknrGSd4JFc1zRkS-TL4SX-25_ZbjcVDos0,10081
|
|
147
147
|
followthemoney/types/country.py,sha256=mUCjwhUbA5Ef5HYuKb1KbH4aZ3MxaNwE1p77uOZMuG0,1745
|
|
148
148
|
followthemoney/types/date.py,sha256=PjcaEyW6CBzf0-gHWKUsKjWIaD3AVBEl0zLSRQOVXxc,3105
|
|
149
|
-
followthemoney/types/email.py,sha256=
|
|
149
|
+
followthemoney/types/email.py,sha256=L3RTYrMABlNQF7hCynXGfzoj6YNEHW5JAY_BwuhoZdA,3375
|
|
150
150
|
followthemoney/types/entity.py,sha256=oDxVEhuxyU1ScpOpebPpUm3o0I9j_p7Qrq-t5yNpluQ,2338
|
|
151
151
|
followthemoney/types/gender.py,sha256=fi9iKLbjAUxDCLBtU1MxWidxv7KgCY2eH5746FYlEGk,1725
|
|
152
152
|
followthemoney/types/identifier.py,sha256=hzD188FtwG0w3TcmbnDwnUMc8MZVcWgQJKGAvrwygc4,2296
|
|
@@ -154,14 +154,14 @@ followthemoney/types/ip.py,sha256=mMFTODFiXAJROCUYJvoLAShyIiTIWVmMBh5zT_GquYM,13
|
|
|
154
154
|
followthemoney/types/json.py,sha256=V3qJD5RxJykNX51u3w1Nx9xqoNBnkulhzkJI9XMYKFo,1690
|
|
155
155
|
followthemoney/types/language.py,sha256=SXgRRH-DyPmyyrqYurSyMiG6WHB8a0Gw81XxroEGD-c,2747
|
|
156
156
|
followthemoney/types/mimetype.py,sha256=NdpqVLx3Bre_myYvnbjmdd5wZBf01tllrbhegjO8_m0,1263
|
|
157
|
-
followthemoney/types/name.py,sha256=
|
|
157
|
+
followthemoney/types/name.py,sha256=1CzwNRgbvNpE5C9hm3PbMmJILCbpTDey5l3eL--bkTQ,2317
|
|
158
158
|
followthemoney/types/number.py,sha256=OdVuHDd4IYIIHhx_317JKeMjBAGtsJ2TAcxoZKZ4MkY,3948
|
|
159
159
|
followthemoney/types/phone.py,sha256=r8uRqWinS0CYnYBTs405k5gO4jeatUDgjdzzijoMKJE,3811
|
|
160
160
|
followthemoney/types/string.py,sha256=fqyTauAm4mNnNaoH-yH087RBbNh-G5ZZUO3awTGQUUg,1230
|
|
161
161
|
followthemoney/types/topic.py,sha256=CS5IoI8gm4MSVxfV6K4mGd20_tT1SaKMkcOt_ObSsAg,3678
|
|
162
162
|
followthemoney/types/url.py,sha256=QFpS_JIV8unFHuh_uGv22SWUUkocBoOpzLsAJWom_gI,1455
|
|
163
|
-
followthemoney-4.0.
|
|
164
|
-
followthemoney-4.0.
|
|
165
|
-
followthemoney-4.0.
|
|
166
|
-
followthemoney-4.0.
|
|
167
|
-
followthemoney-4.0.
|
|
163
|
+
followthemoney-4.1.0.dist-info/METADATA,sha256=aHjJGapyWo-mWOU29zQqjpGS2szD62G2D36wAraAYTE,6791
|
|
164
|
+
followthemoney-4.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
165
|
+
followthemoney-4.1.0.dist-info/entry_points.txt,sha256=caoFTlf213jhg5sz3TNSofutjUTzaKtWATuSIdd9Cps,653
|
|
166
|
+
followthemoney-4.1.0.dist-info/licenses/LICENSE,sha256=H6_EVXisnJC0-18CjXIaqrBSFq_VH3OnS7u3dccOv6g,1148
|
|
167
|
+
followthemoney-4.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|