API

bibliograpy command entrypoint

entrypoint()

The pyenvs command entrypoint.

Source code in bibliograpy/bibliograpy.py
def entrypoint():
    """The pyenvs command entrypoint."""

    commands = {
        'info': _info,
        'process': _process
    }

    ns: Namespace = _create_parser().parse_args()

    commands[ns.CMD](ns)

Bibtex API module.

Article dataclass

Bases: BibtexReference

any article published in a periodical like a journal article or magazine article

An article from a journal or magazine. Required fields: author, title, journal, year. Optional fields: volume, number, pages, month, note.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Article(BibtexReference):
    """any article published in a periodical like a journal article or magazine article

    An article from a journal or magazine.
    Required fields: author, title, journal, year.
    Optional fields: volume, number, pages, month, note."""

    def _mandatory_values(self):
        """Returns all the mandatory values"""
        return {
            'author': self.author,
            'title': self.title,
            'journal': self.journal,
            'year': self.year
        }

BibtexReference dataclass

A bibliography reference.

Source code in bibliograpy/api_bibtex.py
@dataclass(frozen=True, repr=False)
class BibtexReference:
    """A bibliography reference."""

    CITE_KEY_FIELD = 'cite_key'
    NON_STANDARD_FIELD = 'non_standard'
    SCOPE_FIELD = 'scope'
    CROSSREF_FIELD = 'crossref'

    cite_key: str

    address: str | None
    """address of the publisher or the institution

    not used in article, misc and unpublished
    optional everywhere else
    https://www.bibtex.com/f/address-field/"""

    annote: str | None
    """an annotation

    https://www.bibtex.com/f/annote-field/"""

    author: str | None
    """ist of authors of the work

    optional for booklet, manual and misc
    required everywhere else
    https://www.bibtex.com/f/author-field/"""

    booktitle: str | None
    """title of the book

    required for incollection and inproceedings
    not used everywhere else
    https://www.bibtex.com/f/booktitle-field/"""

    chapter: str | None
    """number of a chapter in a book

    required for inbook and incollection
    not used everywhere else
    https://www.bibtex.com/f/chapter-field/"""

    crossref: str | None
    """The database key of the entry being cross referenced."""

    edition: str | None
    """edition number of a book

    optional for book, inbook, incollection and manual
    not used everywhere else
    https://www.bibtex.com/f/edition-field/"""

    editor: str | None
    """list of editors of a book

    required for book and inbook
    optional for incollection and inproceedings
    not used everywhere else
    https://www.bibtex.com/f/editor-field/"""

    howpublished: str | None
    """a publication notice for unusual publications

    optional for booklet and misc
    not used everywhere else
    https://www.bibtex.com/f/howpublished-field/"""

    institution: str | None
    """name of the institution that published and/or sponsored the report

    required for techreport
    not used everywhere else
    https://www.bibtex.com/f/institution-field/
    """

    journal: str | None
    """name of the journal or magazine the article was published in

    required for article
    not used everywhere else
    https://www.bibtex.com/f/journal-field/
    """

    month: str | None
    """the month during the work was published

    optional
    https://www.bibtex.com/f/month-field/"""

    note: str | None
    """
    notes about the reference

    required for unpublished
    optional everywhere else
    https://www.bibtex.com/f/note-field/"""

    number: str | int | None
    """number of the report or the issue number for a journal article

    optional for article, book, inbook, incollection, inproceedings and techreport
    not used everywhere else
    https://www.bibtex.com/f/number-field/"""

    organization: str | None
    """name of the institution that organized or sponsored the conference or that published the manual

    optional for inproceedings and manual
    not used everywhere else
    https://www.bibtex.com/f/organization-field/"""

    pages: str | int | None
    """page numbers or a page range

    required for inbook
    optional for article, incollection and inproceedings
    not used everywhere else
    https://www.bibtex.com/f/pages-field/"""

    publisher: str | None
    """name of the publisher

    required for book, inbook and incollection
    optional for inproceedings
    not used everywhere else
    https://www.bibtex.com/f/publisher-field/"""

    school: str | None
    """name of the university or degree awarding institution

    required for masterthesis and phdthesis
    not used everywhere else
    https://www.bibtex.com/f/school-field/"""

    series: str | None
    """name of the series or set of books

    optional for book, inbook, incollection and inproceedings
    not used everywhere else
    https://www.bibtex.com/f/series-field/"""

    title: str | None
    """title of the work

    optional for misc
    required everywhere else
    https://www.bibtex.com/f/title-field/"""

    type: str | None
    """type of the technical report or thesis

    optional for inbook, incollection, masterthesis and techreport
    not used everywhere else
    https://www.bibtex.com/f/type-field/"""

    volume: str | int | None
    """volume number

    optional for article, book, inbook, incollection and inproceedings
    not used everywhere else
    https://www.bibtex.com/f/volume-field/"""

    year: str | int | None
    """year the book was published

    required for article, book, inbook, incollection, inproceedings, masterthesis, phdthesis, techreport
    optional for booklet, misc and unpublished
    not used for manual
    https://www.bibtex.com/f/year-field/"""

    non_standard: NonStandard | None
    """Non standard fields."""

    scope: dict[str, BibtexReference] | None
    """Environnement de résolution des références croisées."""

    def _hierarchy(self) -> list[BibtexReference]:
        """Calcul de la hiérarchie par références croisées."""
        current: BibtexReference | None = self

        hierarchy: list[BibtexReference] = [current]
        while current is not None:
            if current.crossref is not None and current.scope is not None and current.crossref in current.scope:
                parent: BibtexReference = current.scope[current.crossref]
                hierarchy.append(parent)
                current = parent
            else:
                current = None
        return hierarchy

    def cross_resolved(self) -> BibtexReference:
        """Calcul de la référence héritant des champs des références croisées parentes."""
        hierarchy = self._hierarchy()

        if len(hierarchy) == 1:
            return self

        resolved_standard_dict: dict[str, Any] = {}
        for f in dataclasses.fields(type(self)):

            if f.name in [BibtexReference.NON_STANDARD_FIELD, BibtexReference.SCOPE_FIELD]:
                continue

            for i in hierarchy:
                v = getattr(i, f.name)
                if v is not None:
                    resolved_standard_dict[f.name] = v
                    break

        resolved_non_standard_dict: dict[str, Any] = {}
        for f in dataclasses.fields(NonStandard):

            for i in hierarchy:
                if i.non_standard is not None:
                    v = getattr(i.non_standard, f.name)
                    if v is not None:
                        resolved_non_standard_dict[f.name] = v
                        break

        resolved_standard_dict[BibtexReference.NON_STANDARD_FIELD] = NonStandard.from_dict(resolved_non_standard_dict)

        # il ne faut pas ajouter dans le scope cette instance résolue par références croisées car sa clef étant la même
        # que celle de la référence explicite, les deux entreraient en conflit dans le scope
        # seule la référence explicite doit être ajoutée au scope
        # si on souhaite disposer des champs hérités par références croisées, il faut utiliser l'instance résolue
        return type(self).from_dict(source=resolved_standard_dict,
                                    scope=None)
    @staticmethod
    def to_source_symbol(cite_key: str) -> str:
        """Produces a Python symbol for the reference."""
        return cite_key.upper()

    def to_py(self, scope_symbol: str | None) -> str:
        """Serialization of the reference in processed python code."""

        base = f"{BibtexReference.to_source_symbol(self.cite_key)} = {type(self).__name__}.generic("

        fields = []
        for f in dataclasses.fields(type(self)):

            if BibtexReference.SCOPE_FIELD == f.name:
                continue

            value = getattr(self, f.name)

            if f.name == BibtexReference.CROSSREF_FIELD and value is not None:
                fields.append(f"{f.name}={BibtexReference.to_source_symbol(value)}")
            elif isinstance(value, str):
                if "'" in value:
                    fields.append(f'{f.name}="{value}"')
                else:
                    fields.append(f"{f.name}='{value}'")
            elif isinstance(value, NonStandard):
                fields.append(f'{f.name}={value.to_py()}')
            elif value is not None:
                fields.append(f'{f.name}={value}')

        if scope_symbol is not None:
            fields.append(f'{BibtexReference.SCOPE_FIELD}={scope_symbol}')

        # argument indentation management
        sep = ',\n'
        for _ in range(len(base)):
            sep += ' '

        return f"\n{base}{sep.join(fields)})"

    def to_bib(self) -> dict:
        """converts to a bibtex parser dict"""
        result = {}
        for f in dataclasses.fields(type(self)):

            if BibtexReference.SCOPE_FIELD == f.name:
                continue

            if BibtexReference.CITE_KEY_FIELD == f.name:
                field_name = ID_FIELD_IN_MODEL_DICT
            else:
                field_name = f.name

            value = getattr(self, f.name)

            if isinstance(value, str):
                result[field_name] = value
            elif isinstance(value, NonStandard):
                ns = {}
                for f in dataclasses.fields(NonStandard):
                    v = getattr(value, f.name)
                    if v is not None:
                        ns[f.name] = str(v)

                result = result | ns

            elif value is not None:
                result[field_name] = str(value)

        result[ENTRYTYPE_FIELD_IN_MODEL_DICT] = type(self).bibtex_entry_type()
        return result

    def _mandatory_values(self) -> dict[str, Any]:
        """Checks if standard mandatory fields are not None."""
        raise NotImplementedError

    @classmethod
    def bibtex_entry_type(cls):
        """Gets the bibtex entrytype name"""
        for bibtex, internal_type in TYPES.items():
            if internal_type == cls:
                return bibtex
        raise ValueError

    @classmethod
    def generic(cls,
                cite_key: str,
                address: str | None = None,
                annote: str | None = None,
                booktitle: str | None = None,
                author: str | None = None,
                chapter: str | None = None,
                crossref: str | BibtexReference | None = None,
                edition: str | None = None,
                editor: str | None = None,
                howpublished: str | None = None,
                institution: str | None = None,
                journal: str | None = None,
                month: str | None = None,
                note: str | None = None,
                number: str | None = None,
                organization: str | None = None,
                pages: str | int | None = None,
                publisher: str | None = None,
                school: str | None = None,
                series: str | None = None,
                title: str | None = None,
                type: str | None = None,
                volume: str | int | None = None,
                year: str | int | None = None,
                non_standard: NonStandard | None = None,
                scope: dict[str, BibtexReference] | None = None) -> BibtexReference:
        """builds a generic reference, allowing to init each field"""
        instance = cls(cite_key=cite_key,
                       address=address,
                       annote=annote,
                       booktitle=booktitle,
                       author=author,
                       chapter=chapter,
                       crossref=crossref.cite_key if isinstance(crossref, BibtexReference) else crossref,
                       edition=edition,
                       editor=editor,
                       howpublished=howpublished,
                       institution=institution,
                       journal=journal,
                       month=month,
                       note=note,
                       number=number,
                       organization=organization,
                       pages=pages,
                       publisher=publisher,
                       school=school,
                       series=series,
                       title=title,
                       type=type,
                       volume=volume,
                       year=year,
                       non_standard=non_standard,
                       scope=scope)

        if any(v is None for k, v in instance._mandatory_values().items()):
            if all(v is not None for k, v in instance.cross_resolved()._mandatory_values().items()):
                LOG.info('all mandatory values resolved in scope cross references')
            else:
                raise ValueError(f'missing mandatory field for {cls.__name__} {instance.cite_key}')

        # scope management for crossref
        if scope is not None:
            # les chaines vides doivent être ignorées car elles représentent l'unique clef des citations anonymes
            if cite_key != '' and cite_key in scope:
                raise ValueError(f'{cite_key} is already present in bibliograpy scope for {scope[cite_key]}')

            scope[cite_key] = instance

        return instance

    @classmethod
    def from_dict(cls, source: dict[str, Any], scope: dict[str, BibtexReference] | None) -> BibtexReference:
        """Builds a reference from a dict."""
        return cls.generic(
            cite_key=source[BibtexReference.CITE_KEY_FIELD],
            address=source['address'] if 'address' in source else None,
            annote=source['annote'] if 'annote' in source else None,
            author=source['author'] if 'author' in source else None,
            booktitle=source['booktitle'] if 'booktitle' in source else None,
            chapter=source['chapter'] if 'chapter' in source else None,
            crossref=source['crossref'] if 'crossref' in source else None,
            edition=source['edition'] if 'edition' in source else None,
            editor=source['editor'] if 'editor' in source else None,
            howpublished=source['howpublished'] if 'howpublished' in source else None,
            institution=source['institution'] if 'institution' in source else None,
            journal=source['journal'] if 'journal' in source else None,
            month=source['month'] if 'month' in source else None,
            note=source['note'] if 'note' in source else None,
            number=source['number'] if 'number' in source else None,
            organization=source['organization'] if 'organization' in source else None,
            pages=source['pages'] if 'pages' in source else None,
            publisher=source['publisher'] if 'publisher' in source else None,
            school=source['school'] if 'school' in source else None,
            series=source['series'] if 'series' in source else None,
            title=source['title'] if 'title' in source else None,
            type=source['type'] if 'type' in source else None,
            volume=source['volume'] if 'volume' in source else None,
            year=source['year'] if 'year' in source else None,
            non_standard=NonStandard.from_dict(source),
            scope=scope)

