Repository: beetbox/beets

Issue:
duplicates: Do not report duplicates when only `mb_albumid` is duplicated
```
$ beet duplicates -F
/home/simon/Música/2 Unlimited/Get Ready/03 - The Magic Friend.mp3
/home/simon/Música/2 Unlimited/Get Ready/04 - Contrast.mp3
/home/simon/Música/2 Unlimited/Get Ready/05 - Desire.mp3
/home/simon/Música/2 Unlimited/Get Ready/06 - Pacific Walk.mp3
/home/simon/Música/2 Unlimited/Get Ready/07 - Workaholic.mp3
/home/simon/Música/2 Unlimited/Get Ready/08 - Rougher Than The Average.mp3
/home/simon/Música/2 Unlimited/Get Ready/09 - Delight.mp3
/home/simon/Música/2 Unlimited/Get Ready/10 - Eternally Yours.mp3
/home/simon/Música/2 Unlimited/Get Ready/11 - Twilight Zone (Rave Version Edit).mp3
/home/simon/Música/2 Unlimited/Get Ready/12 - Get Ready For This (Vocal Version).mp3
/home/simon/Música/2 Unlimited/Get Ready/13 - The Magic Friend (Instrumental).mp3
/home/simon/Música/2 Unlimited/Get Ready/14 - Workaholic (Instrumental).mp3
```

```
$ ll Música/2\ Unlimited/Get\ Ready/
total 83M
-rw-rw-r-- 1 simon simon 7,5M oct 10 16:00 03 - The Magic Friend.mp3
-rw-rw-r-- 1 simon simon 6,4M oct 10 16:00 04 - Contrast.mp3
-rw-rw-r-- 1 simon simon 7,9M oct 10 16:00 05 - Desire.mp3
-rw-rw-r-- 1 simon simon 5,7M oct 10 16:00 06 - Pacific Walk.mp3
-rw-rw-r-- 1 simon simon 7,2M oct 10 16:00 07 - Workaholic.mp3
-rw-rw-r-- 1 simon simon 7,6M oct 10 16:00 08 - Rougher Than The Average.mp3
-rw-rw-r-- 1 simon simon 6,5M oct 10 16:00 09 - Delight.mp3
-rw-rw-r-- 1 simon simon 7,6M oct 10 16:00 10 - Eternally Yours.mp3
-rw-rw-r-- 1 simon simon 7,1M oct 10 16:00 11 - Twilight Zone (Rave Version Edit).mp3
-rw-rw-r-- 1 simon simon 6,4M oct 10 16:00 12 - Get Ready For This (Vocal Version).mp3
-rw-rw-r-- 1 simon simon 5,9M oct 10 16:00 13 - The Magic Friend (Instrumental).mp3
-rw-rw-r-- 1 simon simon 7,2M oct 10 16:00 14 - Workaholic (Instrumental).mp3
-rw-rw-r-- 1 simon simon  30K oct 10 16:00 cover.jpg
```

What is the duplicate of that?



Discussion:
That's odd. Can you check whether the keys you're using for comparison might match between these? For example, maybe they're all erroneously tagged with the same `mb_trackid`.

Maybe it would be helpful, in `-F` mode, to print a separator between each group of duplicated tracks…

I can't interpret those results. What is the duplicate of that? 
I print the info about 2 of that tracks:

```
$ beet info 2\ Unlimited/Get\ Ready/03\ -\ The\ Magic\ Friend.mp3 
/home/simon/Música/2 Unlimited/Get Ready/03 - The Magic Friend.mp3
acoustid_fingerprint: AQAAAA
               album: Get Ready
         albumartist: 2 Unlimited
           albumtype: Album
                 art: True
              artist: 2 Unlimited
            bitdepth: 0
             bitrate: 229021
                 bpm: 0
          catalognum: 01624 15407-2
            channels: 2
                comp: False
             country: US
                date: 1992-01-01
                disc: 0
           disctotal: 1
              format: MP3
               genre: Dance
              genres: Dance
               label: Radikal Records
              length: 273.293061224
              lyrics: 
    mb_albumartistid: 4057
          mb_albumid: 869162
         mb_artistid: 4057
               media: CD
       original_year: 0
       rg_album_gain: -6.18
       rg_album_peak: 0.946564
       rg_track_gain: -7.23
       rg_track_peak: 0.946564
          samplerate: 44100
               title: The Magic Friend
               track: 3
          tracktotal: 14
                year: 1992
```

