counterparty 0.1.6__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 (64) hide show
  1. counterparty/__init__.py +29 -0
  2. counterparty/extraction/__init__.py +0 -0
  3. counterparty/extraction/clean.py +124 -0
  4. counterparty/extraction/extract_payer_payee.py +160 -0
  5. counterparty/extraction/infer_counterparty.py +17 -0
  6. counterparty/key_engine/__init__.py +0 -0
  7. counterparty/key_engine/canonical_keys.json +326 -0
  8. counterparty/key_engine/key_detector.py +335 -0
  9. counterparty/key_engine/keys.py +332 -0
  10. counterparty/parsers/LAT_AM/LAT_AM_Entry.py +91 -0
  11. counterparty/parsers/LAT_AM/__init__.py +0 -0
  12. counterparty/parsers/LAT_AM/pattern1.py +169 -0
  13. counterparty/parsers/LAT_AM/pattern10.py +76 -0
  14. counterparty/parsers/LAT_AM/pattern11.py +76 -0
  15. counterparty/parsers/LAT_AM/pattern12.py +99 -0
  16. counterparty/parsers/LAT_AM/pattern2.py +102 -0
  17. counterparty/parsers/LAT_AM/pattern3.py +75 -0
  18. counterparty/parsers/LAT_AM/pattern4.py +128 -0
  19. counterparty/parsers/LAT_AM/pattern5.py +54 -0
  20. counterparty/parsers/LAT_AM/pattern6.py +141 -0
  21. counterparty/parsers/LAT_AM/pattern7.py +116 -0
  22. counterparty/parsers/LAT_AM/pattern8.py +134 -0
  23. counterparty/parsers/LAT_AM/pattern9.py +86 -0
  24. counterparty/parsers/__init__.py +0 -0
  25. counterparty/parsers/ach/__init__.py +0 -0
  26. counterparty/parsers/ach/ach_parser.py +190 -0
  27. counterparty/parsers/avidpay/__init__.py +0 -0
  28. counterparty/parsers/avidpay/avidp_check_parser.py +82 -0
  29. counterparty/parsers/avidpay/avidp_gen_parser.py +59 -0
  30. counterparty/parsers/directdebit/__init__.py +0 -0
  31. counterparty/parsers/directdebit/directdeb.py +80 -0
  32. counterparty/parsers/disbursement/__init__.py +0 -0
  33. counterparty/parsers/disbursement/disb_parser.py +72 -0
  34. counterparty/parsers/fundsTransfer/__init__.py +0 -0
  35. counterparty/parsers/fundsTransfer/fundsTrans_parser.py +80 -0
  36. counterparty/parsers/generic/__init__.py +0 -0
  37. counterparty/parsers/generic/all_parser.py +91 -0
  38. counterparty/parsers/merchref/__init__.py +0 -0
  39. counterparty/parsers/merchref/merch_ref_parser.py +47 -0
  40. counterparty/parsers/misc/__init__.py +0 -0
  41. counterparty/parsers/misc/cardp.py +61 -0
  42. counterparty/parsers/misc/invo.py +78 -0
  43. counterparty/parsers/misc/webt.py +55 -0
  44. counterparty/parsers/paypal/__init__.py +0 -0
  45. counterparty/parsers/paypal/paypal.py +118 -0
  46. counterparty/parsers/processor_eft/__init__.py +0 -0
  47. counterparty/parsers/processor_eft/peft.py +110 -0
  48. counterparty/parsers/remittance/__init__.py +0 -0
  49. counterparty/parsers/remittance/remi.py +79 -0
  50. counterparty/parsers/swift/__init__.py +0 -0
  51. counterparty/parsers/swift/swift_parser.py +97 -0
  52. counterparty/parsers/vendorpay/__init__.py +0 -0
  53. counterparty/parsers/vendorpay/vp_parser.py +54 -0
  54. counterparty/parsers/vendorpymt/__init__.py +0 -0
  55. counterparty/parsers/vendorpymt/vpymt_parser.py +132 -0
  56. counterparty/parsers/wire/__init__.py +0 -0
  57. counterparty/parsers/wire/wire_parser.py +137 -0
  58. counterparty/route.py +116 -0
  59. counterparty/routines.py +72 -0
  60. counterparty/util.py +40 -0
  61. counterparty-0.1.6.dist-info/METADATA +9 -0
  62. counterparty-0.1.6.dist-info/RECORD +64 -0
  63. counterparty-0.1.6.dist-info/WHEEL +5 -0
  64. counterparty-0.1.6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,54 @@
1
+ import re
2
+
3
+ # 1. NORMALIZATION (shared)
4
+ def normalize_narrative(line: str) -> str:
5
+ if not line:
6
+ return ""
7
+ line = line.strip(",")
8
+ line = re.sub(r"\s+", " ", line)
9
+ return line.strip().upper()
10
+
11
+
12
+
13
+ # 2. IDENTIFICATION REGEX
14
+ VENDOR_PAY_RECOGNISE_RE = re.compile(
15
+ r"\bVENDOR\s+PAY\b.*\b\d+\b$"
16
+ )
17
+
18
+
19
+ def is_vendor_pay_narrative(line: str) -> bool:
20
+ norm = normalize_narrative(line)
21
+ if not norm:
22
+ return False
23
+ return bool(VENDOR_PAY_RECOGNISE_RE.search(norm))
24
+
25
+
26
+
27
+ # 3. PARSING REGEX
28
+ VENDOR_PAY_PARSE_RE = re.compile(
29
+ r"""
30
+ ^
31
+ (?P<CTPTY_NAME>.+?)\s+
32
+ VENDOR\s+PAY\s+
33
+ (?P<MANAGER_NAME>.+?)\s+
34
+ (?P<VENDOR_PAY_ID>\d+)
35
+ $
36
+ """,
37
+ re.VERBOSE
38
+ )
39
+
40
+
41
+ def parse_vendor_pay_narrative(line: str) -> dict:
42
+ norm = normalize_narrative(line)
43
+
44
+ match = VENDOR_PAY_PARSE_RE.search(norm)
45
+ if not match:
46
+ return {}
47
+
48
+ return {
49
+ "RAW": line,
50
+ "ENTITY": match.group("CTPTY_NAME"),
51
+ "TRANS_TYPE": "VENDOR_PAY",
52
+ "MANAGER_NAME": match.group("MANAGER_NAME"),
53
+ "VENDOR_PAY_ID": match.group("VENDOR_PAY_ID"),
54
+ }
File without changes
@@ -0,0 +1,132 @@
1
+ import re
2
+
3
+ def normalize_narrative(line: str) -> str:
4
+ if not line:
5
+ return ""
6
+ line = line.lstrip(",")
7
+ line = re.sub(r"[,\s]+$", "", line)
8
+ line = re.sub(r"\s+", " ", line)
9
+ return line.strip().upper()
10
+
11
+
12
+ VENDORPYMT_RMR_RE = re.compile(
13
+ r"VENDORPYMT\s*RMR\*IV\*.+\*\*\d",
14
+ )
15
+
16
+ VENDORPYMT_REMIT_RECOGNISE_RE = re.compile(
17
+ r"VENDORPYMT.*RMR\*IV\*"
18
+ )
19
+
20
+
21
+
22
+ def is_vendor_payment_rmr(line: str) -> bool:
23
+ return bool(VENDORPYMT_RMR_RE.search(normalize_narrative(line)))
24
+
25
+
26
+ def is_vendor_payment_remittance(line: str) -> bool:
27
+ norm = normalize_narrative(line)
28
+ if not norm:
29
+ return False
30
+
31
+ # exclude invoice+amount version (handled elsewhere)
32
+ if "**" in norm:
33
+ return False
34
+
35
+ return bool(VENDORPYMT_REMIT_RECOGNISE_RE.search(norm))
36
+
37
+
38
+
39
+ # PARSER REGEX
40
+ VENDORPYMT_RMR_PARSE_RE = re.compile(
41
+ r"""
42
+ ^
43
+ (?P<COUNTERPARTY_NAME>.+?)
44
+ [\s\-]*
45
+ VENDORPYMT\s*RMR(?:\*IV\*)
46
+ (?P<INVOICE_NO>(?:[A-Z0-9]+\s?)+)
47
+ \*\*
48
+ (?P<AMOUNT>(?:\d+\s+)?\d+(?:\.\d{2})?)
49
+ """,
50
+ re.VERBOSE
51
+ )
52
+
53
+
54
+
55
+ VENDORPYMT_REMIT_PARSE_RE = re.compile(
56
+ r"""
57
+ ^
58
+ (?P<COUNTERPARTY_NAME>.+?)
59
+ \s+VENDORPYMT\b
60
+ \s*
61
+ (?P<META_BLOCK>.*?)
62
+ \s*
63
+ RMR\*IV\*
64
+ (?P<REMIT_BLOCK>.+)
65
+ $
66
+ """,
67
+ re.VERBOSE
68
+ )
69
+
70
+
71
+
72
+ INVOICE_RE = re.compile(r"RMR(?:\*IV\*|IV)([A-Z0-9]+)")
73
+ AMOUNT_RE = re.compile(r"\*\*\s*([\d ]+(?:\.\d{2})?)")
74
+
75
+
76
+ # PARSER
77
+ def parse_vendor_payment_rmr(line: str) -> dict:
78
+ norm = normalize_narrative(line).rstrip("\\")
79
+ m = VENDORPYMT_RMR_PARSE_RE.search(norm)
80
+ if not m:
81
+ return {
82
+ "RAW": line,
83
+ "META": norm,
84
+ "ERROR": "VENDORPYMT_RMR_PARSE_FAILED"
85
+ }
86
+
87
+ raw_amt = m.group("AMOUNT").replace(" ", "")
88
+ if "." not in raw_amt and len(raw_amt) > 2:
89
+ amt = f"{int(raw_amt[:-2])}.{raw_amt[-2:]}"
90
+ else:
91
+ amt = raw_amt
92
+
93
+ invoice_ids = m.group("INVOICE_NO").split()
94
+
95
+ return {
96
+ "RAW": line,
97
+ "ENTITY": m.group("COUNTERPARTY_NAME").rstrip("- "),
98
+ "TRANS_TYPE": "VENDOR_PAYMENT_RMR",
99
+ "INVOICE_NO": invoice_ids,
100
+ "AMOUNT": amt,
101
+ }
102
+
103
+
104
+
105
+ def parse_vendor_payment_remittance(line: str) -> dict:
106
+ norm = normalize_narrative(line)
107
+
108
+ m = VENDORPYMT_REMIT_PARSE_RE.search(norm)
109
+ if not m:
110
+ return {
111
+ "RAW": line,
112
+ "META": norm,
113
+ "ERROR": "VENDORPYMT_REMIT_PARSE_FAILED"
114
+ }
115
+
116
+ remit_block = m.group("REMIT_BLOCK")
117
+
118
+ remit_ids = re.findall(r"\b\d{4,}\b", remit_block)
119
+
120
+ return {
121
+ "RAW": line,
122
+ "ENTITY": m.group("COUNTERPARTY_NAME").strip(),
123
+ "TRANS_TYPE": "VENDOR_PAYMENT_REMITTANCE",
124
+ "VENDOR_META": m.group("META_BLOCK").strip(),
125
+ "REMITTANCE_IDS": remit_ids,
126
+ "RAW_REMIT_BLOCK": remit_block
127
+ }
128
+
129
+
130
+
131
+ if __name__=='__main__':
132
+ pass
File without changes
@@ -0,0 +1,137 @@
1
+ import re
2
+ from counterparty.key_engine.keys import KEYS, INLINE_KEYS
3
+ from counterparty.util import norm
4
+
5
+ KEYS = sorted(set(KEYS), key=len, reverse=True)
6
+ INLINE_KEYS = sorted(INLINE_KEYS, key=len, reverse=True)
7
+ ALLOWED = {' ', ':', '=', '/', '\\', '_', ',', '-'}
8
+
9
+ WIRE_TOKENS = [
10
+ ("WIRE TRANSFER", 3),
11
+ ("FEDWIRE", 3),
12
+ ("SWIFT", 2),
13
+ ("BIC", 2),
14
+ ("IBAN", 2),
15
+ ("ABA", 2),
16
+ ("RTN", 2),
17
+ ("IMAD", 2),
18
+ ("OMAD", 2),
19
+ ("FWT", 2),
20
+ ("WIRE", 1),
21
+ ]
22
+
23
+ WIRE_RE_PARTS = [(re.compile(re.escape(k), re.I), w) for k, w in WIRE_TOKENS]
24
+
25
+
26
+ def is_wire(text: str) -> bool:
27
+ if not text:
28
+ return False
29
+
30
+ t = norm(text)
31
+
32
+ structural_hits = 0
33
+
34
+ if re.search(r'\bBIC\b|BIC:', t): structural_hits += 2
35
+ if re.search(r'\bABA\b|ABA:', t): structural_hits += 2
36
+ if re.search(r'\bIBAN\b|IBAN:', t): structural_hits += 2
37
+ if re.search(r'\bBNK ID\b|\bBANK ID\b', t): structural_hits += 2
38
+ if re.search(r'\bINSTG BNK\b|\bINSTD BNK\b', t): structural_hits += 2
39
+
40
+ if re.search(r'/[A-Z]{1,4}/[A-Z]{1,4}/', text):
41
+ structural_hits += 2
42
+
43
+ keyword_hits = 0
44
+ if "WIRE TRANSFER" in t: keyword_hits += 1
45
+ elif "WIRE" in t: keyword_hits += 0.5
46
+
47
+ return structural_hits >= 2 and (structural_hits + keyword_hits) >= 3
48
+
49
+
50
+
51
+ def is_standalone(text, i, k_len):
52
+ before = text[i - 1] if i > 0 else ' '
53
+ after = text[i + k_len] if i + k_len < len(text) else ' '
54
+ return before in ALLOWED and after in ALLOWED
55
+
56
+
57
+ def find_keys(text, key_list):
58
+ found = {}
59
+ reserved = []
60
+
61
+ for k in key_list:
62
+ k_len = len(k)
63
+ for i in range(len(text) - k_len + 1):
64
+
65
+ if text[i:i + k_len] != k:
66
+ continue
67
+
68
+ if not is_standalone(text, i, k_len):
69
+ continue
70
+
71
+ if any(s <= i < e for s, e in reserved):
72
+ continue
73
+
74
+ found[i] = k
75
+ reserved.append((i, i + k_len))
76
+
77
+ return dict(sorted(found.items()))
78
+
79
+
80
+ def split_inline_keys(text: str):
81
+ marks = find_keys(text, INLINE_KEYS)
82
+ if not marks:
83
+ return text.strip()
84
+
85
+ idx = [0] + list(marks.keys()) + [len(text)]
86
+ out = {}
87
+ out["value"] = text[:idx[1]].strip()
88
+
89
+ for i in range(1, len(idx) - 1):
90
+ start, end = idx[i], idx[i + 1]
91
+ k = marks[start]
92
+ z = start + len(k)
93
+ while z < len(text) and not text[z].isalnum():
94
+ z += 1
95
+ out[k] = text[z:end].strip()
96
+
97
+ return out
98
+
99
+
100
+ def wire_parser_v1(narr: str):
101
+ marks = find_keys(narr, KEYS)
102
+ idx = [0] + list(marks.keys()) + [len(narr)]
103
+ out = {}
104
+ out["META"] = narr[:idx[1]].strip()
105
+
106
+ for i in range(1, len(idx) - 1):
107
+ start, end = idx[i], idx[i + 1]
108
+ k = marks[start]
109
+ z = start + len(k)
110
+
111
+ while z < len(narr) and not narr[z].isalnum():
112
+ z += 1
113
+
114
+ out[k] = narr[z:end].strip()
115
+
116
+ return out
117
+
118
+
119
+ def wire_parser_v2(v1_output: dict):
120
+ out = {}
121
+ for k, v in v1_output.items():
122
+ if 'WIRE' in k or 'SRC' in k:
123
+ out[k] = v
124
+ elif isinstance(v, str):
125
+ out[k] = split_inline_keys(v)
126
+ else:
127
+ out[k] = v
128
+ return out
129
+
130
+
131
+ def wire_parser(narr: str):
132
+ v1 = wire_parser_v1(narr)
133
+ v2 = wire_parser_v2(v1)
134
+ return {
135
+ "RAW": narr,
136
+ **v2
137
+ }
counterparty/route.py ADDED
@@ -0,0 +1,116 @@
1
+ # routes to respective parsers
2
+
3
+ from counterparty.parsers.disbursement.disb_parser import parse_disbursement_narrative,is_disbursement_narrative
4
+ from counterparty.parsers.fundsTransfer.fundsTrans_parser import parse_funds_transfer_frmdep,is_funds_transfer_frmdep
5
+ from counterparty.parsers.vendorpay.vp_parser import parse_vendor_pay_narrative,is_vendor_pay_narrative
6
+ from counterparty.parsers.vendorpymt.vpymt_parser import parse_vendor_payment_rmr, parse_vendor_payment_remittance,is_vendor_payment_remittance,is_vendor_payment_rmr
7
+ from counterparty.parsers.avidpay.avidp_check_parser import parse_avidpay_check,is_avidpay_check
8
+ from counterparty.parsers.avidpay.avidp_gen_parser import parse_avidpay_generic,is_avidpay_generic
9
+ from counterparty.parsers.misc.cardp import parse_card_payment,is_card_payment
10
+ from counterparty.parsers.misc.invo import parse_invoice_reference,is_invoice_reference
11
+ from counterparty.parsers.misc.webt import parse_web_transfer,is_web_transfer
12
+ from counterparty.parsers.remittance.remi import parse_remittance_advice,is_remittance_advice
13
+ from counterparty.parsers.merchref.merch_ref_parser import parse_merchant_reference,is_merchant_reference
14
+ from counterparty.parsers.paypal.paypal import parse_paypal,classify_paypal
15
+ from counterparty.parsers.processor_eft.peft import parse_processor_eft,is_processor_eft
16
+ from counterparty.parsers.directdebit.directdeb import parse_direct_debit,is_direct_debit
17
+ from counterparty.parsers.LAT_AM.LAT_AM_Entry import LATAM_parse,is_LATAM
18
+
19
+ from counterparty.parsers.wire.wire_parser import wire_parser,is_wire
20
+ from counterparty.parsers.ach.ach_parser import ach_parser,is_ach
21
+ from counterparty.parsers.swift.swift_parser import swift_parser,is_swift
22
+
23
+ from counterparty.parsers.generic.all_parser import all_parser
24
+
25
+ from counterparty.key_engine.key_detector import KeyDetector
26
+ from counterparty.routines import routine1
27
+ from counterparty.util import normalize_spaces
28
+
29
+ key_detector = KeyDetector()
30
+
31
+ def route_to_parser(narr: str):
32
+
33
+ # I call key detector to fix keys before delimiter based parsing
34
+ rewritten_narr, hitl = key_detector.rewrite(normalize_spaces(narr))
35
+
36
+ # if a new key is found.
37
+ if hitl: routine1(hitl)
38
+
39
+ if is_wire(narr):
40
+ res = wire_parser(rewritten_narr)
41
+ res["RAW"] = narr
42
+ return res, "wire"
43
+
44
+ if is_ach(narr):
45
+ res = ach_parser(rewritten_narr)
46
+ res["RAW"] = narr
47
+ return res, "ach"
48
+
49
+ if is_swift(narr):
50
+ res = swift_parser(rewritten_narr)
51
+ res["RAW"] = narr
52
+ return res, "swift"
53
+
54
+ # LATAM
55
+ if is_LATAM(narr) is not None:
56
+ return LATAM_parse(narr), "LATAM"
57
+
58
+ # Paypal
59
+ if classify_paypal(narr) is not None:
60
+ return parse_paypal(narr), "PAYPAL"
61
+
62
+ # Disbursement
63
+ if is_disbursement_narrative(narr):
64
+ return parse_disbursement_narrative(narr), "disbursement"
65
+
66
+ # Funds transfer
67
+ if is_funds_transfer_frmdep(narr):
68
+ return parse_funds_transfer_frmdep(narr), "fundstr"
69
+
70
+ # Vendor payments
71
+ if is_vendor_payment_remittance(narr):
72
+ return parse_vendor_payment_remittance(narr), "vpay_remit"
73
+
74
+ if is_vendor_payment_rmr(narr):
75
+ return parse_vendor_payment_rmr(narr), "vpymt"
76
+
77
+ if is_vendor_pay_narrative(narr):
78
+ return parse_vendor_pay_narrative(narr), "vpay"
79
+
80
+ # AvidPay
81
+ if is_avidpay_check(narr):
82
+ return parse_avidpay_check(narr), "avp_check"
83
+
84
+ if is_avidpay_generic(narr):
85
+ return parse_avidpay_generic(narr), "avp_gen"
86
+
87
+ # Card
88
+ if is_card_payment(narr):
89
+ return parse_card_payment(narr), "card"
90
+
91
+ # Invoice / Web
92
+ if is_invoice_reference(narr):
93
+ return parse_invoice_reference(narr), "invo"
94
+
95
+ if is_web_transfer(narr):
96
+ return parse_web_transfer(narr), "webt"
97
+
98
+ # Processor / EFT
99
+ if is_processor_eft(narr):
100
+ return parse_processor_eft(narr), "peft"
101
+
102
+ # Remittance / Merchant
103
+ if is_remittance_advice(narr):
104
+ return parse_remittance_advice(narr), "remi"
105
+
106
+ if is_merchant_reference(narr):
107
+ return parse_merchant_reference(narr), "merch"
108
+
109
+ # Direct Debit
110
+ if is_direct_debit(narr):
111
+ return parse_direct_debit(narr), "ddbt"
112
+
113
+
114
+ res = all_parser(rewritten_narr)
115
+ res["RAW"] = narr
116
+ return res, "generic"
@@ -0,0 +1,72 @@
1
+ import json
2
+ from pathlib import Path
3
+
4
+ def routine1(data):
5
+ # print("NEW KEY-VALUE PAIRS DETECTED.")
6
+ # print(f"ADD THEM TO THE LIST")
7
+ # for k in data[1]:
8
+ # print(f"{k} : {data[1][k]}")
9
+ # print()
10
+ pass
11
+
12
+
13
+ def routine2(key, value, inline=False):
14
+ key = key.strip().lower()
15
+ value = value.strip()
16
+ if not key or not value:
17
+ return
18
+
19
+ value_up = value.upper()
20
+
21
+ base = Path(__file__).resolve().parent
22
+ gamma = base.parent
23
+
24
+ # canonical_keys.json
25
+ canon_path = gamma / "key_engine" / "canonical_keys.json"
26
+ with open(canon_path, "r", encoding="utf-8") as f:
27
+ canon = json.load(f)
28
+
29
+ canon.setdefault(key, [])
30
+ if value.lower() not in canon[key]:
31
+ canon[key].append(value.lower())
32
+ with open(canon_path, "w", encoding="utf-8") as f:
33
+ json.dump(canon, f, indent=2)
34
+
35
+ all_path = gamma / "key_engine" / "keys.py"
36
+ add_to_keys(all_path, value_up, inline)
37
+
38
+
39
+
40
+ def add_to_keys(path, value, inline):
41
+ text = path.read_text(encoding="utf-8")
42
+ name = "INLINE_KEYS" if inline else "KEYS"
43
+
44
+ start = text.find(f"{name} = [")
45
+ if start == -1:
46
+ raise RuntimeError(f"{name} not found in {path}")
47
+
48
+ l = text.find("[", start)
49
+ r = text.find("]", l)
50
+ if l == -1 or r == -1:
51
+ raise RuntimeError(f"Broken {name} list in {path}")
52
+
53
+ body = text[l + 1:r]
54
+ items = []
55
+
56
+ for x in body.split(","):
57
+ x = x.strip().strip('"').strip("'")
58
+ if x:
59
+ items.append(x)
60
+
61
+ if value not in items:
62
+ items.append(value)
63
+
64
+ items = sorted(set(items), key=lambda x: (-len(x), x))
65
+
66
+ new_list = f"{name} = [\n"
67
+ for x in items:
68
+ new_list += f' "{x}",\n'
69
+ new_list += "]"
70
+
71
+ text = text[:start] + new_list + text[r + 1:]
72
+ path.write_text(text, encoding="utf-8")
counterparty/util.py ADDED
@@ -0,0 +1,40 @@
1
+ import re
2
+ from typing import Optional, Dict, Any
3
+ import unicodedata
4
+
5
+ # this is used in extract payer/payee logic
6
+ def norm2(v):
7
+ if v is None: return None
8
+ if isinstance(v, dict): v = v.get("value") or v.get("name")
9
+ s = str(v).strip()
10
+ s = unicodedata.normalize("NFKD", s)
11
+ s = s.encode("ascii", "ignore").decode("ascii")
12
+ s = re.sub(r"\s+", " ", s)
13
+ return s if s else None
14
+
15
+ # This one is for aliasing.
16
+ def normalize(text: str) -> str:
17
+ if not text: return ""
18
+ text = unicodedata.normalize("NFKD", text)
19
+ text = text.encode("ASCII", "ignore").decode("ASCII")
20
+ text = text.upper()
21
+ text = re.sub(r"[.,/\\]+", " ", text)
22
+ text = re.sub(r"\s+", " ", text)
23
+ return text.strip()
24
+
25
+ # This one is for wire/ach/swift detection
26
+ def norm(text: Optional[str]) -> str:
27
+ if not text: return ""
28
+ text = re.sub(r"^[,|]+", "", text)
29
+ text = re.sub(r"[\\|,]+$", "", text)
30
+ text = re.sub(r"\s+", " ", text)
31
+ return text.strip().upper()
32
+
33
+ # This one is when i want to run key_detector
34
+ def normalize_spaces(text: str) -> str:
35
+ text = text.replace('.','')
36
+ text = text.replace(',',' ')
37
+ # add space BEFORE and AFTER delimiter if missing
38
+ text = re.sub(r"(?<!\s)([:,=;#])", r" \1", text)
39
+ text = re.sub(r"([:,=;#])(?!\s)", r"\1 ", text)
40
+ return " ".join(text.split())
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: counterparty
3
+ Version: 0.1.6
4
+ Summary: A library for counterparty extraction and narrative parsing.
5
+ Requires-Python: >=3.9
6
+ Requires-Dist: rapidfuzz>=2.0.0
7
+ Dynamic: requires-dist
8
+ Dynamic: requires-python
9
+ Dynamic: summary
@@ -0,0 +1,64 @@
1
+ counterparty/__init__.py,sha256=LfM7ucTBfJhqumdJOT5411VdVG_RpHYvRoA0rvMNkwI,809
2
+ counterparty/route.py,sha256=Al8fLE0l3ITd-s5TMNR3SPp4bNKKfnH0vRmcnAtYzv0,4300
3
+ counterparty/routines.py,sha256=ELA34Pb36RIgzf7A5MRjcnLKCIZTSWQU09RHQPWs8qE,1915
4
+ counterparty/util.py,sha256=3_Zkcoef9U3qxsP38DANDLTj0khQFICRnHWUpOQIkKI,1319
5
+ counterparty/extraction/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ counterparty/extraction/clean.py,sha256=etNHWosQMM3REi1T6Cap0EZtGvAjxR0F74HWxLj3GoQ,3586
7
+ counterparty/extraction/extract_payer_payee.py,sha256=G92jLvNvLycU2Z9Ub24Rz5CzVXKATuGZaphYbOJlpjM,5296
8
+ counterparty/extraction/infer_counterparty.py,sha256=TmVuiJ0yUHuQUIdQEck9ikrSbp47gJpfu-vq414gGv4,411
9
+ counterparty/key_engine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ counterparty/key_engine/canonical_keys.json,sha256=mNQYbLmAwEFq3C5PwkHS3uMKYiBPLVcPpMm4D9HIAlg,5277
11
+ counterparty/key_engine/key_detector.py,sha256=uVbHRTa5gr-_UZ0eFWOGgjXrRjWtNz_XLVF_g4AV9CA,9592
12
+ counterparty/key_engine/keys.py,sha256=ID42R1lh2h_1NajZI0qouokudcPbhz1QeHLXc4JvGyw,6143
13
+ counterparty/parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ counterparty/parsers/LAT_AM/LAT_AM_Entry.py,sha256=ObjjlKDdwzGaiboSFdqTlxDaiPvxNsxPMJe-G6hIofE,2728
15
+ counterparty/parsers/LAT_AM/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ counterparty/parsers/LAT_AM/pattern1.py,sha256=yPCotFTNThl6MhJjauCzwnaS_gUOP7-JJp5UHwa9KHo,3968
17
+ counterparty/parsers/LAT_AM/pattern10.py,sha256=eivRBqSdMrmkgmPX0qvqzG5l4bP6TQps_3bhCQm3gA0,1658
18
+ counterparty/parsers/LAT_AM/pattern11.py,sha256=2UsgNGLxZbEG9VzcfYpXdshwwuqbgP6q24Sq05ysnwI,1516
19
+ counterparty/parsers/LAT_AM/pattern12.py,sha256=fQY1sgBi0RfpwcU2dLMED9I8HLdRPmHm3Yih9VmnPlg,2432
20
+ counterparty/parsers/LAT_AM/pattern2.py,sha256=pmBh06VQ0rh-FI1KFpDEW3_jTqHqtifxjQ4vDl9RSvA,2651
21
+ counterparty/parsers/LAT_AM/pattern3.py,sha256=hHBiUxQ98uOMuC9UHnNobsPg8QN_ylwqSf4GaY521EY,1702
22
+ counterparty/parsers/LAT_AM/pattern4.py,sha256=A_idcKDZSX93mydQJNSzn-ONODZu1pxUINQTUen_Pwg,3401
23
+ counterparty/parsers/LAT_AM/pattern5.py,sha256=C8jc32oga6VDfO_xy9B6A44ZNa4FBXFaaId51DJ4pXo,1106
24
+ counterparty/parsers/LAT_AM/pattern6.py,sha256=xl1vo4mhbjAYSINVGLQf_ZkPRh4-q_Uzhtx1o0eiHro,3535
25
+ counterparty/parsers/LAT_AM/pattern7.py,sha256=MZrQb4ZbmwxDc2Xlt1SV-de9aXqbN_duvBqxWgXn9ww,2783
26
+ counterparty/parsers/LAT_AM/pattern8.py,sha256=Ci9-O_AmzMxToAM8SE2_4FePwOXcvT-K3f3Mqd78sRg,3273
27
+ counterparty/parsers/LAT_AM/pattern9.py,sha256=NOTLM_TdmANXGW77-668iLfesijoHarR62-z2BE92uA,2113
28
+ counterparty/parsers/ach/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
+ counterparty/parsers/ach/ach_parser.py,sha256=pA6JJw12ry8Hi8Hs7CM2Fsxdv53HLgXe4WFWvtBfbbs,4409
30
+ counterparty/parsers/avidpay/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ counterparty/parsers/avidpay/avidp_check_parser.py,sha256=7usYY7jU4CiaKrS8FGaWhZN2Ls-cmkU3uT7PD9J581g,1825
32
+ counterparty/parsers/avidpay/avidp_gen_parser.py,sha256=jkXviSVukB0SPX-OxQcsAWhfxpgRH7HrQ_zkVJXqLQ4,1435
33
+ counterparty/parsers/directdebit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ counterparty/parsers/directdebit/directdeb.py,sha256=DxSnukw9421LN_-4oZmxsUmfqxxeh0E8ckqPs0F3ORw,1654
35
+ counterparty/parsers/disbursement/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
+ counterparty/parsers/disbursement/disb_parser.py,sha256=xwY4ORQfVZpiyGTjd5r7LYJf8oekqfdFQvU4X22Fdc4,1438
37
+ counterparty/parsers/fundsTransfer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ counterparty/parsers/fundsTransfer/fundsTrans_parser.py,sha256=gFv8bdd9CUdvW0bXJdJamnOfSuvmk8PEUfX_se3CqJ4,1838
39
+ counterparty/parsers/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
+ counterparty/parsers/generic/all_parser.py,sha256=s_mBBJ7x1wOLD9E_IoQ5F9msjbTVSnXr771XZbbrLPc,2272
41
+ counterparty/parsers/merchref/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
+ counterparty/parsers/merchref/merch_ref_parser.py,sha256=INn6QwjNp4CbSOqejuJhLawYj1Zkn207vwKSeY6dsFA,1022
43
+ counterparty/parsers/misc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
+ counterparty/parsers/misc/cardp.py,sha256=_cmKZRWqg2Sjay0rkoe1iTZkHuUulSKc5KHPn2nYf9U,1384
45
+ counterparty/parsers/misc/invo.py,sha256=R3UJSPuDusrT_auFvWdgLBISyLj78DqJjwfWQIrt-0M,2066
46
+ counterparty/parsers/misc/webt.py,sha256=YWX7tpWLlQ-wkArS4ihhiRUeEQRh1H843XrtCG5eFig,1259
47
+ counterparty/parsers/paypal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ counterparty/parsers/paypal/paypal.py,sha256=G_ex6MrIE1QiyUDlXiWXfHU3_uVhEihJ3vdJVNrDoB4,2454
49
+ counterparty/parsers/processor_eft/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
+ counterparty/parsers/processor_eft/peft.py,sha256=LiQ3rJWQ_9BJWCUJELXXdnQDScifu3060pZuEk10lsk,2686
51
+ counterparty/parsers/remittance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ counterparty/parsers/remittance/remi.py,sha256=tgoJhLLcLWxRmzrkEsyYoMjBCvhFilpg1vs07EdLJ_U,1898
53
+ counterparty/parsers/swift/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ counterparty/parsers/swift/swift_parser.py,sha256=szNX55hNIWn82dNwLEnUmvwYq7uw7na7xupYfYyGzSs,2596
55
+ counterparty/parsers/vendorpay/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
+ counterparty/parsers/vendorpay/vp_parser.py,sha256=uVS5c7K0yMfuDqDYtAt2DZG8WJVHeZ1FoFtXq-Xcs5o,1157
57
+ counterparty/parsers/vendorpymt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
+ counterparty/parsers/vendorpymt/vpymt_parser.py,sha256=2ZTzhQXUwBo5iud1IiHYLewPm6PTpu5EBRetV9ctXH8,2953
59
+ counterparty/parsers/wire/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
+ counterparty/parsers/wire/wire_parser.py,sha256=iy1hwB0yztpYZ0uHKI9daISZgq3kqRQR8C9ZB-18R3w,3412
61
+ counterparty-0.1.6.dist-info/METADATA,sha256=-lcL8pr2To_hxp71eEesdC3TcH0xZoAnnW2R3-_JN3I,246
62
+ counterparty-0.1.6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
63
+ counterparty-0.1.6.dist-info/top_level.txt,sha256=4GalgZH-igUEpExaDNOZUNUANXkbQRu3MnRc8Mcczoc,13
64
+ counterparty-0.1.6.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ counterparty