def close(self): """Close and store outstanding changes""" with self.save_lock: with util.update_file_safely(self.filename) as filename: with gzip.open(filename, 'wb') as fp: data = bytes(json.dumps(self._data, separators=(',', ':')), 'utf-8') fp.write(data)
def get_cover(self, podcast, download=False): filename = podcast.cover_file cover_url = podcast.cover_url # Return already existing files for extension in self.EXTENSIONS: if os.path.exists(filename + extension): return filename + extension # If allowed to download files, do so here if download: # YouTube-specific cover art image resolver youtube_cover_url = youtube.get_real_cover(podcast.url) if youtube_cover_url is not None: cover_url = youtube_cover_url if not cover_url: return None # We have to add username/password, because password-protected # feeds might keep their cover art also protected (bug 1521) cover_url = util.url_add_authentication(cover_url, podcast.auth_username, podcast.auth_password) try: logger.info('Downloading cover art: %s', cover_url) data = util.urlopen(cover_url, timeout=self.TIMEOUT).read() except Exception as e: logger.warn('Cover art download failed: %s', e) return None try: extension = None for filetype, check in list(self.SUPPORTED_EXTENSIONS.items()): if check(data): extension = filetype break if extension is None: msg = 'Unknown file type: %s (%r)' % (cover_url, data[:6]) raise ValueError(msg) # Successfully downloaded the cover art - save it! with util.update_file_safely(filename + extension) as temp_filename: with open(temp_filename, 'wb') as fp: fp.write(data) return filename + extension except Exception as e: logger.warn('Cannot save cover art', exc_info=True) return None
def get_cover(self, podcast, download=False): filename = podcast.cover_file cover_url = podcast.cover_url # Return already existing files for extension in self.EXTENSIONS: if os.path.exists(filename + extension): return filename + extension # If allowed to download files, do so here if download: cover_url = registry.cover_art.resolve(podcast, cover_url) if not cover_url: return None # We have to add username/password, because password-protected # feeds might keep their cover art also protected (bug 1521) cover_url = util.url_add_authentication(cover_url, podcast.auth_username, podcast.auth_password) try: logger.info('Downloading cover art: %s', cover_url) data = util.urlopen(cover_url, timeout=self.TIMEOUT).read() except Exception as e: logger.warn('Cover art download failed: %s', e) return None try: extension = None for filetype, check in list(self.SUPPORTED_EXTENSIONS.items()): if check(data): extension = filetype break if extension is None: msg = 'Unknown file type: %s (%r)' % (cover_url, data[:6]) raise ValueError(msg) # Successfully downloaded the cover art - save it! with util.update_file_safely(filename + extension) as temp_filename: with open(temp_filename, 'wb') as fp: fp.write(data) return filename + extension except Exception as e: logger.warn('Cannot save cover art', exc_info=True) return None
def save(self, filename=None): if filename is None: filename = self.__filename logger.info('Flushing settings to disk') try: with util.update_file_safely(filename) as temp_filename: with open(temp_filename, 'wt') as fp: fp.write(repr(self.__json_config)) except Exception as e: logger.error('Cannot write settings to %s: %s', filename, e) raise self.__save_thread = None
def write(self, channels): """ Creates a XML document containing metadata for each channel object in the "channels" parameter, which should be a list of channel objects. OPML 2.0 specification: http://www.opml.org/spec2 Returns True on success or False when there was an error writing the file. """ doc = xml.dom.minidom.Document() opml = doc.createElement('opml') opml.setAttribute('version', '2.0') doc.appendChild(opml) head = doc.createElement('head') head.appendChild( self.create_node(doc, 'title', 'gPodder subscriptions')) head.appendChild( self.create_node(doc, 'dateCreated', formatdate(localtime=True))) opml.appendChild(head) body = doc.createElement('body') for channel in channels: body.appendChild(self.create_outline(doc, channel)) opml.appendChild(body) if self.filename is None: return doc.toprettyxml(indent=' ', newl=os.linesep) else: try: with util.update_file_safely(self.filename) as temp_filename: with open(temp_filename, 'w') as fp: fp.write(doc.toprettyxml(indent=' ', newl=os.linesep)) except: logger.error('Could not open file for writing: %s', self.filename, exc_info=True) return False return True
def write(self, channels): """ Creates a XML document containing metadata for each channel object in the "channels" parameter, which should be a list of channel objects. OPML 2.0 specification: http://www.opml.org/spec2 Returns True on success or False when there was an error writing the file. """ doc = xml.dom.minidom.Document() opml = doc.createElement('opml') opml.setAttribute('version', '2.0') doc.appendChild(opml) head = doc.createElement('head') head.appendChild(self.create_node(doc, 'title', 'gPodder subscriptions')) head.appendChild(self.create_node(doc, 'dateCreated', formatdate(localtime=True))) opml.appendChild(head) body = doc.createElement('body') for channel in channels: body.appendChild(self.create_outline(doc, channel)) opml.appendChild(body) if self.filename is None: return doc.toprettyxml(indent=' ', newl=os.linesep) else: try: with util.update_file_safely(self.filename) as temp_filename: with open(temp_filename, 'w') as fp: fp.write(doc.toprettyxml(indent=' ', newl=os.linesep)) except: logger.error('Could not open file for writing: %s', self.filename, exc_info=True) return False return True