From 1e5a9449573bfe70987dcaf44e120895131e9c66 Mon Sep 17 00:00:00 2001 From: Eliah Kagan Date: Sun, 17 Mar 2024 19:25:34 -0400 Subject: [PATCH] Add a script to validate refactored imports This script can be removed after imports are refactored and checked to see that module contents are the same as before or otherwise non-broken. This script assumes that module contents are the same as the contents of their dictionaries, and that all modules in the project get imported as a consequence of importing the top-level module. These are both the case currently for GitPython, but they do not hold for all projects, and may not hold for GitPython at some point in the future. --- .gitignore | 4 ++++ modattrs.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100755 modattrs.py diff --git a/.gitignore b/.gitignore index 7765293d8..1be4f3201 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,7 @@ output.txt # Finder metadata .DS_Store + +# Output files for modattrs.py (these entries will be removed soon) +a +b diff --git a/modattrs.py b/modattrs.py new file mode 100755 index 000000000..245f68912 --- /dev/null +++ b/modattrs.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +"""Script to get the names and "stabilized" reprs of module attributes in GitPython. + +Run with :envvar:`PYTHONHASHSEED` set to ``0`` for fully comparable results. These are +only still meaningful for comparing if the same platform and Python version are used. + +The output of this script should probably not be committed, because within the reprs of +objects found in modules, it may contain sensitive information, such as API keys stored +in environment variables. The "sanitization" performed here is only for common forms of +whitespace that clash with the output format. +""" + +# fmt: off + +__all__ = ["git", "main"] + +import itertools +import re +import sys + +import git + + +def main(): + # This assumes `import git` causes all of them to be loaded. + gitpython_modules = sorted( + (module_name, module) + for module_name, module in sys.modules.items() + if re.match(r"git(?:\.|$)", module_name) + ) + + # We will print two blank lines between successive module reports. + separators = itertools.chain(("",), itertools.repeat("\n\n")) + + # Report each module's contents. + for (module_name, module), separator in zip(gitpython_modules, separators): + print(f"{separator}{module_name}:") + + attributes = sorted( + (name, value) + for name, value in module.__dict__.items() + if name != "__all__" # Because we are deliberately adding these. + ) + + for name, value in attributes: + sanitized_repr = re.sub(r"[\r\n\v\f]", "?", repr(value)) + normalized_repr = re.sub(r" at 0x[0-9a-fA-F]+", " at 0x...", sanitized_repr) + print(f" {name}: {normalized_repr}") + + +if __name__ == "__main__": + main()