Beispiel #1
0
def parse_bibtex_entry(
    entry,
    pub_dir="publication",
    featured=False,
    overwrite=False,
    normalize=False,
    dry_run=False,
):
    """Parse a bibtex entry and generate corresponding publication bundle"""
    from academic.cli import log

    log.info(f"Parsing entry {entry['ID']}")

    bundle_path = f"content/{pub_dir}/{slugify(entry['ID'])}"
    markdown_path = os.path.join(bundle_path, "index.md")
    cite_path = os.path.join(bundle_path, "cite.bib")
    date = datetime.utcnow()
    timestamp = date.isoformat("T") + "Z"  # RFC 3339 timestamp.

    # Do not overwrite publication bundle if it already exists.
    if not overwrite and os.path.isdir(bundle_path):
        log.warning(
            f"Skipping creation of {bundle_path} as it already exists. "
            f"To overwrite, add the `--overwrite` argument.")
        return

    # Create bundle dir.
    log.info(f"Creating folder {bundle_path}")
    if not dry_run:
        Path(bundle_path).mkdir(parents=True, exist_ok=True)

    # Save citation file.
    log.info(f"Saving citation to {cite_path}")
    db = BibDatabase()
    db.entries = [entry]
    writer = BibTexWriter()
    if not dry_run:
        with open(cite_path, "w", encoding="utf-8") as f:
            f.write(writer.write(db))

    # Prepare YAML front matter for Markdown file.
    hugo = utils.hugo_in_docker_or_local()
    subprocess.call(f"{hugo} new {markdown_path} --kind publication",
                    shell=True)
    if "docker-compose" in hugo:
        time.sleep(2)

    page = EditableFM(bundle_path)
    page.load("index.md")

    page.fm["title"] = clean_bibtex_str(entry["title"])

    year, month, day = "", "01", "01"
    if "date" in entry:
        dateparts = entry["date"].split("-")
        if len(dateparts) == 3:
            year, month, day = dateparts[0], dateparts[1], dateparts[2]
        elif len(dateparts) == 2:
            year, month = dateparts[0], dateparts[1]
        elif len(dateparts) == 1:
            year = dateparts[0]
    if "month" in entry and month == "01":
        month = month2number(entry["month"])
    if "year" in entry and year == "":
        year = entry["year"]
    if len(year) == 0:
        log.error(f'Invalid date for entry `{entry["ID"]}`.')

    page.fm["date"] = "-".join([year, month, day])
    page.fm["publishDate"] = timestamp

    authors = None
    if "author" in entry:
        authors = entry["author"]
    elif "editor" in entry:
        authors = entry["editor"]

    if authors:
        authors = clean_bibtex_authors(
            [i.strip() for i in authors.replace("\n", " ").split(" and ")])
        page.fm["authors"] = authors

    page.fm["publication_types"] = [PUB_TYPES.get(entry["ENTRYTYPE"], "0")]

    if "abstract" in entry:
        page.fm["abstract"] = clean_bibtex_str(entry["abstract"])
    else:
        page.fm["abstract"] = ""

    page.fm["featured"] = featured

    # Publication name.
    if "booktitle" in entry:
        publication = "*" + clean_bibtex_str(entry["booktitle"]) + "*"
    elif "journal" in entry:
        publication = "*" + clean_bibtex_str(entry["journal"]) + "*"
    elif "publisher" in entry:
        publication = "*" + clean_bibtex_str(entry["publisher"]) + "*"
    else:
        publication = ""
    page.fm["publication"] = publication

    if "keywords" in entry:
        page.fm["tags"] = clean_bibtex_tags(entry["keywords"], normalize)

    if "url" in entry:
        page.fm["url_pdf"] = clean_bibtex_str(entry["url"])

    if "doi" in entry:
        page.fm["doi"] = clean_bibtex_str(entry["doi"])

    # Save Markdown file.
    try:
        log.info(f"Saving Markdown to '{markdown_path}'")
        if not dry_run:
            page.dump()
    except IOError:
        log.error("Could not save file.")
