Completed
Push — master ( 079863...3f9dd1 )
by Jace
03:11
created

Template.aliases_stripped()   A

Complexity

Conditions 2

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2
Metric Value
cc 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 2
rs 10
1 1
import os
2 1
import logging
3
4 1
import time
5 1
import requests
6 1
from PIL import Image
0 ignored issues
show
Configuration introduced by
The import PIL could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
7
8 1
from .text import Text
9
10
11 1
log = logging.getLogger(__name__)
12
13
14 1
class Template:
15
    """Blank image to generate a meme."""
16
17 1
    DEFAULT = 'default'
18 1
    EXTENSIONS = ('.png', '.jpg')
19
20 1
    SAMPLE_LINES = ["YOUR TEXT", "GOES HERE"]
21
22 1
    VALID_LINK_FLAG = '.valid_link.tmp'
23
24 1
    MIN_HEIGHT = 240
25 1
    MIN_WIDTH = 240
26
27 1
    def __init__(self, key,
28
                 name=None, lines=None, aliases=None, link=None, root=None):
29 1
        self.key = key
30 1
        self.name = name or ""
31 1
        self.lines = lines or []
32 1
        self.aliases = aliases or []
33 1
        self.link = link or ""
34 1
        self.root = root or ""
35
36 1
    def __str__(self):
37 1
        return self.key
38
39 1
    def __eq__(self, other):
40 1
        return self.key == other.key
41
42 1
    def __ne__(self, other):
43 1
        return self.key != other.key
44
45 1
    def __lt__(self, other):
46 1
        return self.name < other.name
47
48 1
    @property
49
    def dirpath(self):
50 1
        return os.path.join(self.root, self.key)
51
52 1
    @property
53
    def path(self):
54 1
        return self.get_path()
55
56 1
    @property
57
    def default_text(self):
58 1
        return Text(self.lines)
59
60 1
    @property
61
    def default_path(self):
62 1
        return self.default_text.path or Text.EMPTY
63
64 1
    @property
65
    def sample_text(self):
66 1
        return self.default_text or Text(self.SAMPLE_LINES)
67
68 1
    @property
69
    def sample_path(self):
70 1
        return self.sample_text.path
71
72 1
    @property
73
    def aliases_lowercase(self):
74 1
        return [self.strip(a, keep_special=True) for a in self.aliases]
75
76 1
    @property
77
    def aliases_stripped(self):
78 1
        return [self.strip(a, keep_special=False) for a in self.aliases]
79
80 1
    @property
81
    def styles(self):
82 1
        return sorted(self._styles())
83
84 1
    def _styles(self):
85
        """Yield all template style names."""
86 1
        for filename in os.listdir(self.dirpath):
87 1
            name, ext = os.path.splitext(filename.lower())
88 1
            if ext in self.EXTENSIONS and name != self.DEFAULT:
89 1
                yield name
90
91 1
    @staticmethod
92 1
    def strip(text, keep_special=False):
93 1
        text = text.lower().strip().replace(' ', '-')
94 1
        if not keep_special:
95 1
            for char in ('-', '_', '!', "'"):
96 1
                text = text.replace(char, '')
97 1
        return text
98
99 1
    def get_path(self, *styles):
100 1
        for name in (n.lower() for n in (*styles, self.DEFAULT) if n):
101 1
            for extension in self.EXTENSIONS:
102 1
                path = os.path.join(self.dirpath, name + extension)
103 1
                if os.path.isfile(path):
104 1
                    return path
105 1
        return None
106
107 1
    def validate(self, validators=None):
108 1
        if validators is None:
109
            validators = [
110
                self.validate_meta,
111
                self.validate_link,
112
                self.validate_size,
113
            ]
114 1
        for validator in validators:
115 1
            if not validator():
116 1
                return False
117 1
        return True
118
119 1
    def validate_meta(self):
120 1
        if not self.lines:
121
            log.error("Template '%s' has no default lines of text", self)
122
            return False
123 1
        if not self.name:
124 1
            log.error("Template '%s' has no name", self)
125 1
            return False
126 1
        if not self.name[0].isalnum():
127 1
            msg = "Template '%s' name %r should start with an alphanumeric"
128 1
            log.error(msg, self, self.name)
129 1
            return False
130 1
        if not self.path:
131 1
            log.error("Template '%s' has no default image", self)
132 1
            return False
133
        return True
134
135 1
    def validate_link(self):
136 1
        if self.link:
137 1
            flag = os.path.join(self.dirpath, self.VALID_LINK_FLAG)
138 1
            if os.path.isfile(flag):
139 1
                log.info("Link already checked: %s", self.link)
140
            else:
141 1
                log.info("Checking link %s ...", self.link)
142 1
                try:
143 1
                    response = requests.get(self.link, timeout=5)
144
                except requests.exceptions.ReadTimeout:
0 ignored issues
show
Bug introduced by
The Module requests.exceptions does not seem to have a member named ReadTimeout.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
145
                    log.warning("Connection timed out")
146
                    return True  # assume URL is OK; it will be checked again
147 1
                if response.status_code >= 400 and response.status_code != 429:
148 1
                    msg = "Template '%s' link is invalid (%s)"
149 1
                    log.error(msg, self, response.status_code)
150 1
                    return False
151
                else:
152
                    with open(flag, 'w') as stream:
153
                        stream.write(str(int(time.time())))
154 1
        return True
155
156 1
    def validate_size(self):
157 1
        im = Image.open(self.path)
158 1
        w, h = im.size
159 1
        if w < self.MIN_WIDTH or h < self.MIN_HEIGHT:
160 1
            log.error("Image must be at least %ix%i (is %ix%i)",
161
                      self.MIN_WIDTH, self.MIN_HEIGHT, w, h)
162 1
            return False
163
        return True
164