address instance-attribute

address of the publisher or the institution

not used in article, misc and unpublished optional everywhere else https://www.bibtex.com/f/address-field/

annote instance-attribute

an annotation

https://www.bibtex.com/f/annote-field/

author instance-attribute

ist of authors of the work

optional for booklet, manual and misc required everywhere else https://www.bibtex.com/f/author-field/

booktitle instance-attribute

title of the book

required for incollection and inproceedings not used everywhere else https://www.bibtex.com/f/booktitle-field/

chapter instance-attribute

number of a chapter in a book

required for inbook and incollection not used everywhere else https://www.bibtex.com/f/chapter-field/

crossref instance-attribute

The database key of the entry being cross referenced.

edition instance-attribute

edition number of a book

optional for book, inbook, incollection and manual not used everywhere else https://www.bibtex.com/f/edition-field/

editor instance-attribute

list of editors of a book

required for book and inbook optional for incollection and inproceedings not used everywhere else https://www.bibtex.com/f/editor-field/

howpublished instance-attribute

a publication notice for unusual publications

optional for booklet and misc not used everywhere else https://www.bibtex.com/f/howpublished-field/

institution instance-attribute

name of the institution that published and/or sponsored the report

required for techreport not used everywhere else https://www.bibtex.com/f/institution-field/