Beispiel #2
0
def parse_args(args):
    """Parse command-line arguments"""

    # Initialise command parser.
    parser = argparse.ArgumentParser(
        description=f"Academic Admin Tool v{version}\nhttps://sourcethemes.com/academic/", formatter_class=RawTextHelpFormatter,
    )
    subparsers = parser.add_subparsers(help="Sub-commands", dest="command")

    # Sub-parser for import command.
    parser_a = subparsers.add_parser("import", help="Import data into Academic")
    parser_a.add_argument(
        "--assets", action="store_true", help="Import third-party JS and CSS for generating an offline site",
    )
    parser_a.add_argument("--bibtex", required=False, type=str, help="File path to your BibTeX file")
    parser_a.add_argument(
        "--publication-dir",
        required=False,
        type=str,
        default="publication",
        help="Directory that your publications are stored in (default `publication`)",
    )
    parser_a.add_argument("--featured", action="store_true", help="Flag publications as featured")
    parser_a.add_argument("--overwrite", action="store_true", help="Overwrite existing publications")
    parser_a.add_argument(
        "--normalize", action="store_true", help="Normalize each keyword to lowercase with uppercase first letter",
    )
    parser_a.add_argument("-v", "--verbose", action="store_true", required=False, help="Verbose mode")
    parser_a.add_argument(
        "-dr", "--dry-run", action="store_true", required=False, help="Perform a dry run (Bibtex only)",
    )

    known_args, unknown = parser.parse_known_args(args)

    # If no arguments, show help.
    if len(args) == 0:
        parser.print_help()
        parser.exit()

    # If no known arguments, wrap Hugo command.
    elif known_args is None and unknown:
        cmd = utils.hugo_in_docker_or_local()
        if args:
            cmd = " ".join([cmd, args])
        subprocess.call(cmd)
    else:
        # The command has been recognised, proceed to parse it.
        if known_args.command and known_args.verbose:
            # Set logging level to debug if verbose mode activated.
            logging.getLogger().setLevel(logging.DEBUG)
        if known_args.command and known_args.assets:
            # Run command to import assets.
            import_assets()
        elif known_args.command and known_args.bibtex:
            # Run command to import bibtex.
            import_bibtex(
                known_args.bibtex,
                pub_dir=known_args.publication_dir,
                featured=known_args.featured,
                overwrite=known_args.overwrite,
                normalize=known_args.normalize,
                dry_run=known_args.dry_run,
            )
