def get_doc_attrs(cite_key, doc_fname_startswith=None): """Return a dictionary of attributes (name, suffix, type) about the doc. This function is intended to be run only when doc is in the the cite-key directory already. If there is no doc in the cite-key directory, an empty dict will be returned. In general, you should not supply a value for 'doc_fname_startswith'; when left to the default value of None, the value of 'cite_key' will be used, which will generally be the correct behaviour. (The only time a value should be supplied is when the doc filename does *not* begin with 'cite_key', which should only be the case when invoked by 'change_cite_key_and_rename_dir', mid-way through the file-renaming process.) """ if not doc_fname_startswith: doc_fname_startswith = cite_key doc_attrs = {} cite_key_dir_abspath = os.path.join(config.DOCLIB_BASE_ABSPATH, constants.BIBS_SUBDIR, cite_key) if not os.path.exists(cite_key_dir_abspath): raise filesystem_utils.DirectoryNotFound(cite_key_dir_abspath) bib_fname_abspath = os.path.join(cite_key_dir_abspath, cite_key + ".bib") multiple_bib_entries = bibfile_utils.read_entries_from_file( bib_fname_abspath, False) # FIXME: Should check that length of 'multiple_bib_entries' is exactly 1. authors = multiple_bib_entries[0]["authors"] doc_attrs["author-lastnames"] = [author["lastname"] for author in authors] doc_attrs["title"] = multiple_bib_entries[0]["title"] doc_attrs["year-published"] = multiple_bib_entries[0]["year"] #doc_attrs["title"] = "" # We don't know what the filename of the document will be, only that it will # begin with the cite-key, and not end with ".bib". Hence, we will traverse # the directory, looking for any files that match these criteria. # FIXME: This seems inefficient. Would it be better to store the suffix in # a per-cite-key-dir ".meta" file instead? Is it faster to parse a simple # config file or traverse a directory each time? matched_doc_fname = [ fname for fname in os.listdir(cite_key_dir_abspath) if fname.startswith(doc_fname_startswith) and fname[-4:] != ".bib" ] if matched_doc_fname: doc_fname = matched_doc_fname[0] doc_attrs["doc-name"] = doc_fname suffix = filesystem_utils.get_suffix(doc_fname) doc_attrs["doc-suffix"] = suffix doc_attrs["doc-type"] = suffix[1:].upper() date_added = open(os.path.join(cite_key_dir_abspath, ".date-added.txt")).read().split()[0] doc_attrs["date-added"] = date_added return doc_attrs
def store_new_attachment(attachment_fname, short_descr="", source_url="", new_fname="", url_contents=None): """Store a new attachment in the doclib.""" if url_contents: # The user specified a URL rather than the name of a file on disk. # 'url_contents' is a file-like object that contains the contents of the URL. # Hence, don't test whether the 'attachment_fname' file exists on disk. pass elif not os.path.exists(attachment_fname): raise filesystem_utils.FileNotFound(attachment_fname) if new_fname: # We'll use this as the filename instead. target_fname = STRIP_MOST_PUNCTUATION_AND_WHITESPACE(unicode( new_fname.replace(' ', '-').replace('/', '-'))) else: # I've checked that 'os.path.basename' also does the correct thing for URLs. target_fname = os.path.basename(attachment_fname) # Ensure the filename doesn't begin with a dot (which we reserve for # book-keeping files like ".metadata"). target_fname = target_fname.lstrip('.') if target_fname == "": raise filesystem_utils.EmptyFilename() # Since different attachments may very well have duplicate filenames, # we store each attachment in a subdirectory with a "unique" dirname. (dirname, dirname_abspath) = create_unique_dirname(target_fname) if url_contents: # Save the URL contents into an appropriately-named file. target_fname_abspath = os.path.join(dirname_abspath, target_fname) target_f = open(target_fname_abspath, 'wb') shutil.copyfileobj(url_contents, target_f) else: # We want to move a file on disk. new_attachment_fname_abspath = \ filesystem_utils.move_and_rename(attachment_fname, dirname_abspath, target_fname) config_sections = [ ("Description", [ ("short-descr", short_descr), ("source-url", source_url), ]), ("Cache", [ ("filename", target_fname), ("suffix", filesystem_utils.get_suffix(target_fname)), ]), ("Creation", [ ("date-added", filesystem_utils.get_datestamp_str()), ]), ] filesystem_utils.write_config_file(config_sections, os.path.join(dirname_abspath, ".metadata")) repository.add_and_commit_new_attachment_dir(target_fname, dirname) return (dirname, dirname_abspath)
def get_doc_attrs(cite_key, doc_fname_startswith=None): """Return a dictionary of attributes (name, suffix, type) about the doc. This function is intended to be run only when doc is in the the cite-key directory already. If there is no doc in the cite-key directory, an empty dict will be returned. In general, you should not supply a value for 'doc_fname_startswith'; when left to the default value of None, the value of 'cite_key' will be used, which will generally be the correct behaviour. (The only time a value should be supplied is when the doc filename does *not* begin with 'cite_key', which should only be the case when invoked by 'change_cite_key_and_rename_dir', mid-way through the file-renaming process.) """ if not doc_fname_startswith: doc_fname_startswith = cite_key doc_attrs = {} cite_key_dir_abspath = os.path.join(config.DOCLIB_BASE_ABSPATH, constants.BIBS_SUBDIR, cite_key) if not os.path.exists(cite_key_dir_abspath): raise filesystem_utils.DirectoryNotFound(cite_key_dir_abspath) bib_fname_abspath = os.path.join(cite_key_dir_abspath, cite_key + ".bib") multiple_bib_entries = bibfile_utils.read_entries_from_file(bib_fname_abspath, False) # FIXME: Should check that length of 'multiple_bib_entries' is exactly 1. authors = multiple_bib_entries[0]["authors"] doc_attrs["author-lastnames"] = [author["lastname"] for author in authors] doc_attrs["title"] = multiple_bib_entries[0]["title"] doc_attrs["year-published"] = multiple_bib_entries[0]["year"] #doc_attrs["title"] = "" # We don't know what the filename of the document will be, only that it will # begin with the cite-key, and not end with ".bib". Hence, we will traverse # the directory, looking for any files that match these criteria. # FIXME: This seems inefficient. Would it be better to store the suffix in # a per-cite-key-dir ".meta" file instead? Is it faster to parse a simple # config file or traverse a directory each time? matched_doc_fname = [fname for fname in os.listdir(cite_key_dir_abspath) if fname.startswith(doc_fname_startswith) and fname[-4:] != ".bib"] if matched_doc_fname: doc_fname = matched_doc_fname[0] doc_attrs["doc-name"] = doc_fname suffix = filesystem_utils.get_suffix(doc_fname) doc_attrs["doc-suffix"] = suffix doc_attrs["doc-type"] = suffix[1:].upper() date_added = open(os.path.join(cite_key_dir_abspath, ".date-added.txt")).read().split()[0] doc_attrs["date-added"] = date_added return doc_attrs
def store_new_bib(bib_fname, doc_fname=None, abstract_fname=None): """Store a new bib-file in the doclib.""" if not os.path.exists(bib_fname): raise filesystem_utils.FileNotFound(bib_fname) if doc_fname and not os.path.exists(doc_fname): raise filesystem_utils.FileNotFound(doc_fname) if abstract_fname and not os.path.exists(abstract_fname): raise filesystem_utils.FileNotFound(abstract_fname) # Store the bib-entry in a directory named after the cite-key. # This will ensure an almost-unique directory-name for each bib-entry, while # also enabling duplicate bib-entries to be detected. cite_key = get_one_cite_key(bib_fname) bibs_subdir_abspath = os.path.join(config.DOCLIB_BASE_ABSPATH, constants.BIBS_SUBDIR) cite_key_dir_abspath = os.path.join(bibs_subdir_abspath, cite_key) try: os.makedirs(cite_key_dir_abspath) except OSError as e: if e.errno == errno.EEXIST: raise DirectoryAlreadyExistsInBibs(cite_key) else: raise new_bib_fname_abspath = \ filesystem_utils.move_and_rename(bib_fname, cite_key_dir_abspath, cite_key + ".bib") bibfile_utils.replace_cite_key_in_file(cite_key, new_bib_fname_abspath) if doc_fname: filesystem_utils.move_and_rename( doc_fname, cite_key_dir_abspath, cite_key + filesystem_utils.get_suffix(doc_fname)) if abstract_fname: filesystem_utils.move_and_rename(abstract_fname, cite_key_dir_abspath, constants.ABSTRACT_FNAME) filesystem_utils.add_datestamp(cite_key_dir_abspath) repository.add_and_commit_new_cite_key_dir(cite_key) # Do we want to merge the commit in the following function with the commit # in 'add_and_commit_new_cite_key_dir'? topic_tag_file_io.update_topic_tags_for_cite_key(cite_key, [], "new unread") return (cite_key, cite_key_dir_abspath)
def store_new_bib(bib_fname, doc_fname=None, abstract_fname=None): """Store a new bib-file in the doclib.""" if not os.path.exists(bib_fname): raise filesystem_utils.FileNotFound(bib_fname) if doc_fname and not os.path.exists(doc_fname): raise filesystem_utils.FileNotFound(doc_fname) if abstract_fname and not os.path.exists(abstract_fname): raise filesystem_utils.FileNotFound(abstract_fname) # Store the bib-entry in a directory named after the cite-key. # This will ensure an almost-unique directory-name for each bib-entry, while # also enabling duplicate bib-entries to be detected. cite_key = get_one_cite_key(bib_fname) bibs_subdir_abspath = os.path.join(config.DOCLIB_BASE_ABSPATH, constants.BIBS_SUBDIR) cite_key_dir_abspath = os.path.join(bibs_subdir_abspath, cite_key) try: os.makedirs(cite_key_dir_abspath) except OSError as e: if e.errno == errno.EEXIST: raise DirectoryAlreadyExistsInBibs(cite_key) else: raise new_bib_fname_abspath = \ filesystem_utils.move_and_rename(bib_fname, cite_key_dir_abspath, cite_key + ".bib") bibfile_utils.replace_cite_key_in_file(cite_key, new_bib_fname_abspath) if doc_fname: filesystem_utils.move_and_rename(doc_fname, cite_key_dir_abspath, cite_key + filesystem_utils.get_suffix(doc_fname)) if abstract_fname: filesystem_utils.move_and_rename(abstract_fname, cite_key_dir_abspath, constants.ABSTRACT_FNAME) filesystem_utils.add_datestamp(cite_key_dir_abspath) repository.add_and_commit_new_cite_key_dir(cite_key) # Do we want to merge the commit in the following function with the commit # in 'add_and_commit_new_cite_key_dir'? topic_tag_file_io.update_topic_tags_for_cite_key(cite_key, [], "new unread") return (cite_key, cite_key_dir_abspath)