Exemple #1
0
 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()
Exemple #2
0
    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))
Exemple #3
0
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)
Exemple #4
0
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)
Exemple #5
0
 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()
Exemple #6
0
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)
Exemple #7
0
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)
Exemple #8
0
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)
Exemple #9
0
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)
Exemple #10
0
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)
Exemple #11
0
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)))
Exemple #12
0
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)))
Exemple #13
0
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)
Exemple #14
0
 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
Exemple #15
0
    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()
Exemple #16
0
    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()
Exemple #17
0
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
Exemple #18
0
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)
Exemple #19
0
    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
Exemple #20
0
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)))
Exemple #21
0
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)))
Exemple #22
0
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)
Exemple #23
0
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)
Exemple #24
0
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)
Exemple #25
0
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)))
Exemple #26
0
    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()
Exemple #27
0
    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"]
            )
Exemple #28
0
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