We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Don't hard-code cython command
At the moment, the `_build.py` script assumes the Cython command is `cython`, but on my system I have `cython-2.7` and `cython-3.3`. I think one should use the `Cython` module rather than hard-code the command.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `setup.py`
Content:
```
1 #! /usr/bin/env python
2 
3 descr = """Image Processing SciKit
4 
5 Image processing algorithms for SciPy, including IO, morphology, filtering,
6 warping, color manipulation, object detection, etc.
7 
8 Please refer to the online documentation at
9 http://scikit-image.org/
10 """
11 
12 DISTNAME            = 'scikit-image'
13 DESCRIPTION         = 'Image processing routines for SciPy'
14 LONG_DESCRIPTION    = descr
15 MAINTAINER          = 'Stefan van der Walt'
16 MAINTAINER_EMAIL    = 'stefan@sun.ac.za'
17 URL                 = 'http://scikit-image.org'
18 LICENSE             = 'Modified BSD'
19 DOWNLOAD_URL        = 'http://github.com/scikit-image/scikit-image'
20 VERSION             = '0.10dev'
21 PYTHON_VERSION      = (2, 5)
22 DEPENDENCIES        = {
23                         'numpy': (1, 6),
24                         'Cython': (0, 17),
25                         'six': (1, 3),
26                       }
27 
28 
29 import os
30 import sys
31 import re
32 import setuptools
33 from numpy.distutils.core import setup
34 from distutils.command.build_py import build_py
35 
36 
37 def configuration(parent_package='', top_path=None):
38     if os.path.exists('MANIFEST'): os.remove('MANIFEST')
39 
40     from numpy.distutils.misc_util import Configuration
41     config = Configuration(None, parent_package, top_path)
42 
43     config.set_options(
44             ignore_setup_xxx_py=True,
45             assume_default_configuration=True,
46             delegate_options_to_subpackages=True,
47             quiet=True)
48 
49     config.add_subpackage('skimage')
50     config.add_data_dir('skimage/data')
51 
52     return config
53 
54 
55 def write_version_py(filename='skimage/version.py'):
56     template = """# THIS FILE IS GENERATED FROM THE SKIMAGE SETUP.PY
57 version='%s'
58 """
59 
60     vfile = open(os.path.join(os.path.dirname(__file__),
61                               filename), 'w')
62 
63     try:
64         vfile.write(template % VERSION)
65     finally:
66         vfile.close()
67 
68 
69 def get_package_version(package):
70     version = []
71     for version_attr in ('version', 'VERSION', '__version__'):
72         if hasattr(package, version_attr) \
73                 and isinstance(getattr(package, version_attr), str):
74             version_info = getattr(package, version_attr, '')
75             for part in re.split('\D+', version_info):
76                 try:
77                     version.append(int(part))
78                 except ValueError:
79                     pass
80     return tuple(version)
81 
82 
83 def check_requirements():
84     if sys.version_info < PYTHON_VERSION:
85         raise SystemExit('You need Python version %d.%d or later.' \
86                          % PYTHON_VERSION)
87 
88     for package_name, min_version in DEPENDENCIES.items():
89         dep_error = False
90         try:
91             package = __import__(package_name)
92         except ImportError:
93             dep_error = True
94         else:
95             package_version = get_package_version(package)
96             if min_version > package_version:
97                 dep_error = True
98 
99         if dep_error:
100             raise ImportError('You need `%s` version %d.%d or later.' \
101                               % ((package_name, ) + min_version))
102 
103 
104 if __name__ == "__main__":
105 
106     check_requirements()
107 
108     write_version_py()
109 
110     setup(
111         name=DISTNAME,
112         description=DESCRIPTION,
113         long_description=LONG_DESCRIPTION,
114         maintainer=MAINTAINER,
115         maintainer_email=MAINTAINER_EMAIL,
116         url=URL,
117         license=LICENSE,
118         download_url=DOWNLOAD_URL,
119         version=VERSION,
120 
121         classifiers=[
122             'Development Status :: 4 - Beta',
123             'Environment :: Console',
124             'Intended Audience :: Developers',
125             'Intended Audience :: Science/Research',
126             'License :: OSI Approved :: BSD License',
127             'Programming Language :: C',
128             'Programming Language :: Python',
129             'Programming Language :: Python :: 3',
130             'Topic :: Scientific/Engineering',
131             'Operating System :: Microsoft :: Windows',
132             'Operating System :: POSIX',
133             'Operating System :: Unix',
134             'Operating System :: MacOS',
135         ],
136 
137         configuration=configuration,
138 
139         packages=setuptools.find_packages(exclude=['doc']),
140         include_package_data=True,
141         zip_safe=False, # the package can run out of an .egg file
142 
143         entry_points={
144             'console_scripts': ['skivi = skimage.scripts.skivi:main'],
145         },
146 
147         cmdclass={'build_py': build_py},
148     )
149
```

