def run(document, data=dict(), interactive=False, force=False): # 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, force, interactive) document.save() papis.database.get().update(document)
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 update_doc_from_data_interactively( document: Union[papis.document.Document, Dict[str, Any]], data: Dict[str, Any], data_name: str) -> None: import papis.tui.widgets.diff docdata = copy.copy(document) # do not compare some entries docdata.pop('files', None) docdata.pop('tags', None) document.update(papis.tui.widgets.diff.diffdict( docdata, data, namea=papis.document.describe(document), nameb=data_name))
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, data=dict(), interactive=False, force=False, from_yaml=False, from_bibtex=False, from_url=False, from_doi=False, args=False): logger = logging.getLogger('update:run') if from_yaml: import yaml data.update(yaml.load(open(from_yaml))) elif from_bibtex: try: bib_data = papis.bibtex.bibtex_to_dict(from_bibtex) data.update(bib_data[0]) except Exception: pass elif from_url: try: url_data = papis.downloaders.utils.get(from_url) data.update(url_data["data"]) except Exception: pass elif from_doi: logger.debug("Try using doi %s" % from_doi) data.update(papis.utils.doi_to_data(from_doi)) # 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, force, interactive) document.save() papis.database.get().update(document)
def run(document=papis.document.Document(), file_list=[], importer_list=(), file_format=None, folder_format=None, ref_format=None, confirm_flag=True, edit_flag=True, suffix_flag=True): log_prefix = "add:{0}".format("document") logger = logging.getLogger(log_prefix) if file_format is None and user._add_file_name: file_format = user._add_file_name if folder_format is None and user._add_folder_name: folder_format = user._add_folder_name if ref_format is None and user._add_ref_name: ref_format = user._add_ref_name file_list = papis.utils._get_list(file_list) ctx = get_data_from_importer(importer_list) for key in ctx.data.keys(): document.set_key(key, ctx.data[key], append=True) if papis.utils._validate_list(ctx.files): file_list.append(ctx.files[0]) if not document.keys(): logger.error(log.no_data_retrieved) # @log return 1 if confirm_flag: data = papis.document.from_input( document, "The following document will be added to your library") if not data: return 1 else: document.update(data) folder_name, document = papis.support.identifier.get_identifier( data=document, file_list=file_list, folder_format=folder_format, file_format=file_format, ref_format=ref_format, suffix=suffix_flag) lib_mgr = papis.libmanager.get_lib_manager(logger=logger) document = lib_mgr.add(document=document, folder_name=folder_name, value=file_list, doc=True, file_name=document[user._files_name]) 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_editor), fun_mark=None, pick=False) run(doc_mgr, open_task=task._task_editor, verbose=False) return document
def run(document, data=dict()): # 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)
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