GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

CustomBuildExt   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 105
rs 10
wmc 15

7 Methods

Rating   Name   Duplication   Size   Complexity  
A find_in_path() 0 7 3
B customize_compiler_for_c_args_and_nvcc() 0 34 4
A finalize_options() 0 13 1
D load_cuda_config() 0 37 8
A _compile() 0 16 3
A __init__() 0 6 1
A build_extensions() 0 8 1
1
"""PyBM3D packaging and distribution."""
2
import os
3
from setuptools import setup, Extension
4
from setuptools.command.build_ext import build_ext as _build_ext
5
6
7
class CustomBuildExt(_build_ext):
8
    """Custom build extension class."""
9
10
    def __init__(self, *args, **kwargs):
11
        """Extends default class constructor."""
12
        # _build_ext is not a new-style (object) class, which is required for
13
        # super to work
14
        _build_ext.__init__(self, *args, **kwargs)
15
        self.cuda_config = self.load_cuda_config()
16
17
    def build_extensions(self):
18
        """Extends default build_extensions method.
19
20
        Further customizes the compiler to add C file specific compile
21
        arguments and support nvcc compilation of *.cu CUDA files."""
22
23
        self.customize_compiler_for_c_args_and_nvcc()
24
        _build_ext.build_extensions(self)
25
26
    def finalize_options(self):
27
        """Extends default finalize_options method.
28
29
        Injects NumPy`s C include directories into the Cython compilation. This
30
        is done after NumPy was installed through the setuptools setup_requires
31
        argument which removes NumPy from the necessary preinstalled
32
        packages."""
33
34
        _build_ext.finalize_options(self)
35
        # prevent numpy from thinking it is still in its setup process
36
        __builtins__.__NUMPY_SETUP__ = False
37
        import numpy
38
        self.include_dirs.append(numpy.get_include())
39
40
    def customize_compiler_for_c_args_and_nvcc(self):
41
        """Customize the compiler.
42
43
        The customization adds C file specific compile
44
        arguments and support for nvcc compilation of *.cu CUDA files."""
45
46
        self.compiler.src_extensions.append('.cu')
47
48
        # save references to the default compiler_so and _comple methods
49
        default_compiler_so = self.compiler.compiler_so
50
        super = self.compiler._compile
51
52
        # now redefine the _compile method. This gets executed for each
53
        # object but distutils doesn't have the ability to change compilers
54
        # based on source extension: we add it.
55
        def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts):
56
            if os.path.splitext(src)[1] == '.cu':
57
                # use the nvcc for *.cu files
58
                self.compiler.set_executable('compiler_so',
59
                                             self.cuda_config['nvcc'])
60
                postargs = extra_postargs['nvcc']
61
            else:
62
                postargs = extra_postargs['unix']
63
64
                # add C file specific compile arguments
65
                if os.path.splitext(src)[1] == '.c':
66
                    postargs = postargs + extra_postargs['c_args']
67
68
            super(obj, src, ext, cc_args, postargs, pp_opts)
69
            # reset the default compiler_so
70
            self.compiler.compiler_so = default_compiler_so
71
72
        # inject our redefined _compile method into the class
73
        self.compiler._compile = _compile
74
75
    @staticmethod
76
    def load_cuda_config():
77
        """Locate the CUDA environment on the system
78
        Returns a dict with keys 'home', 'nvcc', 'include', and 'lib64'
79
        and values giving the absolute path to each directory.
80
        """
81
        def find_in_path(name, path):
82
            """Finds a file by name in a search path."""
83
            for dir in path.split(os.pathsep):
84
                binpath = os.path.join(dir, name)
85
                if os.path.exists(binpath):
86
                    return os.path.abspath(binpath)
87
            return None
88
89
        # first check if the CUDA_HOME env variable is in use
90
        if 'CUDA_HOME' in os.environ:
91
            home = os.environ['CUDA_HOME']
92
            nvcc = os.path.join(home, 'bin', 'nvcc')
93
        else:
94
            # otherwise, search the PATH for NVCC
95
            nvcc = find_in_path('nvcc', os.environ['PATH'])
96
            if nvcc is None:
97
                return {'cuda_available': False}
98
                raise EnvironmentError('The nvcc binary could not be located '
99
                                       'in your $PATH. Either add it to your '
100
                                       'path, or set $CUDA_HOME')
101
            home = os.path.dirname(os.path.dirname(nvcc))
102
103
        cuda_config = {'home': home, 'nvcc': nvcc,
104
                       'include': os.path.join(home, 'include'),
105
                       'lib64': os.path.join(home, 'lib64')}
106
        for k, v in cuda_config.items():
107
            if not os.path.exists(v):
108
                raise EnvironmentError('The CUDA %s path could not be located '
109
                                       'in %s' % (k, v))
110
111
        return cuda_config
112
113
114
# optimize to the current CPU and enable warnings
115
extra_compile_args = {'unix': ['-march=native', '-Wall', '-Wextra', ],
116
                      'c_args': ['-std=c99', ]}
117
libraries = ["png", "tiff", "jpeg", "fftw3", "fftw3f"]
118
ext_modules = [Extension("pybm3d.bm3d",
119
                         language="c++",
120
                         sources=["pybm3d/bm3d.pyx",
121
                                  "bm3d_src/iio.c",
122
                                  "bm3d_src/bm3d.cpp",
123
                                  "bm3d_src/lib_transforms.cpp",
124
                                  "bm3d_src/utilities.cpp", ],
125
                         extra_compile_args=extra_compile_args,
126
                         libraries=libraries)]
127
128
setup(
129
    name='pybm3d',
130
    version='0.2.1',
131
    description='Python wrapper around BM3D',
132
    author='Eric Jonas',
133
    author_email='[email protected]',
134
    maintainer='Tim Meinhardt',
135
    maintainer_email='[email protected]',
136
    url='https://github.com/ericmjonas/pybm3d',
137
    download_url='https://github.com/ericmjonas/pybm3d/releases/download/v0.2.1/pybm3d-0.2.1.tar.gz',
138
    zip_safe=False,
139
    packages=['pybm3d'],
140
    ext_modules=ext_modules,
141
    cmdclass={'build_ext': CustomBuildExt},
142
    setup_requires=['numpy>=1.13', ],
143
    install_requires=[
144
        'setuptools>=18.0',
145
        'cython>=0.27',
146
        'numpy>=1.13', ],
147
    tests_require=[
148
        'pytest',
149
        'scikit-image', ],
150
)
151