Beispiel #3
0
def parse_bibtex_entry(
    entry,
    pub_dir="publication",
    featured=False,
    overwrite=False,
    normalize=False,
    dry_run=False,
):
    """Parse a bibtex entry and generate corresponding publication bundle"""
    from academic.cli import log

    log.info(f"Parsing entry {entry['ID']}")

    bundle_path = f"content/{pub_dir}/{slugify(entry['ID'])}"
    markdown_path = os.path.join(bundle_path, "index.md")
    cite_path = os.path.join(bundle_path, "cite.bib")
    date = datetime.utcnow()
    timestamp = date.isoformat("T") + "Z"  # RFC 3339 timestamp.

    # Do not overwrite publication bundle if it already exists.
    if not overwrite and os.path.isdir(bundle_path):
        log.warning(
            f"Skipping creation of {bundle_path} as it already exists. "
            f"To overwrite, add the `--overwrite` argument.")
        return

    # Create bundle dir.
    log.info(f"Creating folder {bundle_path}")
    if not dry_run:
        Path(bundle_path).mkdir(parents=True, exist_ok=True)

    # Filter some bib fields
    entry_fields_filter = ["file"]
    entry = {k: v for k, v in entry.items() if k not in entry_fields_filter}
    # for key in entry:
    #     print(key+": "+entry[key])
    #     pass

    # Save citation file.
    log.info(f"Saving citation to {cite_path}")
    db = BibDatabase()
    db.entries = [entry]
    writer = BibTexWriter()
    if not dry_run:
        with open(cite_path, "w", encoding="utf-8") as f:
            f.write(writer.write(db))

    # Prepare YAML front matter for Markdown file.
    hugo = utils.hugo_in_docker_or_local()
    if not dry_run:
        subprocess.call(f"{hugo} new {markdown_path} --kind publication",
                        shell=True)
        if "docker-compose" in hugo:
            time.sleep(2)

    page = EditableFM(Path(bundle_path), dry_run=dry_run)
    page.load(Path("index.md"))

    page.fm["title"] = clean_bibtex_str(entry["title"])
    if 'shorttitle' in entry:
        page.fm["shorttitle"] = clean_bibtex_str(entry["shorttitle"])

    year, month, day = "", "01", "01"
    if "date" in entry:
        dateparts = entry["date"].split("/")[0].split("-")
        if len(dateparts) == 3:
            year, month, day = dateparts[0], dateparts[1], dateparts[2]
        elif len(dateparts) == 2:
            year, month = dateparts[0], dateparts[1]
        elif len(dateparts) == 1:
            year = dateparts[0]
    if "month" in entry and month == "01":
        month = month2number(entry["month"])
    if "year" in entry and year == "":
        year = entry["year"]
    if len(year) == 0:
        log.error(f'Invalid date for entry `{entry["ID"]}`.')

    page.fm["date"] = "-".join([year, month, day])
    page.fm["publishDate"] = timestamp

    # allow for pubstate (in press, submitted, ...) to appear - unless
    # 'unpublished'
    if "howpublished" in entry:
        if "unpublished" not in entry["howpublished"].lower():
            page.fm["weight"] = 1
        page.fm["publication_status"] = entry["howpublished"]

    if "eventtitle" in entry:
        page.fm["event"] = clean_bibtex_str(entry["eventtitle"])
        if "eventurl" in entry:
            page.fm["event_url"] = entry["eventurl"]
        if "type" in entry:
            if entry["type"].lower() != "talk":
                page.fm["eventtype"] = entry["type"]

    if "venue" in entry:
        page.fm["location"] = entry["venue"]

    authors = None
    if "author" in entry:
        authors = entry["author"]
    elif "editor" in entry:
        authors = entry["editor"]

    if authors:
        authors = clean_bibtex_authors(
            [i.strip() for i in authors.replace("\n", " ").split(" and ")])
        page.fm["authors"] = authors

    pubtype = PUB_TYPES.get(entry["ENTRYTYPE"], PublicationType.Uncategorized)
    if "entrysubtype" in entry:
        if (entry["ENTRYTYPE"] == "article"
                and entry["entrysubtype"].lower() == "newspaper"):
            pubtype = PublicationType.NewspaperArticle
    # For talks we want
    # - NO: 'publication_types'
    # - YES: 'all_day: true'
    # lazy check: are we writing in a directory containing 'talk' in its name?
    if "talk" in pub_dir:
        page.fm["all_day"] = True
    else:
        page.fm["publication_types"] = [str(pubtype.value)]

    if "abstract" in entry:
        page.fm["abstract"] = clean_bibtex_str(entry["abstract"])
    else:
        page.fm["abstract"] = ""

    page.fm["featured"] = featured

    # Publication name (booktitle/journaltitle).
    if "booktitle" in entry:
        publication = "*" + clean_bibtex_str(entry["booktitle"]) + "*"
    elif 'journaltitle' in entry:
        publication = "*" + clean_bibtex_str(entry["journaltitle"]) + "*"
    elif "journal" in entry:
        publication = "*" + clean_bibtex_str(entry["journal"]) + "*"
    elif "publisher" in entry:
        publication = "*" + clean_bibtex_str(entry["publisher"]) + "*"
    else:
        publication = ""
    page.fm["publication"] = publication

    # Publication short name (shortjournal).
    if "shortjournal" in entry:
        page.fm["publication_short"] = "*" + clean_bibtex_str(
            entry["shortjournal"]) + "*"
    else:
        page.fm["publication_short"] = ""

    if "keywords" in entry:
        page.fm["tags"] = clean_bibtex_tags(entry["keywords"], normalize)

    if "url" in entry:
        url_type = "url_pdf"
        if "urltype" in entry:
            url_type = "url_" + entry["urltype"]
        page.fm[url_type] = clean_bibtex_str(entry["url"])

    # General url_*: should work for url_{video,slides,code,etc.}
    for key in entry:
        if key.startswith("url") and key != "urltype" and len(key) > 3:
            page.fm["url_" + key[3:]] = clean_bibtex_str(entry[key])

    if "doi" in entry:
        page.fm["doi"] = clean_bibtex_str(entry["doi"])

    # Save Markdown file.
    try:
        log.info(f"Saving Markdown to '{markdown_path}'")
        if not dry_run:
            page.dump()
    except IOError:
        log.error("Could not save file.")
    return page