journal instance-attribute

name of the journal or magazine the article was published in

required for article not used everywhere else https://www.bibtex.com/f/journal-field/

month instance-attribute

the month during the work was published

optional https://www.bibtex.com/f/month-field/

non_standard instance-attribute

Non standard fields.

note instance-attribute

notes about the reference

required for unpublished optional everywhere else https://www.bibtex.com/f/note-field/

number instance-attribute

number of the report or the issue number for a journal article

optional for article, book, inbook, incollection, inproceedings and techreport not used everywhere else https://www.bibtex.com/f/number-field/

organization instance-attribute

name of the institution that organized or sponsored the conference or that published the manual

optional for inproceedings and manual not used everywhere else https://www.bibtex.com/f/organization-field/

pages instance-attribute

page numbers or a page range

required for inbook optional for article, incollection and inproceedings not used everywhere else https://www.bibtex.com/f/pages-field/

publisher instance-attribute

name of the publisher

required for book, inbook and incollection optional for inproceedings not used everywhere else https://www.bibtex.com/f/publisher-field/

school instance-attribute

name of the university or degree awarding institution

required for masterthesis and phdthesis not used everywhere else https://www.bibtex.com/f/school-field/

scope instance-attribute

Environnement de résolution des références croisées.

series instance-attribute

