Skip to content

extractors

CitationSource dataclass

CitationSource(source_file: str, line_number: int, source_type: str)

The data structure to hold citation source information.

CitationInfo dataclass

CitationInfo(key: str, sources: List[CitationSource] = list(), bibliography: Optional[Entry] = None)

The data structure to hold citation information.

TexCitationExtractor

Bases: AbcCitationExtractor

extract_citations

extract_citations(tex_file: Union[str, Path]) -> list[CitationInfo]

Parse a .tex file to find all cited bibliography keys.

Parameters:

  • tex_file ((str, Path)) –

    Path to the .tex file.

Returns:

  • list[CitationInfo] –

    Set of CitationInfo objects representing cited keys and their locations.

Source code in ures/literature/citation/extractors.py
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
def extract_citations(self, tex_file: Union[str, Path]) -> list[CitationInfo]:
    """Parse a .tex file to find all cited bibliography keys.

    Args:
            tex_file (str, Path): Path to the .tex file.

    Returns:
            Set of CitationInfo objects representing cited keys and their locations.
    """
    cited: dict[str, CitationInfo] = {}
    tex_file = Path(tex_file)

    with open(tex_file, "r", encoding="utf-8") as f:
        content = f.read()

    lines = content.split("\n")
    clean_lines = []
    for index, line in enumerate(lines):
        # ensure the % is not escaped
        pos = 0
        while True:
            idx = line.find("%", pos)
            if idx == -1:
                clean_lines.append((line[pos:], index + 1))
                break
            if idx == 0 or line[idx - 1] != "\\":
                clean_lines.append((line[:idx], index + 1))
                break
            pos = idx + 1

    for clean_line, line_no in clean_lines:
        for pattern in self.citation_patterns:
            matches = re.finditer(pattern, clean_line)
            for match in matches:
                # fetch the last group (the one containing citation keys)
                keys_str = match.groups()[-1]
                # split by comma and strip whitespace
                keys = [k.strip() for k in keys_str.split(",")]
                for key in keys:
                    if key not in cited:
                        cited[key] = CitationInfo(
                            key=key,
                            sources=[
                                CitationSource(
                                    source_file=tex_file.name,
                                    line_number=line_no,
                                    source_type="tex",
                                )
                            ],
                        )
                    else:
                        cited[key].sources.append(
                            CitationSource(
                                source_file=tex_file.name,
                                line_number=line_no,
                                source_type="tex",
                            )
                        )
    return list(cited.values())

BBLCitationExtractor

Bases: AbcCitationExtractor

extract_citations

extract_citations(bbl_file: Union[str, Path]) -> List[CitationInfo]

Parse a .bbl file to extract all bibliography entries.

Parameters:

  • bbl_file ((str, Path)) –

    Path to the .bbl file.

Returns:

Source code in ures/literature/citation/extractors.py
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
def extract_citations(self, bbl_file: Union[str, Path]) -> List[CitationInfo]:
    """Parse a .bbl file to extract all bibliography entries.

    Args:
            bbl_file (str, Path): Path to the .bbl file.

    Returns:

    """
    cited = []
    try:
        bbl_file = Path(bbl_file)
        with open(bbl_file, "r", encoding="utf-8") as f:
            content = f.read()

            bibitem_pattern = re.compile(
                r"\\bibitem(?:\[[^\]]*\])?.*?\{(.+?)\}", re.DOTALL
            )
            for match in bibitem_pattern.finditer(content):
                key = match.group(1)
                # Find the line number of the match for better context
                line_num = content.count("\n", 0, match.start()) + 1
                cited.append(
                    CitationInfo(
                        key=key,
                        sources=[
                            CitationSource(
                                source_file=bbl_file.name,
                                line_number=line_num,
                                source_type="bbl",
                            )
                        ],
                    )
                )
    except FileNotFoundError:
        pass
    return cited

AuxCitationExtractor

Bases: AbcCitationExtractor

Read cite keys from a BibTeX .aux file produced by LaTeX.

Records come from \citation{...} (including comma-separated keys) and nested \@input{other.aux} files. \citation{*} is kept as the key *.