There's a bit of history there: an empty 'tags' attribute used to be set to None. This is mostly internal changes, but I suppose if you write a plugin it matters. On this change: https://bitbucket.org/blais/beancount/commits/1a37899b54837abf9f35c574135cce09382ed3c7 I made them guaranteed to always be of a "set" type. In order to remain efficient, when empty, it is set to the same empty frozenset instance. That set referenced by beancount.core.data.EMPTY_SET
(tagset or set()) | set((tagged,)) is a one-liner that will handle both the None or empty set case during the transition. You should be able to assume it's a set object, and do ....tags = entry.tags | set((tagged,)) Now, there's a second aspect to this that was throwing you off: I treat those objects as immutable. That's why you have to use the _replace() method to produce a new object, the namedtuple is not mutable, and while its 'tags' attribute is (if it is a set), it is not if it is a frozenset. So you can't mutate in-place. That's just a better style of programming; it might be a tad uglier in Python, but avoiding side-effects avoids a lot of other problems, though I think in the case of plugins, nothing else holds onto those objects so in theory they could have been mutated in-place without harm. On Sat, Feb 18, 2017 at 9:59 AM, <stalbansrfctreasu...@gmail.com> wrote: > Martin > Thanks. > My question was all around how to test for an empty tag and update it - > your code does this with > > (tagset or set()) | set((tagged,)) > > I tried to do a logic test on if tagset == None: and also if tagset == > set(): but neither seemed to work. > I was going to do > > if tagset == None: > tagset = set(tagged,) > else: > tagset = tagset | set (tagged,) > > But failed. So I wondered what you had as your 'empty set'. I'll have a > look for EMPTY_SET. > > Not sure if my adaptation of your example is of use to anyone. > > Regards > Paul > > > On Saturday, 18 February 2017 14:47:16 UTC, Martin Blais wrote: > >> entry.tags is supposed to be a set. >> If not set, an empty set. >> I reuse a constant in the codebase (see EMPTY_SET). >> >> TBH I'm not 100% sure what your question is. >> >> >> >> >> On Sat, Feb 18, 2017 at 5:04 AM, <stalbansrf...@gmail.com> wrote: >> >>> Now it works. >>> This can flag cash accounts, but is now configurable to flag any >>> transaction what contains any of the listed accounts. >>> >>> I still don't understand how this works, or what type an empty tag set >>> is.... (tagset or set()) | set((tagged,)) >>> >>> Sample header in journal file: >>> >>> plugin "beancount.plugins.auto_accounts" >>> plugin "tagaccount" "{ >>> 'accounts': { >>> 'Assets:Cash:RBS', >>> 'Assets:Cash:MinisFloat', >>> 'Assets:Cash:NatWest' }, >>> 'tag': 'cash' >>> }" >>> >>> Code: >>> >>> """ >>> >>> For example, a possible configuration could be: >>> >>> plugin "tagaccount`" "{ >>> >>> 'accounts': { >>> >>> 'Assets:Cash:Bank', >>> >>> 'Assets:Cash:Float' }, >>> >>> 'tag': 'CASH' >>> >>> }" >>> >>> """ >>> >>> __author__ = 'Paul Hamshere' >>> >>> from beancount.core import data >>> >>> from beancount.core import account_types >>> >>> __plugins__ = ['tagaccount'] >>> >>> def tagaccount(entries, options_map, config): >>> >>> """ >>> >>> Args: >>> >>> entries: a list of entry instances >>> >>> options_map: a dict of options parsed from the file >>> >>> config: A configuration string, which is intended to be a Python dict >>> >>> Returns: >>> >>> A tuple of entries and errors. >>> >>> """ >>> >>> # Parse and extract configuration values. >>> >>> config_obj = eval(config, {}, {}) >>> >>> if not isinstance(config_obj, dict): >>> >>> raise RuntimeError("Invalid plugin configuration: should be a >>> single dict.") >>> >>> accounts = config_obj.pop('accounts', {}) >>> >>> tagged = config_obj.pop('tag',{}) >>> >>> new_entries = [] >>> >>> for entry in entries: >>> >>> if isinstance(entry, data.Transaction): >>> >>> orig_entry = entry >>> >>> for posting in entry.postings: >>> >>> if (posting.account in accounts): >>> >>> tagset = entry.tags >>> >>> tagset = (tagset or set()) | set((tagged,)) >>> >>> entry = entry._replace(tags=tagset) >>> >>> new_entries.append(entry) >>> >>> return new_entries, [] >>> >>> Code completely adapted from the example plugin. >>> Regards >>> Paul >>> >>> On Friday, 17 February 2017 19:12:41 UTC, p.w.ha...@gmail.com wrote: >>> >>>> Oops my error should have put >>>> >>>> entries = entries._replace..... >>>> >>>> Paul >>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Beancount" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to beancount+...@googlegroups.com. >>> To post to this group, send email to bean...@googlegroups.com. >>> To view this discussion on the web visit https://groups.google.com/d/ms >>> gid/beancount/68c72034-53d7-4f1c-91f2-3a66ec32aaab%40googlegroups.com >>> <https://groups.google.com/d/msgid/beancount/68c72034-53d7-4f1c-91f2-3a66ec32aaab%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> -- > You received this message because you are subscribed to the Google Groups > "Beancount" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to beancount+unsubscr...@googlegroups.com. > To post to this group, send email to beancount@googlegroups.com. > To view this discussion on the web visit https://groups.google.com/d/ > msgid/beancount/c6267881-9785-42cb-a568-5bf5e52530e7%40googlegroups.com > <https://groups.google.com/d/msgid/beancount/c6267881-9785-42cb-a568-5bf5e52530e7%40googlegroups.com?utm_medium=email&utm_source=footer> > . > > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Beancount" group. To unsubscribe from this group and stop receiving emails from it, send an email to beancount+unsubscr...@googlegroups.com. To post to this group, send email to beancount@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/CAK21%2BhP9LokjHTHjfrKUbhsttBz2s%2BF%3D7CRAEQC94qxOUatTEw%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.