name of the series or set of books

optional for book, inbook, incollection and inproceedings not used everywhere else https://www.bibtex.com/f/series-field/

title instance-attribute

title of the work

optional for misc required everywhere else https://www.bibtex.com/f/title-field/

type instance-attribute

type of the technical report or thesis

optional for inbook, incollection, masterthesis and techreport not used everywhere else https://www.bibtex.com/f/type-field/

volume instance-attribute

volume number

optional for article, book, inbook, incollection and inproceedings not used everywhere else https://www.bibtex.com/f/volume-field/

year instance-attribute

year the book was published

required for article, book, inbook, incollection, inproceedings, masterthesis, phdthesis, techreport optional for booklet, misc and unpublished not used for manual https://www.bibtex.com/f/year-field/

bibtex_entry_type() classmethod

Gets the bibtex entrytype name

Source code in bibliograpy/api_bibtex.py
@classmethod
def bibtex_entry_type(cls):
    """Gets the bibtex entrytype name"""
    for bibtex, internal_type in TYPES.items():
        if internal_type == cls:
            return bibtex
    raise ValueError

cross_resolved()

Calcul de la référence héritant des champs des références croisées parentes.

Source code in bibliograpy/api_bibtex.py
def cross_resolved(self) -> BibtexReference:
    """Calcul de la référence héritant des champs des références croisées parentes."""
    hierarchy = self._hierarchy()

    if len(hierarchy) == 1:
        return self

    resolved_standard_dict: dict[str, Any] = {}
    for f in dataclasses.fields(type(self)):

        if f.name in [BibtexReference.NON_STANDARD_FIELD, BibtexReference.SCOPE_FIELD]:
            continue

        for i in hierarchy:
            v = getattr(i, f.name)
            if v is not None:
                resolved_standard_dict[f.name] = v
                break

    resolved_non_standard_dict: dict[str, Any] = {}
    for f in dataclasses.fields(NonStandard):

        for i in hierarchy:
            if i.non_standard is not None:
                v = getattr(i.non_standard, f.name)
                if v is not None:
                    resolved_non_standard_dict[f.name] = v
                    break

    resolved_standard_dict[BibtexReference.NON_STANDARD_FIELD] = NonStandard.from_dict(resolved_non_standard_dict)

    # il ne faut pas ajouter dans le scope cette instance résolue par références croisées car sa clef étant la même
    # que celle de la référence explicite, les deux entreraient en conflit dans le scope
    # seule la référence explicite doit être ajoutée au scope
    # si on souhaite disposer des champs hérités par références croisées, il faut utiliser l'instance résolue
    return type(self).from_dict(source=resolved_standard_dict,
                                scope=None)

