followthemoney 4.0.1__py3-none-any.whl → 4.0.3__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.
@@ -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.1"
12
+ __version__ = "4.0.3"
13
13
 
14
14
  # Data model singleton
15
15
  model = Model.instance()
@@ -68,10 +68,8 @@ class Dataset:
68
68
  """A container for entities, often from one source or related to one topic.
69
69
  A dataset is a set of data, sez W3C."""
70
70
 
71
- Model = DatasetModel
72
-
73
71
  def __init__(self: Self, data: Dict[str, Any]) -> None:
74
- self.model = self.Model.model_validate(data)
72
+ self.model = DatasetModel.model_validate(data)
75
73
  self.name = self.model.name
76
74
  self.children: Set[Self] = set()
77
75
 
@@ -1,6 +1,6 @@
1
1
  from typing import Optional
2
2
 
3
- from pydantic import BaseModel
3
+ from pydantic import BaseModel, computed_field
4
4
 
5
5
  from followthemoney.dataset.util import CountryCode, Url
6
6
  from followthemoney.types import registry
@@ -18,6 +18,8 @@ class DataPublisher(BaseModel):
18
18
  official: Optional[bool] = False
19
19
  logo_url: Optional[Url] = None
20
20
 
21
+ # Re: the type: ignore, see https://github.com/python/mypy/issues/1362 and https://docs.pydantic.dev/2.0/usage/computed_fields/
22
+ @computed_field # type: ignore[prop-decorator]
21
23
  @property
22
24
  def country_label(self) -> Optional[str]:
23
25
  if self.country is None:
@@ -1,5 +1,5 @@
1
1
  from typing import Optional
2
- from pydantic import BaseModel, field_validator
2
+ from pydantic import BaseModel, field_validator, computed_field
3
3
 
4
4
  from followthemoney.dataset.util import Url, DateTimeISO
5
5
  from followthemoney.types import registry
@@ -19,10 +19,13 @@ class DataResource(BaseModel):
19
19
  @field_validator("mime_type", mode="after")
20
20
  @classmethod
21
21
  def ensure_mime_type(cls, value: str) -> Optional[str]:
22
- if not registry.mimetype.validate(value):
22
+ cleaned = registry.mimetype.clean_text(value)
23
+ if cleaned is None:
23
24
  raise ValueError(f"Invalid MIME type: {value!r}")
24
- return value
25
+ return cleaned
25
26
 
27
+ # Re: the type: ignore, see https://github.com/python/mypy/issues/1362 and https://docs.pydantic.dev/2.0/usage/computed_fields/
28
+ @computed_field # type: ignore[prop-decorator]
26
29
  @property
27
30
  def mime_type_label(self) -> Optional[str]:
28
31
  if self.mime_type is None:
followthemoney/entity.py CHANGED
@@ -44,15 +44,20 @@ class ValueEntity(EntityProxy):
44
44
  if stmt_data["prop"] != BASE_ID:
45
45
  self.add(stmt_data["prop"], stmt_data["value"])
46
46
 
47
- def merge(self: "ValueEntity", other: "ValueEntity") -> "ValueEntity":
47
+ def merge(self: VE, other: EntityProxy) -> VE:
48
48
  merged = super().merge(other)
49
- merged._caption = pick_name(_defined(self._caption, other._caption))
50
- merged.referents.update(other.referents)
51
- merged.datasets.update(other.datasets)
52
- self.first_seen = min(_defined(self.first_seen, other.first_seen), default=None)
53
- self.last_seen = max(_defined(self.last_seen, other.last_seen), default=None)
54
- changed = _defined(self.last_change, other.last_change)
55
- self.last_change = max(changed, default=None)
49
+ if isinstance(other, ValueEntity):
50
+ merged._caption = pick_name(_defined(self._caption, other._caption))
51
+ merged.referents.update(other.referents)
52
+ merged.datasets.update(other.datasets)
53
+ merged.first_seen = min(
54
+ _defined(self.first_seen, other.first_seen), default=None
55
+ )
56
+ merged.last_seen = max(
57
+ _defined(self.last_seen, other.last_seen), default=None
58
+ )
59
+ changed = _defined(self.last_change, other.last_change)
60
+ merged.last_change = max(changed, default=None)
56
61
  return merged
57
62
 
58
63
  def to_dict(self) -> Dict[str, Any]:
followthemoney/proxy.py CHANGED
@@ -421,7 +421,7 @@ class EntityProxy(object):
421
421
  """Make a deep copy of the current entity proxy."""
422
422
  return self.__class__.from_dict(self.to_dict())
423
423
 
