def test_metadata(self): self.assertTrue(os.path.exists('test.jpg')) info = { 'sourceURL': u'b', 'imageURL': u'd', 'sourceName': u'a', 'sourceLocation': u'c', 'sourceType': u'flickr', 'author': u'автор', 'authorURL': u'url', 'keywords': [u'дума1', u'дума2'], 'headline': u'проба1 проба1', 'description': u'проба2 проба2', 'sfwRating': 50, 'extraData': { 'key1': 'val1', 'key2': 'val2' } } self.assertEqual(info, Util.read_metadata('test.jpg')) self.assertTrue(Util.write_metadata('test.jpg', info)) self.assertEqual(info, Util.read_metadata('test.jpg')) self.assertTrue(os.path.exists('test.svg')) self.assertEqual(info, Util.read_metadata('test.svg')) Util.write_metadata('test.svg', info) self.assertEqual(info, Util.read_metadata('test.svg'))
def test_metadata(self): self.assertTrue(os.path.exists("test.jpg")) info = { "sourceURL": "b", "imageURL": "d", "sourceName": "a", "sourceLocation": "c", "sourceType": "flickr", "author": "автор", "authorURL": "url", "keywords": ["дума1", "дума2"], "headline": "проба1 проба1", "description": "проба2 проба2", "sfwRating": 50, "extraData": { "key1": "val1", "key2": "val2" }, } self.assertEqual(info, Util.read_metadata("test.jpg")) self.assertTrue(Util.write_metadata("test.jpg", info)) self.assertEqual(info, Util.read_metadata("test.jpg")) self.assertTrue(os.path.exists("test.svg")) self.assertEqual(info, Util.read_metadata("test.svg")) Util.write_metadata("test.svg", info) self.assertEqual(info, Util.read_metadata("test.svg"))
def test_metadata(self): self.assertTrue(os.path.exists('test.jpg')) info = { 'sourceURL': u'b', 'imageURL': u'd', 'sourceName': u'a', 'sourceLocation': u'c', 'sourceType': u'flickr', 'author': u'автор', 'authorURL': u'url', 'keywords': [u'дума1', u'дума2'], 'headline': u'проба1', 'description': u'проба2', 'sfwRating': 50, } self.assertTrue(Util.write_metadata('test.jpg', info)) self.assertEqual(info, Util.read_metadata('test.jpg')) self.assertTrue(os.path.exists('test.svg')) Util.write_metadata('test.svg', info) self.assertEqual(info, Util.read_metadata('test.svg'))
def fetch( url, to_folder, origin_url=None, source_type=None, source_location=None, source_name=None, extra_metadata=None, progress_reporter=lambda a, b: None, verbose=True, ): reported = verbose try: logger.info(lambda: "Trying to fetch URL %s to %s " % (url, to_folder)) if verbose: progress_reporter(_("Fetching"), url) if url.startswith("javascript:"): if verbose: progress_reporter(_("Not an image"), url) return None if url.find("://") < 0: url = "file://" + url r = Util.request(url, stream=True) if not "content-type" in r.headers: logger.info(lambda: "Unknown content-type for url " + url) if verbose: progress_reporter(_("Not an image"), url) return None ct = r.headers["content-type"] if not ct.startswith("image/"): logger.info(lambda: "Unsupported content-type for url " + url + ": " + ct) if verbose: progress_reporter(_("Not an image"), url) return None local_name = Util.get_local_name(r.url) if "content-disposition" in r.headers: cd = r.headers["content-disposition"] cd_name = ImageFetcher.extract_filename_from_content_disposition( cd) if cd_name: local_name = cd_name filename = os.path.join(to_folder, local_name) if os.path.exists(filename): m = Util.read_metadata(filename) if m and m.get("imageURL") == url: logger.info( lambda: "Local file already exists (%s)" % filename) return filename else: logger.info( lambda: "File with same name already exists, but from different imageURL; renaming new download" ) filename = Util.find_unique_name(filename) logger.info(lambda: "Fetching to " + filename) if not reported: reported = True progress_reporter(_("Fetching"), url) local_filepath_partial = filename + ".partial" with open(local_filepath_partial, "wb") as f: Util.request_write_to(r, f) try: img = Image.open(local_filepath_partial) except Exception: progress_reporter(_("Not an image"), url) Util.safe_unlink(local_filepath_partial) return None if img.size[0] < 400 or img.size[1] < 400: # too small - delete and do not use progress_reporter(_("Image too small, ignoring it"), url) Util.safe_unlink(local_filepath_partial) return None metadata = { "sourceType": source_type or "fetched", "sourceName": source_name or "Fetched", "sourceURL": origin_url or url, "imageURL": url, } if source_location: metadata["sourceLocation"] = source_location metadata.update(extra_metadata or {}) Util.write_metadata(local_filepath_partial, metadata) os.rename(local_filepath_partial, filename) logger.info(lambda: "Fetched %s to %s." % (url, filename)) return filename except Exception as e: # pylint: disable=no-member logger.exception(lambda: "Fetch failed for URL " + url) if reported: if isinstance( e, HTTPError) and e.response.status_code in (403, 404): progress_reporter( _("Sorry, got %s error...") % str(e.response.status_code), _("This means the link is no longer valid"), ) else: progress_reporter( _("Fetch failed for some reason"), _("To get more information, please run Variety from terminal with -v option and retry the action" ), ) return None
def create_menu(self, file): options = self.load_options() menu = Gtk.Menu() position_menu = Gtk.Menu() for p, v in ThumbsManager.POSITIONS.items(): item = Gtk.CheckMenuItem(ThumbsManager.POSITION_NAMES[p]) item.set_draw_as_radio(True) item.set_active(options.position == v) def _set_position(widget, pos=p): self.set_position(pos) item.connect("activate", _set_position) position_menu.append(item) size_menu = Gtk.Menu() for size in ThumbsManager.SIZES: item = Gtk.CheckMenuItem(str(size)) item.set_draw_as_radio(True) item.set_active(options.breadth == size) def _set_size(widget, size=size): self.set_size(size) item.connect("activate", _set_size) size_menu.append(item) limit_menu = Gtk.Menu() for limit in ThumbsManager.LIMITS: item = Gtk.CheckMenuItem(str(limit)) item.set_draw_as_radio(True) item.set_active(options.limit == limit) def _set_limit(widget, limit=limit): self.set_limit(limit) item.connect("activate", _set_limit) limit_menu.append(item) position_item = Gtk.MenuItem(_("Position")) position_item.set_submenu(position_menu) menu.append(position_item) size_item = Gtk.MenuItem(_("Size")) size_item.set_submenu(size_menu) menu.append(size_item) limit_item = Gtk.MenuItem(_("Maximum Shown Images")) limit_item.set_submenu(limit_menu) menu.append(limit_item) menu.append(Gtk.SeparatorMenuItem.new()) open_file = Gtk.MenuItem(os.path.basename(file).replace("_", "__")) def _open_file(widget): self.parent.open_file(widget, file) open_file.connect("activate", _open_file) menu.append(open_file) open_folder = Gtk.MenuItem(_("Show Containing Folder")) def _open_folder(widget): self.parent.open_folder(widget, file) open_folder.connect("activate", _open_folder) menu.append(open_folder) info = Util.read_metadata(file) if info and "sourceURL" in info and "sourceName" in info: url = info["sourceURL"] source_name = info["sourceName"] if "Fetched" in source_name: label = _("Fetched: Show Origin") else: label = _("View at %s") % source_name if len(label) > 50: label = label[:50] + "..." show_origin = Gtk.MenuItem(label) def _show_origin(widget=None): logger.info(lambda: "Opening url: " + url) webbrowser.open_new_tab(url) show_origin.connect("activate", _show_origin) menu.append(show_origin) menu.append(Gtk.SeparatorMenuItem.new()) rating_item = Gtk.MenuItem(_("Set EXIF Rating")) rating_item.set_submenu( ThumbsManager.create_rating_menu(file, self.parent)) if not os.access(file, os.W_OK): rating_item.set_sensitive(False) menu.append(rating_item) menu.append(Gtk.SeparatorMenuItem.new()) self.copy_to_favorites = Gtk.MenuItem(_("Copy to _Favorites")) self.copy_to_favorites.set_use_underline(True) def _copy_to_favorites(widget): self.parent.copy_to_favorites(widget, file) self.copy_to_favorites.connect("activate", _copy_to_favorites) menu.append(self.copy_to_favorites) self.move_to_favorites = Gtk.MenuItem(_("Move to _Favorites")) self.move_to_favorites.set_use_underline(True) def _move_to_favorites(widget): self.parent.move_to_favorites(widget, file) self.remove_image(file) self.move_to_favorites.connect("activate", _move_to_favorites) self.move_to_favorites.set_visible(False) menu.append(self.move_to_favorites) trash_item = Gtk.MenuItem(_("Delete to _Trash")) trash_item.set_use_underline(True) def _trash(widget): self.parent.move_to_trash(widget, file) trash_item.connect("activate", _trash) menu.append(trash_item) focus = Gtk.MenuItem(_("Where is it from?")) focus.set_sensitive(self.parent.get_source(file) is not None) def _focus(widget): self.parent.focus_in_preferences(widget, file) focus.connect("activate", _focus) menu.append(focus) menu.append(Gtk.SeparatorMenuItem.new()) def close(widget): self.hide(force=True) close_item = Gtk.MenuItem(_("Close")) close_item.connect("activate", close) menu.append(close_item) menu.show_all() favs_op = self.parent.determine_favorites_operation(file) self.parent.update_favorites_menuitems(self, False, favs_op) return menu
def create_menu(self, file): options = self.load_options() menu = Gtk.Menu() position_menu = Gtk.Menu() for p, v in ThumbsManager.POSITIONS.items(): item = Gtk.CheckMenuItem(ThumbsManager.POSITION_NAMES[p]) item.set_draw_as_radio(True) item.set_active(options.position == v) def _set_position(widget, pos=p): self.set_position(pos) item.connect("activate", _set_position) position_menu.append(item) size_menu = Gtk.Menu() for size in ThumbsManager.SIZES: item = Gtk.CheckMenuItem(str(size)) item.set_draw_as_radio(True) item.set_active(options.breadth == size) def _set_size(widget, size=size): self.set_size(size) item.connect("activate", _set_size) size_menu.append(item) position_item = Gtk.MenuItem(_("Position")) position_item.set_submenu(position_menu) menu.append(position_item) size_item = Gtk.MenuItem(_("Size")) size_item.set_submenu(size_menu) menu.append(size_item) menu.append(Gtk.SeparatorMenuItem.new()) open_file = Gtk.MenuItem(os.path.basename(file).replace('_', '__')) def _open_file(widget): self.parent.open_file(widget, file) open_file.connect("activate", _open_file) menu.append(open_file) open_folder = Gtk.MenuItem(_("Show Containing Folder")) def _open_folder(widget): self.parent.open_folder(widget, file) open_folder.connect("activate", _open_folder) menu.append(open_folder) info = Util.read_metadata(file) if info and "sourceURL" in info and "sourceName" in info: url = info["sourceURL"] source_name = info["sourceName"] if "Fetched" in source_name: label = _("Fetched: Show Origin") else: label = _("View at %s") % source_name if len(label) > 50: label = label[:50] + "..." show_origin = Gtk.MenuItem(label) def _show_origin(widget=None): logger.info(lambda: "Opening url: " + url) webbrowser.open_new_tab(url) show_origin.connect("activate", _show_origin) menu.append(show_origin) menu.append(Gtk.SeparatorMenuItem.new()) rating_item = Gtk.MenuItem(_("Set EXIF Rating")) rating_item.set_submenu(ThumbsManager.create_rating_menu(file, self.parent)) if not os.access(file, os.W_OK): rating_item.set_sensitive(False) menu.append(rating_item) menu.append(Gtk.SeparatorMenuItem.new()) self.copy_to_favorites = Gtk.MenuItem(_("Copy to _Favorites")) self.copy_to_favorites.set_use_underline(True) def _copy_to_favorites(widget): self.parent.copy_to_favorites(widget, file) self.copy_to_favorites.connect("activate", _copy_to_favorites) menu.append(self.copy_to_favorites) self.move_to_favorites = Gtk.MenuItem(_("Move to _Favorites")) self.move_to_favorites.set_use_underline(True) def _move_to_favorites(widget): self.parent.move_to_favorites(widget, file) self.remove_image(file) self.move_to_favorites.connect("activate", _move_to_favorites) self.move_to_favorites.set_visible(False) menu.append(self.move_to_favorites) trash_item = Gtk.MenuItem(_("Delete to _Trash")) trash_item.set_use_underline(True) def _trash(widget): self.parent.move_to_trash(widget, file) trash_item.connect("activate", _trash) menu.append(trash_item) focus = Gtk.MenuItem(_("Where is it from?")) focus.set_sensitive(self.parent.get_source(file) is not None) def _focus(widget): self.parent.focus_in_preferences(widget, file) focus.connect("activate", _focus) menu.append(focus) menu.append(Gtk.SeparatorMenuItem.new()) def close(widget): self.hide(gdk_thread=True, force=True) close_item = Gtk.MenuItem(_("Close")) close_item.connect("activate", close) menu.append(close_item) menu.show_all() favs_op = self.parent.determine_favorites_operation(file) self.parent.update_favorites_menuitems(self, False, favs_op) return menu
def fetch(url, to_folder, origin_url=None, source_type=None, source_location=None, source_name=None, extra_metadata={}, progress_reporter=lambda a, b: None, verbose=True): reported = verbose try: logger.info(lambda: "Trying to fetch URL %s to %s " % (url, to_folder)) if verbose: progress_reporter(_("Fetching"), url) if url.startswith('javascript:'): if verbose: progress_reporter(_("Not an image"), url) return None if url.find('://') < 0: url = "file://" + url r = Util.request(url, stream=True) if not "content-type" in r.headers: logger.info(lambda: "Unknown content-type for url " + url) if verbose: progress_reporter(_("Not an image"), url) return None ct = r.headers["content-type"] if not ct.startswith("image/"): logger.info(lambda: "Unsupported content-type for url " + url + ": " + ct) if verbose: progress_reporter(_("Not an image"), url) return None local_name = Util.get_local_name(r.url) if "content-disposition" in r.headers: cd = r.headers["content-disposition"] cd_name = ImageFetcher.extract_filename_from_content_disposition(cd) if cd_name: local_name = cd_name filename = os.path.join(to_folder, local_name) if os.path.exists(filename): m = Util.read_metadata(filename) if m and m.get("imageURL") == url: logger.info(lambda: "Local file already exists (%s)" % filename) return filename else: logger.info(lambda: "File with same name already exists, but from different imageURL; renaming new download") filename = Util.find_unique_name(filename) local_name = os.path.basename(filename) logger.info(lambda: "Fetching to " + filename) if not reported: reported = True progress_reporter(_("Fetching"), url) with open(filename, 'wb') as f: Util.request_write_to(r, f) try: img = Image.open(filename) except Exception: progress_reporter(_("Not an image"), url) os.unlink(filename) return None if img.size[0] < 400 or img.size[1] < 400: # too small - delete and do not use progress_reporter(_("Image too small, ignoring it"), url) os.unlink(filename) return None metadata = {"sourceType": source_type or 'fetched', "sourceName": source_name or "Fetched", "sourceURL": origin_url or url, "imageURL": url} if source_location: metadata["sourceLocation"] = source_location metadata.update(extra_metadata) Util.write_metadata(filename, metadata) logger.info(lambda: "Fetched %s to %s." % (url, filename)) return filename except Exception, e: logger.exception(lambda: "Fetch failed for URL " + url) if reported: if isinstance(e, HTTPError) and e.response.status_code in (403, 404): progress_reporter( _("Sorry, got %s error...") % str(e.response.status_code), _("This means the link is no longer valid")) else: progress_reporter( _("Fetch failed for some reason"), _("To get more information, please run Variety from terminal with -v option and retry the action")) return None