from_dict(source, scope) classmethod

Builds a reference from a dict.

Source code in bibliograpy/api_bibtex.py
@classmethod
def from_dict(cls, source: dict[str, Any], scope: dict[str, BibtexReference] | None) -> BibtexReference:
    """Builds a reference from a dict."""
    return cls.generic(
        cite_key=source[BibtexReference.CITE_KEY_FIELD],
        address=source['address'] if 'address' in source else None,
        annote=source['annote'] if 'annote' in source else None,
        author=source['author'] if 'author' in source else None,
        booktitle=source['booktitle'] if 'booktitle' in source else None,
        chapter=source['chapter'] if 'chapter' in source else None,
        crossref=source['crossref'] if 'crossref' in source else None,
        edition=source['edition'] if 'edition' in source else None,
        editor=source['editor'] if 'editor' in source else None,
        howpublished=source['howpublished'] if 'howpublished' in source else None,
        institution=source['institution'] if 'institution' in source else None,
        journal=source['journal'] if 'journal' in source else None,
        month=source['month'] if 'month' in source else None,
        note=source['note'] if 'note' in source else None,
        number=source['number'] if 'number' in source else None,
        organization=source['organization'] if 'organization' in source else None,
        pages=source['pages'] if 'pages' in source else None,
        publisher=source['publisher'] if 'publisher' in source else None,
        school=source['school'] if 'school' in source else None,
        series=source['series'] if 'series' in source else None,
        title=source['title'] if 'title' in source else None,
        type=source['type'] if 'type' in source else None,
        volume=source['volume'] if 'volume' in source else None,
        year=source['year'] if 'year' in source else None,
        non_standard=NonStandard.from_dict(source),
        scope=scope)

generic(cite_key, address=None, annote=None, booktitle=None, author=None, chapter=None, crossref=None, edition=None, editor=None, howpublished=None, institution=None, journal=None, month=None, note=None, number=None, organization=None, pages=None, publisher=None, school=None, series=None, title=None, type=None, volume=None, year=None, non_standard=None, scope=None) classmethod

builds a generic reference, allowing to init each field

Source code in bibliograpy/api_bibtex.py
@classmethod
def generic(cls,
            cite_key: str,
            address: str | None = None,
            annote: str | None = None,
            booktitle: str | None = None,
            author: str | None = None,
            chapter: str | None = None,
            crossref: str | BibtexReference | None = None,
            edition: str | None = None,
            editor: str | None = None,
            howpublished: str | None = None,
            institution: str | None = None,
            journal: str | None = None,
            month: str | None = None,
            note: str | None = None,
            number: str | None = None,
            organization: str | None = None,
            pages: str | int | None = None,
            publisher: str | None = None,
            school: str | None = None,
            series: str | None = None,
            title: str | None = None,
            type: str | None = None,
            volume: str | int | None = None,
            year: str | int | None = None,
            non_standard: NonStandard | None = None,
            scope: dict[str, BibtexReference] | None = None) -> BibtexReference:
    """builds a generic reference, allowing to init each field"""
    instance = cls(cite_key=cite_key,
                   address=address,
                   annote=annote,
                   booktitle=booktitle,
                   author=author,
                   chapter=chapter,
                   crossref=crossref.cite_key if isinstance(crossref, BibtexReference) else crossref,
                   edition=edition,
                   editor=editor,
                   howpublished=howpublished,
                   institution=institution,
                   journal=journal,
                   month=month,
                   note=note,
                   number=number,
                   organization=organization,
                   pages=pages,
                   publisher=publisher,
                   school=school,
                   series=series,
                   title=title,
                   type=type,
                   volume=volume,
                   year=year,
                   non_standard=non_standard,
                   scope=scope)

    if any(v is None for k, v in instance._mandatory_values().items()):
        if all(v is not None for k, v in instance.cross_resolved()._mandatory_values().items()):
            LOG.info('all mandatory values resolved in scope cross references')
        else:
            raise ValueError(f'missing mandatory field for {cls.__name__} {instance.cite_key}')

    # scope management for crossref
    if scope is not None:
        # les chaines vides doivent être ignorées car elles représentent l'unique clef des citations anonymes
        if cite_key != '' and cite_key in scope:
            raise ValueError(f'{cite_key} is already present in bibliograpy scope for {scope[cite_key]}')

        scope[cite_key] = instance

    return instance

