followthemoney 4.5.0__py3-none-any.whl → 4.5.2__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 +5 -4
- followthemoney/cli/statement.py +13 -7
- followthemoney/cli/util.py +3 -3
- followthemoney/dataset/__init__.py +2 -2
- followthemoney/dataset/dataset.py +2 -0
- followthemoney/proxy.py +21 -3
- followthemoney/statement/entity.py +21 -7
- followthemoney/statement/serialize.py +6 -2
- followthemoney/types/common.py +1 -3
- followthemoney/types/json.py +1 -2
- followthemoney/types/string.py +3 -4
- followthemoney/util.py +2 -0
- {followthemoney-4.5.0.dist-info → followthemoney-4.5.2.dist-info}/METADATA +1 -1
- {followthemoney-4.5.0.dist-info → followthemoney-4.5.2.dist-info}/RECORD +17 -17
- {followthemoney-4.5.0.dist-info → followthemoney-4.5.2.dist-info}/WHEEL +0 -0
- {followthemoney-4.5.0.dist-info → followthemoney-4.5.2.dist-info}/entry_points.txt +0 -0
- {followthemoney-4.5.0.dist-info → followthemoney-4.5.2.dist-info}/licenses/LICENSE +0 -0
followthemoney/__init__.py
CHANGED
|
@@ -2,14 +2,14 @@ from followthemoney.entity import ValueEntity, VE
|
|
|
2
2
|
from followthemoney.model import Model
|
|
3
3
|
from followthemoney.schema import Schema
|
|
4
4
|
from followthemoney.property import Property
|
|
5
|
-
from followthemoney.types import registry
|
|
5
|
+
from followthemoney.types import registry, PropertyType
|
|
6
6
|
from followthemoney.value import Value, Values
|
|
7
7
|
from followthemoney.proxy import EntityProxy, E
|
|
8
8
|
from followthemoney.statement import Statement, StatementEntity, SE
|
|
9
|
-
from followthemoney.dataset import Dataset,
|
|
9
|
+
from followthemoney.dataset import Dataset, UndefinedDataset, DS
|
|
10
10
|
from followthemoney.util import set_model_locale
|
|
11
11
|
|
|
12
|
-
__version__ = "4.5.
|
|
12
|
+
__version__ = "4.5.2"
|
|
13
13
|
|
|
14
14
|
# Data model singleton
|
|
15
15
|
model = Model.instance()
|
|
@@ -20,13 +20,14 @@ __all__ = [
|
|
|
20
20
|
"Model",
|
|
21
21
|
"Schema",
|
|
22
22
|
"Property",
|
|
23
|
+
"PropertyType",
|
|
23
24
|
"Value",
|
|
24
25
|
"Values",
|
|
25
26
|
"EntityProxy",
|
|
26
27
|
"E",
|
|
27
28
|
"registry",
|
|
28
29
|
"Dataset",
|
|
29
|
-
"
|
|
30
|
+
"UndefinedDataset",
|
|
30
31
|
"DS",
|
|
31
32
|
"Statement",
|
|
32
33
|
"StatementEntity",
|
followthemoney/cli/statement.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import click
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from typing import Generator, List
|
|
3
|
+
from typing import Generator, List, Optional
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
from followthemoney.cli.cli import cli
|
|
7
7
|
from followthemoney.cli.util import InPath, OutPath
|
|
8
8
|
from followthemoney.cli.util import path_entities, write_entity, path_writer
|
|
9
|
-
from followthemoney.dataset import Dataset,
|
|
9
|
+
from followthemoney.dataset import Dataset, UndefinedDataset
|
|
10
10
|
from followthemoney.statement import Statement, StatementEntity
|
|
11
11
|
from followthemoney.statement import FORMATS, CSV
|
|
12
12
|
from followthemoney.statement import write_statements
|
|
@@ -16,12 +16,18 @@ from followthemoney.statement import read_path_statements
|
|
|
16
16
|
@cli.command("statements", help="Export entities to statements")
|
|
17
17
|
@click.argument("path", type=InPath)
|
|
18
18
|
@click.option("-o", "--outpath", type=OutPath, default="-")
|
|
19
|
-
@click.option("-d", "--dataset", type=str
|
|
19
|
+
@click.option("-d", "--dataset", type=str)
|
|
20
20
|
@click.option("-f", "--format", type=click.Choice(FORMATS), default=CSV)
|
|
21
|
-
def entity_statements(
|
|
21
|
+
def entity_statements(
|
|
22
|
+
path: Path, outpath: Path, dataset: Optional[str], format: str
|
|
23
|
+
) -> None:
|
|
22
24
|
def make_statements() -> Generator[Statement, None, None]:
|
|
25
|
+
dataset_ = dataset or Dataset.UNDEFINED
|
|
23
26
|
for entity in path_entities(path, StatementEntity):
|
|
24
|
-
|
|
27
|
+
for stmt in Statement.from_entity(entity, dataset=dataset_):
|
|
28
|
+
if dataset is not None:
|
|
29
|
+
stmt = stmt.clone(dataset=dataset)
|
|
30
|
+
yield stmt
|
|
25
31
|
|
|
26
32
|
with path_writer(outpath) as outfh:
|
|
27
33
|
write_statements(outfh, format, make_statements())
|
|
@@ -43,12 +49,12 @@ def format_statements(
|
|
|
43
49
|
@cli.command("aggregate-statements", help="Roll up statements into entities")
|
|
44
50
|
@click.option("-i", "--infile", type=InPath, default="-")
|
|
45
51
|
@click.option("-o", "--outpath", type=OutPath, default="-")
|
|
46
|
-
@click.option("-d", "--dataset", type=str, default=
|
|
52
|
+
@click.option("-d", "--dataset", type=str, default=UndefinedDataset.name)
|
|
47
53
|
@click.option("-f", "--format", type=click.Choice(FORMATS), default=CSV)
|
|
48
54
|
def statements_aggregate(
|
|
49
55
|
infile: Path, outpath: Path, dataset: str, format: str
|
|
50
56
|
) -> None:
|
|
51
|
-
dataset_ = Dataset.make({"name": dataset
|
|
57
|
+
dataset_ = Dataset.make({"name": dataset})
|
|
52
58
|
with path_writer(outpath) as outfh:
|
|
53
59
|
statements: List[Statement] = []
|
|
54
60
|
for stmt in read_path_statements(infile, format=format):
|
followthemoney/cli/util.py
CHANGED
|
@@ -6,7 +6,7 @@ import click
|
|
|
6
6
|
import orjson
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from warnings import warn
|
|
9
|
-
from typing import Any, BinaryIO, Generator, Optional, TextIO, Type
|
|
9
|
+
from typing import Any, BinaryIO, Generator, List, Optional, TextIO, Type
|
|
10
10
|
from banal import is_mapping, is_listish, ensure_list
|
|
11
11
|
|
|
12
12
|
from followthemoney.export.common import Exporter
|
|
@@ -26,7 +26,7 @@ def write_object(stream: TextIO, obj: Any) -> None:
|
|
|
26
26
|
stream.write(data + "\n")
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
def write_entity(fh: BinaryIO, entity:
|
|
29
|
+
def write_entity(fh: BinaryIO, entity: EntityProxy) -> None:
|
|
30
30
|
data = entity.to_dict()
|
|
31
31
|
entity_id = data.pop("id")
|
|
32
32
|
assert entity_id is not None, data
|
|
@@ -131,7 +131,7 @@ def resolve_includes(file_path: PathLike, data: Any) -> Any:
|
|
|
131
131
|
if is_listish(data):
|
|
132
132
|
return [resolve_includes(file_path, i) for i in data]
|
|
133
133
|
if is_mapping(data):
|
|
134
|
-
include_paths = ensure_list(data.pop("include", []))
|
|
134
|
+
include_paths: List[str] = ensure_list(data.pop("include", []))
|
|
135
135
|
for include_path in include_paths:
|
|
136
136
|
dir_prefix = os.path.dirname(file_path)
|
|
137
137
|
include_path = os.path.join(dir_prefix, include_path)
|
|
@@ -4,11 +4,11 @@ from followthemoney.dataset.resource import DataResource
|
|
|
4
4
|
from followthemoney.dataset.publisher import DataPublisher
|
|
5
5
|
from followthemoney.dataset.coverage import DataCoverage
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
UndefinedDataset = Dataset.make({"name": Dataset.UNDEFINED})
|
|
8
8
|
|
|
9
9
|
__all__ = [
|
|
10
10
|
"Dataset",
|
|
11
|
-
"
|
|
11
|
+
"UndefinedDataset",
|
|
12
12
|
"DataCatalog",
|
|
13
13
|
"DataResource",
|
|
14
14
|
"DataPublisher",
|
|
@@ -83,6 +83,8 @@ class Dataset:
|
|
|
83
83
|
"""A container for entities, often from one source or related to one topic.
|
|
84
84
|
A dataset is a set of data, sez W3C."""
|
|
85
85
|
|
|
86
|
+
UNDEFINED = "undefined"
|
|
87
|
+
|
|
86
88
|
def __init__(self: Self, data: Dict[str, Any]) -> None:
|
|
87
89
|
self.model = DatasetModel.model_validate(data)
|
|
88
90
|
self.name = self.model.name
|
followthemoney/proxy.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import hashlib
|
|
2
2
|
import logging
|
|
3
|
-
from typing import TYPE_CHECKING,
|
|
3
|
+
from typing import TYPE_CHECKING, Iterable, Any, cast
|
|
4
4
|
from typing import Dict, Generator, List, Optional, Set, Tuple, Union, Type, TypeVar
|
|
5
5
|
from itertools import product
|
|
6
6
|
from banal import ensure_dict
|
|
@@ -117,11 +117,28 @@ class EntityProxy(object):
|
|
|
117
117
|
an empty list instead of raising an error.
|
|
118
118
|
:return: A list of values.
|
|
119
119
|
"""
|
|
120
|
+
if prop in self.schema.properties:
|
|
121
|
+
return self._properties.get(prop, []) # type: ignore
|
|
122
|
+
|
|
120
123
|
prop_name = self._prop_name(prop, quiet=quiet)
|
|
121
124
|
if prop_name is None:
|
|
122
125
|
return []
|
|
123
126
|
return self._properties.get(prop_name, [])
|
|
124
127
|
|
|
128
|
+
def get_prop(self, prop: Property) -> Iterable[str]:
|
|
129
|
+
"""Get all values of a property, returning an empty list if the property
|
|
130
|
+
does not exist. This has better performance characteristics than `get()`
|
|
131
|
+
as it does not need to resolve the property name.
|
|
132
|
+
|
|
133
|
+
:param prop: can be given as a name or an instance of
|
|
134
|
+
:class:`~followthemoney.property.Property`.
|
|
135
|
+
:return: An iterable of values.
|
|
136
|
+
"""
|
|
137
|
+
try:
|
|
138
|
+
return self._properties[prop.name]
|
|
139
|
+
except KeyError:
|
|
140
|
+
return []
|
|
141
|
+
|
|
125
142
|
def first(self, prop: P, quiet: bool = False) -> Optional[str]:
|
|
126
143
|
"""Get only the first value set for the property.
|
|
127
144
|
|
|
@@ -311,10 +328,11 @@ class EntityProxy(object):
|
|
|
311
328
|
combined = set()
|
|
312
329
|
for prop_name, values in self._properties.items():
|
|
313
330
|
prop = self.schema.properties[prop_name]
|
|
331
|
+
if prop.type is not type_:
|
|
332
|
+
continue
|
|
314
333
|
if matchable and not prop.matchable:
|
|
315
334
|
continue
|
|
316
|
-
|
|
317
|
-
combined.update(values)
|
|
335
|
+
combined.update(values)
|
|
318
336
|
return list(combined)
|
|
319
337
|
|
|
320
338
|
@property
|
|
@@ -15,7 +15,7 @@ from followthemoney.proxy import P
|
|
|
15
15
|
from followthemoney.types import registry
|
|
16
16
|
from followthemoney.value import string_list, Values
|
|
17
17
|
from followthemoney.proxy import EntityProxy
|
|
18
|
-
from followthemoney.dataset import Dataset,
|
|
18
|
+
from followthemoney.dataset import Dataset, UndefinedDataset
|
|
19
19
|
from followthemoney.statement.statement import Statement
|
|
20
20
|
from followthemoney.statement.util import BASE_ID
|
|
21
21
|
|
|
@@ -184,12 +184,24 @@ class StatementEntity(EntityProxy):
|
|
|
184
184
|
return []
|
|
185
185
|
return list({s.value for s in self._statements[prop_name]})
|
|
186
186
|
|
|
187
|
+
def get_prop(self, prop: Property) -> Iterable[str]:
|
|
188
|
+
try:
|
|
189
|
+
statements = self._statements[prop.name]
|
|
190
|
+
return {s.value for s in statements}
|
|
191
|
+
except KeyError:
|
|
192
|
+
return []
|
|
193
|
+
|
|
187
194
|
def get_statements(self, prop: P, quiet: bool = False) -> List[Statement]:
|
|
188
195
|
prop_name = self._prop_name(prop, quiet=quiet)
|
|
189
196
|
if prop_name is None or prop_name not in self._statements:
|
|
190
197
|
return []
|
|
191
198
|
return list(self._statements[prop_name])
|
|
192
199
|
|
|
200
|
+
@property
|
|
201
|
+
def has_statements(self) -> bool:
|
|
202
|
+
"""Return whether the entity has any statements."""
|
|
203
|
+
return len(self._statements) > 0
|
|
204
|
+
|
|
193
205
|
def set(
|
|
194
206
|
self,
|
|
195
207
|
prop: P,
|
|
@@ -336,14 +348,16 @@ class StatementEntity(EntityProxy):
|
|
|
336
348
|
def get_type_statements(
|
|
337
349
|
self, type_: PropertyType, matchable: bool = False
|
|
338
350
|
) -> List[Statement]:
|
|
339
|
-
combined = []
|
|
351
|
+
combined: List[Statement] = []
|
|
340
352
|
for prop_name, statements in self._statements.items():
|
|
341
353
|
prop = self.schema.properties[prop_name]
|
|
354
|
+
# Used in performance-critical code paths:
|
|
355
|
+
if prop.type is not type_:
|
|
356
|
+
continue
|
|
342
357
|
if matchable and not prop.matchable:
|
|
343
358
|
continue
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
combined.append(statement)
|
|
359
|
+
for statement in statements:
|
|
360
|
+
combined.append(statement)
|
|
347
361
|
return combined
|
|
348
362
|
|
|
349
363
|
@property
|
|
@@ -433,7 +447,7 @@ class StatementEntity(EntityProxy):
|
|
|
433
447
|
origins.add(stmt.origin)
|
|
434
448
|
|
|
435
449
|
data["referents"] = list(referents)
|
|
436
|
-
data["datasets"] =
|
|
450
|
+
data["datasets"] = [d for d in datasets if d != Dataset.UNDEFINED]
|
|
437
451
|
if origins:
|
|
438
452
|
data["origin"] = list(origins)
|
|
439
453
|
|
|
@@ -484,7 +498,7 @@ class StatementEntity(EntityProxy):
|
|
|
484
498
|
default_dataset: Optional[Dataset] = None,
|
|
485
499
|
) -> SE:
|
|
486
500
|
# Exists only for backwards compatibility.
|
|
487
|
-
dataset = default_dataset or
|
|
501
|
+
dataset = default_dataset or UndefinedDataset
|
|
488
502
|
return cls(dataset, data, cleaned=cleaned)
|
|
489
503
|
|
|
490
504
|
@classmethod
|
|
@@ -12,6 +12,7 @@ from rigour.env import ENCODING
|
|
|
12
12
|
|
|
13
13
|
from followthemoney.statement.statement import Statement, StatementDict
|
|
14
14
|
from followthemoney.statement.util import unpack_prop
|
|
15
|
+
from followthemoney.util import ENTITY_VALUE_MAX, PROP_VALUE_MAX
|
|
15
16
|
|
|
16
17
|
log = logging.getLogger(__name__)
|
|
17
18
|
|
|
@@ -49,11 +50,12 @@ LEGACY_PACK_COLUMNS = [
|
|
|
49
50
|
"first_seen",
|
|
50
51
|
"last_seen",
|
|
51
52
|
]
|
|
53
|
+
csv.field_size_limit(PROP_VALUE_MAX)
|
|
52
54
|
|
|
53
55
|
|
|
54
56
|
def read_json_statements(
|
|
55
57
|
fh: BinaryIO,
|
|
56
|
-
max_line: int =
|
|
58
|
+
max_line: int = ENTITY_VALUE_MAX,
|
|
57
59
|
) -> Generator[Statement, None, None]:
|
|
58
60
|
while line := fh.readline(max_line):
|
|
59
61
|
data = orjson.loads(line)
|
|
@@ -69,6 +71,8 @@ def read_csv_statements(fh: BinaryIO) -> Generator[Statement, None, None]:
|
|
|
69
71
|
data["lang"] = None
|
|
70
72
|
if row.get("original_value") == "":
|
|
71
73
|
data["original_value"] = None
|
|
74
|
+
if row.get("origin") == "":
|
|
75
|
+
data["origin"] = None
|
|
72
76
|
yield Statement.from_dict(data)
|
|
73
77
|
|
|
74
78
|
|
|
@@ -101,7 +105,7 @@ def read_pack_statements_decoded(fh: TextIO) -> Generator[Statement, None, None]
|
|
|
101
105
|
dataset=data["dataset"],
|
|
102
106
|
lang=data["lang"] or None,
|
|
103
107
|
original_value=data["original_value"] or None,
|
|
104
|
-
origin=data.get("origin"),
|
|
108
|
+
origin=data.get("origin") or None,
|
|
105
109
|
first_seen=data["first_seen"],
|
|
106
110
|
external=data["external"] == "t",
|
|
107
111
|
canonical_id=data["entity_id"],
|
followthemoney/types/common.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from inspect import cleandoc
|
|
2
2
|
from itertools import product
|
|
3
3
|
from babel.core import Locale
|
|
4
|
-
from banal import ensure_list
|
|
5
4
|
from normality import stringify
|
|
6
5
|
from typing import Any, Dict, Optional, Sequence, Callable, TYPE_CHECKING, TypedDict
|
|
7
6
|
|
|
@@ -115,7 +114,6 @@ class PropertyType(object):
|
|
|
115
114
|
"""Helper function for converting multi-valued FtM data into formats that
|
|
116
115
|
allow only a single value per field (e.g. CSV). This is not fully reversible
|
|
117
116
|
and should be used as a last option."""
|
|
118
|
-
values = ensure_list(values)
|
|
119
117
|
return "; ".join(values)
|
|
120
118
|
|
|
121
119
|
def _specificity(self, value: str) -> float:
|
|
@@ -154,7 +152,7 @@ class PropertyType(object):
|
|
|
154
152
|
) -> float:
|
|
155
153
|
"""Compare two sets of values and select the highest-scored result."""
|
|
156
154
|
results = []
|
|
157
|
-
for le, ri in product(
|
|
155
|
+
for le, ri in product(left, right):
|
|
158
156
|
results.append(self.compare(le, ri))
|
|
159
157
|
if not len(results):
|
|
160
158
|
return 0.0
|
followthemoney/types/json.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from typing import Any, Optional, Sequence, TYPE_CHECKING
|
|
3
|
-
from banal import ensure_list
|
|
4
3
|
|
|
5
4
|
from followthemoney.types.common import PropertyType
|
|
6
5
|
from followthemoney.util import sanitize_text, defer as _
|
|
@@ -48,7 +47,7 @@ class JsonType(PropertyType):
|
|
|
48
47
|
|
|
49
48
|
def join(self, values: Sequence[str]) -> str:
|
|
50
49
|
"""Turn multiple values into a JSON array."""
|
|
51
|
-
values = [self.unpack(v) for v in
|
|
50
|
+
values = [self.unpack(v) for v in values]
|
|
52
51
|
data = self.pack(values)
|
|
53
52
|
if data is None:
|
|
54
53
|
return "[]"
|
followthemoney/types/string.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from followthemoney.types.common import PropertyType
|
|
2
|
-
from followthemoney.util import const, defer as _
|
|
3
|
-
from followthemoney.util import MEGABYTE
|
|
2
|
+
from followthemoney.util import PROP_VALUE_MAX, const, defer as _
|
|
4
3
|
|
|
5
4
|
|
|
6
5
|
class StringType(PropertyType):
|
|
@@ -24,7 +23,7 @@ class TextType(StringType):
|
|
|
24
23
|
name = "text"
|
|
25
24
|
label = _("Text")
|
|
26
25
|
plural = _("Texts")
|
|
27
|
-
total_size =
|
|
26
|
+
total_size = PROP_VALUE_MAX
|
|
28
27
|
max_length = 65000
|
|
29
28
|
|
|
30
29
|
|
|
@@ -39,5 +38,5 @@ class HTMLType(StringType):
|
|
|
39
38
|
name = const("html")
|
|
40
39
|
label = _("HTML")
|
|
41
40
|
plural = _("HTMLs")
|
|
42
|
-
total_size =
|
|
41
|
+
total_size = PROP_VALUE_MAX
|
|
43
42
|
max_length = 65000
|
followthemoney/util.py
CHANGED
|
@@ -14,6 +14,8 @@ from rigour.env import ENCODING
|
|
|
14
14
|
from banal import is_mapping, unique_list, ensure_list
|
|
15
15
|
|
|
16
16
|
MEGABYTE = 1024 * 1024
|
|
17
|
+
PROP_VALUE_MAX = 30 * MEGABYTE
|
|
18
|
+
ENTITY_VALUE_MAX = 50 * MEGABYTE
|
|
17
19
|
HASH_ENCODING = "utf-8"
|
|
18
20
|
DEFAULT_LOCALE = "en"
|
|
19
21
|
ENTITY_ID_LEN = 200
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: followthemoney
|
|
3
|
-
Version: 4.5.
|
|
3
|
+
Version: 4.5.2
|
|
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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
followthemoney/__init__.py,sha256=
|
|
1
|
+
followthemoney/__init__.py,sha256=nl5VzBB-U4sYL6j-D7z6ndi6LcvdcZ-ErMyjWbZnFhk,894
|
|
2
2
|
followthemoney/compare.py,sha256=6y6fqtbbfW7ee4_EVXPcKCIr75GjPqXvtHfvExJ-KK0,6119
|
|
3
3
|
followthemoney/entity.py,sha256=biAjuuHlwsVT02imAsaWP0YtgdfU8skCntzBU3mgJpg,4052
|
|
4
4
|
followthemoney/exc.py,sha256=GyMgwY4QVm87hLevDfV7gM1MJsDqfNCi_UQw7F_A8X8,858
|
|
@@ -10,11 +10,11 @@ followthemoney/names.py,sha256=LODQqExKEHdH4z6Mmbhlm0KeKRzGcptaSWzYXZ7lONI,1120
|
|
|
10
10
|
followthemoney/namespace.py,sha256=utggu9IGA8bhgEYom3OUB1KxkAJR_TrMNbY5MUF_db8,4536
|
|
11
11
|
followthemoney/ontology.py,sha256=WWY_PYQGl5Ket4zZBuZglzQxD2Bh9UqHok6GJNNX7GA,3001
|
|
12
12
|
followthemoney/property.py,sha256=1w7p9aKLxRqFRnl3PlssqmvulSErl_0D5T2SefT3UFU,8675
|
|
13
|
-
followthemoney/proxy.py,sha256=
|
|
13
|
+
followthemoney/proxy.py,sha256=nA8trRbMcPfbmoEwHQK8kdiEbZqOpTuwT_GfQkfZj8U,21415
|
|
14
14
|
followthemoney/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
followthemoney/schema.py,sha256=dwZg0eZF7yaxP9fJ5NQUKWadWZYTo9U-sVzzXZn_6do,18500
|
|
16
16
|
followthemoney/settings.py,sha256=wkwrkDPypsAICLo-d7l-zpKrKe_fTVYPllZO-RX3oGM,507
|
|
17
|
-
followthemoney/util.py,sha256=
|
|
17
|
+
followthemoney/util.py,sha256=hkUe2IOCxgZEppANr1vGcMChC4t9RcudSDHuRH2D_Hg,4214
|
|
18
18
|
followthemoney/value.py,sha256=BJ4Sj5Tg2kMrslR6FjQUr96d8Kt75U7ny9NgzVGT0ZE,2335
|
|
19
19
|
followthemoney/cli/__init__.py,sha256=0mmz84uhXRp2qUn3syKnDXofU3MMAAe291s7htqX0Bg,187
|
|
20
20
|
followthemoney/cli/aggregate.py,sha256=xQTFpU3cVVj7fplpX4OJVrRlTVpn6b9kBr_Vb87pKfg,2164
|
|
@@ -22,12 +22,12 @@ followthemoney/cli/cli.py,sha256=cWSQIrMS0b40uzIveoIfR9CEBbQEwcfonYhDTpioqBM,358
|
|
|
22
22
|
followthemoney/cli/exports.py,sha256=arWgIfDhMdEEoAnANOPbgirL68qAR2pCt0otz9MEXmg,4074
|
|
23
23
|
followthemoney/cli/mapping.py,sha256=PGQ-9T5ss6w6qnZg7IjUZZ3PplY15CcPSxZxkyMFLDM,3370
|
|
24
24
|
followthemoney/cli/sieve.py,sha256=wLB35fCVp1ArZ7FDTbARevBk8jH4vnp65fyBZU7Lk_k,1937
|
|
25
|
-
followthemoney/cli/statement.py,sha256=
|
|
26
|
-
followthemoney/cli/util.py,sha256=
|
|
27
|
-
followthemoney/dataset/__init__.py,sha256=
|
|
25
|
+
followthemoney/cli/statement.py,sha256=g1Ksi3iS-YsuVA40AnKpIsVDPRc4SovAe1JCoXNIW4g,3041
|
|
26
|
+
followthemoney/cli/util.py,sha256=EyhR6qLIfueG1OK5_DwDA_7mcDPnhNs5dyijbP3WWZY,4762
|
|
27
|
+
followthemoney/dataset/__init__.py,sha256=1-I1MkuTvu72tpZZcxD2GK-jq0_TwNJ29zaFQIo2ORQ,489
|
|
28
28
|
followthemoney/dataset/catalog.py,sha256=bIpxr0jvJeutNSmCaXREQac7TyvZak2Y_QoCFdCM0d4,3001
|
|
29
29
|
followthemoney/dataset/coverage.py,sha256=rBnKs7VngCtIuaDqrF5D0ygCHg8NAMkYbmtl7336PSI,724
|
|
30
|
-
followthemoney/dataset/dataset.py,sha256=
|
|
30
|
+
followthemoney/dataset/dataset.py,sha256=TV3enQCWJCo2cXZCEz_yPWsF-09W0p_A3RSroRbPWV8,5524
|
|
31
31
|
followthemoney/dataset/publisher.py,sha256=nexZe9XexV8WI5Id999vf5OH_DPUmiKQ_GT3c59eF44,893
|
|
32
32
|
followthemoney/dataset/resource.py,sha256=S_-tNjMwHQ8LcSOsZO_xhXD-vLK90wyxtIRBbyCJ0Xo,1164
|
|
33
33
|
followthemoney/dataset/util.py,sha256=mfVTXdbNnWly6cXo4SjNzHuJK1c1uNBwULYOVg1gK5I,1617
|
|
@@ -115,8 +115,8 @@ followthemoney/schema/Vessel.yaml,sha256=zWHUfSK8g6Pz58ZyCaK0AFJ4u_UHjEIUGC4c_7o
|
|
|
115
115
|
followthemoney/schema/Video.yaml,sha256=LY3DYMWTHXiAhL0hxBCNCz50cp2sPbUlEhhig5Fbjos,327
|
|
116
116
|
followthemoney/schema/Workbook.yaml,sha256=iikWPElz4klA7SkWH7eae6xqhbkMCIP_3zdeXzFEMU0,354
|
|
117
117
|
followthemoney/statement/__init__.py,sha256=7m2VUCAuqNZXIY0WFJRFkw5UG14QuxATL4f_xbqKwhw,633
|
|
118
|
-
followthemoney/statement/entity.py,sha256=
|
|
119
|
-
followthemoney/statement/serialize.py,sha256=
|
|
118
|
+
followthemoney/statement/entity.py,sha256=vpiHsg2uOXnyIDYHRfMr0TWoOvGSzbiEfO2qHx2txQ8,20072
|
|
119
|
+
followthemoney/statement/serialize.py,sha256=fbvTVSvBeeusXIXWw9-_3NZaoncDvEnet6my6diUj7k,7566
|
|
120
120
|
followthemoney/statement/statement.py,sha256=bAwrrKyYRdJVxRGuXDQIOA7cdEngk1NKUaij_gAwSd4,11876
|
|
121
121
|
followthemoney/statement/util.py,sha256=jHBwK3FIBynUJZRlBBOHayalAFrqpXf2f2JwkHi0zAU,1450
|
|
122
122
|
followthemoney/translations/messages.pot,sha256=JhtY9NJ9wP_EAX4APxOqMyvKcX53oIC9kAxBsliJkf4,107703
|
|
@@ -145,7 +145,7 @@ followthemoney/translations/tr/LC_MESSAGES/followthemoney.po,sha256=AZC3marhtVVq
|
|
|
145
145
|
followthemoney/types/__init__.py,sha256=rWwQeiuMh2BNIuvhpMfJ4bPADDvt9Axu1eedvNFi0qY,3350
|
|
146
146
|
followthemoney/types/address.py,sha256=Gc-hqz00dRRkeANqkyPD2wtt7ksR9wMf4CX-U-5XvMo,2214
|
|
147
147
|
followthemoney/types/checksum.py,sha256=_0ev2Wwtd4iX_bLz0Lu-xcJIxNfH_V9kBKKtuZhoAwg,802
|
|
148
|
-
followthemoney/types/common.py,sha256=
|
|
148
|
+
followthemoney/types/common.py,sha256=d2z3E0z93SZRU6mxlQ-ShQdaNU9ilD0FvaE5MpJwxhE,9988
|
|
149
149
|
followthemoney/types/country.py,sha256=pwDiI_ipts9Oi2U7fHALYMJPCJHOqyI_2Liq7XI2XrA,2086
|
|
150
150
|
followthemoney/types/date.py,sha256=SGk8q8qICIrA5Lf6wPbDU6v6oJYEiu1dZFZ18BO7i80,3551
|
|
151
151
|
followthemoney/types/email.py,sha256=L3RTYrMABlNQF7hCynXGfzoj6YNEHW5JAY_BwuhoZdA,3375
|
|
@@ -153,17 +153,17 @@ followthemoney/types/entity.py,sha256=56h6x8Ct7hWZIC3BjZHmRKGy9Ff2vuULNWH3xDRsKi
|
|
|
153
153
|
followthemoney/types/gender.py,sha256=XY9us98Sk25O1xnHN-88tbv9pHy6Mn7SR8GRYi6v5gI,1683
|
|
154
154
|
followthemoney/types/identifier.py,sha256=TYJwE7urjHFxEcDuiZMxGoCN6n34rAIdCt5_96Y7vI0,2198
|
|
155
155
|
followthemoney/types/ip.py,sha256=rCXkRrh_jDeWAhswCgSe6Z4uhIW7yvLAxIEw4x1SM3A,1279
|
|
156
|
-
followthemoney/types/json.py,sha256=
|
|
156
|
+
followthemoney/types/json.py,sha256=8aKPnDXiNHAh-h96D1rxFaM_FyB6O_LVBptFn90RnvU,1633
|
|
157
157
|
followthemoney/types/language.py,sha256=ymEXaHAPIZGlGySUqzadB7tMB6mW1ASsl1G6EtqKdls,2730
|
|
158
158
|
followthemoney/types/mimetype.py,sha256=oqVP8EfGckPAI3WAziHomp6oUN7KXdIPWzGZPsRtIA8,1242
|
|
159
159
|
followthemoney/types/name.py,sha256=zd0aC4VGp1SYUI8Rj0-ZXlrpUI7ZcnJIljZqsEsV-CY,2363
|
|
160
160
|
followthemoney/types/number.py,sha256=vpAyhmc7UQlIm8h7Z5k8k4cTk37ykRF-AgYA1r_g1QQ,3934
|
|
161
161
|
followthemoney/types/phone.py,sha256=_HanfxxTV7jp75gZO2evBc9HWwQTxEMQRaoVDcoXDIQ,3790
|
|
162
|
-
followthemoney/types/string.py,sha256=
|
|
162
|
+
followthemoney/types/string.py,sha256=1h92OUSgVVxu40N4BCiBZvX1VXFmvEgwtfICO92x9kc,1193
|
|
163
163
|
followthemoney/types/topic.py,sha256=9FIH_WmwVOFg1CJRBF4KeE6vNTn-QQkzsKU5XaMqNJ0,4604
|
|
164
164
|
followthemoney/types/url.py,sha256=sSHKtzvm4kc-VTvNCPIDykOG1hUoawhORj6Bklo0a2A,1434
|
|
165
|
-
followthemoney-4.5.
|
|
166
|
-
followthemoney-4.5.
|
|
167
|
-
followthemoney-4.5.
|
|
168
|
-
followthemoney-4.5.
|
|
169
|
-
followthemoney-4.5.
|
|
165
|
+
followthemoney-4.5.2.dist-info/METADATA,sha256=Z568uQ_TOejHVvbnqmRZKHIIySLcx8bd58l6K3cTCMo,6747
|
|
166
|
+
followthemoney-4.5.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
167
|
+
followthemoney-4.5.2.dist-info/entry_points.txt,sha256=caoFTlf213jhg5sz3TNSofutjUTzaKtWATuSIdd9Cps,653
|
|
168
|
+
followthemoney-4.5.2.dist-info/licenses/LICENSE,sha256=H6_EVXisnJC0-18CjXIaqrBSFq_VH3OnS7u3dccOv6g,1148
|
|
169
|
+
followthemoney-4.5.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|