Completed
Push — master ( e240c9...6ac358 )
by Ramon
02:34
created

nptyping._meta()   F

Complexity

Conditions 18

Size

Total Lines 72
Code Lines 59

Duplication

Lines 72
Ratio 100 %

Importance

Changes 0
Metric Value
cc 18
eloc 59
nop 3
dl 72
loc 72
rs 1.2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like nptyping._meta() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""
2
The nptyping module: support for typing Numpy datatypes.
3
"""
4
from functools import lru_cache
5
import numpy as np
6
7
8 View Code Duplication
def _meta(generic_type: type = None, rows: int = ..., cols: int = ...) -> type:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
9
    class _ArrayMeta(type):
10
        _generic_type = generic_type
11
        _rows = rows
12
        _cols = cols
13
14
        @lru_cache(maxsize=32)
15
        def __getitem__(cls, item: object) -> type:
16
            generic_type = item
17
            rows = ...
18
            cols = ...
19
            if isinstance(item, tuple):
20
                if not len(item):
21
                    raise TypeError('Parameter Array[...] cannot be empty')
22
23
                generic_type = tuple()
24
                for index, value in enumerate(item):
25
                    if isinstance(value, type):
26
                        generic_type += (value,)
27
                    else:
28
                        break
29
                else:
30
                    index += 1
0 ignored issues
show
introduced by
The variable index does not seem to be defined in case the for loop on line 24 is not entered. Are you sure this can never be the case?
Loading history...
31
32
                if len(generic_type) == 1:
33
                    generic_type = generic_type[0]
34
35
                rowcol_types = [int, type(...), type(None)]
36
                if len(item) > index:
37
                    if type(item[index]) not in rowcol_types:
38
                        raise TypeError('Unexpected type %s, expecting int or ... or None' % item[index])
39
                    rows = item[index] or ...
40
                index += 1
41
                if len(item) > index:
42
                    if isinstance(generic_type, tuple):
43
                        raise TypeError('You are not allowed to specify a column count, combined with multiple column '
44
                                        'types.')
45
                    if type(item[index]) not in rowcol_types:
46
                        raise TypeError('Unexpected type %s, expecting int or ... or None' % item[index])
47
                    cols = item[index] or ...
48
49
            class _Array(metaclass=_meta(generic_type, rows, cols)):
50
                pass
51
52
            result = type('Array', (_Array,), {})
53
            return result
54
55
        @classmethod
56
        def __instancecheck__(cls, inst):
57
            result = False
58
            if isinstance(inst, np.ndarray):
59
                result = True  # In case of an empty array or no _generic_type.
60
                rows = 0
61
                cols = 0
62
                if len(inst.shape) > 0:
63
                    rows = inst.shape[0]
64
                if len(inst.shape) > 1:
65
                    cols = inst.shape[1]
66
67
                if inst.size > 0 and cls._generic_type:
68
                    if isinstance(cls._generic_type, tuple):
69
                        inst_dtypes = [inst.dtype[name] for name in inst.dtype.names]
70
                        cls_dtypes = [np.dtype(typ) for typ in cls._generic_type]
71
                        result = inst_dtypes == cls_dtypes
72
                    else:
73
                        result = isinstance(inst[0], cls._generic_type)
74
                        result |= inst.dtype == np.dtype(cls._generic_type)
75
                    result &= cls._rows is ... or cls._rows == rows
76
                    result &= cls._cols is ... or cls._cols == cols
77
            return result
78
79
    return _ArrayMeta
80
81
82
class Array(metaclass=_meta()):
83
    """
84
    A representation of the `numpy.ndarray`.
85
86
    Example of an array with an undefined generic type and shape:
87
        `Array`
88
89
    Example of an array with a defined generic type:
90
        `Array[int]`
91
92
    Example of an array with a defined generic type and shape (rows):
93
        `Array[int, 3]`
94
        `Array[int, 3, ...]`
95
        `Array[int, 3, None]`
96
97
    Examples of an array with a defined generic type and shape (cols):
98
        `Array[int, None, 2]`
99
        `Array[int, ..., 2]`
100
101
    Example of an array with a defined generic type and shape (rows and cols):
102
        `Array[int, 3, 2]`
103
104
    """
105