diff --git a/src/.relint.yml b/src/.relint.yml index b408e059131..2b49c758dc0 100644 --- a/src/.relint.yml +++ b/src/.relint.yml @@ -41,12 +41,14 @@ in mathematics it should be "homogeneous" pattern: 'homogenous' -# Modularization anti-patterns (note: a tool to replace such 'from sage.all import' statements is given in SAGE_ROOT/src/sage/misc/replace_dot_all.py) +# Modularization anti-patterns - name: 'namespace_pkg_all_import: import from .all of a namespace package' hint: | Sage library code should not import from sage.PAC.KAGE.all when sage.PAC.KAGE is an implicit - Hint: namespace package. Type import_statements("SOME_IDENTIFIER") to find a more specific import. + Hint: namespace package. Type import_statements("SOME_IDENTIFIER") to find a more specific import, + Hint: or use 'sage --fiximports' to fix automatically in the source file. + # Keep in sync with SAGE_ROOT/src/sage/misc/replace_dot_all.py pattern: 'from\s+sage(|[.](arith|categories|combinat|ext|graphs(|[.]decompositions)|interfaces|libs|matrix|misc|numerical(|[.]backends)|rings|sets))[.]all\s+import' filePattern: '.*[.](py|pyx|pxi)$' error: false # Make this a warning instead of an error for now diff --git a/src/bin/sage b/src/bin/sage index e4d97835bb1..03aec9cfbfc 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -479,6 +479,13 @@ usage_advanced() { echo " Sage documentation for \"string\"." echo " --search_src ... -- same as --grep" echo " --search_doc ... -- same as --grepdoc" + echo " --fixdoctests file.py" + echo " -- Run doctests and replace output of failing doctests" + echo " with actual output." + echo " --fiximports " + echo " -- Replace imports from sage.PAC.KAGE.all by specific" + echo " imports when sage.PAC.KAGE is an implicit namespace" + echo " package" fi echo " --sh [...] -- run a shell with Sage environment variables" echo " as they are set in the runtime of Sage" @@ -974,6 +981,11 @@ if [ "$1" = '-startuptime' -o "$1" = '--startuptime' ]; then exec sage-startuptime.py "$@" fi +if [ "$1" = '-fiximports' -o "$1" = '--fiximports' ]; then + shift + exec sage-python -m sage.misc.replace_dot_all "$@" +fi + if [ "$1" = '-tox' -o "$1" = '--tox' ]; then shift if [ -n "$SAGE_SRC" -a -f "$SAGE_SRC/tox.ini" ]; then diff --git a/src/sage/misc/replace_dot_all.py b/src/sage/misc/replace_dot_all.py index b5093c0f062..ebbeba28fe6 100644 --- a/src/sage/misc/replace_dot_all.py +++ b/src/sage/misc/replace_dot_all.py @@ -1,4 +1,6 @@ r""" +Implementation of the command ``sage --fiximports``. + This file provides a tool to fix the modularization antipattern ``namespace_pkg_all_import`` reported by ``tox -e relint``. Sage library code should not import from ``sage.PAC.KAGE.all`` when ``sage.PAC.KAGE`` is an implicit namespace package. @@ -35,7 +37,7 @@ will fix all files in ``src/sage/arith`` and print out the unusual examples of ``import`` statements it finds. -In some rare cases, such as ``import`` statments appearing in doctests, the program will not be able to fix the ``import`` statement. The program will +In some rare cases, such as ``import`` statements appearing in doctests, the program will not be able to fix the ``import`` statement. The program will print out the location of the file and the line number of the exceptional ``import`` statement. The user can then manually fix the ``import`` statement. The program will also (usually) print out the suggested replacement for the ``import`` statement. The user can then copy and paste this replacement into the file. In the cases a suggested replacement is not printed out, the user should use the function :func:`~sage.misc.dev_tools.import_statements` @@ -62,9 +64,14 @@ def parse_arguments(): parser = argparse.ArgumentParser() # Optional arguments parser.add_argument( - "-l", "--location", help="Location of directory or file (root set at src/sage so input path from here). If no argument given, walks through all files in src/sage.", type=str) - parser.add_argument("-v", "--verbose", help="Increase output verbosity. Shows locations of any unusual cases of import statements and the corresponding changes.", - action="store_true") # Parse arguments + "-l", "--location", + help=("Location of directory or file (root set at src/sage so input path from here). " + "If no argument given, walks through all files in src/sage."), + type=str) + parser.add_argument( + "-v", "--verbose", + help="Increase output verbosity. Shows locations of any unusual cases of import statements and the corresponding changes.", + action="store_true") # Parse arguments args = parser.parse_args() return args