to_bib()

converts to a bibtex parser dict

Source code in bibliograpy/api_bibtex.py
def to_bib(self) -> dict:
    """converts to a bibtex parser dict"""
    result = {}
    for f in dataclasses.fields(type(self)):

        if BibtexReference.SCOPE_FIELD == f.name:
            continue

        if BibtexReference.CITE_KEY_FIELD == f.name:
            field_name = ID_FIELD_IN_MODEL_DICT
        else:
            field_name = f.name

        value = getattr(self, f.name)

        if isinstance(value, str):
            result[field_name] = value
        elif isinstance(value, NonStandard):
            ns = {}
            for f in dataclasses.fields(NonStandard):
                v = getattr(value, f.name)
                if v is not None:
                    ns[f.name] = str(v)

            result = result | ns

        elif value is not None:
            result[field_name] = str(value)

    result[ENTRYTYPE_FIELD_IN_MODEL_DICT] = type(self).bibtex_entry_type()
    return result

to_py(scope_symbol)

Serialization of the reference in processed python code.

Source code in bibliograpy/api_bibtex.py
def to_py(self, scope_symbol: str | None) -> str:
    """Serialization of the reference in processed python code."""

    base = f"{BibtexReference.to_source_symbol(self.cite_key)} = {type(self).__name__}.generic("

    fields = []
    for f in dataclasses.fields(type(self)):

        if BibtexReference.SCOPE_FIELD == f.name:
            continue

        value = getattr(self, f.name)

        if f.name == BibtexReference.CROSSREF_FIELD and value is not None:
            fields.append(f"{f.name}={BibtexReference.to_source_symbol(value)}")
        elif isinstance(value, str):
            if "'" in value:
                fields.append(f'{f.name}="{value}"')
            else:
                fields.append(f"{f.name}='{value}'")
        elif isinstance(value, NonStandard):
            fields.append(f'{f.name}={value.to_py()}')
        elif value is not None:
            fields.append(f'{f.name}={value}')

    if scope_symbol is not None:
        fields.append(f'{BibtexReference.SCOPE_FIELD}={scope_symbol}')

    # argument indentation management
    sep = ',\n'
    for _ in range(len(base)):
        sep += ' '

    return f"\n{base}{sep.join(fields)})"

to_source_symbol(cite_key) staticmethod

Produces a Python symbol for the reference.

Source code in bibliograpy/api_bibtex.py
@staticmethod
def to_source_symbol(cite_key: str) -> str:
    """Produces a Python symbol for the reference."""
    return cite_key.upper()

Book dataclass

Bases: BibtexReference

a book

A book with an explicit publisher. Required fields: author or editor, title, publisher, year. Optional fields: volume or number, series, address, edition, month, note.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Book(BibtexReference):
    """a book

    A book with an explicit publisher.
    Required fields: author or editor, title, publisher, year.
    Optional fields: volume or number, series, address, edition, month, note."""

    def _mandatory_values(self):
        """Returns all the mandatory values."""
        return {
            'author or editor': self.author or self.editor,
            'title': self.title,
            'publisher': self.publisher,
            'year': self.year
        }

Booklet dataclass

Bases: BibtexReference

like a book but without a designated publisher

A work that is printed and bound, but without a named publisher or sponsoring institution. Required field: title. Optional fields: author, howpublished, address, month, year, note.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Booklet(BibtexReference):
    """like a book but without a designated publisher

    A work that is printed and bound, but without a named publisher or sponsoring institution.
    Required field: title.
    Optional fields: author, howpublished, address, month, year, note."""

    def _mandatory_values(self):
        """Returns all the mandatory values."""
        return {'title': self.title}

Conference dataclass

Bases: Inproceedings

The same as INPROCEEDINGS, included for Scribe compatibility.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Conference(Inproceedings):
    """The same as INPROCEEDINGS, included for Scribe compatibility."""

Inbook dataclass

Bases: BibtexReference

a section or chapter in a book

