Repository: beetbox/beets

Issue:
Errors when installed munkres is > 1.0.x
### Problem

When invoking beets, beets errors out on munkres versions newer than 1.0.x. This was introduced by https://github.com/beetbox/beets/pull/3146.

Running this command in verbose (`-vv`) mode:

```python-traceback
> beet -vv import .
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 583, in _build_master
    ws.require(__requires__)
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 900, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 791, in resolve
    raise VersionConflict(dist, req).with_context(dependent_req)
pkg_resources.ContextualVersionConflict: (munkres 1.1.2 (/usr/lib/python3.7/site-packages), Requirement.parse('munkres~=1.0.0'), {'beets'})

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/bin/beet", line 6, in <module>
    from pkg_resources import load_entry_point
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 3191, in <module>
    @_call_aside
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 3175, in _call_aside
    f(*args, **kwargs)
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 3204, in _initialize_master_working_set
    working_set = WorkingSet._build_master()
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 585, in _build_master
    return cls._build_from_requirements(__requires__)
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 598, in _build_from_requirements
    dists = ws.resolve(reqs, Environment())
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 786, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'munkres~=1.0.0' distribution was not found and is required by beets
```

### Setup

* OS: Linux (Arch Linux)
* Python version: 3.7.2
* beets version: 1.4.7.r359.g80f4f0a0-1 (from `pacman -Qi` output, `beet --version` also break due to munkres dependency)
* Turning off plugins made problem go away (yes/no): Didn't try.

My configuration (output of `beet config`) is:

Not relevant.
Errors when installed munkres is > 1.0.x
### Problem

When invoking beets, beets errors out on munkres versions newer than 1.0.x. This was introduced by https://github.com/beetbox/beets/pull/3146.

Running this command in verbose (`-vv`) mode:

```python-traceback
> beet -vv import .
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 583, in _build_master
    ws.require(__requires__)
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 900, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 791, in resolve
    raise VersionConflict(dist, req).with_context(dependent_req)
pkg_resources.ContextualVersionConflict: (munkres 1.1.2 (/usr/lib/python3.7/site-packages), Requirement.parse('munkres~=1.0.0'), {'beets'})

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/bin/beet", line 6, in <module>
    from pkg_resources import load_entry_point
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 3191, in <module>
    @_call_aside
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 3175, in _call_aside
    f(*args, **kwargs)
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 3204, in _initialize_master_working_set
    working_set = WorkingSet._build_master()
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 585, in _build_master
    return cls._build_from_requirements(__requires__)
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 598, in _build_from_requirements
    dists = ws.resolve(reqs, Environment())
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 786, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'munkres~=1.0.0' distribution was not found and is required by beets
```

### Setup

* OS: Linux (Arch Linux)
* Python version: 3.7.2
* beets version: 1.4.7.r359.g80f4f0a0-1 (from `pacman -Qi` output, `beet --version` also break due to munkres dependency)
* Turning off plugins made problem go away (yes/no): Didn't try.

My configuration (output of `beet config`) is:

Not relevant.


Discussion:
@jackwilsdon wrote:
> We could add a conditional version dependency to require munkres 1.0.x on Python <3.5 and allow 1.1.x on >=3.5 if that would solve it @Freso?

I just looked at [munkres’ source](https://github.com/bmc/munkres). Ugh. This would be a non-issue if they'd actually declared supported Python versions in their `setup.{py,cfg}`, then pip et al would automatically pull in the right version for their Python version without downstream like us having to work around this. :(

If a conditional can solve it, then yeah, I guess that's a fine way to go. Preferably with a note (`# FIXME` etc.) to remove the additional logic when 3.5 support is dropped.
Also reported this upstream: https://github.com/bmc/munkres/issues/31
I'm somewhat confused by your setup @Freso, how have you installed the new version of beets without `munkres~=1.0.0`? Surely when installing via `pip` it would have pulled the older munkres version? Do you have something else installed on your system which depends on the newer version of munkres?

I'm still up for adding a conditional version, just trying to work out why your machine has the wrong version.
Following up from @jackwilsdon's proposal in https://github.com/beetbox/beets/pull/3146#issuecomment-466988412, maybe the right policy would be:

- Python < 3.5 (including Python 2)? Then `munkres~=1.0.0` (as it stands).
- Python 3.5? Then `munkres!=1.1.0,!=1.1.1` (i.e., anything but the versions that used the 3.6-specific type annotations).
- Python > 3.5? Then `munkres>=1.0.0` (anything goes, basically).

Would that cover all the cases?
@jackwilsdon I have beets installed through my package manager and the [beets-git AUR package](https://aur.archlinux.org/packages/beets-git/) (that I maintain). This means that the version of munkres being installed is what [Arch Linux's "python-munkres" package](https://www.archlinux.org/packages/community/any/python-munkres/) has.
@jackwilsdon wrote:
> We could add a conditional version dependency to require munkres 1.0.x on Python <3.5 and allow 1.1.x on >=3.5 if that would solve it @Freso?

I just looked at [munkres’ source](https://github.com/bmc/munkres). Ugh. This would be a non-issue if they'd actually declared supported Python versions in their `setup.{py,cfg}`, then pip et al would automatically pull in the right version for their Python version without downstream like us having to work around this. :(

If a conditional can solve it, then yeah, I guess that's a fine way to go. Preferably with a note (`# FIXME` etc.) to remove the additional logic when 3.5 support is dropped.
Also reported this upstream: https://github.com/bmc/munkres/issues/31
I'm somewhat confused by your setup @Freso, how have you installed the new version of beets without `munkres~=1.0.0`? Surely when installing via `pip` it would have pulled the older munkres version? Do you have something else installed on your system which depends on the newer version of munkres?

I'm still up for adding a conditional version, just trying to work out why your machine has the wrong version.
Following up from @jackwilsdon's proposal in https://github.com/beetbox/beets/pull/3146#issuecomment-466988412, maybe the right policy would be:

- Python < 3.5 (including Python 2)? Then `munkres~=1.0.0` (as it stands).
- Python 3.5? Then `munkres!=1.1.0,!=1.1.1` (i.e., anything but the versions that used the 3.6-specific type annotations).
- Python > 3.5? Then `munkres>=1.0.0` (anything goes, basically).

Would that cover all the cases?
@jackwilsdon I have beets installed through my package manager and the [beets-git AUR package](https://aur.archlinux.org/packages/beets-git/) (that I maintain). This means that the version of munkres being installed is what [Arch Linux's "python-munkres" package](https://www.archlinux.org/packages/community/any/python-munkres/) has.

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -88,10 +88,14 @@ def build_manpages():
     install_requires=[
         'six>=1.9',
         'mutagen>=1.33',
-        'munkres~=1.0.0',
         'unidecode',
         'musicbrainzngs>=0.4',
         'pyyaml',
+    ] + [
+        # Avoid a version of munkres incompatible with Python 3.
+        'munkres~=1.0.0' if sys.version_info < (3, 5, 0) else
+        'munkres!=1.1.0,!=1.1.1' if sys.version_info < (3, 6, 0) else
+        'munkres>=1.0.0',
     ] + (
         # Use the backport of Python 3.4's `enum` module.
         ['enum34>=1.0.4'] if sys.version_info < (3, 4, 0) else []


Test patch: