python / python/cpython

"pegen.py python" should validate the output file.

Offen
#101,925 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

build type-bug
Vorherrschende Sprache
Python
Sterne
77.2k
Forks
36k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

I ran pegen python -o grammar_parser.py after making an incorrect change to metagrammar.gram. This was invoked by make regen-pegen-metaparser, or build.bat --regen on Windows.
The resulting output file was syntactically correct, but it could not correctly parse the metagrammar file. So when I ran the make again later, it failed. The call to GeneratedParser.start() raised an exception.

The previous (correctly working) version of grammar_parser.py is now lost, unless I could get it back from Git.

Desired behavior

pegen must be sure that the newly generated output file will work correctly, before writing it out to the filesystem.

Generation of the output file begins in pegen/build.py,

def build_python_generator(
    grammar: Grammar,
    grammar_file: str,
    output_file: str,
    skip_actions: bool = False,
) -> ParserGenerator:
    with open(output_file, "w") as file:
        gen: ParserGenerator = PythonParserGenerator(grammar, file)  # TODO: skip_actions
        gen.generate(grammar_file)
    return gen

This creates a new output file. Even if the body of the with raises an exception, the output file is closed and remains in the filesystem, overwriting the previous version.
Instead,

  1. Use a StringIO as the file, instead of a real open() file. Call it result.
  2. Generate the file, which fills in result.
  3. Validate result (see more below).
  4. If validation succeeds, then write the result to a new open(output_file, "w").
  5. Otherwise, do nothing more. The file designated by output_file will still be intact.

Validating the output file

To validate the output file result, go through the entire process of generating result, except using
result instead of the grammar_parser module. This process is the entire code of build_python_parser_and_generator, not just the build_python_generator function.

grammar_parser is used to import the class GeneratedParser. For validation purposes, exec(result) with an empty globals/locals dict, then use the ['GeneratedParser'] item. Note, in build.py, this class is imported as the name GrammarParser.
This process should generate a new_result StringIO, and it should be identical to result. Perhaps there may be some insignificant differences between the two, and if so, they shouldn't be compared.
If the generation of new_result raises an exception, then the validation has failed.

Linked PRs
  • gh-101937

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne in pegen/build.py, insbesondere bei build_python_generator und build_python_parser_and_generator. Verfolge, wie die Ausgabe des generierten Parsers erzeugt und validiert wird. Bewahre dann die vorhandene Ausgabedatei, wenn die Validierung fehlschlägt, und stelle sicher, dass die erfolgreiche Ausgabe erst nach bestandener Validierung geschrieben wird. Prüfe den verlinkten PR gh-101937 auf bereits laufende Arbeiten.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
build-system, compilers
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
32/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.