A part of a book, which may be a chapter (or section or whatever)and/or a range of pages. Required fields: author or editor, title, chapter and/or pages, publisher, year. Optional fields: volume or number, series, type, address, edition, month, note.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Inbook(BibtexReference):
    """a section or chapter in a book

    A part of a book, which may be a chapter (or section or whatever)and/or a range of pages.
    Required fields: author or editor, title, chapter and/or pages, publisher, year.
    Optional fields: volume or number, series, type, address, edition, month, note."""

    def _mandatory_values(self):
        """Returns all the mandatory values."""
        return {
            'author or editor': self.author or self.editor,
            'title': self.title,
            'chapter or pages': self.chapter or self.pages,
            'publisher': self.publisher,
            'year': self.year
        }

Incollection dataclass

Bases: BibtexReference

an article in a collection

A part of a book having its own title. Required fields: author, title, booktitle, publisher, year. Optional fields: editor, volume or number, series, type, chapter, pages, address, edition, month, note

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Incollection(BibtexReference):
    """an article in a collection

    A part of a book having its own title.
    Required fields: author, title, booktitle, publisher, year.
    Optional fields: editor, volume or number, series, type, chapter, pages, address, edition, month, note"""

    def _mandatory_values(self):
        """Returns all the mandatory values."""
        return {
            'author': self.author,
            'title': self.title,
            'booktitle': self.booktitle,
            'publisher': self.publisher,
            'year': self.year
        }

Inproceedings dataclass

Bases: BibtexReference

a conference paper (same as the conference entry type)

An article in a conference proceedings. Required fields: author, title, booktitle, year. Optional fields: editor, volume or number, series, pages, address, month, organization, publisher, note.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Inproceedings(BibtexReference):
    """a conference paper (same as the conference entry type)

    An article in a conference proceedings.
    Required fields: author, title, booktitle, year.
    Optional fields: editor, volume or number, series, pages, address, month, organization, publisher, note."""

    def _mandatory_values(self):
        """Returns all the mandatory values."""
        return {
            'author': self.author,
            'title': self.title,
            'booktitle': self.booktitle,
            'year': self.year
        }

Manual dataclass

Bases: BibtexReference

a technical manual

manual Technical documentation. Required field: title. Optional fields: author, organization, address, edition, month, year, note.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Manual(BibtexReference):
    """a technical manual

    manual Technical documentation.
    Required field: title.
    Optional fields: author, organization, address, edition, month, year, note."""

    def _mandatory_values(self):
        """Returns all the mandatory values."""
        return {'title': self.title}

Mastersthesis dataclass

Bases: BibtexReference

a Masters thesis

mastersthesis A Master’s thesis. Required fields: author, title, school, year. Optional fields: type, address, month, note.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Mastersthesis(BibtexReference):
    """a Masters thesis

    mastersthesis A Master’s thesis.
    Required fields: author, title, school, year.
    Optional fields: type, address, month, note."""

    def _mandatory_values(self):
        """Returns all the mandatory values."""
        return {
            'author': self.author,
            'title': self.title,
            'school': self.school,
            'year': self.year
        }

Misc dataclass

Bases: BibtexReference

used if nothing else fits

misc Use this type when nothing else fits. Required fields: none. Optional fields: author, title, howpublished, month, year, note.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Misc(BibtexReference):
    """used if nothing else fits

    misc Use this type when nothing else fits.
    Required fields: none.
    Optional fields: author, title, howpublished, month, year, note."""

    def _mandatory_values(self):
        """Returns all the mandatory values."""
        return {}

NonStandard dataclass

Non-standard bibtex bibliography reference fields.

Source code in bibliograpy/api_bibtex.py
@dataclass(frozen=True)
class NonStandard:
    """Non-standard bibtex bibliography reference fields."""

    doi: str | None = None
    """DOI number"""

    issn: str | None = None
    """ISSN number"""

    eissn: str | None = None
    """ISSN number"""

    isbn: str | None = None
    """ISBN number"""

    url: str | None = None
    """URL of a web page"""

    @staticmethod
    def from_dict(source: dict) -> NonStandard | None:
        """Builds a non-standard reference field set from a dict."""
        if any(f in source for f in ['doi', 'issn', 'eisssn', 'isbn', 'url']):
            return NonStandard(
                doi=source['doi'] if 'doi' in source else None,
                issn=source['issn'] if 'issn' in source else None,
                eissn=source['eissn'] if 'eissn' in source else None,
                isbn=source['isbn'] if 'isbn' in source else None,
                url=source['url'] if 'url' in source else None)
        return None


    def to_py(self) -> str:
        """Serialization of the non-standard reference field set in processed python code."""

        base = f"{type(self).__name__}("

        fields = []
        for f in dataclasses.fields(type(self)):
            value = getattr(self, f.name)

            if value is not None:
                fields.append(f"{f.name}='{value}'")

        return f"{base}{', '.join(fields)})"

