| 1 | 1 |  | import os | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 | 1 |  | import hashlib | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 | 1 |  | import shutil | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 | 1 |  | from pathlib import Path | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 | 1 |  | import tempfile | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 | 1 |  | import logging | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 | 1 |  | import time | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 | 1 |  | import requests | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 | 1 |  | from PIL import Image | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 | 1 |  | from .text import Text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 | 1 |  | log = logging.getLogger(__name__) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 | 1 |  | class Template: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |     """Blank image to generate a meme.""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 | 1 |  |     DEFAULT = 'default' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 | 1 |  |     EXTENSIONS = ('.png', '.jpg') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 | 1 |  |     SAMPLE_LINES = ["YOUR TEXT", "GOES HERE"] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 | 1 |  |     VALID_LINK_FLAG = '.valid_link.tmp' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 | 1 |  |     MIN_HEIGHT = 240 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 | 1 |  |     MIN_WIDTH = 240 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 | 1 |  |     def __init__(self, key, name=None, lines=None, aliases=None, link=None, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |                  root=None): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 | 1 |  |         self.key = key | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 | 1 |  |         self.name = name or "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 | 1 |  |         self.lines = lines or [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 | 1 |  |         self.aliases = aliases or [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 | 1 |  |         self.link = link or "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 | 1 |  |         self.root = root or "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 | 1 |  |     def __str__(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 | 1 |  |         return self.key | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 | 1 |  |     def __eq__(self, other): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 | 1 |  |         return self.key == other.key | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 | 1 |  |     def __ne__(self, other): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 | 1 |  |         return self.key != other.key | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 | 1 |  |     def __lt__(self, other): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 | 1 |  |         return self.name < other.name | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 | 1 |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |     def dirpath(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 | 1 |  |         return os.path.join(self.root, self.key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 | 1 |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |     def path(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 | 1 |  |         return self.get_path() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 | 1 |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |     def default_text(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 | 1 |  |         return Text(self.lines) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 | 1 |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |     def default_path(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 | 1 |  |         return self.default_text.path or Text.EMPTY | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 | 1 |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |     def sample_text(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 | 1 |  |         return self.default_text or Text(self.SAMPLE_LINES) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 | 1 |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |     def sample_path(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 | 1 |  |         return self.sample_text.path | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 | 1 |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |     def aliases_lowercase(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 | 1 |  |         return [self.strip(a, keep_special=True) for a in self.aliases] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 | 1 |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |     def aliases_stripped(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 | 1 |  |         return [self.strip(a, keep_special=False) for a in self.aliases] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 | 1 |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |     def styles(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 | 1 |  |         return sorted(self._styles()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 | 1 |  |     def _styles(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |         """Yield all template style names.""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 | 1 |  |         for filename in os.listdir(self.dirpath): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 | 1 |  |             name, ext = os.path.splitext(filename.lower()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 | 1 |  |             if ext in self.EXTENSIONS and name != self.DEFAULT: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 | 1 |  |                 yield name | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 | 1 |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |     def keywords(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 | 1 |  |         words = set() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 | 1 |  |         for fields in [self.key, self.name] + self.aliases + self.lines: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 | 1 |  |             for word in fields.lower().replace(Text.SPACE, ' ').split(' '): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 | 1 |  |                 if word: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 | 1 |  |                     words.add(word) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 | 1 |  |         return words | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 | 1 |  |     @staticmethod | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 | 1 |  |     def strip(text, keep_special=False): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 | 1 |  |         text = text.lower().strip().replace(' ', '-') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 | 1 |  |         if not keep_special: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 | 1 |  |             for char in ('-', '_', '!', "'"): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 | 1 |  |                 text = text.replace(char, '') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 | 1 |  |         return text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 | 1 |  |     def get_path(self, *styles): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 | 1 |  |         for style in styles: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 | 1 |  |             path = download_image(style) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 | 1 |  |             if path: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 | 1 |  |                 return path | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 | 1 |  |         for name in (n.lower() for n in (*styles, self.DEFAULT) if n): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 | 1 |  |             for extension in self.EXTENSIONS: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 | 1 |  |                 path = Path(self.dirpath, name + extension) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 | 1 |  |                 try: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 | 1 |  |                     if path.is_file(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 | 1 |  |                         return path | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |                 except OSError: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |                     continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 | 1 |  |         return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 | 1 |  |     def search(self, query): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |         """Count the number of times a query exists in relevant fields.""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 | 1 |  |         if query is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 | 1 |  |             return -1 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |  | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 134 | 1 |  |         count = 0 | 
            
                                                                        
                            
            
                                    
            
            
                | 135 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 136 | 1 |  |         for field in [self.key, self.name] + self.aliases + self.lines: | 
            
                                                                        
                            
            
                                    
            
            
                | 137 | 1 |  |             count += field.lower().count(query.lower()) | 
            
                                                                        
                            
            
                                    
            
            
                | 138 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 139 | 1 |  |         return count | 
            
                                                                        
                            
            
                                    
            
            
                | 140 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 141 | 1 |  |     def validate(self, validators=None): | 
            
                                                                        
                            
            
                                    
            
            
                | 142 | 1 |  |         if validators is None: | 
            
                                                                        
                            
            
                                    
            
            
                | 143 |  |  |             validators = [ | 
            
                                                                        
                            
            
                                    
            
            
                | 144 |  |  |                 self.validate_meta, | 
            
                                                                        
                            
            
                                    
            
            
                | 145 |  |  |                 self.validate_link, | 
            
                                                                        
                            
            
                                    
            
            
                | 146 |  |  |                 self.validate_size, | 
            
                                                                        
                            
            
                                    
            
            
                | 147 |  |  |             ] | 
            
                                                                        
                            
            
                                    
            
            
                | 148 | 1 |  |         for validator in validators: | 
            
                                                                        
                            
            
                                    
            
            
                | 149 | 1 |  |             if not validator(): | 
            
                                                                        
                            
            
                                    
            
            
                | 150 | 1 |  |                 return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 | 1 |  |         return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 | 1 |  |     def validate_meta(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 | 1 |  |         if not self.lines: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |             self._error("has no default lines of text") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 | 1 |  |         if not self.name: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 | 1 |  |             self._error("has no name") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 | 1 |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 | 1 |  |         if not self.name[0].isalnum(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 | 1 |  |             self._error("name %r should start with an alphanumeric", self.name) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 | 1 |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 | 1 |  |         if not self.path: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 | 1 |  |             self._error("has no default image") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 | 1 |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |         return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 | 1 |  |     def validate_link(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 | 1 |  |         if self.link: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 | 1 |  |             flag = Path(self.dirpath, self.VALID_LINK_FLAG) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 | 1 |  |             if flag.is_file(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 | 1 |  |                 log.info("Link already checked: %s", self.link) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  |             else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 | 1 |  |                 log.info("Checking link %s ...", self.link) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 | 1 |  |                 try: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 | 1 |  |                     response = requests.head(self.link, timeout=5) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  |                 except requests.exceptions.ReadTimeout: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  |                     log.warning("Connection timed out") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  |                     return True  # assume URL is OK; it will be checked again | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 | 1 |  |                 if response.status_code in [403, 429]: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 |  |  |                     self._warn("link is unavailable (%s)", response.status_code) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 | 1 |  |                 elif response.status_code >= 400: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 | 1 |  |                     self._error("link is invalid (%s)", response.status_code) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 | 1 |  |                     return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  |                 else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  |                     with open(str(flag), 'w') as stream: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 |  |  |                         stream.write(str(int(time.time()))) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 | 1 |  |         return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 | 1 |  |     def validate_size(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 | 1 |  |         im = Image.open(self.path) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 | 1 |  |         w, h = im.size | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 | 1 |  |         if w < self.MIN_WIDTH or h < self.MIN_HEIGHT: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 | 1 |  |             log.error("Image must be at least %ix%i (is %ix%i)", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 |  |  |                       self.MIN_WIDTH, self.MIN_HEIGHT, w, h) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 | 1 |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 | 1 |  |         return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 | 1 |  |     def _warn(self, fmt, *objects): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 200 |  |  |         log.warning("Template '%s' " + fmt, self, *objects) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 | 1 |  |     def _error(self, fmt, *objects): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 | 1 |  |         log.error("Template '%s' " + fmt, self, *objects) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 | 1 |  | class Placeholder: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 207 |  |  |     """Default image for missing templates.""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 208 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 209 | 1 |  |     path = None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 210 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 211 | 1 |  |     def __init__(self, key): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 212 | 1 |  |         self.key = key | 
            
                                                                                                            
                            
            
                                    
            
            
                | 213 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 214 | 1 |  |     @staticmethod | 
            
                                                                                                            
                            
            
                                    
            
            
                | 215 |  |  |     def get_path(*styles): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 216 | 1 |  |         path = None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 217 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 218 | 1 |  |         for style in styles: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 219 | 1 |  |             path = download_image(style) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 220 | 1 |  |             if path: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 221 |  |  |                 break | 
            
                                                                                                            
                            
            
                                    
            
            
                | 222 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 223 | 1 |  |         if not path: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 224 | 1 |  |             path = os.path.dirname(__file__) + "/../static/images/missing.png" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 225 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 226 | 1 |  |         return path | 
            
                                                                                                            
                            
            
                                    
            
            
                | 227 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 228 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 229 | 1 |  | def download_image(url): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 230 | 1 |  |     if not url or not url.startswith("http"): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 231 | 1 |  |         return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 232 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 233 | 1 |  |     path = Path(tempfile.gettempdir(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 234 |  |  |                 hashlib.md5(url.encode('utf-8')).hexdigest()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 235 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 236 | 1 |  |     if path.is_file(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 237 | 1 |  |         log.debug("Already downloaded: %s", url) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 238 | 1 |  |         return path | 
            
                                                                                                            
                            
            
                                    
            
            
                | 239 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 240 | 1 |  |     try: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 241 | 1 |  |         response = requests.get(url, stream=True) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 242 | 1 |  |     except requests.exceptions.InvalidURL: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 243 | 1 |  |         log.error("Invalid link: %s", url) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 244 | 1 |  |         return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 245 | 1 |  |     except requests.exceptions.ConnectionError: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 246 | 1 |  |         log.error("Bad connection: %s", url) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 247 | 1 |  |         return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 248 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 249 | 1 |  |     if response.status_code == 200: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 250 | 1 |  |         log.info("Downloading %s", url) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 251 | 1 |  |         with open(str(path), 'wb') as outfile: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 252 | 1 |  |             response.raw.decode_content = True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 253 | 1 |  |             shutil.copyfileobj(response.raw, outfile) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 254 | 1 |  |         return path | 
            
                                                                                                            
                            
            
                                    
            
            
                | 255 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 256 | 1 |  |     log.error("Unable to download: %s", url) | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 257 |  |  |     return None | 
            
                                                        
            
                                    
            
            
                | 258 |  |  |  | 
            
                        
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.
2. Missing __init__.py files
This error could also result from missing
__init__.pyfiles in your module folders. Make sure that you place one file in each sub-folder.