#!/usr/bin/env bash # WARNING: this function is copy/pasted from both src/bin/sage-env and # the top-level "sage" script. Please keep them synchronized. resolvelinks() { # $in is what still needs to be converted (normally has no starting slash) in="$1" # $out is the part which is converted (normally ends with trailing slash) out="./" # Move stuff from $in to $out while [ -n "$in" ]; do # Normalize $in by replacing consecutive slashes by one slash in=$(echo "${in}" | sed 's://*:/:g') # If $in starts with a slash, remove it and set $out to the root in_without_slash=${in#/} if [ "$in" != "$in_without_slash" ]; then in=$in_without_slash out="/" continue fi # Check that the directory $out exists by trying to cd to it. # If this fails, then cd will show an error message (unlike # test -d "$out"), so no need to be more verbose. ( cd "$out" ) || return $? # Get the first component of $in f=${in%%/*} # If it is not a symbolic link, simply move it to $out if [ ! -L "$out$f" ]; then in=${in#"$f"} out="$out$f" # If the new $in starts with a slash, move it to $out in_without_slash=${in#/} if [ "$in" != "$in_without_slash" ]; then in=$in_without_slash out="$out/" fi continue fi # Now resolve the symbolic link "$f" f_resolved=`readlink -n "$out$f" 2>/dev/null` status=$? # status 127 means readlink could not be found. if [ $status -eq 127 ]; then # We don't have "readlink", try a stupid "ls" hack instead. # This will fail if we have filenames like "a -> b". fls=`ls -l "$out$f" 2>/dev/null` status=$? f_resolved=${fls##*-> } # If $fls equals $f_resolved, then certainly # something is wrong if [ $status -eq 0 -a "$fls" = "$f_resolved" ]; then echo >&2 "Cannot parse output from ls -l '$out$f'" return 1 fi fi if [ $status -ne 0 ]; then echo >&2 "Cannot read symbolic link '$out$f'" return $status fi # In $in, replace $f by $f_resolved (leave $out alone) in="${in#${f}}" in="${f_resolved}${in}" done # Return $out echo "$out" } # Resolve the links in $0 so that local/bin/sage can be executed from # a symlink (Issue #30888). SELF=$(resolvelinks "${0}") ##################################################################### # Set up the version-specific symlink in /var/tmp (macOS) ##################################################################### SAVED_CWD="`pwd`" CURDIR=$(resolvelinks "`dirname $0`") cd "$CURDIR/../../../../../../" VERSION_DIR="`pwd`" cd "$SAVED_CWD" runpath_sh=$VERSION_DIR/local/var/lib/sage/runpath.sh if [ -x "$runpath_sh" ]; then . "$runpath_sh" else echo >&2 "Could not find runpath.sh." echo >&2 "The SageMath symlink is probably misconfigured." fi # Check that the installation specific symlink points to this sage # root directory. If not, try to reset it. Strangely, this script # can get called a second time and when that happens we will have # $TARGET == $SAGE_SYMLINK. We had better not set the symlink to # point to itself! if [ -L $SAGE_SYMLINK ] || ! [ -e $SAGE_SYMLINK ]; then OLD_VERSION_DIR=`readlink $SAGE_SYMLINK` if [ "$VERSION_DIR" != "$OLD_VERSION_DIR" ] && [ "$VERSION_DIR" != "$SAGE_SYMLINK" ]; then rm -f $SAGE_SYMLINK 2> /dev/null if [ $? -ne 0 ]; then OWNER=$(stat -f '%Su' $SAGE_SYMLINK) echo echo "Oh no!" echo "You do not have permission to reconfigure this SageMath." echo "Please ask $OWNER to open the app." echo read -p "The app will exit when you press a key." exit fi if [ "$VERSION_DIR" != "$SAGE_SYMLINK" ]; then ln -s "$VERSION_DIR" "$SAGE_SYMLINK" fi fi fi # Display the current version of Sage # usage: sage_version [-v] # -v display the full version banner including release date sage_version() { if [ -f "${SELF}-version.sh" ]; then . "${SELF}-version.sh" else . "$SAGE_ROOT/src/bin/sage-version.sh" fi if [ "$1" = "-v" ]; then echo "${SAGE_VERSION_BANNER}" else echo "${SAGE_VERSION}" fi } usage() { sage_version -v #### 1.......................26..................................................78 #### |.....................--.|...................................................| echo echo "Running Sage:" if command -v sage-ipython &>/dev/null; then echo echo " file.[sage|py|spyx] -- run given .sage, .py or .spyx file" echo " -c <cmd> -- evaluate cmd as sage code" echo " --notebook=[...] -- start the Sage notebook (valid options are" echo " 'default', 'jupyter', 'jupyterlab', and 'export')" echo " Current default is 'jupyter'" echo " -n, --notebook -- shortcut for --notebook=default" echo " --nodotsage -- run Sage without using the user's .sage directory:" echo " create and use a temporary .sage directory instead" echo " -t [options] <--all|files|dir>" echo " -- test examples in .py, .pyx, .sage, .tex or .rst files" echo " selected options:" echo " --long - include lines with the phrase 'long time'" echo " --verbose - print debugging output during the test" echo " --optional - controls which optional tests are run" echo " --help - show all testing options" else echo " (not installed currently, " echo " to install, run sage --pip install sagemath-repl)" fi echo echo "Running external programs:" echo command -v gap &>/dev/null && \ echo " --gap [...] -- run Sage's Gap with given arguments" command -v gp &>/dev/null && \ echo " --gp [...] -- run Sage's PARI/GP calculator with given arguments" echo " --pip [...] -- invoke pip, the Python package manager" command -v maxima &>/dev/null && \ echo " --maxima [...] -- run Sage's Maxima with given arguments" command -v mwrank &>/dev/null && \ echo " --mwrank [...] -- run Sage's mwrank with given arguments" echo " --python [...], --python3 [...] -- run the Python 3 interpreter" command -v R &>/dev/null && \ echo " -R [...] -- run Sage's R with given arguments" command -v singular &>/dev/null && \ echo " --singular [...] -- run Sage's singular with given arguments" echo echo "Getting help:" echo echo " -v, --version -- display Sage version information" echo " -h, -?, --help -- print this help message" echo " --advanced -- list all command line options" if [ -d "$SAGE_ROOT" ]; then exec "$SAGE_ROOT/build/bin/sage-site" "-h" fi exit 0 } # 'usage_advanced', which prints a longer help message, is defined # below, after sourcing sage-env. # Determine SAGE_ROOT, SAGE_LOCAL, and SAGE_VENV. unset SAGE_VENV if [ -x "${SELF}-config" ]; then # optional sage-config console script, installed by sage_conf export SAGE_ROOT=$("${SELF}-config" SAGE_ROOT) export SAGE_LOCAL=$("${SELF}-config" SAGE_LOCAL) fi if [ -f "${SELF}-src-env-config" ]; then # Not installed script, present only in src/bin/ SAGE_SRC_ENV_CONFIG=1 . "${SELF}-src-env-config" >&2 fi if [ -z "$SAGE_VENV" -a -x "${SELF}-venv-config" ]; then # installed by setup.py export SAGE_VENV=$("${SELF}-venv-config" SAGE_VENV) fi if [ -f "${SELF}-env-config" ]; then # As of Issue #22731, sage-env-config is optional. . "${SELF}-env-config" >&2 fi ##################################################################### # Special options to be processed without sage-env ##################################################################### # Check for '--nodotsage' before sourcing sage-env; otherwise sage-env # will already have set some environment variables with the old # setting for DOT_SAGE. if [ "$1" = '--nodotsage' ]; then export DOT_SAGE=`mktemp -d ${TMPDIR:-/tmp}/dotsageXXXXXX` shift command "${SELF}" "$@" status=$? rm -rf "$DOT_SAGE" exit $status fi # build_sage, sage -b, sage -br, etc. could also be moved to # build/bin/sage-site. See #29111; but OTOH #34627. build_sage() { ( cd "$SAGE_ROOT" && make sagelib-no-deps ) || exit $? } # Check for '-i' etc. before sourcing sage-env: running "make" # should be run outside of the Sage shell. if [ "$1" = '-f' ]; then # -f is an alias for -i -f set -- -i "$@" fi if [ "$1" = '-i' ]; then if [ -z "$2" ]; then PACKAGE="the package" else PACKAGE=$2 fi echo "Sorry, this binary distribution does not support installing sage packages." echo "If $PACKAGE is available from pypi you may install it by running" echo " %pip install $PACKAGE" echo "from the sage prompt." exit 1 fi ##################################################################### # Report information about the Sage environment ##################################################################### if [ "$1" = '-dumpversion' -o "$1" = '--dumpversion' ]; then sage_version exit 0 fi if [ "$1" = '-v' -o "$1" = '-version' -o "$1" = '--version' ]; then sage_version -v exit 0 fi if [ "$1" = '-root' -o "$1" = '--root' ]; then echo "$SAGE_ROOT" exit 0 fi ##################################################################### # Source sage-env ($SELF is the name of this "sage" script, so we can just # append -env to that). We redirect stdout to stderr, which is safer # for scripts. ##################################################################### if [ -f "${SELF}-env" ]; then . "${SELF}-env" >&2 if [ $? -ne 0 ]; then echo >&2 "Error setting environment variables by sourcing '${SELF}-env';" echo >&2 "possibly contact sage-devel (see http://groups.google.com/group/sage-devel)." exit 1 fi fi if [ -f "${SELF}-src-env-config.in" ]; then # The sage script is being run out of SAGE_ROOT/src/bin. # In this case, put this directory in the front of the PATH. export PATH="$SAGE_SRC/bin:$PATH" fi if [ -z "$DOT_SAGE" ]; then export DOT_SAGE="$HOME/.sage" fi ##################################################################### # Special environment variables used for the macOS app to prevent # writing into the application bundle and breaking the signature. # and to block warnings about using "if x is 1" and to find the # Jupyter kernel. ##################################################################### export PYTHONPYCACHEPREFIX="$DOT_SAGE/pycache" export PIP_CONFIG_FILE="$SAGE_SYMLINK/Resources/pip.conf" export PYTHONWARNINGS=ignore if ! [ -e /usr/local/share/jupyter/kernels/SageMath-"$SAGE_VERSION"/kernel.json ]; then export JUPYTER_PATH=$SAGE_SYMLINK/Resources/jupyter fi ##################################################################### # Helper functions ##################################################################### # Prepare for running Sage, either interactively or non-interactively. sage_setup() { # Check that we're not in a source tarball which hasn't been built yet (#13561). if [ "$SAGE_SRC_ENV_CONFIG" = 1 ] && [ ! -z "$SAGE_VENV" ] && [ ! -x "$SAGE_VENV/bin/sage" ]; then echo >&2 '************************************************************************' echo >&2 'It seems that you are attempting to run Sage from an unpacked source' echo >&2 'tarball, but you have not compiled it yet (or maybe the build has not' echo >&2 'finished). You should run `make` in the SAGE_ROOT directory first.' echo >&2 'If you did not intend to build Sage from source, you should download' echo >&2 'a binary tarball instead. Read README.txt for more information.' echo >&2 '************************************************************************' exit 1 fi if [ ! -d "$IPYTHONDIR" ]; then # make sure that $DOT_SAGE exists so that ipython will happily # create its config directories there. If DOT_SAGE doesn't # exist, ipython complains. mkdir -p -m 700 "$DOT_SAGE" fi sage-cleaner &>/dev/null & } # Start an interactive Sage session, this function never returns. interactive_sage() { sage_setup exec sage-ipython "$@" -i } ##################################################################### # sage --advanced ##################################################################### usage_advanced() { sage_version -v #### 1.......................26..................................................78 #### |.....................--.|...................................................| echo if command -v sage-ipython &>/dev/null; then echo "Running Sage, the most common options:" echo echo " file.[sage|py|spyx] -- run given .sage, .py or .spyx file" echo " -c cmd -- evaluate cmd as sage code. For example," echo " \"sage -c 'print(factor(35))'\" will" echo " print \"5 * 7\"." echo echo "Running Sage, other options:" echo echo " --preparse file.sage -- preparse \"file.sage\", and produce" echo " the corresponding Python file" echo " \"file.sage.py\"" echo " -q -- quiet; start with no banner" echo " --min -- do not populate global namespace" echo " (must be first option)" echo " --nodotsage -- run Sage without using the user's" echo " .sage directory: create and use a temporary" echo " .sage directory instead." echo " --gthread, --qthread, --q4thread, --wthread, --pylab" echo " -- pass the option through to IPython" echo " --simple-prompt -- pass the option through to IPython: use" echo " this option with sage-shell mode in emacs" echo " --gdb -- run Sage under the control of gdb" echo " --lldb -- run Sage under the control of lldb" else echo "Running Sage:" echo " (not installed currently, " echo " to install, run sage --pip install sagemath-repl)" fi echo echo "Running external programs:" echo echo " --cython [...] -- run Cython with the given arguments" command -v cython &>/dev/null || \ echo " (not installed, run sage --pip install cython)" echo " --ecl [...], --lisp [...] -- run Sage's copy of ECL (Embeddable" echo " Common Lisp) with the given arguments" echo " --gap [...] -- run Sage's Gap with the given arguments" echo " --gap3 [...] -- run Sage's Gap3 with the given arguments" command -v gap3 &>/dev/null || \ echo " (not installed currently, run sage -i gap3)" echo " --git [...] -- run Sage's Git with the given arguments" echo " --gp [...] -- run Sage's PARI/GP calculator with the" echo " given arguments" echo " --ipython [...], --ipython3 [...]" echo " -- run Sage's IPython using the default" echo " environment (not Sage), passing additional" echo " additional options to IPython" echo " --jupyter [...] -- run Sage's Jupyter with given arguments" echo " --kash [...] -- run Sage's Kash with the given arguments" command -v kash &>/dev/null || \ echo " (not installed currently, run sage -i kash)" echo " --M2 [...] -- run Sage's Macaulay2 with the given arguments" command -v M2 &>/dev/null || \ echo " (not installed currently, run sage -i macaulay2)" echo " --maxima [...] -- run Sage's Maxima with the given arguments" echo " --mwrank [...] -- run Sage's mwrank with the given arguments" echo " --pip [...] -- invoke pip, the Python package manager" echo " --polymake [...] -- run Sage's Polymake with given arguments" command -v polymake &>/dev/null || \ echo " (not installed currently, run sage -i polymake)" echo " --python [...], --python3 [...]" echo " -- run the Python 3 interpreter" echo " -R [...] -- run Sage's R with the given arguments" echo " --singular [...] -- run Sage's singular with the given arguments" echo " --sqlite3 [...] -- run Sage's sqlite3 with given arguments" echo echo "Running the notebook:" echo echo " -n [...], --notebook=[...]" echo " -- start the notebook; valid options include" echo " 'default', 'jupyter', 'jupyterlab', and 'export'." echo " Current default is 'jupyter'." echo " Run \"sage --notebook --help\" for more details." echo #### 1.......................26..................................................78 #### |.....................--.|...................................................| echo echo "Some developer utilities:" echo if [ -n "$SAGE_SRC" -a -d "$SAGE_SRC" ]; then echo " --grep [options] <string>" echo " -- regular expression search through the Sage" echo " library for \"string\". Any options will" echo " get passed to the \"grep\" command." echo " --grepdoc [options] <string>" echo " -- regular expression search through the" echo " Sage documentation for \"string\"." echo " --search_src ... -- same as --grep" echo " --search_doc ... -- same as --grepdoc" fi echo " --sh [...] -- run a shell with Sage environment variables" echo " as they are set in the runtime of Sage" echo " --cleaner -- run the Sage cleaner. This cleans up after Sage," echo " removing temporary directories and spawned processes." echo " (This gets run by Sage automatically, so it is usually" echo " not necessary to run it separately.)" #### 1.......................26..................................................78 #### |.....................--.|...................................................| echo "File conversion:" echo echo " --rst2ipynb [...] -- Generates Jupyter notebook (.ipynb) from standalone" echo " reStructuredText source." command -v rst2ipynb &>/dev/null || \ echo " (not installed currently, run sage -i rst2ipynb)" echo " --ipynb2rst [...] -- Generates a reStructuredText source file from" echo " a Jupyter notebook (.ipynb)." echo " --sws2rst <sws doc> -- Generates a reStructuredText source file from" echo " a Sage worksheet (.sws) document." command -v sage-sws2rst >&/dev/null || \ echo " (not installed currently, run sage -i sage_sws2rst)" echo #### 1.......................26..................................................78 #### |.....................--.|...................................................| echo "Getting help:" echo echo " -v, --version -- display Sage version information" echo " --dumpversion -- print brief Sage version" echo " -h, -?, --help -- print a short help message" echo " --advanced -- list all command line options" if [ -d "$SAGE_ROOT" ]; then exec "$SAGE_ROOT/build/bin/sage-site" "--advanced" fi echo exit 0 } if [ $# -gt 0 ]; then if [ "$1" = '-h' -o "$1" = '-?' -o "$1" = '-help' -o "$1" = '--help' ]; then usage fi if [ "$1" = "-advanced" -o "$1" = "--advanced" ]; then usage_advanced fi fi ##################################################################### # Running Sage ##################################################################### if [ "$1" = '-min' -o "$1" = '--min' ]; then shift export SAGE_IMPORTALL=no fi if [ "$1" = '-q' ]; then shift export SAGE_BANNER=no fi if [ $# -eq 0 ]; then interactive_sage fi ##################################################################### # Other basic options ##################################################################### if [ "$1" = '-c' ]; then shift sage_setup unset TERM # See Issue #12263 exec sage-eval "$@" fi if [ "$1" = '-preparse' -o "$1" = "--preparse" ]; then shift exec sage-preparse "$@" fi if [ "$1" = '-cleaner' -o "$1" = '--cleaner' ]; then exec sage-cleaner fi ##################################################################### # Run Sage's versions of Python, pip, IPython, Jupyter. ##################################################################### if [ "$1" = '-pip' -o "$1" = '--pip' -o "$1" = "--pip3" ]; then shift exec python3 -m pip --disable-pip-version-check "$@" fi if [ "$1" = '-python' -o "$1" = '--python' -o "$1" = '-python3' -o "$1" = '--python3' ]; then shift exec python3 "$@" fi if [ "$1" = '-ipython' -o "$1" = '--ipython' -o "$1" = '-ipython3' -o "$1" = '--ipython3' ]; then shift exec ipython3 "$@" fi if [ "$1" = '-jupyter' -o "$1" = '--jupyter' ]; then shift exec jupyter "$@" fi ##################################################################### # Run Sage's versions of its component packages ##################################################################### if [ "$1" = "-cython" -o "$1" = '--cython' -o "$1" = '-pyrex' -o "$1" = "--pyrex" ]; then shift exec cython "$@" fi if [ "$1" = '-gap' -o "$1" = '--gap' ]; then shift # Use "-A" to avoid warnings about missing packages. The gap # interface and libgap within sage both already do this. exec gap -A "$@" fi if [ "$1" = '-gap3' -o "$1" = '--gap3' ]; then shift exec gap3 "$@" fi if [ "$1" = '-gp' -o "$1" = '--gp' ]; then shift exec gp "$@" fi if [ "$1" = '-polymake' -o "$1" = '--polymake' ]; then shift exec polymake "$@" fi if [ "$1" = '-singular' -o "$1" = '--singular' ]; then shift exec Singular "$@" fi if [ "$1" = '-sqlite3' -o "$1" = '--sqlite3' ]; then shift exec sqlite3 "$@" fi if [ "$1" = '-ecl' -o "$1" = '--ecl' ]; then shift exec ecl "$@" fi if [ "$1" = '-lisp' -o "$1" = '--lisp' ]; then shift exec ecl "$@" fi if [ "$1" = '-kash' -o "$1" = '--kash' ]; then shift exec kash "$@" fi if [ "$1" = '-maxima' -o "$1" = '--maxima' ]; then shift maxima_cmd=$(sage-config MAXIMA 2>/dev/null) if [ -z "${maxima_cmd}" ]; then maxima_cmd="maxima" fi exec $maxima_cmd "$@" fi if [ "$1" = '-mwrank' -o "$1" = '--mwrank' ]; then shift exec mwrank "$@" fi if [ "$1" = '-M2' -o "$1" = '--M2' ]; then shift exec M2 "$@" fi if [ "$1" = '-R' -o "$1" = '--R' ]; then shift exec R "$@" fi if [ "$1" = '-git' -o "$1" = '--git' ]; then shift exec git "$@" fi ##################################################################### # sage --sh and sage --buildsh ##################################################################### if [ "$1" = '-sh' -o "$1" = '--sh' -o "$1" = '-buildsh' -o "$1" = '--buildsh' ]; then # AUTHORS: # - Carl Witty and William Stein: initial version # - Craig Citro: add options for not loading profile # - Martin Albrecht: fix zshell prompt (#11866) # - John Palmieri: shorten the prompts, and don't print messages if # there are more arguments to 'sage -sh' (#11790) if [ -z "$SAGE_SHPROMPT_PREFIX" ]; then SAGE_SHPROMPT_PREFIX=sage-sh fi if [ "$1" = '-buildsh' -o "$1" = '--buildsh' ]; then if [ ! -r "$SAGE_ROOT"/build/bin/sage-build-env-config ]; then echo "error: '$SAGE_ROOT' does not contain build/bin/sage-build-env-config. Run configure first." exit 1 fi . "$SAGE_ROOT"/build/bin/sage-build-env-config || (echo "error: Error sourcing $SAGE_ROOT/build/bin/sage-build-env-config"; exit 1) . "$SAGE_ROOT"/build/bin/sage-build-env || (echo "error: Error sourcing $SAGE_ROOT/build/bin/sage-build-env"; exit 1) export SAGE_SHPROMPT_PREFIX=sage-buildsh # We export it so that recursive invocation of 'sage-sh' from a sage-buildsh shows the sage-buildsh prompt; # this makes sense because all environment variables set in build/bin/sage-build-env-config # and build/bin/sage-build-env are exported. fi shift # If $SHELL is unset, default to bash if [ -z "$SHELL" ]; then export SHELL=bash fi # We must start a new shell with no .profile or .bashrc files # processed, so that we know our path is correct SHELL_NAME=`basename "$SHELL"` # Check for SAGE_SHPROMPT. If defined, use for the prompt. If # not, check for already-defined $PS1, and if defined use that. # $PS1 should only be available if it is defined in # $DOT_SAGE/sagerc. if [ -n "$SAGE_SHPROMPT" ]; then oldPS1=$SAGE_SHPROMPT elif [ -n "$PS1" ]; then oldPS1=$PS1 fi # Set the default prompt. If available, use reverse video to # highlight the string "(sage-sh)". if tput rev &>/dev/null; then color_prompt=yes fi case "$SHELL_NAME" in bash) SHELL_OPTS="--norc" if [ "$color_prompt" = yes ]; then PS1="\[$(tput rev)\]($SAGE_SHPROMPT_PREFIX)\[$(tput sgr0)\] \u@\h:\W\$ " else PS1="($SAGE_SHPROMPT_PREFIX) \u@\h:\w\$ " fi export PS1 ;; csh) # csh doesn't seem to allow the specification of a different # .cshrc file, and the prompt can only be set in this file, so # don't bother changing the prompt. SHELL_OPTS="-f" ;; ksh) SHELL_OPTS="-p" if [ "$color_prompt" = yes ] ; then PS1="$(tput rev)($SAGE_SHPROMPT_PREFIX)$(tput sgr0) $USER@`hostname -s`:\${PWD##*/}$ " else PS1="($SAGE_SHPROMPT_PREFIX) $USER@`hostname -s`:\${PWD##*/}$ " fi export PS1 ;; sh) # We don't really know which shell "sh" is (it could be # bash, but this is not guaranteed), so we don't set # SHELL_OPTS. if [ "$color_prompt" = yes ] ; then PS1="$(tput rev)($SAGE_SHPROMPT_PREFIX)$(tput sgr0) $USER@`hostname -s`:\${PWD##*/}$ " else PS1="($SAGE_SHPROMPT_PREFIX) $USER@`hostname -s`:\${PWD}$ " fi export PS1 ;; tcsh) # tcsh doesn't seem to allow the specification of a different # .tcshrc file, and the prompt can only be set in this file, so # don't bother changing the prompt. SHELL_OPTS="-f" ;; zsh) PS1="%S($SAGE_SHPROMPT_PREFIX)%s %n@%m:%~$ " # In zsh, the system /etc/zshenv is *always* run, # and this may change the path (like on OSX), so we'll # create a temporary .zshenv to reset the path ZDOTDIR=$DOT_SAGE && export ZDOTDIR cat >"$ZDOTDIR/.zshenv" <<EOF PATH="$PATH" && export PATH EOF SHELL_OPTS=" -d" export PS1 ;; *) export PS1='($SAGE_SHPROMPT_PREFIX) $ ' ;; esac if [ -n "$oldPS1" ]; then PS1="$oldPS1" export PS1 fi if [ $# -eq 0 ]; then # No arguments, so print informative message... echo >&2 echo >&2 "Starting subshell with Sage environment variables set. Don't forget" echo >&2 "to exit when you are done. Beware:" echo >&2 " * Do not do anything with other copies of Sage on your system." echo >&2 " * Do not use this for installing Sage packages using \"sage -i\" or for" echo >&2 " running \"make\" at Sage's root directory. These should be done" echo >&2 " outside the Sage shell." echo >&2 if [ -n "$SHELL_OPTS" ]; then echo >&2 "Bypassing shell configuration files..." echo >&2 fi echo >&2 "Note: SAGE_ROOT=$SAGE_ROOT" "$SHELL" $SHELL_OPTS "$@" status=$? echo "Exited Sage subshell." 1>&2 else exec "$SHELL" $SHELL_OPTS "$@" # If 'exec' returns, an error occurred: status=$? echo >&2 "Fatal error: 'exec \"$SHELL\" \"$@\"' failed!" fi exit $status fi ##################################################################### # File conversion ##################################################################### if [ "$1" = '-rst2ipynb' -o "$1" = '--rst2ipynb' ]; then shift rst2ipynb --kernel=sagemath "$@" status="${?}" if [ "${status}" -eq "127" ] ; then echo 'rst2ipynb is not installed, please run "sage -i rst2ipynb"' ; fi exit ${status} fi if [ "$1" = '-ipynb2rst' -o "$1" = '--ipynb2rst' ]; then shift exec sage-ipynb2rst "$@" fi if [ "$1" = '-sws2rst' -o "$1" = '--sws2rst' ]; then shift exec sage-sws2rst "$@" fi ##################################################################### # The notebook, grep, building Sage, testing Sage ##################################################################### if [[ "$1" =~ ^--notebook=.* || "$1" =~ ^-n=.* || "$1" =~ ^-notebook=.* ]] ; then sage-cleaner &>/dev/null & exec sage-notebook "$@" fi if [ "$1" = "-notebook" -o "$1" = '--notebook' -o "$1" = '-n' ]; then sage-cleaner &>/dev/null & exec sage-notebook "$@" fi if [ "$1" = "-bn" -o "$1" = "--build-and-notebook" ]; then shift build_sage sage-cleaner &>/dev/null & exec sage-notebook --notebook=default "$@" fi if [ -n "$SAGE_SRC" -a -d "$SAGE_SRC" ]; then # Source inspection facilities, supported on sage-the-distribution and on distributions # that package the Sage sources. if [ "$1" = '-grep' -o "$1" = "--grep" -o "$1" = "-search_src" -o "$1" = "--search_src" ]; then shift sage-grep "$@" exit 0 fi if [ "$1" = '-grepdoc' -o "$1" = "--grepdoc" -o "$1" = "-search_doc" -o "$1" = "--search_doc" ]; then shift sage-grepdoc "$@" exit 0 fi fi if [ "$1" = '-r' ]; then shift interactive_sage fi exec-runtests() { sage_setup export PYTHONIOENCODING="utf-8" # Fix encoding for doctests exec sage-runtests "$@" } if [ "$1" = '-t' -o "$1" = '-tp' ]; then if [ "$1" = '-tp' ]; then shift exec-runtests -p "$@" else shift exec-runtests "$@" fi fi if [ "$1" = '-tnew' ]; then shift exec-runtests --new "$@" fi if [ "$1" = '-testall' -o "$1" = "--testall" ]; then shift exec-runtests -a "$@" fi if [ "$1" = '-fixdoctests' -o "$1" = '--fixdoctests' ]; then shift exec sage-fixdoctests "$@" fi if [ "$1" = "-coverage" -o "$1" = "--coverage" ]; then shift exec sage-coverage "$@" fi if [ "$1" = "-coverageall" -o "$1" = "--coverageall" ]; then shift exec sage-coverage --all "$@" fi 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" = '-fixdistributions' -o "$1" = '--fixdistributions' ]; then shift exec sage-python -m sage.misc.package_dir "$@" fi if [ "$1" = '-tox' -o "$1" = '--tox' ]; then shift if [ -n "$SAGE_SRC" -a -f "$SAGE_SRC/tox.ini" ]; then if command -v tox >/dev/null ; then exec tox -c "$SAGE_SRC" "$@" else echo "Run 'sage -i tox' to install" exit 1 fi else echo >&2 "error: Sage source directory or tox.ini not available" exit 1 fi fi if [ "$1" = '-pytest' -o "$1" = '--pytest' ]; then shift if [ -n "$SAGE_SRC" -a -f "$SAGE_SRC/tox.ini" ]; then if command -v pytest >/dev/null ; then # If no non-option arguments are given, provide one for a in $*; do case $a in -*) ;; *) exec pytest --rootdir="$SAGE_SRC" --doctest "$@" esac done exec pytest --rootdir="$SAGE_SRC" --doctest "$@" "$SAGE_SRC" else echo "Run 'sage -i pytest' to install" exit 1 fi else echo >&2 "error: Sage source directory or tox.ini not available" exit 1 fi fi ##################################################################### # Building the Sage documentation ##################################################################### if [ "$1" = "-docbuild" -o "$1" = "--docbuild" ]; then shift # Issue #30002: ensure an English locale so that it is possible to # scrape out warnings by pattern matching. export LANG=C export LANGUAGE=C # See #30351: bugs in macOS implementations of openblas/libgopm can cause # docbuild to hang if multiple OpenMP threads are allowed. if [ `uname` = 'Darwin' ]; then export OMP_NUM_THREADS=1 fi # Issue #33650: Make sure that user configuration of Jupyter does not # shadow our sagemath kernel when jupyter-sphinx is invoked export JUPYTER_CONFIG_DIR=/doesnotexist export JUPYTER_CONFIG_PATH=/doesnotexist export JUPYTER_DATA_DIR=/doesnotexist export JUPYTER_PATH=/doesnotexist # Redirect stdin from /dev/null. This helps with running TeX which # tends to ask interactive questions if something goes wrong. These # cause the build to hang. If stdin is /dev/null, TeX just aborts. exec sage-python -m sage_docbuild "$@" </dev/null fi ##################################################################### # Creating and handling Sage distributions ##################################################################### # The following could be moved to build/bin/sage-site. See #29111. if [ "$1" = '--location' ]; then # Ignore exit 0 fi if [ "$1" = '-installed' -o "$1" = "--installed" ]; then shift exec sage-list-packages all --installed-only $@ fi if [ "$1" = '-sdist' -o "$1" = "--sdist" ]; then shift exec sage-sdist "$@" fi ##################################################################### # Debugging tools ##################################################################### if [ "$1" = '-gdb' -o "$1" = "--gdb" ]; then shift sage_setup if [ "$SAGE_DEBUG" != "yes" ]; then gdb --eval-command "run" \ -args python "${SELF}-ipython" "$@" -i else sage_dir=$(sage-python -c 'import os, sage; print(os.path.dirname(sage.__file__))') cygdb "$sage_dir" "$SAGE_SRC/sage" \ -- --eval-command "run" \ -args python "${SELF}-ipython" "$@" -i fi exit $? fi if [ "$1" = '-lldb' -o "$1" = "--lldb" ]; then shift sage_setup lldb --one-line "process launch --tty" --one-line "cont" -- python "${SELF}-ipython" "$@" fi if [ "$1" = '-valgrind' -o "$1" = "--valgrind" -o "$1" = '-memcheck' -o "$1" = "--memcheck" ]; then shift sage_setup exec sage-valgrind "$@" fi if [ "$1" = '-massif' -o "$1" = "--massif" ]; then shift sage_setup exec sage-massif "$@" fi if [ "$1" = '-cachegrind' -o "$1" = "--cachegrind" ]; then shift sage_setup exec sage-cachegrind "$@" fi if [ "$1" = '-callgrind' -o "$1" = "--callgrind" ]; then shift sage_setup exec sage-callgrind "$@" fi if [ "$1" = '-omega' -o "$1" = "--omega" ]; then shift sage_setup exec sage-omega "$@" fi if [ "$1" = '-gthread' -o "$1" = '-qthread' -o "$1" = '-q4thread' -o "$1" = '-wthread' -o "$1" = '-pylab' -o "$1" = '--simple-prompt' -o "$1" = '-simple-prompt' ]; then # Intentionally no "shift" here interactive_sage "$@" fi case "$1" in -*) # Delegate further option handling to the non-installed sage-site script. # (These options become unavailable if the directory $SAGE_ROOT is removed.) if [ -d "$SAGE_ROOT" ]; then exec "$SAGE_ROOT/build/bin/sage-site" "$@" # fallthrough if there is no sage-site script fi echo "Error: unknown option: $1" exit 1 ;; esac if [ $# -ge 1 ]; then T=`echo "$1" | sed -e "s/.*\.//"` if [ "$T" = "spkg" ]; then echo "Error: Installing old-style SPKGs is no longer supported." exit 1 fi sage_setup unset TERM # See Issue #12263 # sage-run rejects all command line options as the first argument. exec sage-run "$@" fi