doi = None class-attribute instance-attribute

DOI number

eissn = None class-attribute instance-attribute

ISSN number

isbn = None class-attribute instance-attribute

ISBN number

issn = None class-attribute instance-attribute

ISSN number

url = None class-attribute instance-attribute

URL of a web page

from_dict(source) staticmethod

Builds a non-standard reference field set from a dict.

Source code in bibliograpy/api_bibtex.py
@staticmethod
def from_dict(source: dict) -> NonStandard | None:
    """Builds a non-standard reference field set from a dict."""
    if any(f in source for f in ['doi', 'issn', 'eisssn', 'isbn', 'url']):
        return NonStandard(
            doi=source['doi'] if 'doi' in source else None,
            issn=source['issn'] if 'issn' in source else None,
            eissn=source['eissn'] if 'eissn' in source else None,
            isbn=source['isbn'] if 'isbn' in source else None,
            url=source['url'] if 'url' in source else None)
    return None

to_py()

Serialization of the non-standard reference field set in processed python code.

Source code in bibliograpy/api_bibtex.py
def to_py(self) -> str:
    """Serialization of the non-standard reference field set in processed python code."""

    base = f"{type(self).__name__}("

    fields = []
    for f in dataclasses.fields(type(self)):
        value = getattr(self, f.name)

        if value is not None:
            fields.append(f"{f.name}='{value}'")

    return f"{base}{', '.join(fields)})"

Phdthesis dataclass

Bases: BibtexReference

a PhD thesis

phdthesis A PhD thesis. Required fields: author, title, school, year. Optional fields: type, address, month, note.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Phdthesis(BibtexReference):
    """a PhD thesis

    phdthesis A PhD thesis.
    Required fields: author, title, school, year.
    Optional fields: type, address, month, note."""

    def _mandatory_values(self):
        """Returns all the mandatory values."""
        return {
            'author': self.author,
            'title': self.title,
            'school': self.school,
            'year': self.year
        }

Proceedings dataclass

Bases: BibtexReference

the whole conference proceedings

proceedings The proceedings of a conference. Required fields: title, year. Optional fields: editor, volume or number, series, address, month, organization, publisher, note.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Proceedings(BibtexReference):
    """the whole conference proceedings

    proceedings The proceedings of a conference.
    Required fields: title, year.
    Optional fields: editor, volume or number, series, address, month, organization, publisher, note."""

    def _mandatory_values(self):
        """Returns all the mandatory values."""
        return {
            'title': self.title,
            'year': self.year
        }

TechReport dataclass

Bases: BibtexReference

a technical report, government report or white paper

techreport A report published by a school or other institution, usually numbered within a series. Required fields: author, title, institution, year. Optional fields: type, number, address, month, note.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class TechReport(BibtexReference):
    """a technical report, government report or white paper

    techreport A report published by a school or other institution, usually numbered within a series.
    Required fields: author, title, institution, year.
    Optional fields: type, number, address, month, note."""

    def _mandatory_values(self):
        """Returns all the mandatory values."""
        return {
            'author': self.author,
            'title': self.title,
            'institution': self.institution,
            'year': self.year
        }

Unpublished dataclass

Bases: BibtexReference

a work that has not yet been officially published

unpublished A document having an author and title, but not formally published. Required fields: author, title, note. Optional fields: month, year.

Source code in bibliograpy/api_bibtex.py
@_bibtex_package
@_bibtex_com
@dataclass(frozen=True, repr=False)
class Unpublished(BibtexReference):
    """a work that has not yet been officially published

    unpublished A document having an author and title, but not formally published.
    Required fields: author, title, note.
    Optional fields: month, year."""

    def _mandatory_values(self):
        """Returns all the mandatory values."""
        return {
            'author': self.author,
            'title': self.title,
            'note': self.note
        }

default_bibtex_formatter(r)

The default formatter for bibtex references.

Source code in bibliograpy/api_bibtex.py
def default_bibtex_formatter(r: BibtexReference):
    """The default formatter for bibtex references."""
    r = r.cross_resolved()
    return f"{r.title} [{r.cite_key}]" if r.cite_key != _ANONYM_CITE_KEY else r.title

bibliograpy process module