```
$ beet info 2\ Unlimited/Get\ Ready/13\ -\ The\ Magic\ Friend\ \(Instrumental\).mp3 
/home/simon/Música/2 Unlimited/Get Ready/13 - The Magic Friend (Instrumental).mp3
acoustid_fingerprint: AQAAAA
               album: Get Ready
         albumartist: 2 Unlimited
           albumtype: Album
                 art: True
              artist: 2 Unlimited
            bitdepth: 0
             bitrate: 227996
                 bpm: 0
          catalognum: 01624 15407-2
            channels: 2
                comp: False
             country: US
                date: 1992-01-01
                disc: 0
           disctotal: 1
              format: MP3
               genre: Dance
              genres: Dance
               label: Radikal Records
              length: 213.942857143
              lyrics: 
    mb_albumartistid: 4057
          mb_albumid: 869162
         mb_artistid: 4057
               media: CD
       original_year: 0
       rg_album_gain: -6.18
       rg_album_peak: 0.946564
       rg_track_gain: -6.7
       rg_track_peak: 0.946564
          samplerate: 44100
               title: The Magic Friend (Instrumental)
               track: 13
          tracktotal: 14
                year: 1992
```

:cake: :candy:

_(that's the 1000th PR)_

:tada: A thousand bugs!

@simonbcn Can you try running `duplicates` in verbose mode? What are the results when running _without_ `-F`? Also, what keys are you using for duplicate comparison (the default, or something custom)?

It looks like this may be related to #568. If you're using the default keys, then the plugin is using `mb_trackid` and `mb_albumid`. You seem to be in a strange situation where you have `mb_albumid` set but `mb_trackid` unset, which means that the plugin is falling back to comparing just on the album ID—making these appear to be duplicates. But we'll need details for confirmation.

About #568. In config file I set `backend: command` now. But `duplicates` fails too when it used `backend: gstreamer`

```
$ beet -v duplicates
user configuration: /home/simon/.config/beets/config.yaml
data directory: /home/simon/.config/beets
Sending event: pluginload
artresizer: method is (2, (6, 7, 7))
no config file found at /home/simon/.beetsconfig
library database: /home/simon/.beets/musiclibrary.blb
library directory: /home/simon/Música
Sending event: library_opened
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/02 - I'm Not Driven.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/11 - High.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/12 - Last Lap.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/13 - My End.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/14 - The Jewellery.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/01 - Movin' Up.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/05 - I'll Never Let You Go.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/03 - Prisoners (feat. Ferrara).mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/07 - Wasting Your Life.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/04 - Hungry Games.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/06 - So Young.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/10 - Time.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Charlie Puth & Emily Luther/00 - Someone Like You (Adele).mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/08 - Fire Up.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Carlos Jean/Combustión/09 - Someone.mp3 are null: skipping
duplicates: all keys ['mb_trackid', 'mb_albumid'] on item /home/simon/Música/Christopher Cross/The 40 Year-Old Virgin/13 - Believe It or Not.mp3 are null: skipping
/home/simon/Música/Daft Punk/Daft Club/10 - Aerodynamic (Slum Village Remix).mp3
/home/simon/Música/Daft Punk/Daft Club/11 - Too Long (Gonzales Version).mp3
/home/simon/Música/Barbra Streisand/What Matters Most/02 - Something New In My Life.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/03 - Solitary Moon.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/04 - Nice 'n' Easy.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/05 - Alone In The World.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/06 - So Many Stars.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/07 - The Same Hello, The Same Goodbye.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/08 - That Face.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/09 - I'll Never Say Goodbye.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/10 - What Matters Most.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/11 - The Way We Were.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/12 - What Are You Doing The Rest Of Your Life_.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/13 - You Don't Bring Me Flowers.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/14 - Papa, Can You Hear Me_.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/15 - Pieces Of Dreams.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/16 - The Island.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/17 - The Summer Knows.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/18 - How Do You Keep The Music Playing_.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/19 - After The Rain.mp3
/home/simon/Música/Barbra Streisand/What Matters Most/20 - A Piece Of Sky.mp3
/home/simon/Música/Caradefuego/Masculina/02 - Masculina.mp3
/home/simon/Música/Caradefuego/Masculina/03 - Madrugada.mp3
/home/simon/Música/Caradefuego/Masculina/04 - Lagrimita.mp3
/home/simon/Música/Caradefuego/Masculina/05 - Fina Estampa.mp3
/home/simon/Música/Caradefuego/Masculina/06 - Deusa Do Amor.mp3
/home/simon/Música/Caradefuego/Masculina/07 - Otro Plan.mp3
/home/simon/Música/Caradefuego/Masculina/08 - Oro Verde.mp3
/home/simon/Música/Caradefuego/Masculina/09 - Airena.mp3
/home/simon/Música/Caradefuego/Masculina/10 - Noche De San Juan.mp3
/home/simon/Música/Caradefuego/Masculina/11 - Seda.mp3
/home/simon/Música/Caradefuego/Masculina/12 - Masculina (Tecno Mix).mp3
/home/simon/Música/Caradefuego/Masculina/13 - Otro Plan (Vuelo Mix).mp3
/home/simon/Música/Cher/The Greatest Hits/02 - The Shoop Shoop Song (It's In His Kiss).mp3
/home/simon/Música/Cher/The Greatest Hits/03 - If I Could Turn Back Time.mp3
/home/simon/Música/Cher/The Greatest Hits/04 - Heart Of Stone.mp3
/home/simon/Música/Cher/The Greatest Hits/05 - Love And Understanding.mp3
/home/simon/Música/Cher/The Greatest Hits/06 - Love Hurts.mp3
/home/simon/Música/Cher/The Greatest Hits/07 - Just Like Jesse James.mp3
/home/simon/Música/Cher/The Greatest Hits/08 - I Found Someone.mp3
/home/simon/Música/Cher/The Greatest Hits/09 - One By One.mp3
/home/simon/Música/Cher/The Greatest Hits/10 - Strong Enough.mp3
/home/simon/Música/Cher/The Greatest Hits/12 - Walking In Memphis.mp3
/home/simon/Música/Cher/The Greatest Hits/14 - All I Really Want To Do.mp3
/home/simon/Música/Cher/The Greatest Hits/15 - Bang Bang.mp3
/home/simon/Música/Cher/The Greatest Hits/16 - Gypsies, Tramps And Thieves.mp3
/home/simon/Música/Cher/The Greatest Hits/19 - Dov'è L'Amore (Emilio Estefan Jnr. Mix).mp3
/home/simon/Música/Cher/The Greatest Hits/13 - Love Can Build A Bridge.mp3
/home/simon/Música/Cher/The Greatest Hits/17 - The Beat Goes On.mp3
/home/simon/Música/Cher/The Greatest Hits/18 - I Got You Babe.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/02 - The 80's.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/03 - Someone That Cannot Love.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/04 - Playing Bowies With Me.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/05 - So You Want To Save The World.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/06 - U Make Me Believe.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/07 - You And I (Letter To S.).mp3
/home/simon/Música/David Fonseca/Sing Me Something New/08 - Haunted Home.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/09 - Summer Will Bring You Over.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/10 - Now That I Am You.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/11 - Revolution Edit.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/12 - In Love With Yourself.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/13 - Do You Really Believe That Love Will Keep You From Getting Hurt_.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/14 - Sing Me Something New.mp3
/home/simon/Música/David Fonseca/Sing Me Something New/15 - My Sunshine And My Rain.mp3
/home/simon/Música/2 Unlimited/Get Ready/04 - Contrast.mp3
/home/simon/Música/2 Unlimited/Get Ready/05 - Desire.mp3
/home/simon/Música/2 Unlimited/Get Ready/06 - Pacific Walk.mp3
/home/simon/Música/2 Unlimited/Get Ready/07 - Workaholic.mp3
/home/simon/Música/2 Unlimited/Get Ready/08 - Rougher Than The Average.mp3
/home/simon/Música/2 Unlimited/Get Ready/09 - Delight.mp3
/home/simon/Música/2 Unlimited/Get Ready/10 - Eternally Yours.mp3
/home/simon/Música/2 Unlimited/Get Ready/11 - Twilight Zone (Rave Version Edit).mp3
/home/simon/Música/2 Unlimited/Get Ready/12 - Get Ready For This (Vocal Version).mp3
/home/simon/Música/2 Unlimited/Get Ready/13 - The Magic Friend (Instrumental).mp3
/home/simon/Música/2 Unlimited/Get Ready/14 - Workaholic (Instrumental).mp3
/home/simon/Música/Boy George/This Is What I Do/02 - Bigger Than War.mp3
/home/simon/Música/Boy George/This Is What I Do/03 - Live Your Life.mp3
/home/simon/Música/Boy George/This Is What I Do/04 - My God.mp3
/home/simon/Música/Boy George/This Is What I Do/05 - It's Easy.mp3
/home/simon/Música/Boy George/This Is What I Do/06 - Death Of Samantha.mp3
/home/simon/Música/Boy George/This Is What I Do/07 - Any Road.mp3
/home/simon/Música/Boy George/This Is What I Do/08 - My Star.mp3
/home/simon/Música/Boy George/This Is What I Do/09 - Love And Danger.mp3
/home/simon/Música/Boy George/This Is What I Do/10 - Nice And Slow.mp3
/home/simon/Música/Boy George/This Is What I Do/11 - Play Me.mp3
/home/simon/Música/Boy George/This Is What I Do/12 - Feel The Vibration.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/02 - Rock That Body.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/03 - Meet Me Halfway.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/04 - Imma Be.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/05 - I Gotta Feeling.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/06 - Alive.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/07 - Missing You.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/08 - Ring-A-Ling.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/09 - Party All The Time.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/10 - Out Of My Head.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/11 - Electric City.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/12 - Showdown.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/13 - Now Generation.mp3
/home/simon/Música/Black Eyed Peas/The E.N.D/15 - Rockin To The Beat.mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/02 - Love And Understanding.mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/03 - Save Up All Your Tears.mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/04 - The Shoop Shoop Song (It's In His Kiss).mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/05 - After All (Love Theme From Chances Are).mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/06 - If I Could Turn Back Time.mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/07 - Just Like Jesse James.mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/08 - Heart Of Stone (Remix).mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/09 - I Found Someone.mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/10 - We All Sleep Alone.mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/11 - Bang Bang (New Version).mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/12 - Take Me Home.mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/13 - Dark Lady.mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/14 - Half-Breed.mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/15 - The Way Of Love.mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/16 - Gypsys, Tramps And Thieves.mp3
/home/simon/Música/Cher/If I Could Turn Back Time - Cher's Greatest Hits/17 - I Got You Babe (Sonny & Cher).mp3
/home/simon/Música/Björk/Selmasongs/02 - Cvalda.mp3
/home/simon/Música/Björk/Selmasongs/03 - I've Seen It All.mp3
/home/simon/Música/Björk/Selmasongs/04 - Scatterheart.mp3
/home/simon/Música/Björk/Selmasongs/05 - In The Musicals.mp3
/home/simon/Música/Björk/Selmasongs/06 - 107 Steps.mp3
/home/simon/Música/Björk/Selmasongs/07 - New World.mp3
Sending event: cli_exit
```

Oops! I meant to type #586.

(There is no `backend` option; I don't know what you meant there.)

Thanks for the verbose output. This seems to have confirmed my suspicion. The plugin should not report duplicates when only `mb_albumid` is duplicated, but I'm not sure how to best accomplish that.

I explained about `backend`option because the #568 bug.


Resolving patch:
diff --git a/beetsplug/duplicates.py b/beetsplug/duplicates.py
--- a/beetsplug/duplicates.py
+++ b/beetsplug/duplicates.py
@@ -74,30 +74,37 @@ def _checksum(item, prog, log):
     return key, checksum
 
 
-def _group_by(objs, keys, log):
+def _group_by(objs, keys, strict, log):
     """Return a dictionary with keys arbitrary concatenations of attributes and
     values lists of objects (Albums or Items) with those keys.
+
+    If strict, all attributes must be defined for a duplicate match.
     """
     import collections
     counts = collections.defaultdict(list)
     for obj in objs:
         values = [getattr(obj, k, None) for k in keys]
         values = [v for v in values if v not in (None, '')]
-        if values:
+        if strict and len(values) < len(keys):
+            log.debug(u'{0}: some keys {1} on item {2} are null or empty: '
+                      'skipping',
+                      PLUGIN, keys, displayable_path(obj.path))
+        elif (not strict and not len(values)):
+            log.debug(u'{0}: all keys {1} on item {2} are null or empty: '
+                      'skipping',
+                      PLUGIN, keys, displayable_path(obj.path))
+        else:
             key = '\001'.join(values)
             counts[key].append(obj)
-        else:
-            log.debug(u'{0}: all keys {1} on item {2} are null: skipping',
-                      PLUGIN, keys, displayable_path(obj.path))
 
     return counts
 
 
-def _duplicates(objs, keys, full, log):
+def _duplicates(objs, keys, full, strict, log):
     """Generate triples of keys, duplicate counts, and constituent objects.
     """
     offset = 0 if full else 1
-    for k, objs in _group_by(objs, keys, log).iteritems():
+    for k, objs in _group_by(objs, keys, strict, log).iteritems():
         if len(objs) > 1:
             yield (k, len(objs) - offset, objs[offset:])
 
@@ -113,6 +120,7 @@ def __init__(self):
             'count': False,
             'album': False,
             'full': False,
+            'strict': False,
             'path': False,
             'keys': ['mb_trackid', 'mb_albumid'],
             'checksum': None,
@@ -144,6 +152,11 @@ def __init__(self):
                                         help='show all versions of duplicate'
                                         ' tracks or albums')
 
+        self._command.parser.add_option('-s', '--strict', dest='strict',
+                                        action='store_true',
+                                        help='report duplicates only if all'
+                                        ' attributes are set')
+
         self._command.parser.add_option('-k', '--keys', dest='keys',
                                         action='callback', metavar='KEY1 KEY2',
                                         callback=vararg_callback,
@@ -170,6 +183,7 @@ def _dup(lib, opts, args):
             fmt = self.config['format'].get()
             album = self.config['album'].get(bool)
             full = self.config['full'].get(bool)
+            strict = self.config['strict'].get(bool)
             keys = self.config['keys'].get()
             checksum = self.config['checksum'].get()
             copy = self.config['copy'].get()
@@ -206,6 +220,7 @@ def _dup(lib, opts, args):
             for obj_id, obj_count, objs in _duplicates(items,
                                                        keys=keys,
                                                        full=full,
+                                                       strict=strict,
                                                        log=self._log):
                 if obj_id:  # Skip empty IDs.
                     for o in objs:


Test patch: