Apply a weighted scoring based on "Other" release type for recordings
without releases. Otherwise "no release" always gives full score, while
matching against a releases usually always gives some deduction to the
matching score.
tracktotal in a file is supposed to have the total number of tracks on the specific medium. Comparing to the total tracks of a release across all medium hence gives wrong results.
PICARD-1972: Allow initializing Metadata with another Metadata object
If calling Metadata(other_metadata) make a full copy and don't just treat other_metadata as a dict.
Apart of making the API more intuitive this fixes issues with track metadata being not fully preserved when attaching files to tracks.
Some of Picard's tag names allow an additional description separated by a colon, e.g. "comment:desc". In case the description part is empty and the tag ends on a colon this is now treated the same as without any colon. So "lyrics" and "lyrics:" are the same tag.
Handling this in Metadata makes this change immediately available in scripting and to all formats. Script using both forms will still work.
m['tag'] = 0 wasn't doing the same thing as m.add('tag', 0), because the test in __setitem__()
was different: if value vs if value or value == 0
So modify it to make behavior much more consistent.
m['tag'] = 0 or m.add('tag', 0) actually set tag to ['0']
m.add('tag', '') does nothing
m['tag'] = '' explicitly delete the tag (removing it from store, adding it to deleted tags)
m = Metadata(tag='') doesn't create an entry 'tag' (at all)
m = Metadata(tag=0) creates a tag, with internal value ['0']
This way, one can rewrite:
self.metadata = Metadata()
self.metadata['album'] = name
self.metadata['albumartist'] = artist
self.metadata['totaltracks'] = 0
to:
self.metadata = Metadata(album=name, albumartist=artist, totaltracks=0)
Without this patch, totaltracks wasn't set at all.
```python
m = Metadata(tag1='a', tag2='b')
del m['tag1']
```
```
m store: {'tag2': ['b']}
m deleted: {'tag1'}
```
```python
m2 = Metadata(tag1='c', tag2='d')
del m2['tag2']
```
```
m2 store: {'tag2': ['b']}
m2 deleted: {'tag1'}
```
```python
m.update(m2)
```
```
m store: {'tag1': ['c']}
m deleted: {'tag1', 'tag2'} <---- this was incorrect, and untested case
```
This patch fixes it, and results to:
```
m store: {'tag1': ['c']}
m deleted: {'tag2'}
```