Path: `skimage/_build.py`
Content:
```
1 import sys
2 import os
3 import hashlib
4 import subprocess
5 
6 
7 # WindowsError is not defined on unix systems
8 try:
9     WindowsError
10 except NameError:
11     class WindowsError(Exception):
12         pass
13 
14 
15 def cython(pyx_files, working_path=''):
16     """Use Cython to convert the given files to C.
17 
18     Parameters
19     ----------
20     pyx_files : list of str
21         The input .pyx files.
22 
23     """
24     # Do not build cython files if target is clean
25     if len(sys.argv) >= 2 and sys.argv[1] == 'clean':
26         return
27 
28     try:
29         import Cython
30     except ImportError:
31         # If cython is not found, we do nothing -- the build will make use of
32         # the distributed .c files
33         print("Cython not found; falling back to pre-built %s" \
34               % " ".join([f.replace('.pyx', '.c') for f in pyx_files]))
35     else:
36         for pyxfile in [os.path.join(working_path, f) for f in pyx_files]:
37 
38             # if the .pyx file stayed the same, we don't need to recompile
39             if not _changed(pyxfile):
40                 continue
41 
42             c_file = pyxfile[:-4] + '.c'
43 
44             # run cython compiler
45             cmd = 'cython -o %s %s' % (c_file, pyxfile)
46             print(cmd)
47 
48             try:
49                 subprocess.call(['cython', '-o', c_file, pyxfile])
50             except WindowsError:
51                 # On Windows cython.exe may be missing if Cython was installed
52                 # via distutils. Run the cython.py script instead.
53                 subprocess.call(
54                     [sys.executable,
55                      os.path.join(os.path.dirname(sys.executable),
56                                   'Scripts', 'cython.py'),
57                      '-o', c_file, pyxfile],
58                     shell=True)
59 
60 
61 def _md5sum(f):
62     m = hashlib.new('md5')
63     while True:
64         # Hash one 8096 byte block at a time
65         d = f.read(8096)
66         if not d:
67             break
68         m.update(d)
69     return m.hexdigest()
70 
71 
72 def _changed(filename):
73     """Compare the hash of a Cython file to the cached hash value on disk.
74 
75     """
76     filename_cache = filename + '.md5'
77 
78     try:
79         md5_cached = open(filename_cache, 'rb').read()
80     except IOError:
81         md5_cached = '0'
82 
83     with open(filename, 'rb') as f:
84         md5_new = _md5sum(f)
85 
86         with open(filename_cache, 'wb') as cf:
87             cf.write(md5_new.encode('utf-8'))
88 
89     return md5_cached != md5_new
90
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/setup.py b/setup.py
old mode 100644
new mode 100755
--- a/setup.py
+++ b/setup.py
@@ -21,10 +21,14 @@
 PYTHON_VERSION      = (2, 5)
 DEPENDENCIES        = {
                         'numpy': (1, 6),
-                        'Cython': (0, 17),
                         'six': (1, 3),
                       }
 
+# Only require Cython if we have a developer checkout
+if VERSION.endswith('dev'):
+    DEPENDENCIES['Cython'] = (0, 17)
+
+
 
 import os
 import sys
diff --git a/skimage/_build.py b/skimage/_build.py
--- a/skimage/_build.py
+++ b/skimage/_build.py
@@ -3,7 +3,6 @@
 import hashlib
 import subprocess
 
-
 # WindowsError is not defined on unix systems
 try:
     WindowsError
@@ -26,7 +25,7 @@
         return
 
     try:
-        import Cython
+        from Cython.Build import cythonize
     except ImportError:
         # If cython is not found, we do nothing -- the build will make use of
         # the distributed .c files
@@ -39,24 +38,7 @@
             if not _changed(pyxfile):
                 continue
 
-            c_file = pyxfile[:-4] + '.c'
-
-            # run cython compiler
-            cmd = 'cython -o %s %s' % (c_file, pyxfile)
-            print(cmd)
-
-            try:
-                subprocess.call(['cython', '-o', c_file, pyxfile])
-            except WindowsError:
-                # On Windows cython.exe may be missing if Cython was installed
-                # via distutils. Run the cython.py script instead.
-                subprocess.call(
-                    [sys.executable,
-                     os.path.join(os.path.dirname(sys.executable),
-                                  'Scripts', 'cython.py'),
-                     '-o', c_file, pyxfile],
-                    shell=True)
-
+            cythonize(pyxfile)
 
 def _md5sum(f):
     m = hashlib.new('md5')

{"golden_diff": "diff --git a/setup.py b/setup.py\nold mode 100644\nnew mode 100755\n--- a/setup.py\n+++ b/setup.py\n@@ -21,10 +21,14 @@\n PYTHON_VERSION      = (2, 5)\n DEPENDENCIES        = {\n                         'numpy': (1, 6),\n-                        'Cython': (0, 17),\n                         'six': (1, 3),\n                       }\n \n+# Only require Cython if we have a developer checkout\n+if VERSION.endswith('dev'):\n+    DEPENDENCIES['Cython'] = (0, 17)\n+\n+\n \n import os\n import sys\ndiff --git a/skimage/_build.py b/skimage/_build.py\n--- a/skimage/_build.py\n+++ b/skimage/_build.py\n@@ -3,7 +3,6 @@\n import hashlib\n import subprocess\n \n-\n # WindowsError is not defined on unix systems\n try:\n     WindowsError\n@@ -26,7 +25,7 @@\n         return\n \n     try:\n-        import Cython\n+        from Cython.Build import cythonize\n     except ImportError:\n         # If cython is not found, we do nothing -- the build will make use of\n         # the distributed .c files\n@@ -39,24 +38,7 @@\n             if not _changed(pyxfile):\n                 continue\n \n-            c_file = pyxfile[:-4] + '.c'\n-\n-            # run cython compiler\n-            cmd = 'cython -o %s %s' % (c_file, pyxfile)\n-            print(cmd)\n-\n-            try:\n-                subprocess.call(['cython', '-o', c_file, pyxfile])\n-            except WindowsError:\n-                # On Windows cython.exe may be missing if Cython was installed\n-                # via distutils. Run the cython.py script instead.\n-                subprocess.call(\n-                    [sys.executable,\n-                     os.path.join(os.path.dirname(sys.executable),\n-                                  'Scripts', 'cython.py'),\n-                     '-o', c_file, pyxfile],\n-                    shell=True)\n-\n+            cythonize(pyxfile)\n \n def _md5sum(f):\n     m = hashlib.new('md5')\n", "issue": "Don't hard-code cython command\nAt the moment, the `_build.py` script assumes the Cython command is `cython`, but on my system I have `cython-2.7` and `cython-3.3`. I think one should use the `Cython` module rather than hard-code the command.\n\n", "before_files": [{"content": "#! /usr/bin/env python\n\ndescr = \"\"\"Image Processing SciKit\n\nImage processing algorithms for SciPy, including IO, morphology, filtering,\nwarping, color manipulation, object detection, etc.\n\nPlease refer to the online documentation at\nhttp://scikit-image.org/\n\"\"\"\n\nDISTNAME            = 'scikit-image'\nDESCRIPTION         = 'Image processing routines for SciPy'\nLONG_DESCRIPTION    = descr\nMAINTAINER          = 'Stefan van der Walt'\nMAINTAINER_EMAIL    = 'stefan@sun.ac.za'\nURL                 = 'http://scikit-image.org'\nLICENSE             = 'Modified BSD'\nDOWNLOAD_URL        = 'http://github.com/scikit-image/scikit-image'\nVERSION             = '0.10dev'\nPYTHON_VERSION      = (2, 5)\nDEPENDENCIES        = {\n                        'numpy': (1, 6),\n                        'Cython': (0, 17),\n                        'six': (1, 3),\n                      }\n\n\nimport os\nimport sys\nimport re\nimport setuptools\nfrom numpy.distutils.core import setup\nfrom distutils.command.build_py import build_py\n\n\ndef configuration(parent_package='', top_path=None):\n    if os.path.exists('MANIFEST'): os.remove('MANIFEST')\n\n    from numpy.distutils.misc_util import Configuration\n    config = Configuration(None, parent_package, top_path)\n\n    config.set_options(\n            ignore_setup_xxx_py=True,\n            assume_default_configuration=True,\n            delegate_options_to_subpackages=True,\n            quiet=True)\n\n    config.add_subpackage('skimage')\n    config.add_data_dir('skimage/data')\n\n    return config\n\n\ndef write_version_py(filename='skimage/version.py'):\n    template = \"\"\"# THIS FILE IS GENERATED FROM THE SKIMAGE SETUP.PY\nversion='%s'\n\"\"\"\n\n    vfile = open(os.path.join(os.path.dirname(__file__),\n                              filename), 'w')\n\n    try:\n        vfile.write(template % VERSION)\n    finally:\n        vfile.close()\n\n\ndef get_package_version(package):\n    version = []\n    for version_attr in ('version', 'VERSION', '__version__'):\n        if hasattr(package, version_attr) \\\n                and isinstance(getattr(package, version_attr), str):\n            version_info = getattr(package, version_attr, '')\n            for part in re.split('\\D+', version_info):\n                try:\n                    version.append(int(part))\n                except ValueError:\n                    pass\n    return tuple(version)\n\n\ndef check_requirements():\n    if sys.version_info < PYTHON_VERSION:\n        raise SystemExit('You need Python version %d.%d or later.' \\\n                         % PYTHON_VERSION)\n\n    for package_name, min_version in DEPENDENCIES.items():\n        dep_error = False\n        try:\n            package = __import__(package_name)\n        except ImportError:\n            dep_error = True\n        else:\n            package_version = get_package_version(package)\n            if min_version > package_version:\n                dep_error = True\n\n        if dep_error:\n            raise ImportError('You need `%s` version %d.%d or later.' \\\n                              % ((package_name, ) + min_version))\n\n\nif __name__ == \"__main__\":\n\n    check_requirements()\n\n    write_version_py()\n\n    setup(\n        name=DISTNAME,\n        description=DESCRIPTION,\n        long_description=LONG_DESCRIPTION,\n        maintainer=MAINTAINER,\n        maintainer_email=MAINTAINER_EMAIL,\n        url=URL,\n        license=LICENSE,\n        download_url=DOWNLOAD_URL,\n        version=VERSION,\n\n        classifiers=[\n            'Development Status :: 4 - Beta',\n            'Environment :: Console',\n            'Intended Audience :: Developers',\n            'Intended Audience :: Science/Research',\n            'License :: OSI Approved :: BSD License',\n            'Programming Language :: C',\n            'Programming Language :: Python',\n            'Programming Language :: Python :: 3',\n            'Topic :: Scientific/Engineering',\n            'Operating System :: Microsoft :: Windows',\n            'Operating System :: POSIX',\n            'Operating System :: Unix',\n            'Operating System :: MacOS',\n        ],\n\n        configuration=configuration,\n\n        packages=setuptools.find_packages(exclude=['doc']),\n        include_package_data=True,\n        zip_safe=False, # the package can run out of an .egg file\n\n        entry_points={\n            'console_scripts': ['skivi = skimage.scripts.skivi:main'],\n        },\n\n        cmdclass={'build_py': build_py},\n    )\n", "path": "setup.py"}, {"content": "import sys\nimport os\nimport hashlib\nimport subprocess\n\n\n# WindowsError is not defined on unix systems\ntry:\n    WindowsError\nexcept NameError:\n    class WindowsError(Exception):\n        pass\n\n\ndef cython(pyx_files, working_path=''):\n    \"\"\"Use Cython to convert the given files to C.\n\n    Parameters\n    ----------\n    pyx_files : list of str\n        The input .pyx files.\n\n    \"\"\"\n    # Do not build cython files if target is clean\n    if len(sys.argv) >= 2 and sys.argv[1] == 'clean':\n        return\n\n    try:\n        import Cython\n    except ImportError:\n        # If cython is not found, we do nothing -- the build will make use of\n        # the distributed .c files\n        print(\"Cython not found; falling back to pre-built %s\" \\\n              % \" \".join([f.replace('.pyx', '.c') for f in pyx_files]))\n    else:\n        for pyxfile in [os.path.join(working_path, f) for f in pyx_files]:\n\n            # if the .pyx file stayed the same, we don't need to recompile\n            if not _changed(pyxfile):\n                continue\n\n            c_file = pyxfile[:-4] + '.c'\n\n            # run cython compiler\n            cmd = 'cython -o %s %s' % (c_file, pyxfile)\n            print(cmd)\n\n            try:\n                subprocess.call(['cython', '-o', c_file, pyxfile])\n            except WindowsError:\n                # On Windows cython.exe may be missing if Cython was installed\n                # via distutils. Run the cython.py script instead.\n                subprocess.call(\n                    [sys.executable,\n                     os.path.join(os.path.dirname(sys.executable),\n                                  'Scripts', 'cython.py'),\n                     '-o', c_file, pyxfile],\n                    shell=True)\n\n\ndef _md5sum(f):\n    m = hashlib.new('md5')\n    while True:\n        # Hash one 8096 byte block at a time\n        d = f.read(8096)\n        if not d:\n            break\n        m.update(d)\n    return m.hexdigest()\n\n\ndef _changed(filename):\n    \"\"\"Compare the hash of a Cython file to the cached hash value on disk.\n\n    \"\"\"\n    filename_cache = filename + '.md5'\n\n    try:\n        md5_cached = open(filename_cache, 'rb').read()\n    except IOError:\n        md5_cached = '0'\n\n    with open(filename, 'rb') as f:\n        md5_new = _md5sum(f)\n\n        with open(filename_cache, 'wb') as cf:\n            cf.write(md5_new.encode('utf-8'))\n\n    return md5_cached != md5_new\n", "path": "skimage/_build.py"}], "after_files": [{"content": "#! /usr/bin/env python\n\ndescr = \"\"\"Image Processing SciKit\n\nImage processing algorithms for SciPy, including IO, morphology, filtering,\nwarping, color manipulation, object detection, etc.\n\nPlease refer to the online documentation at\nhttp://scikit-image.org/\n\"\"\"\n\nDISTNAME            = 'scikit-image'\nDESCRIPTION         = 'Image processing routines for SciPy'\nLONG_DESCRIPTION    = descr\nMAINTAINER          = 'Stefan van der Walt'\nMAINTAINER_EMAIL    = 'stefan@sun.ac.za'\nURL                 = 'http://scikit-image.org'\nLICENSE             = 'Modified BSD'\nDOWNLOAD_URL        = 'http://github.com/scikit-image/scikit-image'\nVERSION             = '0.10dev'\nPYTHON_VERSION      = (2, 5)\nDEPENDENCIES        = {\n                        'numpy': (1, 6),\n                        'six': (1, 3),\n                      }\n\n# Only require Cython if we have a developer checkout\nif VERSION.endswith('dev'):\n    DEPENDENCIES['Cython'] = (0, 17)\n\n\n\nimport os\nimport sys\nimport re\nimport setuptools\nfrom numpy.distutils.core import setup\nfrom distutils.command.build_py import build_py\n\n\ndef configuration(parent_package='', top_path=None):\n    if os.path.exists('MANIFEST'): os.remove('MANIFEST')\n\n    from numpy.distutils.misc_util import Configuration\n    config = Configuration(None, parent_package, top_path)\n\n    config.set_options(\n            ignore_setup_xxx_py=True,\n            assume_default_configuration=True,\n            delegate_options_to_subpackages=True,\n            quiet=True)\n\n    config.add_subpackage('skimage')\n    config.add_data_dir('skimage/data')\n\n    return config\n\n\ndef write_version_py(filename='skimage/version.py'):\n    template = \"\"\"# THIS FILE IS GENERATED FROM THE SKIMAGE SETUP.PY\nversion='%s'\n\"\"\"\n\n    vfile = open(os.path.join(os.path.dirname(__file__),\n                              filename), 'w')\n\n    try:\n        vfile.write(template % VERSION)\n    finally:\n        vfile.close()\n\n\ndef get_package_version(package):\n    version = []\n    for version_attr in ('version', 'VERSION', '__version__'):\n        if hasattr(package, version_attr) \\\n                and isinstance(getattr(package, version_attr), str):\n            version_info = getattr(package, version_attr, '')\n            for part in re.split('\\D+', version_info):\n                try:\n                    version.append(int(part))\n                except ValueError:\n                    pass\n    return tuple(version)\n\n\ndef check_requirements():\n    if sys.version_info < PYTHON_VERSION:\n        raise SystemExit('You need Python version %d.%d or later.' \\\n                         % PYTHON_VERSION)\n\n    for package_name, min_version in DEPENDENCIES.items():\n        dep_error = False\n        try:\n            package = __import__(package_name)\n        except ImportError:\n            dep_error = True\n        else:\n            package_version = get_package_version(package)\n            if min_version > package_version:\n                dep_error = True\n\n        if dep_error:\n            raise ImportError('You need `%s` version %d.%d or later.' \\\n                              % ((package_name, ) + min_version))\n\n\nif __name__ == \"__main__\":\n\n    check_requirements()\n\n    write_version_py()\n\n    setup(\n        name=DISTNAME,\n        description=DESCRIPTION,\n        long_description=LONG_DESCRIPTION,\n        maintainer=MAINTAINER,\n        maintainer_email=MAINTAINER_EMAIL,\n        url=URL,\n        license=LICENSE,\n        download_url=DOWNLOAD_URL,\n        version=VERSION,\n\n        classifiers=[\n            'Development Status :: 4 - Beta',\n            'Environment :: Console',\n            'Intended Audience :: Developers',\n            'Intended Audience :: Science/Research',\n            'License :: OSI Approved :: BSD License',\n            'Programming Language :: C',\n            'Programming Language :: Python',\n            'Programming Language :: Python :: 3',\n            'Topic :: Scientific/Engineering',\n            'Operating System :: Microsoft :: Windows',\n            'Operating System :: POSIX',\n            'Operating System :: Unix',\n            'Operating System :: MacOS',\n        ],\n\n        configuration=configuration,\n\n        packages=setuptools.find_packages(exclude=['doc']),\n        include_package_data=True,\n        zip_safe=False, # the package can run out of an .egg file\n\n        entry_points={\n            'console_scripts': ['skivi = skimage.scripts.skivi:main'],\n        },\n\n        cmdclass={'build_py': build_py},\n    )\n", "path": "setup.py"}, {"content": "import sys\nimport os\nimport hashlib\nimport subprocess\n\n# WindowsError is not defined on unix systems\ntry:\n    WindowsError\nexcept NameError:\n    class WindowsError(Exception):\n        pass\n\n\ndef cython(pyx_files, working_path=''):\n    \"\"\"Use Cython to convert the given files to C.\n\n    Parameters\n    ----------\n    pyx_files : list of str\n        The input .pyx files.\n\n    \"\"\"\n    # Do not build cython files if target is clean\n    if len(sys.argv) >= 2 and sys.argv[1] == 'clean':\n        return\n\n    try:\n        from Cython.Build import cythonize\n    except ImportError:\n        # If cython is not found, we do nothing -- the build will make use of\n        # the distributed .c files\n        print(\"Cython not found; falling back to pre-built %s\" \\\n              % \" \".join([f.replace('.pyx', '.c') for f in pyx_files]))\n    else:\n        for pyxfile in [os.path.join(working_path, f) for f in pyx_files]:\n\n            # if the .pyx file stayed the same, we don't need to recompile\n            if not _changed(pyxfile):\n                continue\n\n            cythonize(pyxfile)\n\ndef _md5sum(f):\n    m = hashlib.new('md5')\n    while True:\n        # Hash one 8096 byte block at a time\n        d = f.read(8096)\n        if not d:\n            break\n        m.update(d)\n    return m.hexdigest()\n\n\ndef _changed(filename):\n    \"\"\"Compare the hash of a Cython file to the cached hash value on disk.\n\n    \"\"\"\n    filename_cache = filename + '.md5'\n\n    try:\n        md5_cached = open(filename_cache, 'rb').read()\n    except IOError:\n        md5_cached = '0'\n\n    with open(filename, 'rb') as f:\n        md5_new = _md5sum(f)\n\n        with open(filename_cache, 'wb') as cf:\n            cf.write(md5_new.encode('utf-8'))\n\n    return md5_cached != md5_new\n", "path": "skimage/_build.py"}]}