From 81b7afc2e257d21c5441346e5df961fc9bacf245 Mon Sep 17 00:00:00 2001
From: lguyot <luc.guyot@epfl.ch>
Date: Mon, 28 May 2018 11:19:23 +0200
Subject: [PATCH] [FIX] Support pip versions >= 10

Change-Id: I6718dca7657aa3e3d0bf76b927271e30173573de
---
 Makefile                                      |  2 ++
 hbp_nrp_distributed_nest/setup.py             | 28 ++++++++++++-----
 .../bibi/bibi_music_config.py                 |  2 +-
 .../cle/MUSICPyNNCommunicationAdapter.py      | 12 ++++++--
 .../tests/bibi/test_bibi_music_config.py      |  5 ++--
 hbp_nrp_music_interface/setup.py              | 29 +++++++++++++-----
 hbp_nrp_music_xml/setup.py                    | 30 ++++++++++++++-----
 7 files changed, 81 insertions(+), 27 deletions(-)

diff --git a/Makefile b/Makefile
index 83a5ee6..7a38367 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,8 @@ COVER_PACKAGES=hbp_nrp_music_xml hbp_nrp_music_interface hbp_nrp_distributed_nes
 #documentation to build
 #DOC_MODULES=hbp_nrp_music_xml/doc hbp_nrp_music_interface/doc hbp_nrp_distributed_nest/doc
 
+PYTHON_PIP_VERSION?=pip==9.0.3
+
 ##### DO NOT MODIFY BELOW #####################
 
 ifeq ($(NRP_INSTALL_MODE),user)
diff --git a/hbp_nrp_distributed_nest/setup.py b/hbp_nrp_distributed_nest/setup.py
index 0778ff3..51bfed3 100644
--- a/hbp_nrp_distributed_nest/setup.py
+++ b/hbp_nrp_distributed_nest/setup.py
@@ -5,32 +5,46 @@ from setuptools import setup
 import hbp_nrp_distributed_nest
 import pip
 
-from pip.req import parse_requirements
 from optparse import Option
 options = Option('--workaround')
 options.skip_requirements_regex = None
 reqs_file = './requirements.txt'
 # Hack for old pip versions
-# Versions greater than 1.x have a required parameter "session" in
-# parse_requirements
-if pip.__version__.startswith('1.'):
+if pip.__version__.startswith('10.'):
+    # Versions greater or equal to 10.x don't rely on pip.req.parse_requirements
+    install_reqs = list(val.strip() for val in open(reqs_file))
+    reqs = install_reqs
+elif pip.__version__.startswith('1.'):
+    # Versions 1.x rely on pip.req.parse_requirements
+    # but don't require a "session" parameter
+    from pip.req import parse_requirements # pylint:disable=no-name-in-module, import-error
     install_reqs = parse_requirements(reqs_file, options=options)
+    reqs = [str(ir.req) for ir in install_reqs]
 else:
-    from pip.download import PipSession  # pylint:disable=no-name-in-module
+    # Versions greater than 1.x but smaller than 10.x rely on pip.req.parse_requirements
+    # and requires a "session" parameter
+    from pip.req import parse_requirements # pylint:disable=no-name-in-module, import-error
+    from pip.download import PipSession  # pylint:disable=no-name-in-module, import-error
     options.isolated_mode = False
     install_reqs = parse_requirements(  # pylint:disable=unexpected-keyword-arg
         reqs_file,
         session=PipSession,
         options=options
     )
-reqs = [str(ir.req) for ir in install_reqs]
+    reqs = [str(ir.req) for ir in install_reqs]
 
 # ensure we install numpy before the main list of requirements, ignore
 # failures if numpy/cython are not requirements and just proceed (future proof)
 try:
     cython_req = next(r for r in reqs if r.startswith('cython'))
     numpy_req = next(r for r in reqs if r.startswith('numpy'))
-    pip.main(['install', '--no-clean', cython_req, numpy_req])
+    if pip.__version__.startswith('10.'):
+        import subprocess
+        subprocess.check_call(
+            ["python", '-m', 'pip', 'install', "--no-clean", "--user", cython_req, numpy_req]
+        )
+    else:
+        pip.main(['install', '--no-clean', cython_req, numpy_req]) # pylint:disable=no-member
 # pylint: disable=bare-except
 except:
     pass
diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/bibi/bibi_music_config.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/bibi/bibi_music_config.py
index e910778..60550da 100644
--- a/hbp_nrp_music_interface/hbp_nrp_music_interface/bibi/bibi_music_config.py
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/bibi/bibi_music_config.py
@@ -25,7 +25,7 @@
 Provdes a class to generate a MUSIC configuration from a BIBI configuration.
 """
 
-from hbp_nrp_commons.generated import bibi_api_gen
+from hbp_nrp_commons.generated import bibi_api_gen # pylint:disable=no-name-in-module
 from hbp_nrp_commons.bibi_functions import get_neuron_count
 from hbp_nrp_music_xml.schema.generated import music_xml
 from hbp_nrp_music_xml.config.music_config import Application, MusicConfigWriter, MusicConfigPort
diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICPyNNCommunicationAdapter.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICPyNNCommunicationAdapter.py
index 7359250..6588a93 100644
--- a/hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICPyNNCommunicationAdapter.py
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICPyNNCommunicationAdapter.py
@@ -194,18 +194,26 @@ class MUSICPyNNCommunicationAdapter(PyNNNestCommunicationAdapter):
             if proxy_type == 'sink':
                 # top level population view with no subslicing (e.g. sensors, actors, etc.)
                 if isinstance(population.parent, sim.Population):
+                    # tf_config.music_proxies is set in
+                    # hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICBrainLoader.py
+                    # and not in hbp_nrp_cle.tf_framework.config
+                    # which confuses pylint
+                    # pylint: disable=no-member
                     return tf_config.music_proxies[population.label][proxy_type]
+                    # pylint: enable=no-member
 
                 # otherwise, this is a view of a top level named population view
+                # pylint: disable=no-member
                 parent = tf_config.music_proxies[population.parent.label][proxy_type]
+                # pylint: enable=no-member
                 return sim.PopulationView(parent, population.mask, population.label)
 
             # [NRRPLT-4722] workaround, simply get the first <size> proxy neurons that are
             # frozen for a population, unfreeze and return them for connection, for full
             # population requests only get the real population size
             import nest
-
             # top level population view with no subslicing (e.g. sensors, actors, etc.)
+            # pylint: disable=no-member
             if isinstance(population.parent, sim.Population):
                 proxies = tf_config.music_proxies[population.label][proxy_type]
                 size = proxies.size / MUSICConfiguration.FAUX_DYNAMIC_FUDGE_FACTOR
@@ -214,7 +222,7 @@ class MUSICPyNNCommunicationAdapter(PyNNNestCommunicationAdapter):
             else:
                 proxies = tf_config.music_proxies[population.parent.label][proxy_type]
                 size = population.size
-
+            # pylint: disable=no-member
             # find all of the free/frozen proxy neurons
             mask = []
             for i, p in enumerate(map(int, proxies.all_cells)):
diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/bibi/test_bibi_music_config.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/bibi/test_bibi_music_config.py
index 318c5b4..55bf4fc 100644
--- a/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/bibi/test_bibi_music_config.py
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/bibi/test_bibi_music_config.py
@@ -55,11 +55,12 @@ class TestMusicConfiguration(unittest.TestCase):
         self.assertRaises(Exception, MUSICConfiguration, 'foo')
 
         # brain populations set to none or empty
+        brain_file = "foo.py"
         empty_bibi = api.BIBIConfiguration()
-        empty_bibi.brainModel = api.BrainModel(file=api.PythonFilename("foo.py"),
+        empty_bibi.brainModel = api.BrainModelWithPath(file=api.PythonFilename(brain_file),
                                                populations=None)
         self.assertRaises(Exception, MUSICConfiguration, empty_bibi)
-        empty_bibi.brainModel = api.BrainModel(file=api.PythonFilename("foo.py"),
+        empty_bibi.brainModel = api.BrainModelWithPath(file=api.PythonFilename(brain_file),
                                                populations=[])
         self.assertRaises(Exception, MUSICConfiguration, empty_bibi)
 
diff --git a/hbp_nrp_music_interface/setup.py b/hbp_nrp_music_interface/setup.py
index a06b1e9..a164b22 100644
--- a/hbp_nrp_music_interface/setup.py
+++ b/hbp_nrp_music_interface/setup.py
@@ -5,32 +5,45 @@ from setuptools import setup
 import hbp_nrp_music_interface
 import pip
 
-from pip.req import parse_requirements
 from optparse import Option
 options = Option('--workaround')
 options.skip_requirements_regex = None
 reqs_file = './requirements.txt'
-# Hack for old pip versions
-# Versions greater than 1.x have a required parameter "session" in
-# parse_requirements
-if pip.__version__.startswith('1.'):
+if pip.__version__.startswith('10.'):
+    # Versions greater or equal to 10.x don't rely on pip.req.parse_requirements
+    install_reqs = list(val.strip() for val in open(reqs_file))
+    reqs = install_reqs
+elif pip.__version__.startswith('1.'):
+    # Versions 1.x rely on pip.req.parse_requirements
+    # but don't require a "session" parameter
+    from pip.req import parse_requirements # pylint:disable=no-name-in-module, import-error
     install_reqs = parse_requirements(reqs_file, options=options)
+    reqs = [str(ir.req) for ir in install_reqs]
 else:
-    from pip.download import PipSession  # pylint:disable=no-name-in-module
+    # Versions greater than 1.x but smaller than 10.x rely on pip.req.parse_requirements
+    # and requires a "session" parameter
+    from pip.req import parse_requirements # pylint:disable=no-name-in-module, import-error
+    from pip.download import PipSession  # pylint:disable=no-name-in-module, import-error
     options.isolated_mode = False
     install_reqs = parse_requirements(  # pylint:disable=unexpected-keyword-arg
         reqs_file,
         session=PipSession,
         options=options
     )
-reqs = [str(ir.req) for ir in install_reqs]
+    reqs = [str(ir.req) for ir in install_reqs]
 
 # ensure we install numpy before the main list of requirements, ignore
 # failures if numpy/cython are not requirements and just proceed (future proof)
 try:
     cython_req = next(r for r in reqs if r.startswith('cython'))
     numpy_req = next(r for r in reqs if r.startswith('numpy'))
-    pip.main(['install', '--no-clean', cython_req, numpy_req])
+    if pip.__version__.startswith('10.'):
+        import subprocess
+        subprocess.check_call(
+            ["python", '-m', 'pip', 'install', "--no-clean", "--user", cython_req, numpy_req]
+        )
+    else:
+        pip.main(['install', '--no-clean', cython_req, numpy_req]) # pylint:disable=no-member
 # pylint: disable=bare-except
 except:
     pass
diff --git a/hbp_nrp_music_xml/setup.py b/hbp_nrp_music_xml/setup.py
index fe40451..ba19ca8 100644
--- a/hbp_nrp_music_xml/setup.py
+++ b/hbp_nrp_music_xml/setup.py
@@ -5,32 +5,48 @@ from setuptools import setup
 import hbp_nrp_music_xml
 import pip
 
-from pip.req import parse_requirements
 from optparse import Option
 options = Option('--workaround')
 options.skip_requirements_regex = None
 reqs_file = './requirements.txt'
+options = Option("--workaround")
+options.skip_requirements_regex = None
 # Hack for old pip versions
-# Versions greater than 1.x have a required parameter "session" in
-# parse_requirements
-if pip.__version__.startswith('1.'):
+if pip.__version__.startswith('10.'):
+    # Versions greater or equal to 10.x don't rely on pip.req.parse_requirements
+    install_reqs = list(val.strip() for val in open(reqs_file))
+    reqs = install_reqs
+elif pip.__version__.startswith('1.'):
+    # Versions 1.x rely on pip.req.parse_requirements
+    # but don't require a "session" parameter
+    from pip.req import parse_requirements # pylint:disable=no-name-in-module, import-error
     install_reqs = parse_requirements(reqs_file, options=options)
+    reqs = [str(ir.req) for ir in install_reqs]
 else:
-    from pip.download import PipSession  # pylint:disable=no-name-in-module
+    # Versions greater than 1.x but smaller than 10.x rely on pip.req.parse_requirements
+    # and requires a "session" parameter
+    from pip.req import parse_requirements # pylint:disable=no-name-in-module, import-error
+    from pip.download import PipSession  # pylint:disable=no-name-in-module, import-error
     options.isolated_mode = False
     install_reqs = parse_requirements(  # pylint:disable=unexpected-keyword-arg
         reqs_file,
         session=PipSession,
         options=options
     )
-reqs = [str(ir.req) for ir in install_reqs]
+    reqs = [str(ir.req) for ir in install_reqs]
 
 # ensure we install numpy before the main list of requirements, ignore
 # failures if numpy/cython are not requirements and just proceed (future proof)
 try:
     cython_req = next(r for r in reqs if r.startswith('cython'))
     numpy_req = next(r for r in reqs if r.startswith('numpy'))
-    pip.main(['install', '--no-clean', cython_req, numpy_req])
+    if pip.__version__.startswith('10.'):
+        import subprocess
+        subprocess.check_call(
+            ["python", '-m', 'pip', 'install', "--no-clean", "--user", cython_req, numpy_req]
+        )
+    else:
+        pip.main(['install', '--no-clean', cython_req, numpy_req]) # pylint:disable=no-member
 # pylint: disable=bare-except
 except:
     pass
-- 
GitLab