forked from seltzered/beancount-plugins-metadata-spray
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmetadata_spray.py
145 lines (117 loc) · 4.6 KB
/
metadata_spray.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# metadata_spray.py
import collections
import re
from beancount.core import data
from beancount.core import account
from beancount.core import getters
from beancount.core.data import Custom
from datetime import datetime
__plugins__ = ('metadata_spray_entries',)
MetadataSprayError = collections.namedtuple(
'MetadataSprayError', 'source message entry')
# Supported spray types
MetadataSprayTypes = ['account_open']
# Metadata Replace Types
# ---
# This dictates how the metadata spray will deal with situations
# where a type of metadata already exists.
# Generally the default is to return an error,
# but the options to either not overwrite metadata or
# replace all also exist.
MetadataSprayReplaceType = ['return_error', 'dont_overwrite', 'overwrite']
metadata_spray_error_meta = data.new_metadata('<metadata_spray>', 0)
def metadata_spray(entry,
replace_type,
metadata_dict):
errors = []
entry_meta = entry[0].meta
for metadata_key in metadata_dict:
if metadata_key in entry_meta:
if replace_type == 'return_error':
error_meta = data.new_metadata(
'<metadata_spray>', entry[0].meta['lineno'])
errors.append(
MetadataSprayError(
error_meta,
"Existing metadata \'{}\' found in account \'{}\', skipping".format(
metadata_key, entry[0].account), None))
continue
elif replace_type == 'dont_overwrite':
continue
value = metadata_dict[metadata_key]
try:
value = datetime.strptime(value, '%Y-%m-%d').date()
except ValueError:
pass
entry_meta[metadata_key] = value
return entry_meta, errors
def metadata_spray_account_open(entries,
replace_type,
pattern,
metadata_dict):
errors = []
account_entries = getters.get_account_open_close(entries)
regexer = re.compile(pattern)
for account_ in account_entries:
# Only operate on account Open entries
entry = account_entries[account_]
if(getattr(entry[0].__class__, '__name__') != 'Open'):
continue
if(regexer.match(account_)):
spray_meta, spray_errors = metadata_spray(
entry,
replace_type,
metadata_dict)
spray_entry = data.Open(spray_meta,
entry[0].date,
entry[0].account,
None,
None)
# Modify entries and update errors
entry_index = entries.index(entry[0])
entries[entry_index] = spray_entry
errors += spray_errors
return entries, errors
def metadata_spray_entries(entries, options_map, config_str):
"""
Insert metadata on
"""
errors = []
config_obj = eval(config_str, {}, {})
sprays = config_obj['sprays']
for spray in sprays:
if ('spray_type' not in spray) or \
('replace_type' not in spray):
errors.append(
MetadataSprayError(metadata_spray_error_meta,
"Missing spray or replace type, \
skipping this spray operation",
None)
)
continue
spray_type = spray['spray_type']
if spray_type not in MetadataSprayTypes:
errors.append(
MetadataSprayError(metadata_spray_error_meta,
"Invalid spray type: {} \
skipping this spray operation".format(
spray_type),
None))
continue
replace_type = spray['replace_type']
if(replace_type not in MetadataSprayReplaceType):
errors.append(
MetadataSprayError(metadata_spray_error_meta,
"Invalid spray type: {} \
skipping this spray operation".format(
spray_type),
None))
continue
if spray_type == 'account_open':
entries, new_errors = metadata_spray_account_open(
entries,
replace_type,
spray['pattern'],
spray['metadata_dict'])
errors += new_errors
return entries, errors