pypen.drawing.color.Color.from_user_input()   F
last analyzed

Complexity

Conditions 16

Size

Total Lines 54
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 42
nop 2
dl 0
loc 54
rs 2.4
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 pypen.drawing.color.Color.from_user_input() 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
import colorsys
2
import re
3
4
from pypen.utils.math import clamp
5
from pypen.drawing.css_colors import _CSS_COLORS
6
7
_COLORS = {
8
    "default_background_color": (0),
9
    "default_fill_color": (30, 60, 125),
10
    "default_stroke_color": (15, 30, 60),
11
12
    "red": (200, 30, 30),
13
    "green": (30, 200, 30),
14
    "blue": (30, 30, 200)
15
}
16
17
_CSS_COLORS.update(_COLORS)
18
_COLORS = _CSS_COLORS
19
20
_COLORS_CACHE = {}
21
22
23
class Color:
24
    def __init__(self, r=0, g=0, b=0, a=255):
25
        self.r = clamp(r, 0, 255)/255
26
        self.g = clamp(g, 0, 255)/255
27
        self.b = clamp(b, 0, 255)/255
28
        self.a = clamp(a, 0, 255)/255
29
30
    def rgb(self):
31
        return self.r, self.g, self.b
32
33
    def rgba(self):
34
        return self.r, self.g, self.b, self.a
35
36
    @classmethod
37
    def from_user_input(cls, user_input):
38
        if isinstance(user_input, Color):
39
            return user_input
40
41
        if isinstance(user_input, int) or isinstance(user_input, float):
42
            r = g = b = user_input
43
            return cls(r, g, b)
44
45
        if isinstance(user_input, tuple) or isinstance(user_input, list):
46
            if len(user_input) == 1:
47
                r = g = b = user_input[0]
48
                return cls(r, g, b)
49
50
            if len(user_input) == 3:
51
                r, g, b = user_input
52
                return cls(r, g, b)
53
54
            if len(user_input) == 4:
55
                r, g, b, a = user_input
56
                return cls(r, g, b, a)
57
58
        if isinstance(user_input, str):
59
            if user_input in _COLORS_CACHE:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable _COLORS_CACHE does not seem to be defined.
Loading history...
60
                return _COLORS_CACHE[user_input]
61
62
            if user_input in _COLORS.keys():
63
                color = Color.from_user_input(_COLORS[user_input])
64
                _COLORS_CACHE[user_input] = color
65
                return color
66
67
            hex_match = re.match(r"(\#|0x)(.*)", user_input)
68
69
            if hex_match:
70
                hex_match_group = hex_match.group(2)
71
                hex_digits = re.findall(r".{1,2}", hex_match_group)
72
                new_user_input = tuple([int(h, 16) for h in hex_digits])
73
                color = Color.from_user_input(new_user_input)
74
                _COLORS_CACHE[user_input] = color
75
                return color
76
77
            rgb_rgba_match = re.match(r"(rgb|rgba)\((.*)\)", user_input)
78
79
            if rgb_rgba_match:
80
                rgb_rgba_match_group = rgb_rgba_match.group(2)
81
                new_user_input = tuple([int(d) for d in rgb_rgba_match_group.split(",")])
82
                color = Color.from_user_input(new_user_input)
83
                _COLORS_CACHE[user_input] = color
84
                return color
85
86
        if isinstance(user_input, bool) or isinstance(user_input, type(None)):
87
            return cls(0, 0, 0, 0)
88
89
        return cls()
90