# Get initials only of artists

**URL:** <https://discourse.beets.io/t/get-initials-only-of-artists/807>\
**Category:** Help\
**Created:** [June 18, 2019, 1:15pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807 "2019-06-18T13:15:23Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![dosoe](https://avatars.discourse-cdn.com/v4/letter/d/f6c823/32.png) [@dosoe](https://discourse.beets.io/u/dosoe)\
**Post date:** [June 18, 2019, 1:15pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/1 "2019-06-18T13:15:23Z")

</div>

Hi!  
I’m still working on my ideal beets setup. This involves shortening paths as windows has limits on the length of paths it can handle. One easy way to do it would be to use only the initials of artists, like `Vivaldi, A.` instead of `Vivaldi, Antonio` . If there is nothing specific, would there be a way to hack it, something like split strings with commas or other separators, then replace every second block with its initials. Is there currently a way of doing this with beets?  
Thanks,  
Dorian

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [June 18, 2019, 1:37pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/2 "2019-06-18T13:37:02Z")

</div>

Hello! This is probably a good case for using [the `inline` plugin](http://docs.beets.io/en/stable/plugins/inline.html). It lets you write little Python snippets, which would be perfect for implementing custom string-manipulation logic like this.

---

<div class="post-metadata">

**Author:** ![dosoe](https://avatars.discourse-cdn.com/v4/letter/d/f6c823/32.png) [@dosoe](https://discourse.beets.io/u/dosoe)\
**Post date:** [June 18, 2019, 8:55pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/3 "2019-06-18T20:55:18Z")

</div>

Thanks! How exactly could I do it? How do the python snippets work? It would be something like

```auto
tmp = re.split('(\W+)',albumartist_sort) # cut artist name into pieces
a_artist_initials = ''
fname = True # marker for family name
for i in tmp: 
    if fname: # family name, kept as-is
        a_artist_initials += ' ' + i
    elif i == ',' or i == ';' or i == '&': # we want to keep the separators
        a_artist_initials += i
        fname=not fname
    elif i=='II': # for numbers in names as in Joseph Strauss II
        a_artist_initials += ' ' + i
    else: # First name
        a_artist_initials += ' ' + i[0] + '.'

```

How do I transform this into a snippet? Do I need to import `re`, how do I do this? Then I need way to deal with orchestras/choirs that don’t have family names or similar stuff.

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [June 20, 2019, 1:38pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/4 "2019-06-20T13:38:38Z")

</div>

I think the best way to sort this out would be with trial and error! Can you give it a shot and see what kinds of problems you run into?

---

<div class="post-metadata">

**Author:** ![dosoe](https://avatars.discourse-cdn.com/v4/letter/d/f6c823/32.png) [@dosoe](https://discourse.beets.io/u/dosoe)\
**Post date:** [June 20, 2019, 2:05pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/5 "2019-06-20T14:05:06Z")

</div>

No, I mean, how do snippets behave? How do you transform python code into a python snippet? How do you tell him what the final output is?

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [June 20, 2019, 2:21pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/6 "2019-06-20T14:21:14Z")

</div>

Sorry; I should have just said “Python code.” There’s not really any such thing as a “snippet.”

The example in the docs should be able to clarify how the code works (you just `return` the result):  
[http://docs.beets.io/en/stable/plugins/inline.html#block-definitions](http://docs.beets.io/en/stable/plugins/inline.html#block-definitions)

---

<div class="post-metadata">

**Author:** ![dosoe](https://avatars.discourse-cdn.com/v4/letter/d/f6c823/32.png) [@dosoe](https://discourse.beets.io/u/dosoe)\
**Post date:** [June 20, 2019, 7:30pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/7 "2019-06-20T19:30:44Z")

</div>

Another (related) question: in a python code for `inline`, what is the equivalent of `%ifdef` ?

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [June 20, 2019, 7:42pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/8 "2019-06-20T19:42:49Z")

</div>

Beets itself does not provide one. But the values are just local variables—you may be able to pull some kind Python hack to test whether a local variable is defined, such as catching a `NameError` exception.

---

<div class="post-metadata">

**Author:** ![dosoe](https://avatars.discourse-cdn.com/v4/letter/d/f6c823/32.png) [@dosoe](https://discourse.beets.io/u/dosoe)\
**Post date:** [June 20, 2019, 9:03pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/9 "2019-06-20T21:03:50Z")

</div>

`inline` allows to set new variables to use for `path`, but can it also set the `path` itself? i. e. is it possible to set the entire path in `inline` and then just call in in `path`?  
I’m thinking of something like

```auto
return('Non-Classique/'+albumartist_sort+'/'+album+' ('+albumdisambig')/'+disc+'-'+track+' '+title)

```

which doesn’t work right now, the `/` are replaced with underscores (and I don’t want it to stop replacing the `/` as it appears in some album titles). Is there a way to circumvent this?

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [June 20, 2019, 9:20pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/10 "2019-06-20T21:20:38Z")

</div>

No, that’s not currently possible.

---

<div class="post-metadata">

**Author:** ![dosoe](https://avatars.discourse-cdn.com/v4/letter/d/f6c823/32.png) [@dosoe](https://discourse.beets.io/u/dosoe)\
**Post date:** [June 20, 2019, 9:30pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/11 "2019-06-20T21:30:34Z")

</div>

Ok, thanks for all the clarifications. I now have the following problem: I tried

```auto
item_fields:
    pw: |
        try:
            pw=parentwork
            return pw
        except NameError:
            return 'No_Work'
path: 
    default: $pw/$albumartist_sort/$album/$disc-$track $title

```

I don’t get what I expect (i. e. everything that has no `parentwork` tag goes into a `No_Work` folder). Instead, all those without `parentwork` go in the folder corresponding to one of the works. Do you have an idea why?

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [June 20, 2019, 9:49pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/12 "2019-06-20T21:49:02Z")

</div>

I think you’re probably running into this:

> <https://github.com/beetbox/beets/issues/2406#issuecomment-274423601>

Which I recently fixed on master:

> <https://github.com/beetbox/beets/commit/81b1faa053867be53f9b3f72fbc148d11ca67b07>

---

<div class="post-metadata">

**Author:** ![dosoe](https://avatars.discourse-cdn.com/v4/letter/d/f6c823/32.png) [@dosoe](https://discourse.beets.io/u/dosoe)\
**Post date:** [June 20, 2019, 9:54pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/13 "2019-06-20T21:54:10Z")

</div>

Ah thanks! I’m still using an older version because of [https://github.com/beetbox/beets/issues/3308](https://github.com/beetbox/beets/issues/3308) and the discussion we had on [https://github.com/beetbox/beets/pull/3279](https://github.com/beetbox/beets/pull/3279) . I will update and check again.

---

<div class="post-metadata">

**Author:** ![dosoe](https://avatars.discourse-cdn.com/v4/letter/d/f6c823/32.png) [@dosoe](https://discourse.beets.io/u/dosoe)\
**Post date:** [June 20, 2019, 10:02pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/14 "2019-06-20T22:02:00Z")

</div>

It solved it, thanks!

---

<div class="post-metadata">

**Author:** ![dosoe](https://avatars.discourse-cdn.com/v4/letter/d/f6c823/32.png) [@dosoe](https://discourse.beets.io/u/dosoe)\
**Post date:** [June 20, 2019, 11:13pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/15 "2019-06-20T23:13:49Z")

</div>

Now I’m getting repeatedly errors like this:

```auto
beetsplug.inline.InlineError: <exception str() failed>

```

The line triggering them is:

```auto
item_fields:
    type: |
        nc_artist = []
        nc_albumartist = []
        nc_album = []
        nc_artist_sort = []
        nc_albumartist_sort= []
        if artist in nc_artist or albumartist in nc_albumartist or album in nc_album or artist_sort in nc_artist_sort or albumartist_sort in nc_albumartist_sort:
            return 'non-classical'
        medieval=['Coro de monjes de la Abadía de Montserrat, Choralschola des Klosters Maria Einsiedeln, Choralschola der Benediktinerabtei Münsterschwarzach, Chœur des moines de l’Abbaye Notre-Dame de Fontgombault, The Benedictine Monks of Santo Domingo de Silos, Cappella Musicale del duomo di Milano','Hildegard von Bingen; Ensemble Belcanto, Dietburg Spohr','Hildegard von Bingen; Gothic Voices, Christopher Page, Emma Kirkby']
        if artist in non_classical or albumartist in non_classical or album in non_classical:
            return 'medieval'
        return 'classical'
path: 
    type::'non-classical': Non-Classique/%ifdef{$album,$albumartist_sort/$album/$tr,$artist_sort/$tr}
    type::'medieval': Medieval/%ifdef{$album,$albumartist_sort/$album/$tr,$artist_sort/$tr}
    pw::'No_Work': No_Work/$albumartist_sort/$album/$tr
    work_prefix::'None': $pc/$pw/$albumartist_sort/$album/$tr
    default: $pc/$work_prefix/$pw/$albumartist_sort/$album/$tr

```

(`$pw`, `$pc` and `$work_prefix` work fine)  
Do you have an idea why it behaves this way?

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [June 20, 2019, 11:59pm UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/16 "2019-06-20T23:59:57Z")

</div>

It would be really helpful to see what’s going wrong if you were to minimize this definition. I usually do that by deleting pieces until the problem goes away, then brining back only the part I just deleted and trying again.

---

<div class="post-metadata">

**Author:** ![dosoe](https://avatars.discourse-cdn.com/v4/letter/d/f6c823/32.png) [@dosoe](https://discourse.beets.io/u/dosoe)\
**Post date:** [June 21, 2019, 8:53am UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/17 "2019-06-21T08:53:30Z")

</div>

Hi! The problem seems to be

```auto
medieval=['Coro de monjes de la Abadía de Montserrat, Choralschola des Klosters Maria Einsiedeln, Choralschola der Benediktinerabtei Münsterschwarzach, Chœur des moines de l’Abbaye Notre-Dame de Fontgombault, The Benedictine Monks of Santo Domingo de Silos, Cappella Musicale del duomo di Milano','Hildegard von Bingen; Ensemble Belcanto, Dietburg Spohr','Hildegard von Bingen; Gothic Voices, Christopher Page, Emma Kirkby']
if albumartist in medieval:
    return 'medieval'

```

I get lots of `<string>:331: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal`  
which mean that I have trouble with my encoding. It seems like some accents in the `medieval` list cannot be properly translated to Unicode. It seems related to [http://beets.io/blog/paths.html](http://beets.io/blog/paths.html) .  
If I convert everything to Unicode with

```auto
 medieval=[u'Coro de monjes de la Abadía de Montserrat, Choralschola des Klosters Maria Einsiedeln, Choralschola der Benediktinerabtei Münsterschwarzach, Chœur des moines de l’Abbaye Notre-Dame de Fontgombault, The Benedictine Monks of Santo Domingo de Silos, Cappella Musicale del duomo di Milano',u'Hildegard von Bingen; Ensemble Belcanto, Dietburg Spohr',u'Hildegard von Bingen; Gothic Voices, Christopher Page, Emma Kirkby']
if albumartist in medieval:
    return 'medieval'

```

then it works fine.

---

<div class="post-metadata">

**Author:** ![dosoe](https://avatars.discourse-cdn.com/v4/letter/d/f6c823/32.png) [@dosoe](https://discourse.beets.io/u/dosoe)\
**Post date:** [June 23, 2019, 10:41am UTC](https://discourse.beets.io/t/get-initials-only-of-artists/807/18 "2019-06-23T10:41:47Z")

</div>

Hi!  
I’m getting another interesting error:

```auto
beetsplug.inline.InlineError: error in inline path field code:
if singleton:
    tr=title
else:
    tr=str(disc)+'-' + str(track) + ' ' + title
return tr

NameError: global name 'singleton' is not defined

```

It seems like the `singleton` tag can’t be used as a Python variable.  
I had fun getting the initials of artist lists where the artists are separated by commas only and it only includes people (not orchestras, choirs or similar stuff) , here exemplified for the`parent_composer_sort` tag that fulfills the above conditions:

```auto
        try: 
            parent_composer_sort.split(',')
            pc=[]
            fam=True
            for p in parent_composer_sort.split(','):
                if p=='Sir' or p=='Dame':
                    continue
                if fam:
                    pc.append(p.strip())
                else: 
                    a=p.split()
                    b=[]
                    for x in a:
                        if previous.strip()=='Strauss' or x=='van' or x=='von' or x=='de':
                            b.append(x)
                        else: 
                            b.append(x.strip()[0])
                    pc.append(' '.join(b))
                previous=p
                fam=not fam
            return(', '.join(pc))
        except NameError:
            return 'No_Parent_Composer'

```

more generalized splitting shouldn’t be a problem, but orchestras will be, as this piece of code supposes that every text block is a family name, then a comma, then a list of first names (that are then replaced by the corresponding initals) then the next family name. Groups mess this system up as 1. they don’t really have family and first names, so putting initals doesn’t make sense and 2. they are not always split in two parts separated by a comma, so it messes up all following names. Apart from having a list of all orchestras somewhere in a text file or making MB queries for each artist, I don’t see how to circumvent this problem.  
I make an exception for the Strauss family, because I want to be able to discriminate between Josef, Johann I and Johann II.

Another interesting bit of info: for flexible attributes like `parentwork` if the tag is not set python raises a `NameError` but for core attributes like `album` or `disc` they are set to the corresponding zero (empty string or 0 as an int).