424
- def merge(self: E, other: E) -> E:
424
+ def merge(self: E, other: "EntityProxy") -> E:
425
425
  """Merge another entity proxy into this one. This will try and find
426
426
  the common schema between both entities and then add all property
427
427
  values from the other entity into this one."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: followthemoney
3
- Version: 4.0.1
3
+ Version: 4.0.3
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,6 +1,6 @@
1
- followthemoney/__init__.py,sha256=UMJQnsCliiYxAhnQCvqSOCInreUI-bmpiReqDA7ZHhc,856
1
+ followthemoney/__init__.py,sha256=GmOdQXf1GougYiuFmDULXblg9PKnVRmTQkxLPGc1LgI,856
2
2
  followthemoney/compare.py,sha256=rtITMzJOXLDOSj7yKPfOxFaknIu6kRpiLDIM22zakpI,5619
3
- followthemoney/entity.py,sha256=GThAfNNZ4xdtvKTeue3GbtxCaBPngxhZDItpZnNHTtE,2932
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
6
6
  followthemoney/helpers.py,sha256=Btb6BlHg_c-qCXZo-NP_LURKG-qu-QD3Fj1ev_c7Xic,7956
@@ -10,7 +10,7 @@ followthemoney/names.py,sha256=LODQqExKEHdH4z6Mmbhlm0KeKRzGcptaSWzYXZ7lONI,1120
10
10
  followthemoney/namespace.py,sha256=cp7X8aGaZ8HHf7SOfHr2vJHPI2todz2DoyLdiZLNMyg,4472
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=Pj1GquUD7gdsM1fXb18QnYeT3E9N4ouhwJmPKNKd8ak,19605
13
+ followthemoney/proxy.py,sha256=KhByvSQk1BrZxTinKjjUsbEuD96RveQQ4LRzQIz6pUA,19617
14
14
  followthemoney/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  followthemoney/schema.py,sha256=WYnPE4Lego0pJHlojECEv0aO9Miw_YIvEb35HoDo4Zk,18087
16
16
  followthemoney/util.py,sha256=DhhcRilSetZpzvCew56AE6zNwenW5a4Y-KtmKM43rjc,4447
@@ -26,9 +26,9 @@ followthemoney/cli/util.py,sha256=C3nGMVY3-9JHSFLn3AGvTNcAdvGcgfFS-7jXIzKg6Ik,47
26
26
  followthemoney/dataset/__init__.py,sha256=rOKsI39dccDaYcSa7ASoNKkhmbFYUArxMCRqtrxy2iE,477
27
27
  followthemoney/dataset/catalog.py,sha256=bIpxr0jvJeutNSmCaXREQac7TyvZak2Y_QoCFdCM0d4,3001
28
28
  followthemoney/dataset/coverage.py,sha256=rBnKs7VngCtIuaDqrF5D0ygCHg8NAMkYbmtl7336PSI,724
29
- followthemoney/dataset/dataset.py,sha256=0zsynko9-xkbDFMh7xKlgSwytRT6bak1fHjCA6WguA4,4748
30
- followthemoney/dataset/publisher.py,sha256=eHbguTyDRVRC0ohD6phaLIm5d9Y-eJK6XYIQaelrnN4,694
31
- followthemoney/dataset/resource.py,sha256=SZpnY6TKNAFZHinaJNrEpT7YgdrCSMhYDT_UNn9Fmko,931
29
+ followthemoney/dataset/dataset.py,sha256=wWUzWsdzDW9qXLy8lS6Bpy08WMcaNU30oiMXU8jfo14,4724
30
+ followthemoney/dataset/publisher.py,sha256=nexZe9XexV8WI5Id999vf5OH_DPUmiKQ_GT3c59eF44,893
31
+ followthemoney/dataset/resource.py,sha256=S_-tNjMwHQ8LcSOsZO_xhXD-vLK90wyxtIRBbyCJ0Xo,1164
32
32
  followthemoney/dataset/util.py,sha256=ajUIBRF64dizdgy9LAp2abvFXRFOWCqQX9sDbToWFYo,1607
33
33
  followthemoney/export/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
34
  followthemoney/export/common.py,sha256=5b-Qlu3MaA0kSzzMAP93FAWncpgiioENnCnHikWYxhs,1021
@@ -160,8 +160,8 @@ followthemoney/types/phone.py,sha256=r8uRqWinS0CYnYBTs405k5gO4jeatUDgjdzzijoMKJE
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.1.dist-info/METADATA,sha256=Ctiv_lnTOczS2bc4C0UJzlqwS0BoiQQYym0GxtwOxlY,6791
164
- followthemoney-4.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
165
- followthemoney-4.0.1.dist-info/entry_points.txt,sha256=caoFTlf213jhg5sz3TNSofutjUTzaKtWATuSIdd9Cps,653
166
- followthemoney-4.0.1.dist-info/licenses/LICENSE,sha256=H6_EVXisnJC0-18CjXIaqrBSFq_VH3OnS7u3dccOv6g,1148
167
- followthemoney-4.0.1.dist-info/RECORD,,
163
+ followthemoney-4.0.3.dist-info/METADATA,sha256=yUOxdiPQceDy0QyIYrvGxXJq4CYCplr-fSFipACeg1s,6791
164
+ followthemoney-4.0.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
165
+ followthemoney-4.0.3.dist-info/entry_points.txt,sha256=caoFTlf213jhg5sz3TNSofutjUTzaKtWATuSIdd9Cps,653
166
+ followthemoney-4.0.3.dist-info/licenses/LICENSE,sha256=H6_EVXisnJC0-18CjXIaqrBSFq_VH3OnS7u3dccOv6g,1148
167
+ followthemoney-4.0.3.dist-info/RECORD,,