def main(self): documents = self.get_db().query(self.args.search) document = self.pick(documents) if not document: return status.file_not_found if self.get_args().file: filepath = papis.api.pick( document.get_files() ) if not filepath: return status.file_not_found if not self.args.force: if not papis.utils.confirm("Are you sure?"): return status.success print("Removing %s..." % filepath) return run( document, filepath=filepath ) else: if not self.args.force: if not papis.utils.confirm("Are you sure?"): return status.success print("Removing ...") return run(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 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( documents: List[papis.document.Document], libraries: bool = False, downloaders: bool = False, pick: bool = False, files: bool = False, folders: bool = False, info_files: bool = False, notes: bool = False, fmt: str = "", template: Optional[str] = None ) -> Sequence[Union[str, papis.document.Document]]: """Main method to the list command :returns: List different objects :rtype: list """ if downloaders: return [str(d) for d in papis.downloaders.get_available_downloaders()] if template is not None: if not os.path.exists(template): logger.error("Template file {} not found".format(template)) return [] with open(template) as fd: fmt = fd.read() if libraries: config = papis.config.get_configuration() return [ section + ' ' + config[section]['dir'] for section in config if 'dir' in config[section] ] if files: return [ doc_file for files in [document.get_files() for document in documents] for doc_file in files ] elif notes: return [ os.path.join(d.get_main_folder() or '', d["notes"]) for d in documents if d.get_main_folder() is not None and d.has("notes") and isinstance(d["notes"], str) and os.path.exists( os.path.join(d.get_main_folder() or '', d["notes"])) ] elif info_files: return [d.get_info_file() for d in documents] elif fmt: return [papis.format.format(fmt, document) for document in documents] elif folders: return [ str(d.get_main_folder()) for d in documents if d.get_main_folder() is not None ] else: return documents
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, 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 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 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 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) document['files'] = document.get_files() + new_file_list document.save() return status.success
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 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"] )