def add(self, document): docs = self.get_documents() self.logger.debug('adding ...') docs.append(document) assert (docs[-1].get_main_folder() == document.get_main_folder()) assert (os.path.exists(document.get_main_folder())) self.save()
def main(self): documents = self.get_db().query(self.args.search) if self.args.json and self.args.folder or \ self.args.yaml and self.args.folder: self.logger.warning("Only --folder flag will be considered") if not self.args.all: document = self.pick(documents) if not document: return 0 documents = [document] if self.args.out and not self.get_args().folder \ and not self.args.file: self.args.out = open(self.get_args().out, 'a+') if not self.args.out and not self.get_args().folder \ and not self.args.file: self.args.out = sys.stdout ret_string = run(documents, yaml=self.args.yaml, bibtex=self.args.bibtex, json=self.args.json, text=self.args.text) if ret_string is not None: self.args.out.write(ret_string) return 0 for document in documents: if self.args.folder: folder = document.get_main_folder() outdir = self.args.out or document.get_main_folder_name() if not len(documents) == 1: outdir = os.path.join(outdir, document.get_main_folder_name()) shutil.copytree(folder, outdir) if not self.args.no_bibtex: open(os.path.join(outdir, "info.bib"), "a+").write(papis.document.to_bibtex(document)) elif self.args.file: files = document.get_files() if self.args.all: files_to_open = files else: files_to_open = [ papis.api.pick( files, pick_config=dict(header_filter=lambda x: x.replace( document.get_main_folder(), ""))) ] for file_to_open in filter(lambda x: x, files_to_open): print(file_to_open) shutil.copyfile( file_to_open, self.args.out or os.path.basename(file_to_open))
def cli(query: str, doc_folder: str, git: bool, notes: bool, _all: bool, editor: Optional[str], sort_field: Optional[str], sort_reverse: bool) -> None: """Edit document information from a given library""" logger = logging.getLogger('cli:edit') if doc_folder: documents = [papis.document.from_folder(doc_folder)] else: documents = papis.database.get().query(query) if sort_field: documents = papis.document.sort(documents, sort_field, sort_reverse) if editor is not None: papis.config.set('editor', editor) if not _all: documents = list(papis.pick.pick_doc(documents)) if len(documents) == 0: logger.warning(papis.strings.no_documents_retrieved_message) return for document in documents: if notes: logger.debug("Editing notes") if not document.has("notes"): logger.warning( "The document selected has no notes attached, \n" "creating a notes files" ) document["notes"] = papis.config.getstring("notes-name") document.save() notes_path = os.path.join( str(document.get_main_folder()), document["notes"] ) if not os.path.exists(notes_path): logger.info("Creating {0}".format(notes_path)) open(notes_path, "w+").close() papis.api.edit_file(notes_path) if git: papis.git.add_and_commit_resource( str(document.get_main_folder()), str(document.get_info_file()), "Update notes for '{0}'".format( papis.document.describe(document))) else: run(document, git=git)
def cli(query, yaml, bibtex, json, folder, out, text, all, file): """Export a document from a given library""" logger = logging.getLogger('cli:export') documents = papis.database.get().query(query) if json and folder or yaml and folder: logger.warning("Only --folder flag will be considered") if not all: document = papis.api.pick_doc(documents) if not document: return 0 documents = [document] ret_string = run(documents, yaml=yaml, bibtex=bibtex, json=json, text=text) if ret_string is not None: if out is not None: logger.info("Dumping to {0}".format(out)) with open(out, 'w+') as fd: fd.write(ret_string) else: logger.info("Dumping to stdout") print(ret_string) return 0 for document in documents: if folder: folder = document.get_main_folder() outdir = out or document.get_main_folder_name() if not len(documents) == 1: outdir = os.path.join(outdir, document.get_main_folder_name()) shutil.copytree(folder, outdir) elif file: logger.info("Exporting file") files = document.get_files() assert (isinstance(files, list)) if not files: logger.error('No files found for doc in {0}'.format( document.get_main_folder())) continue files_to_open = [ papis.api.pick( files, pick_config=dict(header_filter=lambda x: x.replace( document.get_main_folder(), ""))) ] files_to_copy = list(filter(lambda x: x, files_to_open)) for file_to_open in files_to_copy: if out is not None and len(files_to_open) == 1: out_file = out else: out_file = os.path.basename(file_to_open) logger.info("copy {0} to {1}".format(file_to_open, out_file)) shutil.copyfile(file_to_open, out_file)
def add(self, document: papis.document.Document) -> None: docs = self.get_documents() self.logger.debug('adding ...') docs.append(document) assert(docs[-1].get_main_folder() == document.get_main_folder()) _folder = document.get_main_folder() assert(_folder is not None) assert(os.path.exists(_folder)) self.save()
def cli(query: str, doc_folder: str, sort_field: Optional[str], sort_reverse: bool, folder: str, out: str, fmt: str, _all: bool) -> None: """Export a document from a given library""" if doc_folder: documents = [papis.document.from_folder(doc_folder)] else: documents = papis.database.get().query(query) if fmt and folder: logger.warning("Only --folder flag will be considered") if not documents: logger.warning(papis.strings.no_documents_retrieved_message) return if not _all: documents = [d for d in papis.pick.pick_doc(documents)] if not documents: return if sort_field: documents = papis.document.sort(documents, sort_field, sort_reverse) # Get the local folder of the document so that third-party apps # can actually go to the folder without checking with papis for d in documents: d["_papis_local_folder"] = d.get_main_folder() ret_string = run(documents, to_format=fmt) if ret_string is not None and not folder: if out is not None: logger.info("Dumping to {0}".format(out)) with open(out, 'a+') as fd: fd.write(ret_string) else: logger.info("Dumping to stdout") print(ret_string) return for document in documents: if folder: _doc_folder = document.get_main_folder() _doc_folder_name = document.get_main_folder_name() outdir = out or _doc_folder_name if not _doc_folder or not _doc_folder_name or not outdir: raise Exception(papis.strings.no_folder_attached_to_document) if not len(documents) == 1: outdir = os.path.join(out, _doc_folder_name) logger.info("Exporting doc {0} to {1}".format( papis.document.describe(document), outdir )) shutil.copytree(_doc_folder, outdir)
def cli(query, file, force): """Delete command for several objects""" documents = papis.database.get().query(query) logger = logging.getLogger('cli:rm') if not documents: logger.warning(papis.strings.no_documents_retrieved_message) return 0 document = papis.api.pick_doc(documents) if not document: return if file: filepath = papis.api.pick(document.get_files()) if not filepath: return if not force: tbar = 'The file {0} would be removed'.format(filepath) if not papis.utils.confirm("Are you sure?", bottom_toolbar=tbar): return logger.info("Removing %s..." % filepath) return run(document, filepath=filepath) else: if not force: tbar = 'The folder {0} would be removed'.format( document.get_main_folder()) logger.warning("This document will be removed, check it") papis.utils.text_area(title=tbar, text=papis.document.dump(document), lexer_name='yaml') if not papis.utils.confirm("Are you sure?", bottom_toolbar=tbar): return logger.info("Removing ...") return run(document)
def run(document: papis.document.Document, new_name: str, git: bool = False) -> None: db = papis.database.get() logger = logging.getLogger('rename:run') folder = document.get_main_folder() if not folder: raise Exception(papis.strings.no_folder_attached_to_document) subfolder = os.path.dirname(folder) new_folder_path = os.path.join(subfolder, new_name) if os.path.exists(new_folder_path): logger.warning("Path '%s' already exists", new_folder_path) return cmd = ['git', '-C', folder] if git else [] cmd += ['mv', folder, new_folder_path] import subprocess logger.debug(cmd) subprocess.call(cmd) if git: papis.git.commit(new_folder_path, "Rename from {} to '{}'".format(folder, new_name)) db.delete(document) logger.debug("New document folder: '%s'", new_folder_path) document.set_folder(new_folder_path) db.add(document)
def cli(query, file, force): """Delete command for several objects""" documents = papis.database.get().query(query) document = papis.api.pick_doc(documents) if not document: return status.file_not_found if file: filepath = papis.api.pick(document.get_files()) if not filepath: return status.file_not_found if not force: toolbar = 'The file {0} would be removed'.format(filepath) if not papis.utils.confirm("Are you sure?", bottom_toolbar=toolbar): return status.success click.echo("Removing %s..." % filepath) return run(document, filepath=filepath) else: if not force: toolbar = 'The folder {0} would be removed'.format( document.get_main_folder()) if not papis.utils.confirm("Are you sure?", bottom_toolbar=toolbar): return status.success click.echo("Removing ...") return run(document)
def run(document: papis.document.Document, filepath: Optional[str] = None, git: bool = False) -> None: """Main method to the rm command """ db = papis.database.get() _doc_folder = document.get_main_folder() if not _doc_folder: raise Exception(papis.strings.no_folder_attached_to_document) if filepath is not None: os.remove(filepath) document['files'].remove(os.path.basename(filepath)) document.save() db.update(document) if git: papis.git.rm(_doc_folder, filepath) papis.git.add(_doc_folder, document.get_info_file()) papis.git.commit(_doc_folder, "Remove file '{0}'".format(filepath)) else: if git: _topfolder = os.path.dirname(os.path.abspath(_doc_folder)) papis.git.rm(_doc_folder, _doc_folder, recursive=True) papis.git.commit( _topfolder, "Remove document '{0}'".format( papis.document.describe(document))) else: papis.document.delete(document) db.delete(document)
def run(document: papis.document.Document, filepaths: List[str], git: bool = False) -> None: logger = logging.getLogger('addto') from string import ascii_lowercase g = papis.utils.create_identifier(ascii_lowercase) string_append = '' _doc_folder = document.get_main_folder() if not _doc_folder: raise Exception("Document does not have a folder attached") for i in range(len(document.get_files())): string_append = next(g) new_file_list = [] for i in range(len(filepaths)): in_file_path = filepaths[i] if not os.path.exists(in_file_path): raise Exception("{} not found".format(in_file_path)) # Rename the file in the staging area new_filename = papis.utils.clean_document_name( papis.commands.add.get_file_name(papis.document.to_dict(document), in_file_path, suffix=string_append)) new_file_list.append(new_filename) end_document_path = os.path.join(_doc_folder, new_filename) string_append = next(g) # Check if the absolute file path is > 255 characters if len(os.path.abspath(end_document_path)) >= 255: logger.warning('Length of absolute path is > 255 characters. ' 'This may cause some issues with some pdf viewers') if os.path.exists(end_document_path): logger.warning("%s already exists, ignoring...", end_document_path) continue import shutil logger.info("[CP] '%s' to '%s'", in_file_path, end_document_path) shutil.copy(in_file_path, end_document_path) if "files" not in document.keys(): document["files"] = [] document['files'] += new_file_list document.save() papis.database.get().update(document) if git: for r in new_file_list + [document.get_info_file()]: papis.git.add(_doc_folder, r) papis.git.commit( _doc_folder, "Add new files to '{}'".format(papis.document.describe(document)))
def edit_notes(document: papis.document.Document, git: bool = False) -> None: logger = logging.getLogger('edit:notes') logger.debug("Editing notes") if not document.has("notes"): document["notes"] = papis.config.getstring("notes-name") document.save() notes_path = os.path.join(str(document.get_main_folder()), document["notes"]) if not os.path.exists(notes_path): logger.debug("Creating {0}".format(notes_path)) open(notes_path, "w+").close() papis.api.edit_file(notes_path) if git: papis.git.add_and_commit_resource( str(document.get_main_folder()), str(document.get_info_file()), "Update notes for '{0}'".format(papis.document.describe(document)))
def cli(query: str, git: bool, _file: bool, force: bool, _all: bool, doc_folder: str, sort_field: Optional[str], sort_reverse: bool) -> None: """Delete a document or a file""" if doc_folder: documents = [papis.document.from_folder(doc_folder)] else: documents = papis.database.get().query(query) if sort_field: documents = papis.document.sort(documents, sort_field, sort_reverse) logger = logging.getLogger('cli:rm') if not documents: logger.warning(papis.strings.no_documents_retrieved_message) return if not _all: documents = list(papis.pick.pick_doc(documents)) if _file: for document in documents: filepaths = papis.pick.pick(document.get_files()) if not filepaths: continue filepath = filepaths[0] if not force: tbar = 'The file {0} would be removed'.format(filepath) if not papis.tui.utils.confirm( "Are you sure?", bottom_toolbar=tbar): continue logger.info("Removing '%s'...", filepath) run(document, filepath=filepath, git=git) else: for document in documents: if not force: tbar = 'The folder {0} would be removed'.format( document.get_main_folder()) logger.warning("This document will be removed, check it") papis.tui.utils.text_area( title=tbar, text=papis.document.dump(document), lexer_name='yaml') if not papis.tui.utils.confirm( "Are you sure?", bottom_toolbar=tbar): continue logger.warning("Removing ...") run(document, git=git)
def _locate_document(self, document): assert (isinstance(document, papis.document.Document)) result = list( filter( lambda d: d[1].get_main_folder() == document.get_main_folder(), enumerate(self.get_documents()))) if len(result) == 0: raise Exception( 'The document passed could not be found in the library') return result
def get_id_value(self, document): """Get the value that is stored in the unique key identifier of the documents in the database. In the case of papis this is just the path of the documents. :param document: Papis document :type document: papis.document.Document :returns: Path for the document :rtype: str """ return document.get_main_folder()
def main(self): # TODO: Try to recycle some of this code with command add. documents = papis.api.get_documents_in_lib(self.get_args().lib, self.get_args().search) document = self.pick(documents) if not document: return 0 data = dict() if self.args.auto: if 'doi' in document.keys() and not self.args.from_doi: self.args.from_doi = document['doi'] if 'title' in document.keys() and not self.args.from_isbnplus: self.args.from_isbnplus = document['title'] if self.args.from_yaml: import yaml data.update(yaml.load(open(self.args.from_yaml))) if self.args.from_isbnplus: doc = self.pick([ papis.document.Document(data=d) for d in papis.isbn.get_data(query=self.args.from_isbnplus) ]) if doc: data.update(doc.to_dict()) if self.args.from_bibtex: bib_data = papis.bibtex.bibtex_to_dict(self.args.from_bibtex) if len(bib_data) > 1: self.logger.warning( 'Your bibtex file contains more than one entry,' ' I will be taking the first entry') data.update(bib_data[0]) if self.args.from_url: url_data = papis.downloaders.utils.get(self.args.from_url) data.update(url_data["data"]) document_paths = url_data["documents_paths"] if not len(document_paths) == 0: document_path = document_paths[0] old_doc = self.pick(document["files"]) if papis.utils.confirm("Really replace document %s?" % old_doc): new_path = os.path.join(document.get_main_folder(), old_doc) self.logger.debug("Moving %s to %s" % (document_path, new_path)) shutil.move(document_path, new_path) if self.args.from_doi: self.logger.debug("Try using doi %s" % self.args.from_doi) data.update(papis.utils.doi_to_data(self.args.from_doi)) document.update(data, self.args.force, self.args.interactive) document.save()
def add_folder(template, doc_mgr, edit_flag=True, pick_flag=True): # prepare logging log_prefix = "add:{0}".format("folder") logger = logging.getLogger(log_prefix) doc_mgr_tmp = _lib_mgr.set_doc_item(query=template, fun_item=task.get_item(task._task_dir), pick=pick_flag) if doc_mgr_tmp.is_empty(): logger.info(log.no_item_retrieved("documents")) # @log return 1 document = doc_mgr.get_document() document_tmp = doc_mgr_tmp.get_document() import os.path dirs = [ d for d in os.listdir(document_tmp.get_main_folder()) if os.path.isdir(os.path.join(document_tmp.get_main_folder(), d)) ] for d in dirs: logger.info("[CP] '{0}' to '{1}'".format( # @log os.path.join(document_tmp.get_main_folder(), d), os.path.join(document.get_main_folder(), d))) shutil.copytree(os.path.join(document_tmp.get_main_folder(), d), os.path.join(document.get_main_folder(), d)) if edit_flag: from papis.commands.open import run doc_mgr = _lib_mgr.set_doc_item(doc_list=[document], fun_item=task.get_item( task._task_workspace), fun_mark=None, pick=False) run(doc_mgr, open_task=task._task_workspace, verbose=False) return
def run(document: papis.document.Document, opener: Optional[str] = None, folder: bool = False, mark: bool = False) -> None: logger = logging.getLogger('open:run') if opener is not None: papis.config.set("opentool", opener) _doc_folder = document.get_main_folder() if _doc_folder is None: raise Exception(papis.strings.no_folder_attached_to_document) if folder: # Open directory papis.api.open_dir(_doc_folder) else: if mark: logger.debug("Getting document's marks") marks = document[papis.config.getstring("mark-key-name")] if marks: logger.info("Picking marks") _mark_fmt = papis.config.getstring("mark-header-format") _mark_name = papis.config.getstring("mark-format-name") _mark_opener = papis.config.getstring("mark-opener-format") if not _mark_fmt: raise Exception("No mark header format") if not _mark_name: raise Exception("No mark name format") mark_dict = papis.api.pick( marks, header_filter=lambda x: papis.format.format( _mark_fmt, x, doc_key=_mark_name), match_filter=lambda x: papis.format.format( _mark_fmt, x, doc_key=_mark_name)) if mark_dict: if not _mark_opener: raise Exception("mark-opener-format not set") opener = papis.format.format(_mark_opener, papis.document.from_data( mark_dict[0]), doc_key=_mark_name) logger.info("Setting opener to '%s'", opener) papis.config.set("opentool", opener) files = document.get_files() if len(files) == 0: logger.error("The document chosen has no files attached") return files_to_open = papis.api.pick(files, header_filter=os.path.basename) for file_to_open in files_to_open: papis.api.open_file(file_to_open, wait=False)
def get_id_value(self, document: papis.document.Document) -> str: """Get the value that is stored in the unique key identifier of the documents in the database. In the case of papis this is just the path of the documents. :param document: Papis document :type document: papis.document.Document :returns: Path for the document :rtype: str """ _folder = document.get_main_folder() if _folder is None: raise Exception(papis.strings.no_folder_attached_to_document) else: return _folder
def run(document: papis.document.Document, wait: bool = True, git: bool = False) -> None: database = papis.database.get() info_file_path = document.get_info_file() if not info_file_path: raise Exception(papis.strings.no_folder_attached_to_document) papis.utils.general_open(info_file_path, "editor", wait=wait) document.load() database.update(document) if git: papis.git.add_and_commit_resource( str(document.get_main_folder()), info_file_path, "Update information for '{0}'".format( papis.document.describe(document)))
def run(document: papis.document.Document, data: Dict[str, Any] = dict(), git: bool = False) -> None: # Keep the ref the same, otherwise issues can be caused when # writing LaTeX documents and all the ref's change data['ref'] = document['ref'] document.update(data) _update_with_database(document) folder = document.get_main_folder() info = document.get_info_file() if not folder or not info: raise Exception(papis.strings.no_folder_attached_to_document) if git: papis.git.add_and_commit_resource( folder, info, "Update information for '{0}'".format( papis.document.describe(document)))
def run(document: papis.document.Document, new_folder_path: str, git: bool = False) -> None: logger = logging.getLogger('mv:run') folder = document.get_main_folder() if not folder: raise Exception(papis.strings.no_folder_attached_to_document) cmd = ['git', '-C', folder] if git else [] cmd += ['mv', folder, new_folder_path] db = papis.database.get() logger.debug(cmd) subprocess.call(cmd) db.delete(document) new_document_folder = os.path.join(new_folder_path, os.path.basename(folder)) logger.debug("New document folder: {}".format(new_document_folder)) document.set_folder(new_document_folder) db.add(document)
def cli(query, folder, out, format, all, **kwargs): """Export a document from a given library""" documents = papis.database.get().query(query) if format and folder: logger.warning("Only --folder flag will be considered") if not documents: logger.warning(papis.strings.no_documents_retrieved_message) return if not all: document = papis.api.pick_doc(documents) if not document: return 0 documents = [document] ret_string = run( documents, to_format=format, ) if ret_string is not None and not folder: if out is not None: logger.info("Dumping to {0}".format(out)) with open(out, 'a+') as fd: fd.write(ret_string) else: logger.info("Dumping to stdout") print(ret_string) return 0 for document in documents: if folder: folder = document.get_main_folder() outdir = out or document.get_main_folder_name() if not len(documents) == 1: outdir = os.path.join((out or ''), document.get_main_folder_name()) logger.info("Exporting doc {0} to {1}".format( papis.document.describe(document), outdir)) shutil.copytree(folder, outdir)
def run(document, filepaths): logger = logging.getLogger('addto') g = papis.utils.create_identifier(ascii_lowercase) string_append = '' for i in range(len(document.get_files())): string_append = next(g) new_file_list = [] for i in range(len(filepaths)): in_file_path = filepaths[i] if not os.path.exists(in_file_path): raise Exception("{} not found".format(in_file_path)) # Rename the file in the staging area new_filename = papis.utils.clean_document_name( papis.commands.add.get_file_name(papis.document.to_dict(document), in_file_path, suffix=string_append)) new_file_list.append(new_filename) endDocumentPath = os.path.join(document.get_main_folder(), new_filename) string_append = next(g) # Check if the absolute file path is > 255 characters if len(os.path.abspath(endDocumentPath)) >= 255: logger.warning('Length of absolute path is > 255 characters. ' 'This may cause some issues with some pdf viewers') if os.path.exists(endDocumentPath): logger.warning("%s already exists, ignoring..." % endDocumentPath) continue logger.debug("[CP] '%s' to '%s'" % (in_file_path, endDocumentPath)) shutil.copy(in_file_path, endDocumentPath) if not "files" in document.keys(): document["files"] = [] document['files'] += new_file_list document.save() papis.database.get().update(document)
def run(document: papis.document.Document, wait: bool = True, git: bool = False) -> None: logger = logging.getLogger('run:edit') info_file_path = document.get_info_file() if not info_file_path: raise Exception(papis.strings.no_folder_attached_to_document) _old_dict = papis.document.to_dict(document) papis.utils.general_open(info_file_path, "editor", wait=wait) document.load() _new_dict = papis.document.to_dict(document) # If nothing changed there is nothing else to be done if _old_dict == _new_dict: logger.debug("old and new are equal, doing nothing") return papis.database.get().update(document) papis.hooks.run("on_edit_done") if git: papis.git.add_and_commit_resource( str(document.get_main_folder()), info_file_path, "Update information for '{0}'".format( papis.document.describe(document)))
def main(self): # TODO: Try to recycle some of this code with command add. import papis.api documents = papis.api.get_documents_in_lib(self.get_args().lib, self.get_args().search) data = dict() if self.args.from_bibtex: bib_data = papis.bibtex.bibtex_to_dict(self.args.from_bibtex) # Then it means that the user wants to update all the information # appearing in the bibtex file if len(bib_data) > 1: self.logger.warning( 'Your bibtex file contains more than one entry,') self.logger.warning( 'It is supposed that you want to update all the' 'documents appearing inside the bibtex file.') for bib_element in bib_data: doc = papis.document.Document(data=bib_element) located_doc = papis.utils.locate_document(doc, documents) if located_doc is None: self.logger.error( "The following information could not be located") self.logger.error('\n' + doc.dump()) else: located_doc.update(bib_element, self.args.force, self.args.interactive) located_doc.save() return 0 data.update(bib_data[0]) if self.args.from_yaml: import yaml data.update(yaml.load(open(self.args.from_yaml))) # For the coming parts we need to pick a document document = self.pick(documents) if not document: return 0 if self.args.auto: if 'doi' in document.keys() and not self.args.from_doi: self.args.from_doi = document['doi'] if 'title' in document.keys() and not self.args.from_isbnplus: self.args.from_isbnplus = document['title'] if self.args.from_isbnplus: import papis.isbn doc = self.pick([ papis.document.Document(data=d) for d in papis.isbn.get_data(query=self.args.from_isbnplus) ]) if doc: data.update(doc.to_dict()) if self.args.from_url: url_data = papis.downloaders.utils.get(self.args.from_url) data.update(url_data["data"]) document_paths = url_data["documents_paths"] if not len(document_paths) == 0: document_path = document_paths[0] old_doc = self.pick(document["files"]) if papis.utils.confirm("Really replace document %s?" % old_doc): new_path = os.path.join(document.get_main_folder(), old_doc) self.logger.debug("Moving %s to %s" % (document_path, new_path)) shutil.move(document_path, new_path) if self.args.from_doi: self.logger.debug("Try using doi %s" % self.args.from_doi) data.update(papis.utils.doi_to_data(self.args.from_doi)) document.update(data, self.args.force, self.args.interactive) document.save()
def main(self): if papis.config.in_mode("contact"): self.init_contact_mode() lib_dir = os.path.expanduser(papis.config.get('dir')) data = dict() # The folder name of the new document that will be created out_folder_name = None # The real paths of the documents to be added in_documents_paths = self.args.document # The basenames of the documents to be added in_documents_names = [] # The folder name of the temporary document to be created temp_dir = tempfile.mkdtemp("-"+self.args.lib) if self.args.from_lib: doc = self.pick( papis.api.get_documents_in_lib(self.get_args().from_lib) ) if doc: self.args.from_folder = doc.get_main_folder() if self.args.from_folder: original_document = papis.document.Document(self.args.from_folder) self.args.from_yaml = original_document.get_info_file() in_documents_paths = original_document.get_files() if self.args.from_url: url_data = papis.downloaders.utils.get(self.args.from_url) data.update(url_data["data"]) in_documents_paths.extend(url_data["documents_paths"]) # If no data was retrieved and doi was found, try to get # information with the document's doi if not data and url_data["doi"] is not None and\ not self.args.from_doi: self.logger.warning( "I could not get any data from %s" % self.args.from_url ) self.args.from_doi = url_data["doi"] if self.args.from_bibtex: bib_data = papis.bibtex.bibtex_to_dict(self.args.from_bibtex) if len(bib_data) > 1: self.logger.warning( 'Your bibtex file contains more than one entry,' ' I will be taking the first entry' ) data.update(bib_data[0]) if self.args.from_pmid: self.logger.debug( "I'll try using PMID %s via HubMed" % self.args.from_pmid ) hubmed_url = "http://pubmed.macropus.org/articles/"\ "?format=text%%2Fbibtex&id=%s" % self.args.from_pmid bibtex_data = papis.downloaders.utils.get_downloader( hubmed_url, "get" ).get_document_data().decode("utf-8") bibtex_data = papis.bibtex.bibtex_to_dict(bibtex_data) if len(bibtex_data): data.update(bibtex_data[0]) if "doi" in data and not self.args.from_doi: self.args.from_doi = data["doi"] else: self.logger.error( "PMID %s not found or invalid" % self.args.from_pmid ) if self.args.from_doi: self.logger.debug("I'll try using doi %s" % self.args.from_doi) data.update(papis.utils.doi_to_data(self.args.from_doi)) if len(self.get_args().document) == 0 and \ papis.config.get('doc-url-key-name') in data.keys(): doc_url = data[papis.config.get('doc-url-key-name')] self.logger.info( 'I am trying to download the document from %s' % doc_url ) down = papis.downloaders.utils.get_downloader( doc_url, 'get' ) file_name = tempfile.mktemp() with open(file_name, 'wb+') as fd: fd.write(down.get_document_data()) self.logger.info('Opening the file') papis.api.open_file(file_name) if papis.utils.confirm('Do you want to use this file?'): self.args.document.append(file_name) if self.args.from_yaml: self.logger.debug("Yaml input file = %s" % self.args.from_yaml) data.update(papis.utils.yaml_to_data(self.args.from_yaml)) if self.args.from_vcf: data.update(papis.utils.vcf_to_data(self.args.from_vcf)) in_documents_names = [ papis.utils.clean_document_name(doc_path) for doc_path in in_documents_paths ] # Decide if we are adding the documents to an already existing document # or it is a new document if self.args.to: self.logger.debug( "Searching for the document where to add the files" ) documents = papis.api.get_documents_in_dir( lib_dir, self.args.to ) document = self.pick(documents) if not document: return 0 document.update( data, interactive=self.args.interactive ) document.save() data = document.to_dict() in_documents_paths = document.get_files() + in_documents_paths data["files"] = [os.path.basename(f) for f in in_documents_paths] # set out folder name the folder of the found document out_folder_name = document.get_main_folder_name() out_folder_path = document.get_main_folder() else: document = papis.document.Document(temp_dir) if not papis.config.in_mode("contact"): if len(in_documents_paths) == 0: if not self.get_args().no_document: self.logger.error("No documents to be added") return 1 else: in_documents_paths = [document.get_info_file()] # We need the names to add them in the file field # in the info file in_documents_names = [papis.utils.get_info_file_name()] # Save document to create the info file document.update( data, force=True, interactive=self.args.interactive ) document.save() data["title"] = self.args.title or self.get_default_title( data, in_documents_paths[0] ) data["author"] = self.args.author or self.get_default_author( data, in_documents_paths[0] ) self.logger.debug("Author = % s" % data["author"]) self.logger.debug("Title = % s" % data["title"]) if not self.args.name: self.logger.debug("Getting an automatic name") out_folder_name = self.get_hash_folder( data, in_documents_paths[0] ) else: temp_doc = papis.document.Document(data=data) out_folder_name = papis.utils.format_doc( self.args.name, temp_doc ) out_folder_name = papis.utils.clean_document_name( out_folder_name ) del temp_doc if len(out_folder_name) == 0: self.logger.error('The output folder name is empty') return 1 data["files"] = in_documents_names out_folder_path = os.path.join( lib_dir, self.args.dir, out_folder_name ) self.logger.debug("Folder name = % s" % out_folder_name) self.logger.debug("Folder path = % s" % out_folder_path) self.logger.debug("File(s) = % s" % in_documents_paths) # Create folders if they do not exists. if not os.path.isdir(temp_dir): self.logger.debug("Creating directory '%s'" % temp_dir) os.makedirs(temp_dir, mode=papis.config.getint('dir-umask')) # Check if the user wants to edit before submitting the doc # to the library if self.args.edit: document.update( data, force=True, interactive=self.args.interactive ) document.save() self.logger.debug("Editing file before adding it") papis.api.edit_file(document.get_info_file()) self.logger.debug("Loading the changes made by editing") document.load() data = document.to_dict() # First prepare everything in the temporary directory for i in range(min(len(in_documents_paths), len(data["files"]))): in_doc_name = data["files"][i] in_file_path = in_documents_paths[i] assert(os.path.exists(in_file_path)) endDocumentPath = os.path.join( document.get_main_folder(), in_doc_name ) if os.path.exists(endDocumentPath): self.logger.debug( "%s already exists, ignoring..." % endDocumentPath ) continue if not self.args.no_document: self.logger.debug( "[CP] '%s' to '%s'" % (in_file_path, endDocumentPath) ) shutil.copy(in_file_path, endDocumentPath) # Duplication checking self.logger.debug("Check if the added document is already existing") found_document = papis.utils.locate_document( document, papis.api.get_documents_in_lib(papis.api.get_lib()) ) if found_document is not None: self.logger.warning("DUPLICATION WARNING") self.logger.warning( "This document seems to be already in your libray: \n\n" + found_document.dump() ) self.logger.warning( "Use the update command if you just want to update the info." ) self.args.confirm = True document.update(data, force=True) if self.get_args().open: for d_path in in_documents_paths: papis.api.open_file(d_path) if self.args.confirm: if not papis.utils.confirm('Really add?'): return 0 document.save() if self.args.to: return 0 self.logger.debug( "[MV] '%s' to '%s'" % (document.get_main_folder(), out_folder_path) ) shutil.move(document.get_main_folder(), out_folder_path) # Let us chmod it because it might come from a temp folder # and temp folders are per default 0o600 os.chmod(out_folder_path, papis.config.getint('dir-umask')) papis.api.clear_lib_cache() if self.args.commit and papis.utils.lib_is_git_repo(self.args.lib): subprocess.call(["git", "-C", out_folder_path, "add", "."]) subprocess.call( ["git", "-C", out_folder_path, "commit", "-m", "Add document"] )
def run(paths, data=dict(), name=None, file_name=None, subfolder=None, interactive=False, from_bibtex=None, from_yaml=None, from_folder=None, from_url=None, from_doi=None, from_pmid=None, confirm=False, open_file=False, edit=False, commit=False, no_document=False): """ :param paths: Paths to the documents to be added :type paths: [] :param data: Data for the document to be added. If more data is to be retrieved from other sources, the data dictionary will be updated from these sources. :type data: dict :param name: Name of the folder where the document will be stored :type name: str :param file_name: File name of the document's files to be stored. :type file_name: str :param subfolder: Folder within the library where the document's folder should be stored. :type subfolder: str :param interactive: Wether or not interactive functionality of this command should be activated. :type interactive: bool :param from_bibtex: Filepath where to find a file containing bibtex info. :type from_bibtex: str :param from_yaml: Filepath where to find a file containing yaml info. :type from_yaml: str :param from_folder: Filepath where to find a papis document (folder + info file) to be added to the library. :type from_folder: str :param from_url: Url to try to download information and files from. :type from_url: str :param from_url: doi number to try to download information from. :type from_url: str :param from_url: pmid number to try to download information from. :type from_url: str :param confirm: Wether or not to ask user for confirmation before adding. :type confirm: bool :param open_file: Wether or not to ask user for opening file before adding. :type open_file: bool :param edit: Wether or not to ask user for editing the infor file before adding. :type edit: bool :param commit: Wether or not to ask user for committing before adding, in the case of course that the library is a git repository. :type commit: bool :param no_document: Wether or not the document has no files attached. :type no_document: bool """ logger = logging.getLogger('add:run') # The folder name of the new document that will be created out_folder_name = None # The real paths of the documents to be added in_documents_paths = paths # The basenames of the documents to be added in_documents_names = [] # The folder name of the temporary document to be created temp_dir = tempfile.mkdtemp() if from_folder: original_document = papis.document.Document(from_folder) from_yaml = original_document.get_info_file() in_documents_paths = original_document.get_files() if from_url: url_data = papis.downloaders.utils.get(from_url) data.update(url_data["data"]) in_documents_paths.extend(url_data["documents_paths"]) # If no data was retrieved and doi was found, try to get # information with the document's doi if not data and url_data["doi"] is not None and\ not from_doi: logger.warning("I could not get any data from %s" % from_url) from_doi = url_data["doi"] if from_bibtex: bib_data = papis.bibtex.bibtex_to_dict(from_bibtex) if len(bib_data) > 1: logger.warning('Your bibtex file contains more than one entry,' ' I will be taking the first entry') data.update(bib_data[0]) if from_pmid: logger.debug("I'll try using PMID %s via HubMed" % from_pmid) hubmed_url = "http://pubmed.macropus.org/articles/"\ "?format=text%%2Fbibtex&id=%s" % from_pmid bibtex_data = papis.downloaders.utils.get_downloader( hubmed_url, "get").get_document_data().decode("utf-8") bibtex_data = papis.bibtex.bibtex_to_dict(bibtex_data) if len(bibtex_data): data.update(bibtex_data[0]) if "doi" in data and not from_doi: from_doi = data["doi"] else: logger.error("PMID %s not found or invalid" % from_pmid) if from_doi: logger.debug("I'll try using doi %s" % from_doi) data.update(papis.utils.doi_to_data(from_doi)) if len(paths) == 0 and \ papis.config.get('doc-url-key-name') in data.keys(): doc_url = data[papis.config.get('doc-url-key-name')] logger.info('I am trying to download the document from %s' % doc_url) down = papis.downloaders.utils.get_downloader(doc_url, 'get') file_name = tempfile.mktemp() with open(file_name, 'wb+') as fd: fd.write(down.get_document_data()) logger.info('Opening the file') papis.api.open_file(file_name) if papis.utils.confirm('Do you want to use this file?'): paths.append(file_name) if from_yaml: logger.debug("Yaml input file = %s" % from_yaml) data.update(papis.utils.yaml_to_data(from_yaml)) for p in in_documents_paths: if not os.path.exists(p): raise IOError('Document %s not found' % p) in_documents_names = [ papis.utils.clean_document_name(doc_path) for doc_path in in_documents_paths ] document = papis.document.Document(temp_dir) if len(in_documents_paths) == 0: if not no_document: logger.error("No documents to be added") return status.file_not_found else: in_documents_paths = [document.get_info_file()] # We need the names to add them in the file field # in the info file in_documents_names = [papis.utils.get_info_file_name()] # Save document to create the info file document.update(data, force=True, interactive=interactive) document.save() if not name: logger.debug("Getting an automatic name") if not os.path.isfile(in_documents_paths[0]): return status.file_not_found out_folder_name = get_hash_folder(data, in_documents_paths[0]) else: temp_doc = papis.document.Document(data=data) out_folder_name = papis.utils.format_doc(name, temp_doc) out_folder_name = papis.utils.clean_document_name(out_folder_name) del temp_doc if len(out_folder_name) == 0: logger.error('The output folder name is empty') return status.file_not_found data["files"] = in_documents_names out_folder_path = os.path.expanduser( os.path.join(papis.config.get('dir'), subfolder or '', out_folder_name)) logger.debug("Folder name = % s" % out_folder_name) logger.debug("Folder path = % s" % out_folder_path) logger.debug("File(s) = % s" % in_documents_paths) # First prepare everything in the temporary directory g = papis.utils.create_identifier(ascii_lowercase) string_append = '' if file_name is not None: # Use args if set papis.config.set("file-name", file_name) new_file_list = [] for i in range(min(len(in_documents_paths), len(data["files"]))): in_file_path = in_documents_paths[i] if not os.path.exists(in_file_path): return status.file_not_found # Rename the file in the staging area new_filename = papis.utils.clean_document_name( get_file_name(data, in_file_path, suffix=string_append)) new_file_list.append(new_filename) endDocumentPath = os.path.join(document.get_main_folder(), new_filename) string_append = next(g) # Check if the absolute file path is > 255 characters if len(os.path.abspath(endDocumentPath)) >= 255: logger.warning('Length of absolute path is > 255 characters. ' 'This may cause some issues with some pdf viewers') if os.path.exists(endDocumentPath): logger.debug("%s already exists, ignoring..." % endDocumentPath) continue if not no_document: logger.debug("[CP] '%s' to '%s'" % (in_file_path, endDocumentPath)) shutil.copy(in_file_path, endDocumentPath) data['files'] = new_file_list # Check if the user wants to edit before submitting the doc # to the library if edit: document.update(data, force=True, interactive=interactive) document.save() logger.debug("Editing file before adding it") papis.api.edit_file(document.get_info_file(), wait=True) logger.debug("Loading the changes made by editing") document.load() data = papis.document.to_dict(document) # Duplication checking logger.debug("Check if the added document is already existing") found_document = papis.utils.locate_document( document, papis.api.get_documents_in_lib(papis.api.get_lib())) if found_document is not None: logger.warning('\n' + papis.document.dump(found_document)) print("\n\n") logger.warning("DUPLICATION WARNING") logger.warning( "The document above seems to be already in your library: \n\n") logger.warning( "(Hint) Use the update command if you just want to update" " the info.") confirm = True document.update(data, force=True) if open_file: for d_path in in_documents_paths: papis.api.open_file(d_path) if confirm: if not papis.utils.confirm('Really add?'): return status.success document.save() logger.debug("[MV] '%s' to '%s'" % (document.get_main_folder(), out_folder_path)) papis.document.move(document, out_folder_path) papis.database.get().add(document) if commit and papis.utils.lib_is_git_repo(papis.config.get_lib()): subprocess.call(["git", "-C", out_folder_path, "add", "."]) subprocess.call( ["git", "-C", out_folder_path, "commit", "-m", "Add document"]) return status.success