followthemoney 1.3.7__py3-none-any.whl → 3.8.1__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.
Files changed (186) hide show
  1. followthemoney/__init__.py +5 -3
  2. followthemoney/cli/__init__.py +17 -0
  3. followthemoney/cli/aggregate.py +56 -0
  4. followthemoney/cli/cli.py +88 -0
  5. followthemoney/cli/exports.py +121 -0
  6. followthemoney/cli/mapping.py +85 -0
  7. followthemoney/cli/sieve.py +67 -0
  8. followthemoney/cli/util.py +142 -0
  9. followthemoney/compare.py +130 -60
  10. followthemoney/exc.py +19 -6
  11. followthemoney/export/common.py +29 -0
  12. followthemoney/export/csv.py +82 -0
  13. followthemoney/export/excel.py +75 -0
  14. followthemoney/export/graph.py +79 -0
  15. followthemoney/export/neo4j.py +182 -0
  16. followthemoney/export/rdf.py +26 -0
  17. followthemoney/graph.py +308 -0
  18. followthemoney/helpers.py +212 -0
  19. followthemoney/mapping/__init__.py +1 -1
  20. followthemoney/mapping/csv.py +67 -35
  21. followthemoney/mapping/entity.py +116 -44
  22. followthemoney/mapping/property.py +90 -44
  23. followthemoney/mapping/query.py +27 -19
  24. followthemoney/mapping/source.py +15 -5
  25. followthemoney/mapping/sql.py +75 -61
  26. followthemoney/messages.py +13 -7
  27. followthemoney/model.py +108 -56
  28. followthemoney/namespace.py +119 -0
  29. followthemoney/offshore.py +48 -0
  30. followthemoney/ontology.py +77 -0
  31. followthemoney/property.py +204 -71
  32. followthemoney/proxy.py +455 -118
  33. followthemoney/rdf.py +9 -0
  34. followthemoney/schema/Address.yaml +78 -0
  35. followthemoney/schema/Airplane.yaml +17 -10
  36. followthemoney/schema/Analyzable.yaml +54 -0
  37. followthemoney/schema/Article.yaml +16 -0
  38. followthemoney/schema/Assessment.yaml +32 -0
  39. followthemoney/schema/Asset.yaml +10 -4
  40. followthemoney/schema/Associate.yaml +41 -0
  41. followthemoney/schema/Audio.yaml +24 -0
  42. followthemoney/schema/BankAccount.yaml +53 -9
  43. followthemoney/schema/Call.yaml +48 -0
  44. followthemoney/schema/CallForTenders.yaml +117 -0
  45. followthemoney/schema/Company.yaml +37 -12
  46. followthemoney/schema/Contract.yaml +41 -7
  47. followthemoney/schema/ContractAward.yaml +30 -11
  48. followthemoney/schema/CourtCase.yaml +16 -10
  49. followthemoney/schema/CourtCaseParty.yaml +17 -6
  50. followthemoney/schema/CryptoWallet.yaml +48 -0
  51. followthemoney/schema/Debt.yaml +37 -0
  52. followthemoney/schema/Directorship.yaml +17 -4
  53. followthemoney/schema/Document.yaml +72 -139
  54. followthemoney/schema/Documentation.yml +38 -0
  55. followthemoney/schema/EconomicActivity.yaml +32 -17
  56. followthemoney/schema/Email.yaml +76 -0
  57. followthemoney/schema/Employment.yaml +39 -0
  58. followthemoney/schema/Event.yaml +35 -3
  59. followthemoney/schema/Family.yaml +41 -0
  60. followthemoney/schema/Folder.yaml +13 -0
  61. followthemoney/schema/HyperText.yaml +21 -0
  62. followthemoney/schema/Identification.yaml +40 -0
  63. followthemoney/schema/Image.yaml +25 -0
  64. followthemoney/schema/Interest.yaml +3 -6
  65. followthemoney/schema/Interval.yaml +56 -5
  66. followthemoney/schema/LegalEntity.yaml +81 -20
  67. followthemoney/schema/License.yaml +7 -3
  68. followthemoney/schema/Membership.yaml +19 -4
  69. followthemoney/schema/Mention.yaml +54 -0
  70. followthemoney/schema/Message.yaml +78 -0
  71. followthemoney/schema/Note.yaml +23 -0
  72. followthemoney/schema/Occupancy.yaml +44 -0
  73. followthemoney/schema/Organization.yaml +38 -3
  74. followthemoney/schema/Ownership.yaml +16 -4
  75. followthemoney/schema/Package.yaml +17 -0
  76. followthemoney/schema/Page.yaml +43 -0
  77. followthemoney/schema/Pages.yaml +23 -0
  78. followthemoney/schema/Passport.yaml +16 -17
  79. followthemoney/schema/Payment.yaml +38 -7
  80. followthemoney/schema/Person.yaml +61 -5
  81. followthemoney/schema/PlainText.yaml +17 -0
  82. followthemoney/schema/Position.yaml +50 -0
  83. followthemoney/schema/Post.yaml +42 -0
  84. followthemoney/schema/Project.yaml +27 -0
  85. followthemoney/schema/ProjectParticipant.yaml +36 -0
  86. followthemoney/schema/PublicBody.yaml +14 -3
  87. followthemoney/schema/RealEstate.yaml +19 -3
  88. followthemoney/schema/Representation.yaml +17 -6
  89. followthemoney/schema/Sanction.yaml +45 -21
  90. followthemoney/schema/Security.yaml +59 -0
  91. followthemoney/schema/Similar.yaml +37 -0
  92. followthemoney/schema/Succession.yaml +36 -0
  93. followthemoney/schema/Table.yaml +32 -0
  94. followthemoney/schema/TaxRoll.yaml +27 -9
  95. followthemoney/schema/Thing.yaml +69 -13
  96. followthemoney/schema/Trip.yaml +42 -0
  97. followthemoney/schema/UnknownLink.yaml +17 -6
  98. followthemoney/schema/UserAccount.yaml +44 -0
  99. followthemoney/schema/Value.yaml +5 -1
  100. followthemoney/schema/Vehicle.yaml +25 -8
  101. followthemoney/schema/Vessel.yaml +18 -10
  102. followthemoney/schema/Video.yaml +20 -0
  103. followthemoney/schema/Workbook.yaml +18 -0
  104. followthemoney/schema.py +436 -135
  105. followthemoney/translations/ar/LC_MESSAGES/followthemoney.mo +0 -0
  106. followthemoney/translations/ar/LC_MESSAGES/followthemoney.po +2900 -787
  107. followthemoney/translations/bs/LC_MESSAGES/followthemoney.mo +0 -0
  108. followthemoney/translations/bs/LC_MESSAGES/followthemoney.po +2108 -520
  109. followthemoney/translations/de/LC_MESSAGES/followthemoney.mo +0 -0
  110. followthemoney/translations/de/LC_MESSAGES/followthemoney.po +2902 -782
  111. followthemoney/translations/es/LC_MESSAGES/followthemoney.mo +0 -0
  112. followthemoney/translations/es/LC_MESSAGES/followthemoney.po +2893 -779
  113. followthemoney/translations/fr/LC_MESSAGES/followthemoney.mo +0 -0
  114. followthemoney/translations/fr/LC_MESSAGES/followthemoney.po +4362 -0
  115. followthemoney/translations/fr/followthemoney.po +3861 -0
  116. followthemoney/translations/messages.pot +3021 -725
  117. followthemoney/translations/nb/LC_MESSAGES/followthemoney.mo +0 -0
  118. followthemoney/translations/nb/LC_MESSAGES/followthemoney.po +3778 -0
  119. followthemoney/translations/nl/LC_MESSAGES/followthemoney.mo +0 -0
  120. followthemoney/translations/nl/LC_MESSAGES/followthemoney.po +3837 -0
  121. followthemoney/translations/pt_BR/LC_MESSAGES/followthemoney.mo +0 -0
  122. followthemoney/translations/pt_BR/LC_MESSAGES/followthemoney.po +3784 -0
  123. followthemoney/translations/ru/LC_MESSAGES/followthemoney.mo +0 -0
  124. followthemoney/translations/ru/LC_MESSAGES/followthemoney.po +2837 -539
  125. followthemoney/translations/ru/followthemoney.po +4221 -0
  126. followthemoney/translations/tr/LC_MESSAGES/followthemoney.mo +0 -0
  127. followthemoney/translations/tr/LC_MESSAGES/followthemoney.po +2073 -491
  128. followthemoney/types/__init__.py +35 -17
  129. followthemoney/types/address.py +50 -21
  130. followthemoney/types/checksum.py +25 -0
  131. followthemoney/types/common.py +233 -88
  132. followthemoney/types/country.py +50 -56
  133. followthemoney/types/date.py +59 -76
  134. followthemoney/types/email.py +66 -35
  135. followthemoney/types/entity.py +66 -13
  136. followthemoney/types/gender.py +66 -0
  137. followthemoney/types/iban.py +47 -28
  138. followthemoney/types/identifier.py +49 -22
  139. followthemoney/types/ip.py +35 -21
  140. followthemoney/types/json.py +58 -0
  141. followthemoney/types/language.py +124 -37
  142. followthemoney/types/mimetype.py +44 -0
  143. followthemoney/types/name.py +56 -12
  144. followthemoney/types/number.py +30 -0
  145. followthemoney/types/phone.py +92 -34
  146. followthemoney/types/registry.py +52 -0
  147. followthemoney/types/string.py +43 -0
  148. followthemoney/types/topic.py +94 -0
  149. followthemoney/types/url.py +39 -17
  150. followthemoney/util.py +139 -45
  151. followthemoney-3.8.1.dist-info/METADATA +153 -0
  152. followthemoney-3.8.1.dist-info/RECORD +157 -0
  153. {followthemoney-1.3.7.dist-info → followthemoney-3.8.1.dist-info}/WHEEL +1 -2
  154. followthemoney-3.8.1.dist-info/entry_points.txt +17 -0
  155. followthemoney-1.3.7.dist-info/LICENSE.txt → followthemoney-3.8.1.dist-info/licenses/LICENSE +1 -1
  156. followthemoney/link.py +0 -75
  157. followthemoney/schema/Associate.yml +0 -19
  158. followthemoney/schema/Family.yml +0 -19
  159. followthemoney/schema/Land.yml +0 -9
  160. followthemoney/schema/Relationship.yaml +0 -26
  161. followthemoney/types/domain.py +0 -50
  162. followthemoney-1.3.7.dist-info/DESCRIPTION.rst +0 -3
  163. followthemoney-1.3.7.dist-info/METADATA +0 -39
  164. followthemoney-1.3.7.dist-info/RECORD +0 -108
  165. followthemoney-1.3.7.dist-info/entry_points.txt +0 -3
  166. followthemoney-1.3.7.dist-info/metadata.json +0 -1
  167. followthemoney-1.3.7.dist-info/namespace_packages.txt +0 -1
  168. followthemoney-1.3.7.dist-info/top_level.txt +0 -3
  169. ns/ontology.py +0 -128
  170. tests/types/test_addresses.py +0 -24
  171. tests/types/test_common.py +0 -32
  172. tests/types/test_countries.py +0 -27
  173. tests/types/test_dates.py +0 -73
  174. tests/types/test_domains.py +0 -23
  175. tests/types/test_emails.py +0 -32
  176. tests/types/test_entity.py +0 -19
  177. tests/types/test_iban.py +0 -109
  178. tests/types/test_identifiers.py +0 -27
  179. tests/types/test_ip.py +0 -29
  180. tests/types/test_languages.py +0 -23
  181. tests/types/test_names.py +0 -33
  182. tests/types/test_phones.py +0 -24
  183. tests/types/test_registry.py +0 -14
  184. tests/types/test_urls.py +0 -23
  185. {ns → followthemoney/export}/__init__.py +0 -0
  186. /tests/types/__init__.py → /followthemoney/py.typed +0 -0
