From 90d0eb6ed3211022c3b600521aee85568b9ed905 Mon Sep 17 00:00:00 2001 From: hut Date: Tue, 13 Jan 2015 14:29:43 +0100 Subject: start turning ext.papermanager to core.metadata --- ranger/config/commands.py | 6 +- ranger/config/rc.conf | 8 +- ranger/container/settings.py | 2 +- ranger/core/actions.py | 4 +- ranger/core/fm.py | 8 +- ranger/core/metadata.py | 164 ++++++++++++++++++++++++++++++++++ ranger/ext/papermanager.py | 171 ------------------------------------ ranger/gui/widgets/browsercolumn.py | 2 +- 8 files changed, 179 insertions(+), 186 deletions(-) create mode 100644 ranger/core/metadata.py delete mode 100644 ranger/ext/papermanager.py diff --git a/ranger/config/commands.py b/ranger/config/commands.py index a8813de2..5d303b86 100644 --- a/ranger/config/commands.py +++ b/ranger/config/commands.py @@ -1378,7 +1378,7 @@ class paper(Command): col.need_redraw = True def _paper_fill_console(self, key): - paperinfo = self.fm.papermanager.get_paper_info(self.fm.thisfile.path) + paperinfo = self.fm.metadata.get_metadata(self.fm.thisfile.path) if key in paperinfo and paperinfo[key]: existing_value = paperinfo[key] else: @@ -1398,11 +1398,11 @@ class paper_title(paper): def execute(self): update_dict = dict() update_dict[self._key] = self.rest(1) - self.fm.papermanager.set_paper_info(self.fm.thisfile.path, update_dict) + self.fm.metadata.set_metadata(self.fm.thisfile.path, update_dict) self._process_command_stack() def tab(self): - paperinfo = self.fm.papermanager.get_paper_info(self.fm.thisfile.path) + paperinfo = self.fm.metadata.get_metadata(self.fm.thisfile.path) if paperinfo[self._key]: return self.arg(0) + " " + paperinfo[self._key] diff --git a/ranger/config/rc.conf b/ranger/config/rc.conf index 4c8fd799..a9e1fa23 100644 --- a/ranger/config/rc.conf +++ b/ranger/config/rc.conf @@ -174,10 +174,10 @@ set show_selection_in_titlebar true # increases CPU load. set idle_delay 2000 -# When the paper manager module looks for metadata, should it only look for a -# ".paperinfo" file in the current directory, or do a deep search and check all -# directories above the current one as well? -set papermanager_deep_search false +# When the metadata manager module looks for metadata, should it only look for +# a ".metadata.json" file in the current directory, or do a deep search and +# check all directories above the current one as well? +set metadata_deep_search false # =================================================================== # == Local Options diff --git a/ranger/container/settings.py b/ranger/container/settings.py index 106ef5fb..55585029 100644 --- a/ranger/container/settings.py +++ b/ranger/container/settings.py @@ -28,10 +28,10 @@ ALLOWED_SETTINGS = { 'idle_delay': int, 'max_console_history_size': (int, type(None)), 'max_history_size': (int, type(None)), + 'metadata_deep_search': bool, 'mouse_enabled': bool, 'open_all_images': bool, 'padding_right': bool, - 'papermanager_deep_search': bool, 'preview_directories': bool, 'preview_files': bool, 'preview_images': bool, diff --git a/ranger/core/actions.py b/ranger/core/actions.py index 82ceeba3..c7468be9 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -52,8 +52,8 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): self.garbage_collect(-1) self.enter_dir(old_path) self.change_mode('normal') - if self.papermanager: - self.papermanager.reset() + if self.metadata: + self.metadata.reset() def change_mode(self, mode): if mode == self.mode: diff --git a/ranger/core/fm.py b/ranger/core/fm.py index 816bf5f1..87c14f7a 100644 --- a/ranger/core/fm.py +++ b/ranger/core/fm.py @@ -20,7 +20,7 @@ from ranger.gui.ui import UI from ranger.container.bookmarks import Bookmarks from ranger.core.runner import Runner from ranger.ext.img_display import ImageDisplayer -from ranger.ext.papermanager import PaperManager +from ranger.core.metadata import MetadataManager from ranger.ext.rifle import Rifle from ranger.container.directory import Directory from ranger.ext.signals import SignalDispatcher @@ -61,7 +61,7 @@ class FM(Actions, SignalDispatcher): self.loader = Loader() self.copy_buffer = set() self.do_cut = False - self.papermanager = PaperManager() + self.metadata = MetadataManager() try: self.username = pwd.getpwuid(os.geteuid()).pw_name @@ -164,8 +164,8 @@ class FM(Actions, SignalDispatcher): self.notify(text, bad=True) self.run = Runner(ui=self.ui, logfunc=mylogfunc, fm=self) - self.settings.signal_bind('setopt.papermanager_deep_search', - lambda signal: setattr(signal.fm.papermanager, 'deep_search', + self.settings.signal_bind('setopt.metadata_deep_search', + lambda signal: setattr(signal.fm.metadata, 'deep_search', signal.value)) def destroy(self): diff --git a/ranger/core/metadata.py b/ranger/core/metadata.py new file mode 100644 index 00000000..7391dcc6 --- /dev/null +++ b/ranger/core/metadata.py @@ -0,0 +1,164 @@ +# Copyright (C) 2014 Roman Zimbelmann +# This software is distributed under the terms of the GNU GPL version 3. + +""" +A Metadata Manager that reads information about files from a json database. + +The database is contained in a local .metadata.json file. +""" + +METADATA_FILE_NAME = ".metadata.json" +DEEP_SEARCH_DEFAULT = False + +import csv +from os.path import join, dirname, exists, basename + +from ranger.ext.openstruct import OpenStruct + +class MetadataManager(object): + def __init__(self): + self.metadata_cache = dict() + self.metafile_cache = dict() + self.deep_search = DEEP_SEARCH_DEFAULT + + def reset(self): + self.metadata_cache.clear() + self.metafile_cache.clear() + + def get_metadata(self, filename): + try: + return self.metadata_cache[filename] + except KeyError: + result = OpenStruct(filename=filename, title=None, year=None, + authors=None, url=None) + + valid = (filename, basename(filename)) + for metafile in self._get_metafile_names(filename): + for entry in self._get_metafile_content(metafile): + if entry[0] in valid: + self._fill_ostruct_with_data(result, entry) + self.metadata_cache[filename] = result + return result + + # Cache the value + self.metadata_cache[filename] = result + return result + + def set_metadata(self, filename, update_dict): + result = None + found = False + valid = (filename, basename(filename)) + first_metafile = None + + if not self.deep_search: + metafile = next(self._get_metafile_names(filename)) + return self._set_metadata_raw(filename, update_dict, metafile) + + for i, metafile in enumerate(self._get_metafile_names(filename)): + if i == 0: + first_metafile = metafile + + csvfile = None + try: + csvfile = open(metafile, "r") + except: + # .metadata.json file doesn't exist... look for another one. + pass + else: + reader = csv.reader(csvfile, skipinitialspace=True) + for row in reader: + name, year, title, authors, url = row + if name in valid: + return self._set_metadata_raw(filename, update_dict, + metafile) + self.metadata_cache[filename] = result + finally: + if csvfile: + csvfile.close() + + # No .metadata.json file found, so let's create a new one in the same + # path as the given file. + if first_metafile: + return self._set_metadata_raw(filename, update_dict, first_metafile) + + def _set_metadata_raw(self, filename, update_dict, metafile): + valid = (filename, basename(filename)) + metadata = OpenStruct(filename=filename, title=None, year=None, + authors=None, url=None) + + try: + with open(metafile, "r") as infile: + reader = csv.reader(infile, skipinitialspace=True) + rows = list(reader) + except IOError: + rows = [] + + with open(metafile, "w") as outfile: + writer = csv.writer(outfile) + found = False + + # Iterate through all rows and write them back to the file. + for row in rows: + if not found and row[0] in valid: + # When finding the row that corresponds to the given filename, + # update the items with the information from update_dict. + self._fill_row_with_ostruct(row, update_dict) + self._fill_ostruct_with_data(metadata, row) + self.metadata_cache[filename] = metadata + found = True + writer.writerow(row) + + # If the row was never found, create a new one. + if not found: + row = [basename(filename), None, None, None, None] + self._fill_row_with_ostruct(row, update_dict) + self._fill_ostruct_with_data(metadata, row) + self.metadata_cache[filename] = metadata + writer.writerow(row) + + def _get_metafile_content(self, metafile): + if metafile in self.metafile_cache: + return self.metafile_cache[metafile] + else: + if exists(metafile): + reader = csv.reader(open(metafile, "r"), skipinitialspace=True) + + entries = list(entry for entry in reader if len(entry) == 5) + self.metafile_cache[metafile] = entries + return entries + else: + return [] + + def _get_metafile_names(self, path): + # Iterates through the paths of all .metadata.json files that could + # influence the metadata of the given file. + # When deep_search is deactivated, this only yields the .metadata.json + # file in the same directory as the given file. + + base = dirname(path) + yield join(base, METADATA_FILE_NAME) + if self.deep_search: + dirs = base.split("/")[1:] + for i in reversed(range(len(dirs))): + yield join("/" + "/".join(dirs[0:i]), METADATA_FILE_NAME) + + def _fill_ostruct_with_data(self, ostruct, dataset): + # Copy data from a CSV row to a dict/ostruct + + filename, year, title, authors, url = dataset + if year: ostruct['year'] = year + if title: ostruct['title'] = title + if authors: ostruct['authors'] = authors + if url: ostruct['url'] = url + + def _fill_row_with_ostruct(self, row, update_dict): + # Copy data from a dict/ostruct into a CSV row + for key, value in update_dict.items(): + if key == "year": + row[1] = value + elif key == "title": + row[2] = value + elif key == "authors": + row[3] = value + elif key == "url": + row[4] = value diff --git a/ranger/ext/papermanager.py b/ranger/ext/papermanager.py deleted file mode 100644 index 1f258af3..00000000 --- a/ranger/ext/papermanager.py +++ /dev/null @@ -1,171 +0,0 @@ -# Copyright (C) 2014 Roman Zimbelmann -# This software is distributed under the terms of the GNU GPL version 3. - -""" -A Paper Manager that reads metadata information about papers from a file. - -The file is named .paperinfo and is formatted as comma-separated values. - -The columns are: -1. Filename -2. Date -3. Title -4. Authors -5. URL -""" - -PAPERINFO_FILE_NAME = ".paperinfo" -DEEP_SEARCH_DEFAULT = False - -import csv -from os.path import join, dirname, exists, basename - -from ranger.ext.openstruct import OpenStruct - -class PaperManager(object): - def __init__(self): - self.metadata_cache = dict() - self.metafile_cache = dict() - self.deep_search = DEEP_SEARCH_DEFAULT - - def reset(self): - self.metadata_cache.clear() - self.metafile_cache.clear() - - def get_paper_info(self, filename): - try: - return self.metadata_cache[filename] - except KeyError: - result = OpenStruct(filename=filename, title=None, year=None, - authors=None, url=None) - - valid = (filename, basename(filename)) - for metafile in self._get_metafile_names(filename): - for entry in self._get_metafile_content(metafile): - if entry[0] in valid: - self._fill_ostruct_with_data(result, entry) - self.metadata_cache[filename] = result - return result - - # Cache the value - self.metadata_cache[filename] = result - return result - - def set_paper_info(self, filename, update_dict): - result = None - found = False - valid = (filename, basename(filename)) - first_metafile = None - - if not self.deep_search: - metafile = next(self._get_metafile_names(filename)) - return self._set_paper_info_raw(filename, update_dict, metafile) - - for i, metafile in enumerate(self._get_metafile_names(filename)): - if i == 0: - first_metafile = metafile - - csvfile = None - try: - csvfile = open(metafile, "r") - except: - # .paperinfo file doesn't exist... look for another one. - pass - else: - reader = csv.reader(csvfile, skipinitialspace=True) - for row in reader: - name, year, title, authors, url = row - if name in valid: - return self._set_paper_info_raw(filename, update_dict, - metafile) - self.metadata_cache[filename] = result - finally: - if csvfile: - csvfile.close() - - # No .paperinfo file found, so let's create a new one in the same path - # as the given file. - if first_metafile: - return self._set_paper_info_raw(filename, update_dict, first_metafile) - - def _set_paper_info_raw(self, filename, update_dict, metafile): - valid = (filename, basename(filename)) - paperinfo = OpenStruct(filename=filename, title=None, year=None, - authors=None, url=None) - - try: - with open(metafile, "r") as infile: - reader = csv.reader(infile, skipinitialspace=True) - rows = list(reader) - except IOError: - rows = [] - - with open(metafile, "w") as outfile: - writer = csv.writer(outfile) - found = False - - # Iterate through all rows and write them back to the file. - for row in rows: - if not found and row[0] in valid: - # When finding the row that corresponds to the given filename, - # update the items with the information from update_dict. - self._fill_row_with_ostruct(row, update_dict) - self._fill_ostruct_with_data(paperinfo, row) - self.metadata_cache[filename] = paperinfo - found = True - writer.writerow(row) - - # If the row was never found, create a new one. - if not found: - row = [basename(filename), None, None, None, None] - self._fill_row_with_ostruct(row, update_dict) - self._fill_ostruct_with_data(paperinfo, row) - self.metadata_cache[filename] = paperinfo - writer.writerow(row) - - def _get_metafile_content(self, metafile): - if metafile in self.metafile_cache: - return self.metafile_cache[metafile] - else: - if exists(metafile): - reader = csv.reader(open(metafile, "r"), skipinitialspace=True) - - entries = list(entry for entry in reader if len(entry) == 5) - self.metafile_cache[metafile] = entries - return entries - else: - return [] - - def _get_metafile_names(self, path): - # Iterates through the paths of all .paperinfo files that could - # influence the metadata of the given file. - # When deep_search is deactivated, this only yields the .paperinfo file - # in the same directory as the given file. - - base = dirname(path) - yield join(base, PAPERINFO_FILE_NAME) - if self.deep_search: - dirs = base.split("/")[1:] - for i in reversed(range(len(dirs))): - yield join("/" + "/".join(dirs[0:i]), PAPERINFO_FILE_NAME) - - def _fill_ostruct_with_data(self, ostruct, dataset): - # Copy data from a CSV row to a dict/ostruct - - filename, year, title, authors, url = dataset - if year: ostruct['year'] = year - if title: ostruct['title'] = title - if authors: ostruct['authors'] = authors - if url: ostruct['url'] = url - - def _fill_row_with_ostruct(self, row, update_dict): - # Copy data from a dict/ostruct into a CSV row - for key, value in update_dict.items(): - if key == "year": - row[1] = value - elif key == "title": - row[2] = value - elif key == "authors": - row[3] = value - elif key == "url": - row[4] = value diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py index 7fe4927b..1dcfa40b 100644 --- a/ranger/gui/widgets/browsercolumn.py +++ b/ranger/gui/widgets/browsercolumn.py @@ -252,7 +252,7 @@ class BrowserColumn(Pager): paperinfo = None use_linemode = drawn._linemode if use_linemode == "papertitle": - paperinfo = self.fm.papermanager.get_paper_info(drawn.path) + paperinfo = self.fm.metadata.get_metadata(drawn.path) if not paperinfo.title: use_linemode = "filename" -- cgit 1.4.1-2-gfad0