ns/ontology.py DELETED
@@ -1,128 +0,0 @@
1
- import sys
2
- import json
3
- from datetime import datetime
4
- from rdflib import Graph, Namespace, URIRef, Literal
5
- from rdflib.namespace import OWL, DCTERMS, RDF, RDFS, XSD
6
-
7
- from followthemoney import model, types
8
-
9
-
10
- class Ontology(object):
11
-
12
- def __init__(self, ns_uri):
13
-
14
- self.ns_uri = ns_uri
15
- self.uri = URIRef(ns_uri)
16
- self.ns = Namespace(ns_uri)
17
-
18
- self.graph = Graph(identifier=ns_uri)
19
- self.graph.namespace_manager.bind('ftm', self.ns)
20
- self.graph.namespace_manager.bind('owl', OWL)
21
- self.graph.namespace_manager.bind('dct', DCTERMS)
22
-
23
- self.graph.add((self.uri, RDF.type, OWL.Ontology))
24
- self.graph.add((self.uri, RDFS.label, Literal("Follow The Money")))
25
- self.graph.add((self.uri, RDFS.comment, Literal(
26
- "A vocabulary for investigative reporting, based on real life.")))
27
- self.graph.add((self.uri, DCTERMS.modified,
28
- Literal(datetime.now().strftime('%Y-%m-%dT%H:%I:%M'), datatype=XSD.dateTime)))
29
-
30
- self.add_schemata()
31
-
32
- def uri_for(self, thing):
33
- url = self.uri + thing.name # Not using urljoin for this because it loses fragments
34
- return URIRef(url)
35
-
36
- def property_range(self, prop):
37
- if prop.type == types.entities:
38
- return self.uri_for(model[prop.range])
39
- elif prop.type == types.dates:
40
- return XSD.dateTime
41
- return None
42
-
43
- def add_class(self, entity):
44
- entity_uri = self.uri_for(entity)
45
- self.graph.add((entity_uri, RDF.type, RDFS.Class))
46
- self.graph.add((entity_uri, RDFS.isDefinedBy, self.uri))
47
- for extends in entity.extends:
48
- self.graph.add((entity_uri, RDFS.subClassOf,
49
- self.uri_for(model[extends])))
50
-
51
- self.graph.add((entity_uri, RDFS.label, Literal(entity.label)))
52
- if entity.description is not None:
53
- self.graph.add((entity_uri, RDFS.comment,
54
- Literal(entity.description)))
55
-
56
- def add_property(self, entity, prop):
57
- prop_uri = self.uri_for(prop)
58
- self.graph.add((prop_uri, RDF.type, RDF.Property))
59
- self.graph.add((prop_uri, RDFS.isDefinedBy, self.uri))
60
-
61
- self.graph.add((prop_uri, RDFS.label, Literal(prop.label)))
62
- if prop.description is not None:
63
- self.graph.add((prop_uri, RDFS.comment, Literal(prop.description)))
64
-
65
- self.graph.add((prop_uri, RDFS.domain, self.uri_for(entity)))
66
- prop_range = self.property_range(prop)
67
- if prop_range is not None:
68
- self.graph.add((prop_uri, RDFS.range, prop_range))
69
-
70
- def add_schemata(self):
71
- for schema in model:
72
- self.add_class(schema)
73
- for prop in schema._own_properties:
74
- self.add_property(schema, prop)
75
-
76
- def serialize(self, format='n3'):
77
- return self.graph.serialize(format=format)
78
-
79
- def jsonld_context(self):
80
- context = {
81
- '@context': {
82
- 'xsd': 'http://www.w3.org/2001/XMLSchema#',
83
- 'ftm': self.ns_uri
84
- }
85
- }
86
-
87
- for s, p, o in self.graph.triples((None, None, None)):
88
- name = s.split(self.ns_uri)[1]
89
- if name != "":
90
- # id_types = ['entity', 'url', 'uri']
91
- # if model.property_types.get(name) in id_types:
92
- # context['@context'][name] = {
93
- # '@id': 'ftm:%s' % name,
94
- # '@type': '@id'
95
- # }
96
- # elif model.property_types.get(name) == 'date':
97
- # context['@context'][name] = {
98
- # '@id': 'ftm:%s' % name,
99
- # '@type': 'xsd:dateTime'
100
- # }
101
- # else:
102
- context['@context'][name] = 'ftm:%s' % name
103
-
104
- return context
105
-
106
- def write_namespace_docs(self, path):
107
- ttl_fn = '%s/ftm.ttl' % path
108
- with open(ttl_fn, 'w') as ttl_file:
109
- ttl = self.serialize()
110
- ttl_file.write(ttl.decode('utf-8'))
111
-
112
- xml_fn = '%s/ftm.xml' % path
113
- with open(xml_fn, 'w') as xml_file:
114
- xml = self.serialize('xml')
115
- xml_file.write(xml.decode('utf-8'))
116
-
117
- json_fn = '%s/ftm.jsonld' % path
118
- with open(json_fn, 'w') as json_file:
119
- json_file.write(json.dumps(
120
- self.jsonld_context(), indent=4, sort_keys=True))
121
-
122
-
123
- if __name__ == '__main__':
124
- uri = sys.argv[1]
125
- path = sys.argv[2]
126
- o = Ontology(uri)
127
- o.write_namespace_docs(path)
128
- print("Namespace docs written to %s" % path)
@@ -1,24 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import addresses
4
-
5
- UK = """43 Duke Street
6
- Edinburgh
7
- EH6 8HH"""
8
-
9
-
10
- class AddressesTest(unittest.TestCase):
11
-
12
- def test_clean(self):
13
- self.assertEqual(addresses.clean(UK),
14
- '43 Duke Street, Edinburgh, EH6 8HH')
15
- self.assertEqual(addresses.clean('huhu\n haha'), 'huhu, haha')
16
- self.assertEqual(addresses.clean('huhu,\n haha'), 'huhu, haha')
17
-
18
- def test_normalize(self):
19
- self.assertEqual(addresses.normalize(UK), ['43 Duke Street, Edinburgh, EH6 8HH']) # noqa
20
- self.assertEqual(addresses.normalize('\n '), [])
21
-
22
- def test_specificity(self):
23
- self.assertGreater(addresses.specificity(UK), 0.2)
24
- self.assertLess(addresses.specificity('London'), 0.2)
@@ -1,32 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import registry
4
-
5
-
6
- class CommonTest(unittest.TestCase):
7
-
8
- def test_normalise_set(self):
9
- t = registry.name
10
- self.assertEqual(t.normalize_set(None), [])
11
- self.assertEqual(t.normalize_set('boban'), ['boban'])
12
- self.assertEqual(t.normalize_set(['boban']), ['boban'])
13
-
14
- def test_ref(self):
15
- t = registry.name
16
- self.assertEqual(t.ref(''), None)
17
- self.assertEqual(t.ref({'id': 'banana'}), 'n:banana')
18
- self.assertEqual(t.ref('banana'), 'n:banana')
19
- nt, v = registry.deref('n:banana')
20
- self.assertEqual(v, 'banana')
21
- self.assertEqual(t, nt)
22
-
23
- def test_funcs(self):
24
- t = registry.name
25
- self.assertEqual(t.country_hint('banana'), None)
26
- self.assertEqual(str(t), 'name')
27
- self.assertEqual(hash(t), hash('name'))
28
-
29
- self.assertGreater(t.compare_sets(['banana'], ['banana']), 0)
30
- self.assertEqual(t.compare_sets(['banana'], []), 0)
31
- self.assertIsNotNone(t.ref('banana'))
32
- self.assertIsNone(registry.text.ref('banana'))
@@ -1,27 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import countries
4
-
5
-
6
- class CountriesTest(unittest.TestCase):
7
-
8
- def test_country_codes(self):
9
- self.assertEqual(countries.clean('DE'), 'de')
10
- self.assertTrue(countries.validate('DE'))
11
- self.assertFalse(countries.validate('DEU'))
12
- self.assertFalse(countries.validate(''))
13
- self.assertFalse(countries.validate(None))
14
- self.assertFalse(countries.validate(4))
15
- self.assertFalse(countries.validate('SU'))
16
- self.assertTrue(countries.validate('XK'))
17
- self.assertTrue(countries.validate('EU'))
18
-
19
- self.assertEqual(countries.country_hint('eu'), 'eu')
20
- assert 'iso-3166-1:eu' in countries.rdf('eu')
21
-
22
- def test_country_names(self):
23
- self.assertEqual(countries.clean(None), None)
24
- self.assertEqual(countries.clean('Takatukaland', guess=False), None)
25
- self.assertEqual(countries.clean('Germany'), 'de')
26
- # self.assertEqual(countries.clean('Germani'), 'de')
27
- self.assertEqual(countries.clean('Soviet Union'), 'suhh')
tests/types/test_dates.py DELETED
@@ -1,73 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- import unittest
3
- from datetime import datetime
4
-
5
- from followthemoney.types import dates
6
-
7
-
8
- class DatesTest(unittest.TestCase):
9
-
10
- def test_validate(self):
11
- self.assertTrue(dates.validate('2017-04-04T10:30:29'))
12
- self.assertTrue(dates.validate('2017-04-04T10:30:29Z'))
13
- self.assertTrue(dates.validate('2017-04-04T10:30:29+01'))
14
- self.assertTrue(dates.validate('2017-04-04T10:30:29+0200'))
15
- self.assertTrue(dates.validate('2017-04-04T10:30:29+03:00'))
16
- self.assertTrue(dates.validate('2017-04-04T10:30:29-04:00'))
17
- self.assertTrue(dates.validate(datetime.utcnow().isoformat()))
18
- self.assertFalse(dates.validate('01-02-2003'))
19
- self.assertFalse(dates.validate('Thursday 21 March 2017'))
20
-
21
- def test_is_partial_date(self):
22
- self.assertTrue(dates.validate('2017-04-04 10:30:29'))
23
- self.assertTrue(dates.validate('2017-04-04 10:30'))
24
- self.assertTrue(dates.validate('2017-04-04 10'))
25
- self.assertTrue(dates.validate('2017-04-04'))
26
- self.assertTrue(dates.validate('2017-4-4'))
27
- self.assertTrue(dates.validate('2017-4'))
28
- self.assertTrue(dates.validate('2017'))
29
- self.assertFalse(dates.validate('0017'))
30
- self.assertFalse(dates.validate(None))
31
- self.assertFalse(dates.validate(5))
32
- self.assertFalse(dates.validate('2017-20-01'))
33
-
34
- def test_chop_dates(self):
35
- self.assertEquals(dates.clean('2017-00-00'), '2017')
36
- self.assertEquals(dates.clean('2017-00-00T00:00:00'), '2017')
37
- self.assertEquals(dates.clean('2017-00-00T12:03:49'), '2017')
38
- self.assertEquals(dates.clean('2017-01-01T00:00:00'), '2017-01-01')
39
-
40
- def test_patch_dates(self):
41
- self.assertEquals(dates.clean('2017-1-3'), '2017-01-03')
42
- self.assertEquals(dates.clean('2017-3'), '2017-03')
43
- self.assertEquals(dates.clean('2017-0'), '2017')
44
- self.assertEquals(dates.clean('2017-5-2T00:00:00'), '2017-05-02')
45
- self.assertEquals(dates.clean('2017-5-2T10:00:00'), '2017-05-02T10:00:00') # noqa
46
-
47
- def test_convert_datetime(self):
48
- dt = datetime.utcnow()
49
- iso, _ = dt.isoformat().split('.', 1)
50
- self.assertEquals(dates.clean(dt), iso)
51
- self.assertTrue(dates.validate(iso))
52
-
53
- dt = datetime.utcnow().date()
54
- iso = dt.isoformat()
55
- self.assertEquals(dates.clean(dt), iso)
56
-
57
- def test_parse_date(self):
58
- self.assertEquals(dates.clean(None), None)
59
- self.assertEquals(dates.clean(''), None)
60
- self.assertEquals(dates.clean('banana'), None)
61
- self.assertEquals(dates.clean('2017-04-04'), '2017-04-04')
62
- self.assertEquals(dates.clean('2017-4-4'), '2017-04-04')
63
-
64
- self.assertEquals(dates.clean('4/2017', format="%m/%Y"), '2017-04')
65
- self.assertEquals(dates.clean('4/2017', format="4/%Y"), '2017')
66
- self.assertEquals(dates.clean('4/2xx017', format="%m/%Y"), None)
67
-
68
- def test_specificity(self):
69
- self.assertEqual(dates.specificity('2011'), 0)
70
- self.assertGreater(dates.specificity('2011-01-01'), 0.1)
71
-
72
- def test_compare(self):
73
- self.assertGreater(dates.compare('2011-01-01', '2011-01-01'), 0.9)
@@ -1,23 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import domains
4
-
5
-
6
- class DomainsTest(unittest.TestCase):
7
-
8
- def test_parse(self):
9
- self.assertEqual(domains.clean('pudo.org'), 'pudo.org')
10
- self.assertEqual(domains.clean('pudoorg'), None)
11
- self.assertEqual(domains.clean(None), None)
12
- self.assertEqual(domains.clean('x.a'), None)
13
-
14
- def test_normalize(self):
15
- self.assertEqual(domains.normalize('PUDO'), [])
16
- self.assertEqual(domains.normalize('PUDO.org'), ['pudo.org'])
17
-
18
- def test_domain_validity(self):
19
- self.assertTrue(domains.validate('pudo.org'))
20
- self.assertFalse(domains.validate('pudo'))
21
- self.assertFalse(domains.validate('x.a'))
22
- self.assertFalse(domains.validate(''))
23
- self.assertFalse(domains.validate('@pudo.org'))
@@ -1,32 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import emails
4
-
5
-
6
- class EmailsTest(unittest.TestCase):
7
-
8
- def test_parse(self):
9
- self.assertEqual(emails.clean('foo@pudo.org'), 'foo@pudo.org')
10
- self.assertEqual(emails.clean('"foo@pudo.org"'), 'foo@pudo.org')
11
- self.assertEqual(emails.clean('pudo.org'), None)
12
- self.assertEqual(emails.clean('foo@'), None)
13
- self.assertEqual(emails.clean(None), None)
14
- self.assertEqual(emails.clean(5), None)
15
- self.assertEqual(emails.clean('foo@PUDO.org'), 'foo@pudo.org')
16
- self.assertEqual(emails.clean('FOO@PUDO.org'), 'FOO@pudo.org')
17
-
18
- def test_normalize(self):
19
- self.assertEqual(emails.normalize(None), [])
20
- self.assertEqual(emails.normalize('FOO@PUDO'), [])
21
- self.assertEqual(emails.normalize('FOO@PUDO.org'), ['foo@pudo.org'])
22
-
23
- def test_domain_validity(self):
24
- self.assertTrue(emails.validate('foo@pudo.org'))
25
- self.assertFalse(emails.validate('foo@pudo'))
26
- self.assertFalse(emails.validate(None))
27
- self.assertFalse(emails.validate(''))
28
- self.assertFalse(emails.validate('@pudo.org'))
29
- self.assertFalse(emails.validate('foo@'))
30
-
31
- def test_specificity(self):
32
- self.assertEqual(emails.specificity('foo@pudo.org'), 1)
@@ -1,19 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import entities
4
-
5
-
6
- class EntityTest(unittest.TestCase):
7
-
8
- def test_parse(self):
9
- self.assertEqual(entities.clean('88'), '88')
10
- self.assertEqual(entities.clean(88), '88')
11
- self.assertEqual(entities.clean({'id': 88}), '88')
12
- self.assertEqual(entities.clean(None), None)
13
-
14
- def test_normalize(self):
15
- self.assertEqual(entities.normalize('FOO'), ['FOO'])
16
- self.assertEqual(entities.normalize(None), [])
17
-
18
- def test_funcs(self):
19
- self.assertEqual(entities.specificity('bla'), 1)
tests/types/test_iban.py DELETED
@@ -1,109 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import ibans
4
-
5
-
6
- class IbansTest(unittest.TestCase):
7
-
8
- def test_parse(self):
9
- self.assertEqual(ibans.clean('GB29 NWBK 6016 1331 9268 19'),
10
- 'GB29NWBK60161331926819')
11
-
12
- def test_domain_validity(self):
13
- self.assertTrue(ibans.validate('GB29 NWBK 6016 1331 9268 19'))
14
- self.assertTrue(ibans.validate('GB29NWBK60161331926819'))
15
- self.assertFalse(ibans.validate('GB28 NWBK 6016 1331 9268 19'))
16
- self.assertFalse(ibans.validate('GB29NWBKN0161331926819'))
17
- self.assertFalse(ibans.validate(None))
18
- self.assertTrue(ibans.validate('AL35202111090000000001234567'))
19
- self.assertTrue(ibans.validate('AD1400080001001234567890'))
20
- self.assertTrue(ibans.validate('AT483200000012345864'))
21
- self.assertTrue(ibans.validate('AZ96AZEJ00000000001234567890'))
22
- self.assertTrue(ibans.validate('BH02CITI00001077181611'))
23
- # self.assertTrue(ibans.validate('BY86AKBB10100000002966000000'))
24
- self.assertTrue(ibans.validate('BE71096123456769'))
25
- self.assertTrue(ibans.validate('BA275680000123456789'))
26
- self.assertTrue(ibans.validate('BR1500000000000010932840814P2'))
27
- self.assertTrue(ibans.validate('BG18RZBB91550123456789'))
28
- # self.assertTrue(ibans.validate('CR37012600000123456789'))
29
- self.assertTrue(ibans.validate('HR1723600001101234565'))
30
- self.assertTrue(ibans.validate('CY21002001950000357001234567'))
31
- self.assertTrue(ibans.validate('CZ5508000000001234567899'))
32
- self.assertTrue(ibans.validate('DK9520000123456789'))
33
- self.assertTrue(ibans.validate('DO22ACAU00000000000123456789'))
34
- # self.assertTrue(ibans.validate('SV43ACAT00000000000000123123'))
35
- self.assertTrue(ibans.validate('EE471000001020145685'))
36
- self.assertTrue(ibans.validate('FO9264600123456789'))
37
- self.assertTrue(ibans.validate('FI1410093000123458'))
38
- self.assertTrue(ibans.validate('FR7630006000011234567890189'))
39
- self.assertTrue(ibans.validate('GE60NB0000000123456789'))
40
- self.assertTrue(ibans.validate('DE91100000000123456789'))
41
- self.assertTrue(ibans.validate('GI04BARC000001234567890'))
42
- self.assertTrue(ibans.validate('GR9608100010000001234567890'))
43
- self.assertTrue(ibans.validate('GL8964710123456789'))
44
- self.assertTrue(ibans.validate('GT20AGRO00000000001234567890'))
45
- self.assertTrue(ibans.validate('HU93116000060000000012345676'))
46
- self.assertTrue(ibans.validate('IS030001121234561234567890'))
47
- # self.assertTrue(ibans.validate('IQ20CBIQ861800101010500'))
48
- self.assertTrue(ibans.validate('IE64IRCE92050112345678'))
49
- self.assertTrue(ibans.validate('IL170108000000012612345'))
50
- self.assertTrue(ibans.validate('IT60X0542811101000000123456'))
51
- self.assertTrue(ibans.validate('JO71CBJO0000000000001234567890'))
52
- self.assertTrue(ibans.validate('KZ563190000012344567'))
53
- self.assertTrue(ibans.validate('XK051212012345678906'))
54
- self.assertTrue(ibans.validate('KW81CBKU0000000000001234560101'))
55
- self.assertTrue(ibans.validate('LV97HABA0012345678910'))
56
- self.assertTrue(ibans.validate('LB92000700000000123123456123'))
57
- self.assertTrue(ibans.validate('LI7408806123456789012'))
58
- self.assertTrue(ibans.validate('LT601010012345678901'))
59
- self.assertTrue(ibans.validate('LU120010001234567891'))
60
- self.assertTrue(ibans.validate('MK07200002785123453'))
61
- self.assertTrue(ibans.validate('MT31MALT01100000000000000000123'))
62
- self.assertTrue(ibans.validate('MR1300020001010000123456753'))
63
- self.assertTrue(ibans.validate('MU43BOMM0101123456789101000MUR'))
64
- self.assertTrue(ibans.validate('MD21EX000000000001234567'))
65
- self.assertTrue(ibans.validate('MC5810096180790123456789085'))
66
- self.assertTrue(ibans.validate('ME25505000012345678951'))
67
- self.assertTrue(ibans.validate('NL02ABNA0123456789'))
68
- self.assertTrue(ibans.validate('NO8330001234567'))
69
- self.assertTrue(ibans.validate('PK36SCBL0000001123456702'))
70
- self.assertTrue(ibans.validate('PS92PALS000000000400123456702'))
71
- self.assertTrue(ibans.validate('PL10105000997603123456789123'))
72
- self.assertTrue(ibans.validate('PT50002700000001234567833'))
73
- self.assertTrue(ibans.validate('QA54QNBA000000000000693123456'))
74
- self.assertTrue(ibans.validate('RO09BCYP0000001234567890'))
75
- self.assertTrue(ibans.validate('LC14BOSL123456789012345678901234'))
76
- self.assertTrue(ibans.validate('SM76P0854009812123456789123'))
77
- self.assertTrue(ibans.validate('ST23000200000289355710148'))
78
- self.assertTrue(ibans.validate('SA4420000001234567891234'))
79
- self.assertTrue(ibans.validate('RS35105008123123123173'))
80
- self.assertTrue(ibans.validate('SC52BAHL01031234567890123456USD'))
81
- self.assertTrue(ibans.validate('SK8975000000000012345671'))
82
- self.assertTrue(ibans.validate('SI56192001234567892'))
83
- self.assertTrue(ibans.validate('ES7921000813610123456789'))
84
- self.assertTrue(ibans.validate('SE1412345678901234567890'))
85
- self.assertTrue(ibans.validate('CH5604835012345678009'))
86
- self.assertTrue(ibans.validate('TL380080012345678910157'))
87
- self.assertTrue(ibans.validate('TN4401000067123456789123'))
88
- self.assertTrue(ibans.validate('TR320010009999901234567890'))
89
- self.assertTrue(ibans.validate('UA903052992990004149123456789'))
90
- self.assertTrue(ibans.validate('AE460090000000123456789'))
91
- self.assertTrue(ibans.validate('GB98MIDL07009312345678'))
92
- self.assertTrue(ibans.validate('VG21PACG0000000123456789'))
93
-
94
- def test_specificity(self):
95
- self.assertEqual(ibans.specificity('VG21PACG0000000123456789'), 1)
96
-
97
- def test_country(self):
98
- iban = 'AE460090000000123456789'
99
- assert 'ae' == ibans.country_hint(iban)
100
- assert ibans.country_hint('') is None
101
-
102
- def test_compare(self):
103
- iban = 'AE460090000000123456789'
104
- comp = ibans.compare_safe(iban, iban)
105
- assert comp == 1, comp
106
- comp = ibans.compare_safe(iban, iban + 'X')
107
- assert comp == 0, comp
108
- comp = ibans.compare_safe(iban, None)
109
- assert comp == 0, comp
@@ -1,27 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import identifiers
4
-
5
-
6
- class IdentifiersTest(unittest.TestCase):
7
-
8
- def test_parse(self):
9
- self.assertEqual(identifiers.clean('88/9'), '88/9')
10
-
11
- def test_normalize(self):
12
- self.assertEqual(identifiers.normalize('FOO'), ['foo'])
13
- self.assertEqual(identifiers.normalize('xx '), ['xx'])
14
- self.assertEqual(identifiers.normalize(' '), [])
15
-
16
- def test_domain_validity(self):
17
- self.assertTrue(identifiers.validate('foo@pudo.org'))
18
-
19
- def test_compare(self):
20
- comp = identifiers.compare('AS98187', '98187')
21
- assert comp == 0.7, comp
22
- comp = identifiers.compare_safe(None, '98187')
23
- assert comp == 0, comp
24
- comp = identifiers.compare_sets(['AS98187'], ['98187'])
25
- assert comp == 0.7, comp
26
- comp = identifiers.compare_sets(['98187'], ['AS98187'])
27
- assert comp == 0.7, comp
tests/types/test_ip.py DELETED
@@ -1,29 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import ips
4
-
5
-
6
- class IPsTest(unittest.TestCase):
7
-
8
- def test_ip_validate(self):
9
- self.assertTrue(ips.validate('172.16.254.1'))
10
- self.assertFalse(ips.validate('355.16.254.1'))
11
- self.assertFalse(ips.validate('16.254.1'))
12
- self.assertFalse(ips.validate('172.162541'))
13
- self.assertFalse(ips.validate(None))
14
-
15
- self.assertTrue(ips.validate('2001:db8:0:1234:0:567:8:1'))
16
- self.assertFalse(ips.validate('2001:zz8:0:1234:0:567:8:1'))
17
- self.assertFalse(ips.validate('20001:db8:0:1234:0:567:8:1'))
18
- self.assertFalse(ips.validate(None))
19
-
20
- def test_ip_clean(self):
21
- self.assertEqual(ips.clean('172.16.254.1'), '172.16.254.1')
22
- self.assertEqual(ips.clean(None), None)
23
- self.assertEqual(ips.clean('-1'), None)
24
-
25
- def test_funcs(self):
26
- self.assertEqual(str(ips.rdf('172.16.254.1')), 'ip:172.16.254.1')
27
-
28
- def test_specificity(self):
29
- self.assertEqual(ips.specificity('172.16.254.1'), 1)
@@ -1,23 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import languages
4
-
5
-
6
- class LanguagesTest(unittest.TestCase):
7
-
8
- def test_validate(self):
9
- self.assertTrue(languages.validate('de'))
10
- self.assertTrue(languages.validate('en'))
11
- self.assertFalse(languages.validate('us'))
12
- self.assertFalse(languages.validate(None))
13
-
14
- def test_cleam(self):
15
- self.assertEquals(languages.clean('de'), 'de')
16
- self.assertEquals(languages.clean('xx'), None)
17
- self.assertEquals(languages.clean(None), None)
18
-
19
- def test_funcs(self):
20
- self.assertEqual(str(languages.rdf('de')), 'iso-639:de')
21
-
22
- def test_specificity(self):
23
- self.assertEqual(languages.specificity('de'), 0)
tests/types/test_names.py DELETED
@@ -1,33 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import names
4
-
5
-
6
- class NamesTest(unittest.TestCase):
7
-
8
- def test_repr(self):
9
- self.assertEqual(repr(names), '<NameType()>')
10
-
11
- def test_parse(self):
12
- self.assertEqual(names.clean('Hans Well'), 'Hans Well')
13
- self.assertEqual(names.clean('Hans Well '), 'Hans Well')
14
- self.assertEqual(names.clean('"Hans Well"'), 'Hans Well')
15
-
16
- def test_normalize(self):
17
- self.assertEqual(names.normalize('FOO'), ['FOO'])
18
- self.assertEqual(names.normalize('xx '), ['xx'])
19
- self.assertEqual(names.normalize(' '), [])
20
-
21
- def test_domain_validity(self):
22
- self.assertTrue(names.validate('huhu'))
23
- self.assertFalse(names.validate(''))
24
-
25
- def test_normalize_set(self):
26
- self.assertEqual(names.normalize_set('FOO'), ['FOO'])
27
- self.assertEqual(names.normalize_set(['FOO', '']), ['FOO'])
28
- self.assertEqual(names.normalize_set(['FOO', 'FOO']), ['FOO'])
29
- self.assertEqual(len(names.normalize_set(['FOO', 'BAR'])), 2)
30
-
31
- def test_specificity(self):
32
- self.assertEqual(names.specificity('bo'), 0)
33
- self.assertGreater(names.specificity('boban'), 0)
@@ -1,24 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import phones
4
-
5
-
6
- class PhonesTest(unittest.TestCase):
7
-
8
- def test_us_number(self):
9
- self.assertEqual(phones.clean('+1-800-784-2433'), '+18007842433')
10
- self.assertEqual(phones.clean('+1 800 784 2433'), '+18007842433')
11
- self.assertEqual(phones.clean('+18007842433'), '+18007842433')
12
- self.assertEqual(phones.clean('+1 555 8379'), None)
13
-
14
- def test_de_number(self):
15
- self.assertEqual(phones.clean('017623423980'), None)
16
- self.assertEqual(phones.clean('017623423980', countries='DE'),
17
- '+4917623423980')
18
-
19
- def test_specificity(self):
20
- self.assertEqual(phones.specificity('+4917623423980'), 1)
21
-
22
- def test_country_hint(self):
23
- self.assertEqual(phones.country_hint('+4917623423980'), 'de')
24
- self.assertEqual(phones.country_hint(None), None)
@@ -1,14 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import registry
4
-
5
-
6
- class RegistryTest(unittest.TestCase):
7
-
8
- def test_ref(self):
9
- assert registry.entity == registry.get('entity')
10
- assert registry.get('banana') is None
11
- assert registry.entity.ref('banana') == 'e:banana'
12
- t, v = registry.deref('e:banana')
13
- assert t == registry.entity
14
- assert v == 'banana'
tests/types/test_urls.py DELETED
@@ -1,23 +0,0 @@
1
- import unittest
2
-
3
- from followthemoney.types import urls
4
-
5
-
6
- class UrlsTest(unittest.TestCase):
7
-
8
- def test_is_url(self):
9
- self.assertTrue(urls.validate('http://foo.org'))
10
- self.assertFalse(urls.validate(None))
11
- self.assertFalse(urls.validate('hello'))
12
-
13
- def test_parse_url(self):
14
- self.assertEqual(urls.clean('http://foo.com'), 'http://foo.com/')
15
- self.assertEqual(urls.clean('http://foo.com/#lala'), 'http://foo.com/')
16
-
17
- self.assertEqual(urls.clean('http://foo.com?b=1&a=2'),
18
- 'http://foo.com/?a=2&b=1')
19
- self.assertEqual(urls.clean('http://FOO.com'), 'http://foo.com/')
20
- self.assertEqual(urls.clean('http://FOO.com/A'), 'http://foo.com/A')
21
-
22
- def test_specificity(self):
23
- self.assertEqual(urls.specificity('http://foo.com/'), 1)
File without changes
File without changes