diff --git a/VERSION.txt b/VERSION.txt index 0f3dc25e446..386a587f11e 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -Sage version 6.2.beta1, released 2014-02-07 +Sage version 6.2.beta2, released 2014-02-15 diff --git a/build/deps b/build/deps index b27ddb3ff9e..3809e9555d2 100644 --- a/build/deps +++ b/build/deps @@ -224,9 +224,16 @@ $(INST)/$(NTL): $(INST)/$(MPIR) $(INST)/$(GF2X) $(INST)/$(FPLLL): $(INST)/$(MPIR) $(INST)/$(MPFR) +$(PIPE) "$(SAGE_SPKG) $(FPLLL) 2>&1" "tee -a $(SAGE_LOGS)/$(FPLLL).log" -$(INST)/$(PARI): $(INST)/$(READLINE) $(INST)/$(MPIR) +$(INST)/$(PARI): $(INST)/$(READLINE) $(INST)/$(MPIR) \ + $(INST)/$(PARI_GALDATA) $(INST)/$(PARI_SEADATA_SMALL) +$(PIPE) "$(SAGE_SPKG) $(PARI) 2>&1" "tee -a $(SAGE_LOGS)/$(PARI).log" +$(INST)/$(PARI_GALDATA): + +$(PIPE) "$(SAGE_SPKG) $(PARI_GALDATA) 2>&1" "tee -a $(SAGE_LOGS)/$(PARI_GALDATA).log" + +$(INST)/$(PARI_SEADATA_SMALL): + +$(PIPE) "$(SAGE_SPKG) $(PARI_SEADATA_SMALL) 2>&1" "tee -a $(SAGE_LOGS)/$(PARI_SEADATA_SMALL).log" + $(INST)/$(POLYBORI): $(INST)/$(PYTHON) $(INST)/$(IPYTHON) \ $(INST)/$(SCONS) $(INST)/$(BOOST_CROPPED) \ $(INST)/$(M4RI) $(INST)/$(GD) diff --git a/build/install b/build/install index f0aba7e3ae3..05d0b575b07 100755 --- a/build/install +++ b/build/install @@ -408,6 +408,8 @@ NTL=`newest_version ntl` NUMPY=`newest_version numpy` PALP=`newest_version palp` PARI=`newest_version pari` +PARI_GALDATA=`newest_version pari_galdata` +PARI_SEADATA_SMALL=`newest_version pari_seadata_small` PATCH=`newest_version patch` PEXPECT=`newest_version pexpect` PILLOW=`newest_version pillow` diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 6f3ab7ee9de..641d5ea226f 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=e0f0951560918d79141995852f276ac3e99a42f4 -md5=33b6cac80bafecc0ad880fd68cf258e6 -cksum=3483617699 +sha1=dc1ef3079014c19d7af48bf628a275b3dbcf2e11 +md5=1ab9d75a4babc66433730e4d95c24843 +cksum=4250141818 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index b4de3947675..48082f72f08 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -11 +12 diff --git a/build/pkgs/git/.hgignore b/build/pkgs/git/.hgignore deleted file mode 100644 index 85de9cf9334..00000000000 --- a/build/pkgs/git/.hgignore +++ /dev/null @@ -1 +0,0 @@ -src diff --git a/build/pkgs/ncurses/.hgignore b/build/pkgs/ncurses/.hgignore deleted file mode 100644 index 85de9cf9334..00000000000 --- a/build/pkgs/ncurses/.hgignore +++ /dev/null @@ -1 +0,0 @@ -src diff --git a/build/pkgs/pari/SPKG.txt b/build/pkgs/pari/SPKG.txt index df136592543..d06562afa18 100644 --- a/build/pkgs/pari/SPKG.txt +++ b/build/pkgs/pari/SPKG.txt @@ -14,8 +14,6 @@ Originally developed by Henri Cohen and his co-workers (Université Bordeaux I, France), PARI is now under the GPL and maintained by Karim Belabas with the help of many volunteer contributors. -Website: http://pari.math.u-bordeaux.fr/ - == License == GPL version 2+ @@ -27,42 +25,13 @@ GPL version 2+ * Jeroen Demeyer == Upstream Contact == - * Karim Belabas, http://www.math.u-bordeaux.fr/~belabas/ - * pari-dev@list.cr.yp.to + * http://pari.math.u-bordeaux.fr/ == Dependencies == * MPIR (in place of GMP) * Readline - * Termcap * GNU patch (shipped with Sage) == Special Update/Build Instructions == See patches/README.txt for a list of patches. - -Most of the building of a new version of the PARI spkg is automated -in the script spkg-src. Normally, the following should work. In case -of doubt, have a look at the file spkg-src. - - 0) Edit the line "git checkout pari-2.5.5". - - 1) ./spkg-src - This will download the git sources to the directory parigit/ - and will also download galdata.tgz and ellsea-small.tgz. - Then, a src/ directory will be created. - WARNING: This script will remove any existing src/ directory. - NOTES: The script ./spkg-src will actually compile PARI/GP, but - the compiled files are not used for the spkg. We only need a few - files, in particular those created by bison. - Running spkg-src should be done on a reasonably standard machine - on which PARI/GP compiles out of the box. - - 2) Check that everything is okay somehow. In particular, look at - patches/README.txt - - 3) rm -rf parigit - The directory parigit contains a git repository for the PARI sources. - When making this package just for testing, you can keep the parigit - directory. However, it should not be there in a final version. - - 4) cd ..; sage --spkg pari-version-name diff --git a/build/pkgs/pari/checksums.ini b/build/pkgs/pari/checksums.ini index 4abbeb60cef..1dea556836e 100644 --- a/build/pkgs/pari/checksums.ini +++ b/build/pkgs/pari/checksums.ini @@ -1,4 +1,4 @@ tarball=pari-VERSION.tar.bz2 -sha1=b58fe67c0c05416ae7de48bb990350056cc66a7d -md5=3cd63f5ca9f7b37fbcb68e44c4c1f1b0 -cksum=2913087451 +sha1=3f0838940fcf1cb7748979fe16e4b5cab0d19080 +md5=4c54710f7e2d4de7b8781edb9d604c60 +cksum=2949888924 diff --git a/build/pkgs/pari/package-version.txt b/build/pkgs/pari/package-version.txt index fffdb6b0fe7..f31d42e7373 100644 --- a/build/pkgs/pari/package-version.txt +++ b/build/pkgs/pari/package-version.txt @@ -1 +1 @@ -2.5.5.p2 +2.5.5b.p1 diff --git a/build/pkgs/pari/patches/README.txt b/build/pkgs/pari/patches/README.txt index 92ec68be9a9..85c543c24c0 100644 --- a/build/pkgs/pari/patches/README.txt +++ b/build/pkgs/pari/patches/README.txt @@ -38,14 +38,6 @@ Patches to configuration files: - http://pari.math.u-bordeaux.fr/archives/pari-dev-1301/msg00000.html C files: -* src/kernel/gmp/mp.c (Leif Leonhardy): - Do not override GMP's memory functions. - In addition, let PARI use "GMP internals" (access members of GMP - structures directly) *conditionally*. (We *don't* disable that by - default, since at least currently this is compatible with both GMP - *and* MPIR. To disable the use, add "-DPARI_DONT_USE_GMP_INTERNALS" - to CFLAGS. This is a trivial patch to mp.c only; see also the comment - there.): * GCC_PR49330.patch (Jeroen Demeyer): in pari_init_functions(), reorder code to work around a GCC bug concerning pointer arithmetic: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49330 diff --git a/build/pkgs/pari/patches/mp.c.patch b/build/pkgs/pari/patches/mp.c.patch deleted file mode 100644 index c731d6fd9b5..00000000000 --- a/build/pkgs/pari/patches/mp.c.patch +++ /dev/null @@ -1,50 +0,0 @@ -Index: src/kernel/gmp/mp.c -=================================================================== ---- a/src/kernel/gmp/mp.c (revision 13151) -+++ b/src/kernel/gmp/mp.c (working copy) -@@ -45,18 +45,8 @@ - /*We need PARI invmod renamed to invmod_pari*/ - #define INVMOD_PARI - --static void *gmp_realloc(void *ptr, size_t old_size, size_t new_size) { -- (void)old_size; return (void *) pari_realloc(ptr,new_size); --} -- --static void gmp_free(void *ptr, size_t old_size){ -- (void)old_size; pari_free(ptr); --} -- - int pari_kernel_init(void) - { -- /* Use pari_malloc instead of malloc */ -- mp_set_memory_functions((void *(*)(size_t)) pari_malloc, gmp_realloc, gmp_free); - return 0; - } - -@@ -1036,7 +1026,16 @@ - - /* EXACT INTEGER DIVISION */ - --#if 1 /* use undocumented GMP interface */ -+#ifndef PARI_DONT_USE_GMP_INTERNALS /* Use GMP/MPIR internals */ -+/* -+ * Note: This refers to directly accessing ("private") members of -+ * GMP's mpz_t / __mpz_struct types, which are defined in gmp.h. -+ * This is in fact (at least) compatible with both -+ * - GMP (<= 5.0.1) *and* -+ * - MPIR (<= 2.1.2), -+ * so we *don't* disable the use by default. -+ */ -+ - static void - GEN2mpz(mpz_t X, GEN x) - { -@@ -1095,7 +1094,7 @@ - mpz2GEN(z, Z); return z; - } - } --#else -+#else /* Don't use GMP/MPIR internals */ - /* assume y != 0 and the division is exact */ - GEN - diviuexact(GEN x, ulong y) diff --git a/build/pkgs/pari/spkg-src b/build/pkgs/pari/spkg-src deleted file mode 100755 index 759d997872a..00000000000 --- a/build/pkgs/pari/spkg-src +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env bash -# -# Script to prepare a PARI spkg for Sage. This script is only for the -# package maintainer, not for building PARI during a Sage install. -# WARNING: This script will delete/overwrite files in this directory -# and its subdirectories! -# -# HOW TO MAKE THE SPKG: -# 1) ./spkg-src -# 2) rm -rf parigit (For final distribution, not necessary for testing) -# 3) cd ..; sage --spkg pari-2.5.1.whatever_the_name_of_the_package_is -# -# If something goes wrong, try rm -rf parigit and try again. -# -# This script does the following: -# * If the directory parigit/ exists, it is assumed to be a git -# repository of the PARI sources. If it does not exist, the git -# sources are automatically downloaded. In any case, a specific -# version is checked out. -# * If the file parigit/galdata.tgz does not exist, it is downloaded. -# * The same for the file parigit/seadata-small.tgz -# * PARI is configured and built in the parigit directory. The built -# executables are not needed, but some files generated in the -# process (using bison for example) are needed. -# * The necessary files are copied from parigit/ to src/ using a -# mechanism very similar to "make snapshot" from PARI. -# * The files parigit/galdata.tgz and parigit/seadata-small.tgz are -# extracted. -# -# AUTHOR: -# -# - Jeroen Demeyer (July 2010): initial version -# -# - Jeroen Demeyer (February 2012): use git instead of svn, upgrade to PARI 2.5.1 - -# Automatically exit on errors -set -e - - -# Sanity check: must be run from current directory -if ! [ -f spkg-src ]; then - echo >&2 "This script must be run from its own source directory!" - exit 1 -fi - - -# Clean an existing src/ directory -rm -rf src -mkdir src - - -# Download or update git sources in parigit/ -if [ -d parigit ]; then - cd parigit - git fetch -else - git clone http://pari.math.u-bordeaux.fr/git/pari.git parigit - cd parigit -fi - -# Download galdata.tgz and seadata-small.tgz -wget --timestamping http://pari.math.u-bordeaux.fr/pub/pari/packages/galdata.tgz -wget --timestamping http://pari.math.u-bordeaux.fr/pub/pari/packages/seadata-small.tgz - - -# Use the specified git version -git checkout pari-2.5.5 - - -# make pari (must run bison, etc...) but disable optimization to speed -# up compilation (the output of the compiling is not used anyway). -env CFLAGS="-O0" ./Configure -make gp doc - - -# Copy the needed files to src using a tar pipe. This is based on code -# from config/settar. -# -# Add src/desc/pari.desc to remove build-time dependency on perl -# -- Jeroen Demeyer -tar -c -T <( config/get_MANIFEST && echo src/desc/pari.desc ) | ( cd ../src && tar xv ) - -# Hardcode version number in config/version. -vcsversion=git-`git log -1 --pretty=format:%h` -sed "s/^vcsversion=$/vcsversion=$vcsversion # hardcoded by spkg-src/" ../src/config/version - - -# Extract the tgz files -for tgzfile in galdata.tgz seadata-small.tgz; do - ( cd ../src && tar xvz ) < "$tgzfile" -done - - -# We're done! -cd .. -echo "======================================================" -echo "Done downloading PARI and creating the src/ directory." -echo "If everything looks okay, proceed as follows:" -echo " rm -rf parigit" -echo " cd .." -echo -n " sage --spkg "; basename `pwd` diff --git a/build/pkgs/pari_galdata/SPKG.txt b/build/pkgs/pari_galdata/SPKG.txt new file mode 100644 index 00000000000..ea272bcbbf7 --- /dev/null +++ b/build/pkgs/pari_galdata/SPKG.txt @@ -0,0 +1,22 @@ += pari_galdata = + +== Description == + +PARI package "galdata": Needed by polgalois to compute Galois group in +degrees 8 through 11. + +== License == + +GPL version 2+ + +== SPKG Maintainers == + +* Jeroen Demeyer + +== Upstream Contact == + +http://pari.math.u-bordeaux.fr/ + +== Dependencies == + +None (package contains data files only) diff --git a/build/pkgs/pari_galdata/checksums.ini b/build/pkgs/pari_galdata/checksums.ini new file mode 100644 index 00000000000..82fe02e0371 --- /dev/null +++ b/build/pkgs/pari_galdata/checksums.ini @@ -0,0 +1,4 @@ +tarball=pari_galdata-VERSION.tar.bz2 +sha1=4ae710687cb711c49645314c28d53ab3b3a38706 +md5=b661c455bb1b2028b3b957d3bc8595de +cksum=3937576682 diff --git a/build/pkgs/pari_galdata/package-version.txt b/build/pkgs/pari_galdata/package-version.txt new file mode 100644 index 00000000000..32d157fe2be --- /dev/null +++ b/build/pkgs/pari_galdata/package-version.txt @@ -0,0 +1 @@ +20080411 diff --git a/build/pkgs/pari_galdata/spkg-install b/build/pkgs/pari_galdata/spkg-install new file mode 100755 index 00000000000..7d5fe4a9369 --- /dev/null +++ b/build/pkgs/pari_galdata/spkg-install @@ -0,0 +1,4 @@ +#!/bin/sh + +mkdir -p "$SAGE_SHARE/pari" +cd data && cp -R * "$SAGE_SHARE/pari" diff --git a/build/pkgs/pari_seadata_small/SPKG.txt b/build/pkgs/pari_seadata_small/SPKG.txt new file mode 100644 index 00000000000..d5677307eb6 --- /dev/null +++ b/build/pkgs/pari_seadata_small/SPKG.txt @@ -0,0 +1,24 @@ += pari_seadata_small = + +== Description == + +PARI package "seadata_small": Needed by ellap for large primes. This +"small" one is a much smaller version that should be suitable for +primes up to 350 bits. These polynomials were extracted from the ECHIDNA +databases and computed by David R. Kohel. + +== License == + +GPL version 2+ + +== SPKG Maintainers == + +* Jeroen Demeyer + +== Upstream Contact == + +http://pari.math.u-bordeaux.fr/ + +== Dependencies == + +None (package contains data files only) diff --git a/build/pkgs/pari_seadata_small/checksums.ini b/build/pkgs/pari_seadata_small/checksums.ini new file mode 100644 index 00000000000..efca3bbdc15 --- /dev/null +++ b/build/pkgs/pari_seadata_small/checksums.ini @@ -0,0 +1,4 @@ +tarball=pari_seadata_small-VERSION.tar.bz2 +sha1=9df70728bfae81fad4ff66a3c7f57d99bbe70732 +md5=5a9a6200e4536d2c6b4020c4313721f5 +cksum=3561726107 diff --git a/build/pkgs/pari_seadata_small/package-version.txt b/build/pkgs/pari_seadata_small/package-version.txt new file mode 100644 index 00000000000..5a0327d9bc6 --- /dev/null +++ b/build/pkgs/pari_seadata_small/package-version.txt @@ -0,0 +1 @@ +20090618 diff --git a/build/pkgs/pari_seadata_small/spkg-install b/build/pkgs/pari_seadata_small/spkg-install new file mode 100755 index 00000000000..7d5fe4a9369 --- /dev/null +++ b/build/pkgs/pari_seadata_small/spkg-install @@ -0,0 +1,4 @@ +#!/bin/sh + +mkdir -p "$SAGE_SHARE/pari" +cd data && cp -R * "$SAGE_SHARE/pari" diff --git a/build/pkgs/python/SPKG.txt b/build/pkgs/python/SPKG.txt index a7bd2f1141b..ed97d904159 100644 --- a/build/pkgs/python/SPKG.txt +++ b/build/pkgs/python/SPKG.txt @@ -75,9 +75,13 @@ http://www.python.org/community/ * inc_lib_dirs-issue_17990.patch: Only modify include and library search paths when cross-compiling. * node-issue_3871.patch: fix _PyNode_Sizeof declaration. + * tinfo.patch: make sure tinfo is correctly linked in when needed on Cygwin. == Changelog == +=== python-2.7.5.p2 (Jean-Pierre Flori, 5 January 2014) === + * Trac #15317: Make sure tinfo is correctly linked in when needed on Cygwin. + === python-2.7.5.p1 (Jean-Pierre Flori, 3 June 2013) === * Trac #14600: give patches more talkative names. * Fix hashlibfallbacks patch. diff --git a/build/pkgs/python/package-version.txt b/build/pkgs/python/package-version.txt index b41e9d7405e..6d6d941b1b9 100644 --- a/build/pkgs/python/package-version.txt +++ b/build/pkgs/python/package-version.txt @@ -1 +1 @@ -2.7.5.p1 +2.7.5.p2 diff --git a/build/pkgs/python/patches/tinfo.patch b/build/pkgs/python/patches/tinfo.patch new file mode 100644 index 00000000000..afcb916dd1e --- /dev/null +++ b/build/pkgs/python/patches/tinfo.patch @@ -0,0 +1,118 @@ +diff -druN src.orig/Lib/distutils/ccompiler.py src/Lib/distutils/ccompiler.py +--- src.orig/Lib/distutils/ccompiler.py 2014-01-05 18:57:04.783053177 +0100 ++++ src/Lib/distutils/ccompiler.py 2014-01-05 19:57:50.586433772 +0100 +@@ -842,8 +842,8 @@ + def library_filename(self, libname, lib_type='static', # or 'shared' + strip_dir=0, output_dir=''): + assert output_dir is not None +- if lib_type not in ("static", "shared", "dylib"): +- raise ValueError, "'lib_type' must be \"static\", \"shared\" or \"dylib\"" ++ if lib_type not in ("static", "shared", "dylib", "import"): ++ raise ValueError, "'lib_type' must be \"static\", \"shared\", \"dylib\" or \"import\"" + fmt = getattr(self, lib_type + "_lib_format") + ext = getattr(self, lib_type + "_lib_extension") + +diff -druN src.orig/Lib/distutils/unixccompiler.py src/Lib/distutils/unixccompiler.py +--- src.orig/Lib/distutils/unixccompiler.py 2014-01-05 18:57:04.779053224 +0100 ++++ src/Lib/distutils/unixccompiler.py 2014-01-05 20:24:44.862580174 +0100 +@@ -79,9 +79,11 @@ + static_lib_extension = ".a" + shared_lib_extension = ".so" + dylib_lib_extension = ".dylib" +- static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s" ++ import_lib_extension = ".dll.a" ++ import_lib_format = static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s" + if sys.platform == "cygwin": + exe_extension = ".exe" ++ shared_lib_extension = ".dll" + + def preprocess(self, source, + output_file=None, macros=None, include_dirs=None, +@@ -246,6 +248,7 @@ + shared_f = self.library_filename(lib, lib_type='shared') + dylib_f = self.library_filename(lib, lib_type='dylib') + static_f = self.library_filename(lib, lib_type='static') ++ import_f = self.library_filename(lib, lib_type='import') + + if sys.platform == 'darwin': + # On OSX users can specify an alternate SDK using +@@ -261,6 +264,7 @@ + + + for dir in dirs: ++ implib = os.path.join(dir, import_f) + shared = os.path.join(dir, shared_f) + dylib = os.path.join(dir, dylib_f) + static = os.path.join(dir, static_f) +@@ -277,7 +281,9 @@ + # data to go on: GCC seems to prefer the shared library, so I'm + # assuming that *all* Unix C compilers do. And of course I'm + # ignoring even GCC's "-static" option. So sue me. +- if os.path.exists(dylib): ++ if os.path.exists(implib): ++ return implib ++ elif os.path.exists(dylib): + return dylib + elif os.path.exists(shared): + return shared +@@ -286,3 +292,22 @@ + + # Oops, didn't find it in *any* of 'dirs' + return None ++ ++ def implib_to_dll(self, dirs, implib, debug=0): ++ fp = os.popen("dlltool -I %s" % implib) ++ dlltool_output = fp.readlines() ++ ret = fp.close() ++ ++ if ret is None or ret >> 8 == 0: ++ for ln in dlltool_output: ++ for dir in dirs: ++ dll = os.path.join(dir, ln.rstrip('\n')) ++ # We're second-guessing the linker here, with not much hard ++ # data to go on: GCC seems to prefer the shared library, so I'm ++ # assuming that *all* Unix C compilers do. And of course I'm ++ # ignoring even GCC's "-static" option. So sue me. ++ if os.path.exists(dll): ++ return dll ++ ++ # Oops, didn't find it in *any* of 'dirs' ++ return None +diff -druN src.orig/setup.py src/setup.py +--- src.orig/setup.py 2014-01-05 18:57:04.559055835 +0100 ++++ src/setup.py 2014-01-05 20:19:37.086365466 +0100 +@@ -702,8 +702,12 @@ + do_readline = self.compiler.find_library_file(lib_dirs, 'readline') + readline_termcap_library = "" + curses_library = "" +- # Determine if readline is already linked against curses or tinfo. ++ # Determine if readline is linked against curses or tinfo. + if do_readline and find_executable('ldd'): ++ # On Cygwin we have to find out which dll the implib point to ++ if host_platform == "cygwin" and find_executable('dlltool'): ++ do_readline = self.compiler.implib_to_dll(os.getenv('PATH').split(os.pathsep) + lib_dirs, do_readline) ++ + fp = os.popen("ldd %s" % do_readline) + ldd_output = fp.readlines() + ret = fp.close() +@@ -752,7 +756,10 @@ + + readline_libs = ['readline'] + if readline_termcap_library: +- pass # Issue 7384: Already linked against curses or tinfo. ++ if host_platform != "cygwin": ++ pass # Issue 7384: Already linked against curses or tinfo. ++ else: ++ readline_libs.append(readline_termcap_library) + elif curses_library: + readline_libs.append(curses_library) + elif self.compiler.find_library_file(lib_dirs + +@@ -1344,6 +1351,8 @@ + # _curses_panel.so must link with panelw. + panel_library = 'panelw' + curses_libs = [curses_library] ++ if readline_termcap_library == 'tinfo' and host_platform == "cygwin": ++ curses_libs.append(readline_termcap_library) + exts.append( Extension('_curses', ['_cursesmodule.c'], + libraries = curses_libs) ) + elif curses_library == 'curses' and host_platform != 'darwin': diff --git a/build/pkgs/setuptools/SPKG.txt b/build/pkgs/setuptools/SPKG.txt index 4bf3cd2372d..baadb4499c5 100644 --- a/build/pkgs/setuptools/SPKG.txt +++ b/build/pkgs/setuptools/SPKG.txt @@ -2,13 +2,12 @@ == Description == -setuptools is a collection of enhancements to the Python distutils (for Python 2.3.5 and up on most platforms; 64-bit platforms require a minimum of Python 2.4) that allow you to more easily build and distribute Python packages, especially ones that have dependencies on other packages. +setuptools is a collection of enhancements to the Python distutils (for +Python 2.6 and up) that allow you to more easily build and distribute +Python packages, especially ones that have dependencies on other packages. Website: http://pypi.python.org/pypi/setuptools/ -The present spkg is based on the fork of setuptools known as distribute. -Website: http://pypi.python.org/pypi/distribute - == License == PSF or ZPL. i.e Python Software Foundation License or Zope Public License @@ -24,7 +23,14 @@ PSF or ZPL. i.e Python Software Foundation License or Zope Public License == Dependencies == * python -== Changelog == +== Build Instructions/Changes == + +The following patches are in the patches subdirectory. +The patches are applied during the build process. + + * pkg_resources.py.patch: silence warning about permissions. + += Changelog == === setuptools-0.6.16.p0 (Jeroen Demeyer, 27 February 2012) === * Trac #12599: make spkg-install executable. diff --git a/build/pkgs/setuptools/checksums.ini b/build/pkgs/setuptools/checksums.ini index 996f0a33239..a36e14803cd 100644 --- a/build/pkgs/setuptools/checksums.ini +++ b/build/pkgs/setuptools/checksums.ini @@ -1,4 +1,4 @@ -tarball=setuptools-VERSION.tar.bz2 -sha1=81edded48d006618496496c11e7f289cb430d3d5 -md5=4d1515d1274f2e6b1fb2b30df9e04bd7 -cksum=1306902237 +tarball=setuptools-VERSION.tar.gz +sha1=5283b4dca46d45efd1156713ab51836509646c03 +md5=04aedc705644fda5848b7b428774e5ff +cksum=1381252756 diff --git a/build/pkgs/setuptools/package-version.txt b/build/pkgs/setuptools/package-version.txt index cd213f4119b..38f77a65b30 100644 --- a/build/pkgs/setuptools/package-version.txt +++ b/build/pkgs/setuptools/package-version.txt @@ -1 +1 @@ -0.6.16.p0 +2.0.1 diff --git a/build/pkgs/setuptools/patches/distribute-0.6.16-fix_deprecation_warnings.patch b/build/pkgs/setuptools/patches/distribute-0.6.16-fix_deprecation_warnings.patch deleted file mode 100644 index b8128c238e4..00000000000 --- a/build/pkgs/setuptools/patches/distribute-0.6.16-fix_deprecation_warnings.patch +++ /dev/null @@ -1,123 +0,0 @@ ---- pkg_resources.py -+++ pkg_resources.py -@@ -210,9 +210,10 @@ - needs some hacks for Linux and Mac OS X. - """ - try: -- from distutils.util import get_platform -- except ImportError: -+ # Python 2.7 or >=3.2 - from sysconfig import get_platform -+ except ImportError: -+ from distutils.util import get_platform - - plat = get_platform() - if sys.platform == "darwin" and not plat.startswith('macosx-'): ---- setuptools/command/bdist_egg.py -+++ setuptools/command/bdist_egg.py -@@ -7,10 +7,14 @@ - from setuptools import Command - from distutils.dir_util import remove_tree, mkpath - try: -- from distutils.sysconfig import get_python_version, get_python_lib -+ # Python 2.7 or >=3.2 -+ from sysconfig import get_path, get_python_version -+ def _get_purelib(): -+ return get_path("purelib") - except ImportError: -- from sysconfig import get_python_version -- from distutils.sysconfig import get_python_lib -+ from distutils.sysconfig import get_python_version, get_python_lib -+ def _get_purelib(): -+ return get_python_lib(False) - - from distutils import log - from distutils.errors import DistutilsSetupError -@@ -130,7 +134,7 @@ - # Hack for packages that install data to install's --install-lib - self.get_finalized_command('install').install_lib = self.bdist_dir - -- site_packages = os.path.normcase(os.path.realpath(get_python_lib())) -+ site_packages = os.path.normcase(os.path.realpath(_get_purelib())) - old, self.distribution.data_files = self.distribution.data_files,[] - - for item in old: ---- setuptools/command/build_ext.py -+++ setuptools/command/build_ext.py -@@ -9,9 +9,14 @@ - from distutils.file_util import copy_file - from setuptools.extension import Library - from distutils.ccompiler import new_compiler --from distutils.sysconfig import customize_compiler, get_config_var --get_config_var("LDSHARED") # make sure _config_vars is initialized --from distutils.sysconfig import _config_vars -+try: -+ # Python 2.7 or >=3.2 -+ from distutils.ccompiler import customize_compiler -+ from sysconfig import get_config_var, _CONFIG_VARS -+except ImportError: -+ from distutils.sysconfig import customize_compiler, get_config_var -+ get_config_var("LDSHARED") # make sure _config_vars is initialized -+ from distutils.sysconfig import _config_vars as _CONFIG_VARS - from distutils import log - from distutils.errors import * - -@@ -133,16 +138,16 @@ - compiler=self.compiler, dry_run=self.dry_run, force=self.force - ) - if sys.platform == "darwin": -- tmp = _config_vars.copy() -+ tmp = _CONFIG_VARS.copy() - try: - # XXX Help! I don't have any idea whether these are right... -- _config_vars['LDSHARED'] = "gcc -Wl,-x -dynamiclib -undefined dynamic_lookup" -- _config_vars['CCSHARED'] = " -dynamiclib" -- _config_vars['SO'] = ".dylib" -+ _CONFIG_VARS['LDSHARED'] = "gcc -Wl,-x -dynamiclib -undefined dynamic_lookup" -+ _CONFIG_VARS['CCSHARED'] = " -dynamiclib" -+ _CONFIG_VARS['SO'] = ".dylib" - customize_compiler(compiler) - finally: -- _config_vars.clear() -- _config_vars.update(tmp) -+ _CONFIG_VARS.clear() -+ _CONFIG_VARS.update(tmp) - else: - customize_compiler(compiler) - ---- setuptools/command/easy_install.py -+++ setuptools/command/easy_install.py -@@ -15,9 +15,22 @@ - from setuptools import Command, _dont_write_bytecode - from setuptools.sandbox import run_setup - from distutils import log, dir_util -+try: -+ # Python 2.7 or >=3.2 -+ from sysconfig import get_config_vars, get_path -+ def _get_platlib(): -+ return get_path("platlib") -+ def _get_purelib(): -+ return get_path("purelib") -+except ImportError: -+ from distutils.sysconfig import get_config_vars, get_python_lib -+ def _get_platlib(): -+ return get_python_lib(True) -+ def _get_purelib(): -+ return get_python_lib(False) -+ - from distutils.util import get_platform - from distutils.util import convert_path, subst_vars --from distutils.sysconfig import get_python_lib, get_config_vars - from distutils.errors import DistutilsArgError, DistutilsOptionError, \ - DistutilsError, DistutilsPlatformError - from distutils.command.install import INSTALL_SCHEMES, SCHEME_KEYS -@@ -1348,8 +1361,7 @@ - 'Python', - sys.version[:3], - 'site-packages')) -- for plat_specific in (0,1): -- site_lib = get_python_lib(plat_specific) -+ for site_lib in (_get_purelib(), _get_platlib()): - if site_lib not in sitedirs: sitedirs.append(site_lib) - - if HAS_USER_SITE: diff --git a/build/pkgs/setuptools/patches/pkg_resources.py.patch b/build/pkgs/setuptools/patches/pkg_resources.py.patch new file mode 100644 index 00000000000..d65174439cf --- /dev/null +++ b/build/pkgs/setuptools/patches/pkg_resources.py.patch @@ -0,0 +1,23 @@ +--- src/pkg_resources.py 2013-12-13 08:31:50.000000000 -0800 ++++ src/pkg_resources.py 2014-02-04 15:24:58.000000000 -0800 +@@ -959,19 +959,7 @@ + + See Distribute #375 for more details. + """ +- if os.name == 'nt' and not path.startswith(os.environ['windir']): +- # On Windows, permissions are generally restrictive by default +- # and temp directories are not writable by other users, so +- # bypass the warning. +- return +- mode = os.stat(path).st_mode +- if mode & stat.S_IWOTH or mode & stat.S_IWGRP: +- msg = ("%s is writable by group/others and vulnerable to attack " +- "when " +- "used with get_resource_filename. Consider a more secure " +- "location (set with .set_extraction_path or the " +- "PYTHON_EGG_CACHE environment variable)." % path) +- warnings.warn(msg, UserWarning) ++ return + + def postprocess(self, tempname, filename): + """Perform any platform-specific postprocessing of `tempname` diff --git a/build/pkgs/setuptools/patches/setuptools-noexecs.patch b/build/pkgs/setuptools/patches/setuptools-noexecs.patch deleted file mode 100644 index a191bdb3d22..00000000000 --- a/build/pkgs/setuptools/patches/setuptools-noexecs.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- setup.py.orig 2011-05-25 13:45:02.013595745 +1200 -+++ setup.py 2011-05-25 13:45:45.408111819 +1200 -@@ -137,7 +137,6 @@ - test_suite = 'setuptools.tests', - src_root = src_root, - packages = find_packages(), -- package_data = {'setuptools':['*.exe']}, - - py_modules = ['pkg_resources', 'easy_install', 'site'], - diff --git a/build/pkgs/setuptools/spkg-install b/build/pkgs/setuptools/spkg-install index 54962915983..6f7e9aa0bb4 100755 --- a/build/pkgs/setuptools/spkg-install +++ b/build/pkgs/setuptools/spkg-install @@ -1,9 +1,28 @@ -#!/bin/sh +#!/usr/bin/env bash + +if [ "$SAGE_LOCAL" = "" ]; then + echo "SAGE_LOCAL undefined ... exiting"; + echo "Maybe run 'sage -sh'?" + exit 1 +fi + +# distribute doesn't allow itself to be replaced by setuptools +# so we manually have to delete it +rm -rf "$SAGE_LOCAL"/lib/python*/site-packages/setuptools* +rm -rf "$SAGE_LOCAL"/lib/python*/site-packages/distribute* + +export PYTHON_EGG_CACHE="$DOT_SAGE/.python-eggs" cd src -patch -p0 < ../patches/setuptools-noexecs.patch -patch -p0 < ../patches/distribute-0.6.16-fix_deprecation_warnings.patch +# Apply patches. See SPKG.txt for information about what each patch +# does. +for patch in ../patches/*.patch; do + patch -p1 <"$patch" + if [ $? -ne 0 ]; then + echo >&2 "Error applying '$patch'" + exit 1 + fi +done python setup.py install - diff --git a/src/bin/sage-banner b/src/bin/sage-banner index 1130cabd6b6..849195721a6 100644 --- a/src/bin/sage-banner +++ b/src/bin/sage-banner @@ -1,5 +1,5 @@ ┌────────────────────────────────────────────────────────────────────┐ -│ Sage Version 6.2.beta1, Release Date: 2014-02-07 │ +│ Sage Version 6.2.beta2, Release Date: 2014-02-15 │ │ Type "notebook()" for the browser-based notebook interface. │ │ Type "help()" for help. │ └────────────────────────────────────────────────────────────────────┘ diff --git a/src/bin/sage-cleaner b/src/bin/sage-cleaner index bea962e5b87..5729a1a6244 100755 --- a/src/bin/sage-cleaner +++ b/src/bin/sage-cleaner @@ -17,15 +17,42 @@ #***************************************************************************** -from __future__ import print_function +import os, shutil, sys, time, socket, errno, signal, atexit -import os, shutil, sys, time, socket -import signal HOSTNAME = os.environ.get('HOSTNAME', socket.gethostname()) - DOT_SAGE = os.environ['DOT_SAGE'] + SAGE_TMP_ROOT = os.path.join(DOT_SAGE, 'temp', HOSTNAME) +logfile = os.path.join(SAGE_TMP_ROOT, 'cleaner.log') +pidfile = os.path.join(SAGE_TMP_ROOT, 'cleaner.pid') +# pidfile used by earlier versions of sage-cleaner (before #15457) +old_pidfile = os.path.join(DOT_SAGE, 'temp', 'cleaner-%s.pid'%HOSTNAME) + +import logging +logger = logging.getLogger(__name__) + + +def mkdir_p(path): + """ + A "mkdir -p" command that makes intermediate directories if necessary + """ + try: + os.makedirs(path) + except OSError as e: + if not os.path.isdir(path): + raise + + +def rm_rf(file_or_path): + """ + Force recursive delete, ignoring errors. + """ + try: + os.unlink(file_or_path) + except OSError as e: + if e.errno == errno.EISDIR: + shutil.rmtree(file_or_path, ignore_errors=True) def is_running(pid): @@ -38,71 +65,100 @@ def is_running(pid): except OSError: return False + def cleanup(): tmp_dirs = os.listdir(SAGE_TMP_ROOT) + try: + tmp_dirs.remove('cleaner.pid') + tmp_dirs.remove('cleaner.log') + except ValueError: + logger.error('No cleaner pid/log in SAGE_TMP_ROOT') # Convert strings to integers pid_list = [] - for dir in tmp_dirs: + for dir_entry in tmp_dirs: try: - pid_list.append(int(dir)) + pid_list.append(int(dir_entry)) except ValueError: - pass + badfile = os.path.join(SAGE_TMP_ROOT, dir_entry) + logger.warning('File %s must not be in SAGE_TMP_ROOT, deleting', badfile) + rm_rf(badfile) - print("Checking PIDs", pid_list) + logger.info("Checking PIDs %s", pid_list) for parent_pid in pid_list: - if not is_running(parent_pid): - print("Process %s is no longer running, so we clean up"%parent_pid) - d = os.path.join(SAGE_TMP_ROOT, str(parent_pid)) - spawned_processes = os.path.join(d, 'spawned_processes') - e = os.path.isdir(spawned_processes) - if not e or (e and kill_spawned_jobs(spawned_processes, parent_pid)): - print("Deleting %s"%d) - try: - shutil.rmtree(d) - except OSError: - pass - - return len(tmp_dirs) - -def kill_spawned_jobs(file, parent_pid): - print("Killing %s's spawned jobs"%parent_pid) + try: + if not is_running(parent_pid): + logger.info("Process %s is no longer running, so we clean up", parent_pid) + dir_name = os.path.join(SAGE_TMP_ROOT, str(parent_pid)) + spawned_processes = os.path.join(dir_name, 'spawned_processes') + if not os.path.isfile(spawned_processes) \ + or kill_spawned_jobs(spawned_processes, parent_pid): + logger.info('Deleting %s', dir_name) + rm_rf(dir_name) + except Exception: + logger.error("Exception while cleaning up PID %s:", parent_pid, exc_info=True) + + return len(pid_list) + +def kill_spawned_jobs(jobfile, parent_pid): + logger.info("Killing %s's spawned jobs", parent_pid) killed_them_all = True - for L in open(file).readlines(): - i = L.find(' ') - pid = L[:i].strip() - cmd = L[i+1:].strip() + for job in open(jobfile).readlines(): + pid, cmd = job.strip().split(' ', 1) + logger.info("--> Killing '%s' with PID %s and parent PID %s", cmd, pid, parent_pid) + pid = int(pid) try: - print("Killing %s with parent %s"%(pid, parent_pid) ) - os.killpg(int(pid), signal.SIGKILL) - except OSError, msg: - try: - os.kill(int(pid), signal.SIGKILL) - except OSError, msg: - pass + pgrp = os.getpgid(pid) + logger.info("--> Killing process group %s", pgrp) + os.killpg(pgrp, signal.SIGKILL) + except OSError: + pass if is_running(pid): - print("Failed to kill %s!"%pid) + logger.error("--> Failed to kill %s", pid) # try again later killed_them_all = False return killed_them_all -pidfile = os.path.join(DOT_SAGE, 'temp', 'cleaner-%s.pid'%HOSTNAME) +def exit_handler(): + logger.info("Removing pidfile and logfile") + rm_rf(pidfile) + rm_rf(logfile) + + def setup_daemon(): - print("SAGE_TMP_ROOT =", SAGE_TMP_ROOT) - if not os.path.isdir(SAGE_TMP_ROOT): - print("No directory %s, exiting"%SAGE_TMP_ROOT) - sys.exit(0) + mkdir_p(SAGE_TMP_ROOT) + + logger.setLevel(logging.DEBUG) + h = logging.StreamHandler() # log to stderr + h.setLevel(logging.DEBUG) + logger.addHandler(h) + h = logging.FileHandler(filename=logfile) # log to logfile + h.setLevel(logging.INFO) + logger.addHandler(h) + + logger.info("SAGE_TMP_ROOT = %s", SAGE_TMP_ROOT) + # Check old pidfile (to allow old and new sage-cleaners to peacefully coexist) try: - pid = int(open(pidfile).read()) + pid = int(open(old_pidfile).read()) except (IOError, ValueError): pass else: if is_running(pid): - print("sage-cleaner is already running with PID %s, exiting"%pid) + logger.info("old sage-cleaner is already running with PID %s, exiting", pid) sys.exit(0) - open(pidfile,'w').write(str(os.getpid())) + try: + pid = int(open(pidfile).read()) + except (IOError, ValueError): + pass + else: + if is_running(pid): + logger.info("sage-cleaner is already running with PID %s, exiting", pid) + sys.exit(0) + with open(pidfile, 'w') as f: + f.write(str(os.getpid())) # initialize pid file + atexit.register(exit_handler) def fix_old_mistakes(): @@ -113,8 +169,8 @@ def fix_old_mistakes(): wrong_hostname = HOSTNAME.replace('-','_').replace('/','_').replace('\\','_') wrong_sage_tmp_root = os.path.join(DOT_SAGE, 'temp', wrong_hostname) if wrong_sage_tmp_root != SAGE_TMP_ROOT and os.path.exists(wrong_sage_tmp_root): - print('deleting invalid temp dir {0}'.format(wrong_sage_tmp_root)) - shutil.rmtree(wrong_sage_tmp_root, ignore_errors=True) + logger.warning('Deleting invalid temp dir %s', wrong_sage_tmp_root) + rm_rf(wrong_sage_tmp_root) # SAGE_TMP in DOT_SAGE/tmp instead of DOT_SAGE/temp import glob @@ -122,44 +178,39 @@ def fix_old_mistakes(): if wrong_hostname != HOSTNAME: old_root += glob.glob(os.path.join(DOT_SAGE, 'tmp', wrong_hostname+'-*')) for old_tmp in old_root: - print('deleting invalid temp dir {0}'.format(old_tmp)) - shutil.rmtree(old_tmp, ignore_errors=True) + logger.warning('Deleting invalid temp dir %s', old_tmp) + rm_rf(old_tmp) + + # PID file before it was moved into SAGE_TMP_ROOT + rm_rf(old_pidfile) if __name__ == '__main__': setup_daemon() fix_old_mistakes() + logger.info("Starting sage-cleaner with PID %s", os.getpid()) - try: - print("Starting sage-cleaner") - - if len(sys.argv) > 1: - wait = int(sys.argv[1]) - else: - wait = 10 - - # Initial cleanup, ignore time + if len(sys.argv) > 1: + wait = int(sys.argv[1]) + else: + wait = 10 + + # Initial cleanup, ignore time + running_sages = cleanup() + cleanup_time = 0.0 + count = 1 + + # In the first 10 iterations, continue anyway (even if there are + # no Sage processes running) because it can happen that Sage is + # not yet started. + while count < 10 or running_sages > 0: + # Time to wait = "wait" plus 20 times the time of last cleanup(). + # This ensures that sage-cleaner causes a load of at most 5%. + time.sleep(wait + 20*cleanup_time) + count += 1 + t0 = time.time() running_sages = cleanup() - cleanup_time = 0.0 - count = 1 - - # In the first 10 iterations, continue anyway (even if there are - # no Sage processes running) because it can happen that Sage is - # not yet started. - while count < 10 or running_sages > 0: - # Time to wait = "wait" plus 20 times the time of last cleanup(). - # This ensures that sage-cleaner causes a load of at most 5%. - time.sleep(wait + 20*cleanup_time) - count += 1 - t0 = time.time() - running_sages = cleanup() - cleanup_time = time.time() - t0 - print("cleanup() #{:d} took {:.2f}s".format(count, cleanup_time)) - - print("sage-cleaner is finished") - - finally: - try: - os.unlink(pidfile) - except OSError: - pass + cleanup_time = time.time() - t0 + logger.debug("cleanup() #{:d} took {:.2f}s".format(count, cleanup_time)) + + logger.info("sage-cleaner is finished") diff --git a/src/bin/sage-env b/src/bin/sage-env index a9021b7d401..496948be0a2 100644 --- a/src/bin/sage-env +++ b/src/bin/sage-env @@ -353,7 +353,6 @@ if [ "$DOT_SAGE" = "" ]; then export DOT_SAGE fi - if [ "$SAGE_STARTUP_FILE" = "" ]; then SAGE_STARTUP_FILE="$DOT_SAGE/init.sage" export SAGE_STARTUP_FILE @@ -361,6 +360,11 @@ fi export IPYTHONDIR="$DOT_SAGE/ipython-0.12" +if [ "$PYTHON_EGG_CACHE" = "" ]; then + PYTHON_EGG_CACHE="$DOT_SAGE/.python-eggs" + export PYTHON_EGG_CACHE +fi + if [ -d "$SAGE_ROOT/local/lib/python" ]; then PYTHONPATH="$SAGE_ROOT/local/lib/python" if [ -n "$SAGE_PATH" ]; then diff --git a/src/bin/sage-spkg b/src/bin/sage-spkg index 13adc925da2..9f20d312a70 100755 --- a/src/bin/sage-spkg +++ b/src/bin/sage-spkg @@ -300,7 +300,6 @@ elif [ -z "$PKG_HAS_PATH" ]; then if [ $INFO -eq 0 ]; then # see if we can the source tarball locally - cd "$SAGE_DISTFILES" if [ -f "$SAGE_DISTFILES/$PKG_NAME_UPSTREAM" ]; then # Found a good tarball PKG_SRC="$SAGE_DISTFILES/$PKG_NAME_UPSTREAM" @@ -574,7 +573,7 @@ fi if [ "$USE_LOCAL_SCRIPTS" = yes ]; then echo "Setting up build directory for $PKG_NAME" cp -Rp "$PKG_SCRIPTS" "$PKG_NAME" - cd "$PKG_NAME" + cd "$PKG_NAME" || exit $? else echo "Extracting package $PKG_SRC" ls -l "$PKG_SRC" @@ -587,23 +586,22 @@ if [ $? -ne 0 ]; then fi if [ "$USE_LOCAL_SCRIPTS" = yes ]; then - mv "${PKG_NAME_UPSTREAM%.tar*}" src - cd .. + mv 2>/dev/null "${PKG_NAME_UPSTREAM%.tar*}" src echo "Finished set up" else echo "Finished extraction" + + cd "$PKG_NAME" + if [ $? -ne 0 ]; then + echo >&2 "Error: after extracting, the directory $PKG_NAME does not exist" + exit 1 + fi fi ################################################################## # The package has been extracted, prepare for installation ################################################################## -cd "$PKG_NAME" -if [ $? -ne 0 ]; then - echo >&2 "Error: after extracting, the directory $PKG_NAME does not exist" - exit 1 -fi - # When there is no spkg-install, assume the "spkg" is a tarball not # specifically made for Sage. Since we want it to be as easy as # possible to install such a package, we "guess" spkg-install. diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index d818fa4bfed..b87ea6672c6 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,4 +1,4 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='6.2.beta1' -SAGE_RELEASE_DATE='2014-02-07' +SAGE_VERSION='6.2.beta2' +SAGE_RELEASE_DATE='2014-02-15' diff --git a/src/doc/common/conf.py b/src/doc/common/conf.py index de14a807114..fb95e6f652b 100644 --- a/src/doc/common/conf.py +++ b/src/doc/common/conf.py @@ -292,6 +292,10 @@ def add(subdoc=''): \usepackage{mathrsfs} \DeclareUnicodeCharacter{01CE}{\capitalcaron a} \DeclareUnicodeCharacter{0428}{cyrillic Sha} +\DeclareUnicodeCharacter{250C}{+} +\DeclareUnicodeCharacter{2510}{+} +\DeclareUnicodeCharacter{2514}{+} +\DeclareUnicodeCharacter{2518}{+} """ # Documents to append as an appendix to all manuals. diff --git a/src/doc/common/custom-sphinx-build.py b/src/doc/common/custom-sphinx-build.py index 2a1f50cd34b..808937dce5b 100644 --- a/src/doc/common/custom-sphinx-build.py +++ b/src/doc/common/custom-sphinx-build.py @@ -56,7 +56,7 @@ def term_width_line(text): re.compile('Exception occurred'), re.compile('Sphinx error')) -if 'pdf' not in sys.argv: +if 'latex' not in sys.argv: warnings += (re.compile('WARNING'),) class SageSphinxLogger(object): diff --git a/src/doc/en/reference/interfaces/index.rst b/src/doc/en/reference/interfaces/index.rst index 6db5661f0be..4ead0690a94 100644 --- a/src/doc/en/reference/interfaces/index.rst +++ b/src/doc/en/reference/interfaces/index.rst @@ -62,6 +62,7 @@ and testing to make sure nothing funny is going on). sage/interfaces/expect sage/interfaces/axiom + sage/interfaces/ecm sage/interfaces/four_ti_2 sage/interfaces/gap sage/interfaces/gap3 diff --git a/src/sage/algebras/free_algebra_element.py b/src/sage/algebras/free_algebra_element.py index 5a9e7763b18..e665b88206e 100644 --- a/src/sage/algebras/free_algebra_element.py +++ b/src/sage/algebras/free_algebra_element.py @@ -210,7 +210,7 @@ def _add_(self, y): ## if isinstance(y, (int, long, Integer)): ## z_elt = dict(self.__monomial_coefficients) ## e = A.monoid()(1) -## if z_elt.has_key(e): +## if e in z_elt: ## z_elt[e] += A.base_ring()(y) ## else: ## z_elt[e] = A.base_ring()(y) @@ -265,7 +265,7 @@ def _sub_(self, y): ## if isinstance(y, (int, long, Integer)): ## z_elt = dict(self.__monomial_coefficients) ## e = A.monoid()(1) -## if z_elt.has_key(e): +## if e in z_elt: ## z_elt[e] += A.base_ring()(-y) ## else: ## z_elt[e] = A.base_ring()(-y) diff --git a/src/sage/categories/category.py b/src/sage/categories/category.py index 214dbb9dd7a..b90b56f4676 100644 --- a/src/sage/categories/category.py +++ b/src/sage/categories/category.py @@ -2191,7 +2191,7 @@ def __init__(self, super_categories, **kwds): # Use __super_categories to not overwrite the lazy attribute Category._super_categories # Maybe this would not be needed if the flattening/sorting is does consistently? self.__super_categories = list(super_categories) - if kwds.has_key('name'): + if 'name' in kwds: Category.__init__(self, kwds['name']) else: Category.__init__(self) diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index 65c88468e3f..46b36e16ec9 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -168,7 +168,7 @@ cdef class Map(Element): # Several pickles exist without a _repr_type_str, so # if there is none saved, we just set it to None. - if _slots.has_key('_repr_type_str'): + if '_repr_type_str' in _slots: self._repr_type_str = _slots['_repr_type_str'] else: self._repr_type_str = None diff --git a/src/sage/categories/rings.py b/src/sage/categories/rings.py index 19fb59d4ec3..e4b7a36afa3 100644 --- a/src/sage/categories/rings.py +++ b/src/sage/categories/rings.py @@ -347,7 +347,7 @@ def ideal(self, *args, **kwds): of Full MatrixSpace of 2 by 2 dense matrices over Rational Field """ - if kwds.has_key('coerce'): + if 'coerce' in kwds: coerce = kwds['coerce'] del kwds['coerce'] else: @@ -402,7 +402,7 @@ def ideal(self, *args, **kwds): for h in gens[1:]: g = g.gcd(h) gens = [g] - if kwds.has_key('ideal_class'): + if 'ideal_class' in kwds: C = kwds['ideal_class'] del kwds['ideal_class'] else: diff --git a/src/sage/coding/code_bounds.py b/src/sage/coding/code_bounds.py index 2b0ec2480b3..5dfc63c3fd2 100644 --- a/src/sage/coding/code_bounds.py +++ b/src/sage/coding/code_bounds.py @@ -470,7 +470,7 @@ def gv_info_rate(n,delta,q): ans=log(gilbert_lower_bound(n,q,int(n*delta)),q)/n return ans -def entropy(x,q): +def entropy(x, q=2): """ Computes the entropy at `x` on the `q`-ary symmetric channel. @@ -478,7 +478,8 @@ def entropy(x,q): - ``x`` - real number in the interval `[0, 1]`. - - ``q`` - integer greater than 1. This is the base of the logarithm. + - ``q`` - (default: 2) integer greater than 1. This is the base of the + logarithm. EXAMPLES:: @@ -513,6 +514,56 @@ def entropy(x,q): H = x*log(q-1,q)-x*log(x,q)-(1-x)*log(1-x,q) return H +def entropy_inverse(x, q=2): + """ + Find the inverse of the ``q``-ary entropy function at the point ``x``. + + INPUT: + + - ``x`` -- real number in the interval `[0, 1]`. + + - ``q`` - (default: 2) integer greater than 1. This is the base of the + logarithm. + + OUTPUT: + + Real number in the interval `[0, 1-1/q]`. The function has multiple + values if we include the entire interval `[0, 1]`; hence only the + values in the above interval is returned. + + EXAMPLES:: + + sage: from sage.coding.code_bounds import entropy_inverse + sage: entropy_inverse(0.1) + 0.012986862055848683 + sage: entropy_inverse(1) + 1/2 + sage: entropy_inverse(0, 3) + 0 + sage: entropy_inverse(1, 3) + 2/3 + + """ + # No nice way to compute the inverse. We resort to root finding. + if x < 0 or x > 1: + raise ValueError("The inverse entropy function is defined only for " + "x in the interval [0, 1]") + q = ZZ(q) # This will error out if q is not an integer + if q < 2: # Here we check that q is actually at least 2 + raise ValueError("The value q must be an integer greater than 1") + + eps = 4.5e-16 # find_root has about this as the default xtol + ymax = 1 - 1/q + if x <= eps: + return 0 + if x >= 1-eps: + return ymax + + # find_root will error out if the root can not be found + from sage.numerical.optimize import find_root + f = lambda y: entropy(y, q) - x + return find_root(f, 0, ymax) + def gv_bound_asymp(delta,q): """ Computes the asymptotic GV bound for the information rate, R. diff --git a/src/sage/combinat/composition_tableau.py b/src/sage/combinat/composition_tableau.py index 086a8a6d234..677fb8099c8 100644 --- a/src/sage/combinat/composition_tableau.py +++ b/src/sage/combinat/composition_tableau.py @@ -449,7 +449,7 @@ def __init__(self, **kwds): sage: CT = CompositionTableaux() sage: TestSuite(CT).run() """ - if kwds.has_key('max_entry'): + if 'max_entry' in kwds: self.max_entry = kwds['max_entry'] kwds.pop('max_entry') else: diff --git a/src/sage/combinat/core.py b/src/sage/combinat/core.py index 4f1c6064f06..7306da937ee 100644 --- a/src/sage/combinat/core.py +++ b/src/sage/combinat/core.py @@ -108,6 +108,52 @@ def __init__(self, parent, core): CombinatorialObject.__init__(self, core) Element.__init__(self, parent) + def __eq__(self, other): + """ + EXAMPLES:: + + sage: c = Core([4,2,1,1],5) + sage: d = Core([4,2,1,1],5) + sage: e = Core([4,2,1,1],6) + sage: c == [4,2,1,1] + False + sage: c == d + True + sage: c == e + False + """ + if isinstance(other, Core): + return self._list.__eq__(other._list) and self.parent().k == other.parent().k + else: + return False + + def __hash__(self): + """ + Computes the hash of ``self`` by computing the hash of the + underlying list and of the additional parameter. + The hash is cached and stored in ``self._hash``. + + EXAMPLES:: + + sage: c = Core([4,2,1,1],3) + sage: c._hash is None + True + sage: hash(c) #random + 1335416675971793195 + sage: c._hash #random + 1335416675971793195 + + TESTS:: + + sage: c = Core([4,2,1,1],5) + sage: d = Core([4,2,1,1],6) + sage: hash(c) == hash(d) + False + """ + if self._hash is None: + self._hash = hash(tuple(self._list)) + hash(self.parent().k) + return self._hash + def _latex_(self): """ Outputs the LaTeX representation of this core as a partition. See the diff --git a/src/sage/combinat/crystals/direct_sum.py b/src/sage/combinat/crystals/direct_sum.py index 6501f9c7f73..f201f3f287b 100644 --- a/src/sage/combinat/crystals/direct_sum.py +++ b/src/sage/combinat/crystals/direct_sum.py @@ -96,7 +96,7 @@ def __init__(self, crystals, **options): sage: isinstance(B, DirectSumOfCrystals) True """ - if options.has_key('keepkey'): + if 'keepkey' in options: keepkey = options['keepkey'] else: keepkey = False diff --git a/src/sage/combinat/crystals/monomial_crystals.py b/src/sage/combinat/crystals/monomial_crystals.py index 81838358453..b9a2d17b621 100644 --- a/src/sage/combinat/crystals/monomial_crystals.py +++ b/src/sage/combinat/crystals/monomial_crystals.py @@ -319,7 +319,7 @@ def phi(self,i): d = copy(dict) K = max(x[1] for x in list(d) if x[0] ==i) for a in range(K): - if d.has_key((i,a)): + if (i,a) in d: continue else: d[(i,a)] = 0 @@ -351,7 +351,7 @@ def _ke(self,i): d = copy(dict) K = max(x[1] for x in list(d) if x[0] ==i) for a in range(K): - if d.has_key((i,a)): + if (i,a) in d: continue else: d[(i,a)] = 0 @@ -387,7 +387,7 @@ def _kf(self,i): else: K = max(x[1] for x in list(d) if x[0] ==i) for a in range(K): - if d.has_key((i,a)): + if (i,a) in d: continue else: d[(i,a)] = 0 @@ -455,7 +455,7 @@ def e(self,i): if cm[j-shift][i-shift] != 0: Aik[(j, ke+c)] = cm[j-shift][i-shift] for key,value in Aik.iteritems(): - if newdict.has_key(key): + if key in newdict: newdict[key] +=value else: newdict[key] = value @@ -503,7 +503,7 @@ def f(self,i): if cm[j-shift][i-shift] != 0: Aik[(j, kf+c)] = -cm[j-shift][i-shift] for key,value in Aik.iteritems(): - if newdict.has_key(key): + if key in newdict: newdict[key] +=value else: newdict[key] = value diff --git a/src/sage/combinat/crystals/tensor_product.py b/src/sage/combinat/crystals/tensor_product.py index d39b8d1ebf7..a637b8da129 100644 --- a/src/sage/combinat/crystals/tensor_product.py +++ b/src/sage/combinat/crystals/tensor_product.py @@ -684,7 +684,7 @@ def __init__(self, crystals, **options): category = Category.meet([crystal.category() for crystal in crystals]) Parent.__init__(self, category = category) self.crystals = crystals - if options.has_key('cartan_type'): + if 'cartan_type' in options: self._cartan_type = CartanType(options['cartan_type']) else: if len(crystals) == 0: @@ -1728,9 +1728,9 @@ def __init__(self, parent, *args, **options): if len(args) == 1: if isinstance(args[0], Tableau): options['rows'] = args[0] - if options.has_key('list'): + if 'list' in options: list = options['list'] - elif options.has_key('rows'): + elif 'rows' in options: rows=options['rows'] # list=Tableau(rows).to_word_by_column() rows=Tableau(rows).conjugate() @@ -1738,7 +1738,7 @@ def __init__(self, parent, *args, **options): for col in rows: col.reverse() list+=col - elif options.has_key('columns'): + elif 'columns' in options: columns=options['columns'] list=[] for col in columns: diff --git a/src/sage/combinat/designs/ext_rep.py b/src/sage/combinat/designs/ext_rep.py index 8feac581c20..60d6c7ea688 100644 --- a/src/sage/combinat/designs/ext_rep.py +++ b/src/sage/combinat/designs/ext_rep.py @@ -694,7 +694,7 @@ def __getattr__(self, attr): [0, 1, 2] """ - if self.xt_attributes.has_key(attr): + if attr in self.xt_attributes: return self.xt_attributes[attr] else: for child in self.xt_children: diff --git a/src/sage/combinat/k_tableau.py b/src/sage/combinat/k_tableau.py index e46bc0b4623..aee089c604e 100644 --- a/src/sage/combinat/k_tableau.py +++ b/src/sage/combinat/k_tableau.py @@ -3947,7 +3947,7 @@ def _repr_( self ): sage: StrongTableaux(3, [[],[]], weight=[]) Set of strong 3-tableaux of shape [] and of weight () """ - if self._inner_shape==[]: + if self._inner_shape==Core([],self.k+1): s = "Set of strong %s-tableaux"%self.k s +=" of shape %s"%self._outer_shape else: diff --git a/src/sage/combinat/matrices/latin.py b/src/sage/combinat/matrices/latin.py index d67d545e1b8..8671fc3d609 100644 --- a/src/sage/combinat/matrices/latin.py +++ b/src/sage/combinat/matrices/latin.py @@ -663,7 +663,7 @@ def is_partial_latin_square(self): if e >= n: return False # Entry has already appeared in this row: - if vals_in_row.has_key(e): return False + if e in vals_in_row: return False vals_in_row[e] = True @@ -679,7 +679,7 @@ def is_partial_latin_square(self): if e >= n: return False # Entry has already appeared in this column: - if vals_in_col.has_key(e): return False + if e in vals_in_col: return False vals_in_col[e] = True @@ -1057,8 +1057,8 @@ def disjoint_mate_dlxcpp_rows_and_map(self, allow_subtrade): if (not allow_subtrade) and self[r, c] == e: continue # The permissible symbols must come from this row/column. - if not(valsrow.has_key(e)): continue - if not(valscol.has_key(e)): continue + if e not in valsrow: continue + if e not in valscol: continue dlx_rows.append([c_OFFSET, r_OFFSET, xy_OFFSET]) @@ -2216,7 +2216,7 @@ def pq_group_bitrade_generators(p, q): P = [] seenValues = {} for i in range(2, q): - if seenValues.has_key(i): + if i in seenValues: continue cycle = [] @@ -2594,8 +2594,8 @@ def dlxcpp_rows_and_map(P): # We only want the correct value to pop in here if P[r, c] >= 0 and P[r, c] != e: continue - if P[r, c] < 0 and valsrow.has_key(e): continue - if P[r, c] < 0 and valscol.has_key(e): continue + if P[r, c] < 0 and e in valsrow: continue + if P[r, c] < 0 and e in valscol: continue dlx_rows.append([c_OFFSET, r_OFFSET, xy_OFFSET]) diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index 2b9645cb3ba..f45c12ae272 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -481,7 +481,7 @@ def SymmetricGroupBruhatIntervalPoset(start, end): nodes[perm] = [succ_perm for succ_perm in perm.bruhat_succ() if succ_perm.bruhat_lequal(end)] for succ_perm in nodes[perm]: - if not nodes.has_key(succ_perm): + if succ_perm not in nodes: unseen.append(succ_perm) return Poset(nodes) diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 66398856558..9e83d36d14c 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -4541,7 +4541,7 @@ def _ford_fulkerson_chronicle(G, s, t, a): else: # Step MC2b in Britz-Fomin, Algorithm 7.2. for v in G.vertex_iterator(): - if not X.has_key(v): + if v not in X: pi[v] += 1 p += 1 diff --git a/src/sage/combinat/rigged_configurations/rigged_configurations.py b/src/sage/combinat/rigged_configurations/rigged_configurations.py index 9124accbf04..9763730dac8 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configurations.py +++ b/src/sage/combinat/rigged_configurations/rigged_configurations.py @@ -682,7 +682,7 @@ def _calc_vacancy_number(self, partitions, a, i, **options): vac_num += min(row_len, len(tableau[0])) elif "L" in options: L = options["L"] - if L.has_key(a): + if a in L: for kvp in L[a].items(): vac_num += min(kvp[0], row_len) * kvp[1] elif "dims" in options: @@ -1008,7 +1008,7 @@ def _calc_vacancy_number(self, partitions, a, i, **options): vac_num += min(row_len, len(tableau[0])) elif "L" in options: L = options["L"] - if L.has_key(a): + if a in L: for kvp in L[a].items(): vac_num += min(kvp[0], row_len) * kvp[1] elif "dims" in options: @@ -1350,7 +1350,7 @@ def _calc_vacancy_number(self, partitions, a, i, **options): vac_num += min(row_len, len(tableau[0])) elif "L" in options: L = options["L"] - if L.has_key(a): + if a in L: for kvp in L[a].items(): vac_num += min(kvp[0], row_len) * kvp[1] elif "dims" in options: @@ -1505,7 +1505,7 @@ def _calc_vacancy_number(self, partitions, a, i, **options): vac_num += min(row_len, len(tableau[0])) elif "L" in options: L = options["L"] - if L.has_key(a): + if a in L: for kvp in L[a].items(): vac_num += min(kvp[0], row_len) * kvp[1] elif "dims" in options: diff --git a/src/sage/combinat/root_system/branching_rules.py b/src/sage/combinat/root_system/branching_rules.py index 9ee05fdac1c..5bc958609ce 100644 --- a/src/sage/combinat/root_system/branching_rules.py +++ b/src/sage/combinat/root_system/branching_rules.py @@ -2205,7 +2205,7 @@ def maximal_subgroups(ct, mode="print_rules"): for line in rul: [k, br] = line.split(":") br = eval(br) - if d.has_key(k): + if k in d: if type(d[k]) is not list: d[k] = [d[k]] d[k].append(br) diff --git a/src/sage/combinat/root_system/weyl_group.py b/src/sage/combinat/root_system/weyl_group.py index c59c47077c6..783c7526e0a 100644 --- a/src/sage/combinat/root_system/weyl_group.py +++ b/src/sage/combinat/root_system/weyl_group.py @@ -566,7 +566,7 @@ def bruhat_graph(self, x, y): ref = self.reflections() d = {} for x in g: - d[x] = [y for y in g if x.length() < y.length() and ref.has_key(x*y.inverse())] + d[x] = [y for y in g if x.length() < y.length() and x*y.inverse() in ref] return DiGraph(d) diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index 4943228da17..000189f8a76 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -1100,7 +1100,6 @@ def _apply_multi_module_morphism(self, x, y, f, orthogonal=False): # could check which of x and y has less terms # for mx, cx in x: for mx, cx in x._monomial_coefficients.iteritems(): - # if not y.has_key(mx): if mx not in y._monomial_coefficients: continue else: diff --git a/src/sage/combinat/skew_partition.py b/src/sage/combinat/skew_partition.py index 76624f2b6a5..94cd39ebe9f 100644 --- a/src/sage/combinat/skew_partition.py +++ b/src/sage/combinat/skew_partition.py @@ -1169,6 +1169,13 @@ class SkewPartitions(Parent, UniqueRepresentation): """ Skew partitions. + .. WARNING:: + + The iterator of this class only yields skew partitions which + are reduced, in the sense that there are no empty rows + before the last nonempty row, and there are no empty columns + before the last nonempty column. + EXAMPLES:: sage: SkewPartitions(4) @@ -1435,14 +1442,14 @@ def __iter__(self): class SkewPartitions_n(SkewPartitions): """ - The set of skew partitions of ``n`` with overlap - at least ``overlap`` and no empty row. + The set of skew partitions of ``n`` with overlap at least + ``overlap`` and no empty row. INPUT: - - ``n`` -- A non-negative integer + - ``n`` -- a non-negative integer - - ``overlap`` -- An integer + - ``overlap`` -- an integer (default: `0`) Caveat: this set is stable under conjugation only for ``overlap`` equal to 0 or 1. What exactly happens for negative overlaps is not yet @@ -1474,12 +1481,7 @@ def __classcall_private__(cls, n, overlap=0): def __init__(self, n, overlap): """ - INPUT: - - - ``n`` -- a non-negative integer - - ``overlap`` -- an integer - - Returns the set of the skew partitions of ``n`` with overlap + Return the set of the skew partitions of ``n`` with overlap at least ``overlap``, and no empty row. The iteration order is not specified yet. @@ -1495,6 +1497,11 @@ def __init__(self, n, overlap): ``SkewPartition(n, row_lengths=...)``, and one would want to "inherit" list and cardinality from this composition. + INPUT: + + - ``n`` -- a non-negative integer + - ``overlap`` -- an integer + TESTS:: sage: S = SkewPartitions(3) @@ -1583,7 +1590,9 @@ def _count_slide(self, co, overlap=0): def cardinality(self): """ - Return the number of skew partitions of the integer `n`. + Return the number of skew partitions of the integer `n` + (with given overlap, if specified; and with no empty rows before + the last row). EXAMPLES:: @@ -1617,7 +1626,9 @@ def cardinality(self): def __iter__(self): """ - Iterate through the skew partitions of `n`. + Iterate through the skew partitions of `n` + (with given overlap, if specified; and with no empty rows before + the last row). EXAMPLES:: diff --git a/src/sage/combinat/skew_tableau.py b/src/sage/combinat/skew_tableau.py index 369bcfb7b9d..99d055f5ce5 100644 --- a/src/sage/combinat/skew_tableau.py +++ b/src/sage/combinat/skew_tableau.py @@ -37,6 +37,7 @@ from sage.rings.all import Integer, QQ, ZZ from sage.functions.all import factorial +from sage.rings.infinity import PlusInfinity from sage.matrix.all import zero_matrix from sage.combinat.combinat import CombinatorialObject @@ -63,7 +64,7 @@ class SkewTableau(CombinatorialObject, Element): [2, 2] The ``expr`` form of a skew tableau consists of the inner partition - followed by a list of the entries in row from bottom to top:: + followed by a list of the entries in each row from bottom to top:: sage: SkewTableau(expr=[[1,1],[[5],[3,4],[1,2]]]) [[None, 1, 2], [None, 3, 4], [5]] @@ -1622,33 +1623,103 @@ class SemistandardSkewTableaux(SkewTableaux): r""" Semistandard skew tableaux. - EXAMPLES:: + This class can be initialized with several optional variables: + the size of the skew tableaux (as a nameless integer variable), + their shape (as a nameless skew partition variable), their + weight (:meth:`~sage.combinat.skew_tableau.SkewTableau.weight`, + as a nameless second variable after either the size or the + shape) and their maximum entry (as an optional keyword variable + called ``max_entry``, unless the weight has been specified). If + neither the weight nor the maximum entry is specified, the + maximum entry defaults to the size of the tableau. + + Note that "maximum entry" does not literally mean the highest + entry; instead it is just an upper bound that no entry is + allowed to surpass. + + EXAMPLES: + + The (infinite) class of all semistandard skew tableaux:: sage: SemistandardSkewTableaux() Semistandard skew tableaux - :: + The (still infinite) class of all semistandard skew tableaux + with maximum entry `2`:: + + sage: SemistandardSkewTableaux(max_entry=2) + Semistandard skew tableaux with maximum entry 2 + + The class of all semistandard skew tableaux of given size `3` + and maximum entry `3`:: sage: SemistandardSkewTableaux(3) - Semistandard skew tableaux of size 3 + Semistandard skew tableaux of size 3 and maximum entry 3 - :: + To set a different maximum entry:: - sage: SemistandardSkewTableaux([[2,1],[]]) - Semistandard skew tableaux of shape [2, 1] / [] + sage: SemistandardSkewTableaux(3, max_entry = 7) + Semistandard skew tableaux of size 3 and maximum entry 7 - :: + Specifying a shape:: + + sage: SemistandardSkewTableaux([[2,1],[]]) + Semistandard skew tableaux of shape [2, 1] / [] and maximum entry 3 + + Specifying both a shape and a maximum entry:: + + sage: S = SemistandardSkewTableaux([[2,1],[1]], max_entry = 3); S + Semistandard skew tableaux of shape [2, 1] / [1] and maximum entry 3 + sage: S.list() + [[[None, 1], [1]], + [[None, 2], [1]], + [[None, 1], [2]], + [[None, 3], [1]], + [[None, 1], [3]], + [[None, 2], [2]], + [[None, 3], [2]], + [[None, 2], [3]], + [[None, 3], [3]]] + + sage: for n in range(5): + ....: print n, len(SemistandardSkewTableaux([[2,2,1],[1]], max_entry = n)) + 0 0 + 1 0 + 2 1 + 3 9 + 4 35 + + Specifying a shape and a weight:: sage: SemistandardSkewTableaux([[2,1],[]],[2,1]) Semistandard skew tableaux of shape [2, 1] / [] and weight [2, 1] - :: + (the maximum entry is redundant in this case and thus is ignored). + + Specifying a size and a weight:: sage: SemistandardSkewTableaux(3, [2,1]) Semistandard skew tableaux of size 3 and weight [2, 1] + + .. WARNING:: + + If the shape is not specified, the iterator of this class + yields only skew tableaux whose shape is reduced, in the + sense that there are no empty rows before the last nonempty + row, and there are no empty columns before the last + nonempty column. (Otherwise it would go on indefinitely.) + + .. WARNING:: + + This class acts as a factory. The resulting classes are mainly + useful for iteration. Do not rely on their containment tests, + as they are not correct, e. g.:: + + sage: SkewTableau([[None]]) in SemistandardSkewTableaux(2) + True """ @staticmethod - def __classcall_private__(cls, p=None, mu=None): + def __classcall_private__(cls, p=None, mu=None, max_entry=None): """ Return the correct parent based upon the input. @@ -1659,23 +1730,23 @@ def __classcall_private__(cls, p=None, mu=None): sage: SSST1 is SSST2 True """ - if p is None and mu is None: - return SemistandardSkewTableaux_all() - if p is None: - raise ValueError("You must specify either a size or shape") + if mu is None: + return SemistandardSkewTableaux_all(max_entry) + raise ValueError("You must specify either a size or a shape") if isinstance(p, (int, Integer)): if mu is None: - return SemistandardSkewTableaux_size(p) + return SemistandardSkewTableaux_size(p, max_entry) else: return SemistandardSkewTableaux_size_weight(p, mu) if p in SkewPartitions(): if mu is None: - return SemistandardSkewTableaux_shape(p) + return SemistandardSkewTableaux_shape(p, max_entry) else: return SemistandardSkewTableaux_shape_weight(p, mu) + raise ValueError("Invalid input") def __contains__(self, x): @@ -1702,9 +1773,10 @@ def __contains__(self, x): class SemistandardSkewTableaux_all(SemistandardSkewTableaux): """ - Class of all semistandard skew tableaux. + Class of all semistandard skew tableaux, possibly with a given + maximum entry. """ - def __init__(self): + def __init__(self, max_entry): """ Initialize ``self``. @@ -1712,8 +1784,15 @@ def __init__(self): sage: S = SemistandardSkewTableaux() sage: TestSuite(S).run() + + sage: S = SemistandardSkewTableaux(3) + sage: TestSuite(S).run() """ SemistandardSkewTableaux.__init__(self, category=InfiniteEnumeratedSets()) + if max_entry is None: + self.max_entry = PlusInfinity() + else: + self.max_entry = max_entry def _repr_(self): """ @@ -1722,7 +1801,10 @@ def _repr_(self): sage: SemistandardSkewTableaux() Semistandard skew tableaux """ - return "Semistandard skew tableaux" + if self.max_entry == PlusInfinity(): + return "Semistandard skew tableaux" + else: + return "Semistandard skew tableaux with maximum entry %s"%(repr(self.max_entry)) def __iter__(self): """ @@ -1730,6 +1812,25 @@ def __iter__(self): EXAMPLES:: + sage: it = SemistandardSkewTableaux(max_entry = 5).__iter__() + sage: [it.next() for x in range(12)] + [[], + [[1]], + [[2]], + [[3]], + [[4]], + [[5]], + [[1, 1]], + [[1, 2]], + [[1, 3]], + [[1, 4]], + [[1, 5]], + [[2, 2]]] + + If no max entry is specified, the iteration goes over all + semistandard skew tableaux of size `n` with max entry `n`, + for all `n`:: + sage: it = SemistandardSkewTableaux().__iter__() sage: [it.next() for x in range(10)] [[], @@ -1743,17 +1844,27 @@ def __iter__(self): [[None, 1], [2]], [[None, 2], [2]]] """ - n = 0 - while True: - for ssst in SemistandardSkewTableaux_size(n): - yield self.element_class(self, ssst) - n += 1 + if self.max_entry == PlusInfinity(): + # Old behavior, kept here for backwards compatibility. + # The usefulness of this iterator is questionable. + n = 0 + while True: + for ssst in SemistandardSkewTableaux_size(n, n): + yield self.element_class(self, ssst) + n += 1 + else: + n = 0 + while True: + for ssst in SemistandardSkewTableaux_size(n, self.max_entry): + yield self.element_class(self, ssst) + n += 1 class SemistandardSkewTableaux_size(SemistandardSkewTableaux): """ - Class of all semistandard skew tableaux of a fixed size `n`. + Class of all semistandard skew tableaux of a fixed size `n`, + possibly with a given maximum entry. """ - def __init__(self, n): + def __init__(self, n, max_entry): """ EXAMPLES:: @@ -1761,6 +1872,10 @@ def __init__(self, n): sage: TestSuite(S).run() """ self.n = n + if max_entry is None: + self.max_entry = n + else: + self.max_entry = max_entry SemistandardSkewTableaux.__init__(self, category=FiniteEnumeratedSets()) def _repr_(self): @@ -1768,9 +1883,11 @@ def _repr_(self): EXAMPLES:: sage: SemistandardSkewTableaux(3) - Semistandard skew tableaux of size 3 + Semistandard skew tableaux of size 3 and maximum entry 3 + sage: SemistandardSkewTableaux(3, max_entry=8) + Semistandard skew tableaux of size 3 and maximum entry 8 """ - return "Semistandard skew tableaux of size %s"%self.n + return "Semistandard skew tableaux of size %s and maximum entry %s"%(repr(self.n), repr(self.max_entry)) def cardinality(self): """ @@ -1781,7 +1898,7 @@ def cardinality(self): """ count = 0 for p in SkewPartitions(self.n): - count += SemistandardSkewTableaux_shape(p).cardinality() + count += SemistandardSkewTableaux_shape(p, self.max_entry).cardinality() return count def __iter__(self): @@ -1799,7 +1916,7 @@ def __iter__(self): [[None, 2], [2]]] """ for p in SkewPartitions(self.n): - for ssst in SemistandardSkewTableaux_shape(p): + for ssst in SemistandardSkewTableaux_shape(p, self.max_entry): yield self.element_class(self, ssst) class SemistandardSkewTableaux_size_weight(SemistandardSkewTableaux): @@ -1865,10 +1982,26 @@ def __iter__(self): class SemistandardSkewTableaux_shape(SemistandardSkewTableaux): r""" - Class of semistandard skew tableaux of a fixed skew shape `\lambda / \mu`. + Class of semistandard skew tableaux of a fixed skew shape + `\lambda / \mu` with a given max entry. + + A semistandard skew tableau with max entry `i` is required to have all + its entries less or equal to `i`. It is not required to actually + contain an entry `i`. + + INPUT: + + - ``p`` -- A skew partition + + - ``max_entry`` -- The max entry; defaults to the size of ``p``. + + .. WARNING:: + + Input is not checked; please use :class:`SemistandardSkewTableaux` to + ensure the options are properly parsed. """ @staticmethod - def __classcall_private__(cls, p): + def __classcall_private__(cls, p, max_entry=None): """ Normalize our input to ensure we have a unique representation. @@ -1879,9 +2012,11 @@ def __classcall_private__(cls, p): sage: S is S2 True """ - return super(SemistandardSkewTableaux_shape, cls).__classcall__(cls, SkewPartition(p)) + if max_entry is None: + max_entry = sum(p[0])-sum(p[1]) + return super(SemistandardSkewTableaux_shape, cls).__classcall__(cls, SkewPartition(p), max_entry) - def __init__(self, p): + def __init__(self, p, max_entry): """ EXAMPLES:: @@ -1891,6 +2026,7 @@ def __init__(self, p): sage: TestSuite(S).run() """ self.p = p + self.max_entry = max_entry SemistandardSkewTableaux.__init__(self, category=FiniteEnumeratedSets()) def _repr_(self): @@ -1898,9 +2034,9 @@ def _repr_(self): EXAMPLES:: sage: SemistandardSkewTableaux([[2,1],[]]) - Semistandard skew tableaux of shape [2, 1] / [] + Semistandard skew tableaux of shape [2, 1] / [] and maximum entry 3 """ - return "Semistandard skew tableaux of shape %s"%repr(self.p) + return "Semistandard skew tableaux of shape %s and maximum entry %s"%(repr(self.p), repr(self.max_entry)) def cardinality(self): """ @@ -1908,9 +2044,11 @@ def cardinality(self): sage: SemistandardSkewTableaux([[2,1],[]]).cardinality() 8 + sage: SemistandardSkewTableaux([[2,1],[]], max_entry=2).cardinality() + 2 """ count = 0 - for mu in IntegerVectors(self.p.size(), self.p.size()): + for mu in IntegerVectors(self.p.size(), self.max_entry): count += SemistandardSkewTableaux_shape_weight(self.p, mu).cardinality() return count @@ -1927,8 +2065,11 @@ def __iter__(self): [[1, 3], [3]], [[2, 2], [3]], [[2, 3], [3]]] + sage: from sage.combinat.skew_tableau import SemistandardSkewTableaux_shape + sage: SemistandardSkewTableaux_shape([[2,1],[]], max_entry=2).list() + [[[1, 1], [2]], [[1, 2], [2]]] """ - for mu in IntegerVectors(self.p.size(), self.p.size()): + for mu in IntegerVectors(self.p.size(), self.max_entry): for ssst in SemistandardSkewTableaux_shape_weight(self.p, mu): yield self.element_class(self, ssst) @@ -2034,7 +2175,7 @@ def SemistandardSkewTableaux_n(*args, **kargs): sage: sage.combinat.skew_tableau.SemistandardSkewTableaux_n(3) doctest:...: DeprecationWarning: this class is deprecated. Use SemistandardSkewTableaux_size instead See http://trac.sagemath.org/9265 for details. - Semistandard skew tableaux of size 3 + Semistandard skew tableaux of size 3 and maximum entry 3 """ from sage.misc.superseded import deprecation deprecation(9265,'this class is deprecated. Use SemistandardSkewTableaux_size instead') @@ -2060,7 +2201,7 @@ def SemistandardSkewTableaux_p(*args, **kargs): sage: sage.combinat.skew_tableau.SemistandardSkewTableaux_p([[2,1],[]]) doctest:1: DeprecationWarning: this class is deprecated. Use SemistandardSkewTableaux_shape instead See http://trac.sagemath.org/9265 for details. - Semistandard skew tableaux of shape [2, 1] / [] + Semistandard skew tableaux of shape [2, 1] / [] and maximum entry 3 """ from sage.misc.superseded import deprecation deprecation(9265,'this class is deprecated. Use SemistandardSkewTableaux_shape instead') diff --git a/src/sage/combinat/symmetric_group_representations.py b/src/sage/combinat/symmetric_group_representations.py index d126fa65118..7da84b9cade 100644 --- a/src/sage/combinat/symmetric_group_representations.py +++ b/src/sage/combinat/symmetric_group_representations.py @@ -321,8 +321,8 @@ def __eq__(self, other): return False return (self._ring,self._partition)==(other._ring,other._partition) # # both self and other must have caching enabled -# if self.__dict__.has_key('representation_matrix'): -# if not other.__dict__.has_key('representation_matrix'): +# if 'representation_matrix' in self.__dict__: +# if 'representation_matrix' not in other.__dict__: # return False # else: # for key in self.__dict__: @@ -332,7 +332,7 @@ def __eq__(self, other): # else: # return True # else: -# if other.__dict__.has_key('representation_matrix'): +# if 'representation_matrix' in other.__dict__: # return False # else: # return self.__dict__.__eq__(other.__dict__) diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index 77a747ac8f3..d193e250b24 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -4084,7 +4084,8 @@ class SemistandardTableaux(Tableaux): - ``size`` -- The size of the tableaux - ``shape`` -- The shape of the tableaux - - ``eval`` -- The weight (also called content or weight) of the tableaux + - ``eval`` -- The weight (also called content or evaluation) of + the tableaux - ``max_entry`` -- A maximum entry for the tableaux. This can be a positive integer or infinity (``oo``). If ``size`` or ``shape`` are specified, ``max_entry`` defaults to be ``size`` or the size of @@ -4093,7 +4094,7 @@ class SemistandardTableaux(Tableaux): Positional arguments: - The first argument is interpreted as either ``size`` or ``shape`` - according to whether it is an integer or a partition + according to whether it is an integer or a partition - The second keyword argument will always be interpreted as ``eval`` OUTPUT: @@ -4366,7 +4367,7 @@ def __init__(self, **kwds): sage: S = SemistandardTableaux() sage: TestSuite(S).run() """ - if kwds.has_key('max_entry'): + if 'max_entry' in kwds: self.max_entry = kwds['max_entry'] kwds.pop('max_entry') else: @@ -5705,20 +5706,19 @@ def __iter__(self): yield self.element_class(self, tableau) - if self.cardinality() == 1: - last_tableau = True - else: - last_tableau = False + # iterate until we reach the last tableau which is + # filled with the row indices. + last_tableau=flatten([ [row]*l for (row,l) in enumerate(pi)]) - while not last_tableau: - #Convert the tableau to "vector format" - #tableau_vector[i] is the row that number i - #is in - tableau_vector = [None]*size - for row in range(len(pi)): - for col in range(pi[row]): - tableau_vector[tableau[row][col]-1] = row + #Convert the tableau to "vector format" + #tableau_vector[i] is the row that number i + #is in + tableau_vector = [None]*size + for row in range(len(pi)): + for col in range(pi[row]): + tableau_vector[tableau[row][col]-1] = row + while tableau_vector!=last_tableau: #Locate the smallest integer j such that j is not #in the lowest corner of the subtableau T_j formed by #1,...,j. This happens to be first j such that @@ -5770,20 +5770,6 @@ def __iter__(self): yield self.element_class(self, tableau) - #Check to see if we are at the last tableau - #The last tableau if given by filling in the - #partition along the rows. For example, the - #last tableau corresponding to [3,2] is - #[[1,2,3], - # [4,5]] - last_tableau = True - i = 1 - for row in range(len(pi)): - for col in range(pi[row]): - if tableau[row][col] != i: - last_tableau = False - i += 1 - return diff --git a/src/sage/combinat/words/finite_word.py b/src/sage/combinat/words/finite_word.py index 9ab08cbc786..8a660bf7f7e 100644 --- a/src/sage/combinat/words/finite_word.py +++ b/src/sage/combinat/words/finite_word.py @@ -6128,7 +6128,7 @@ def letters(self): """ seen, res = {}, [] for x in self: - if not seen.has_key(x): + if x not in seen: res.append(x) seen[x] = True return res diff --git a/src/sage/combinat/words/suffix_trees.py b/src/sage/combinat/words/suffix_trees.py index f9c81166822..eef36dc2b7c 100644 --- a/src/sage/combinat/words/suffix_trees.py +++ b/src/sage/combinat/words/suffix_trees.py @@ -113,7 +113,7 @@ def _process_letter(self, letter): # While r is not the auxiliary vertex, or # there is not transition from r along letter, ... while r != -1 and \ - not self._transition_function.has_key((r,letter)): + (r,letter) not in self._transition_function: # adjoin a new state s s = len(self._suffix_link) self._suffix_link.append(None) @@ -748,7 +748,7 @@ def _find_transition(self, state, letter): if state == -1: return ((0, 0), 0) else: - if self._transition_function.has_key(state): + if state in self._transition_function: for ((k,p),s) in self._transition_function[state].iteritems(): if self._letters[k-1] == letter: return ((k,p), s) @@ -1020,7 +1020,7 @@ def suffix_link(self, state): ... TypeError: there is no suffix link from -1 """ - if self._suffix_link.has_key(state): + if state in self._suffix_link: return self._suffix_link[state] else: raise TypeError, "there is no suffix link from %s" % state diff --git a/src/sage/combinat/words/word_infinite_datatypes.py b/src/sage/combinat/words/word_infinite_datatypes.py index 2de3140babb..930dad6ed0a 100644 --- a/src/sage/combinat/words/word_infinite_datatypes.py +++ b/src/sage/combinat/words/word_infinite_datatypes.py @@ -357,7 +357,7 @@ def __iter__(self): letter_cache = self._letter_cache func = self._func for x in domain: - if not letter_cache.has_key(x): + if x not in letter_cache: letter_cache[x] = func(x) yield letter_cache[x] @@ -491,7 +491,7 @@ def __getitem__(self, key): if isinstance(key, slice): return super(WordDatatype_callable_with_caching, self).__getitem__(key) else: - if not self._letter_cache.has_key(key): + if key not in self._letter_cache: self._letter_cache[key] = \ super(WordDatatype_callable_with_caching, self).__getitem__(key) return self._letter_cache[key] diff --git a/src/sage/combinat/yang_baxter_graph.py b/src/sage/combinat/yang_baxter_graph.py index f21a6f4f955..11641432f7d 100644 --- a/src/sage/combinat/yang_baxter_graph.py +++ b/src/sage/combinat/yang_baxter_graph.py @@ -384,9 +384,9 @@ def plot(self, *args, **kwds): sage: Y.plot() sage: Y.plot(edge_labels=False) """ - if not kwds.has_key("edge_labels"): + if "edge_labels" not in kwds: kwds["edge_labels"] = True - if not kwds.has_key("vertex_labels"): + if "vertex_labels" not in kwds: kwds["vertex_labels"] = True return self._digraph.plot(*args, **kwds) diff --git a/src/sage/crypto/boolean_function.pyx b/src/sage/crypto/boolean_function.pyx index 3d4ff835adf..41f43833db6 100644 --- a/src/sage/crypto/boolean_function.pyx +++ b/src/sage/crypto/boolean_function.pyx @@ -714,7 +714,7 @@ cdef class BooleanFunction(SageObject): """ d = {} for i in self.walsh_hadamard_transform(): - if d.has_key(abs(i)): + if abs(i) in d: d[abs(i)] += 1 else: d[abs(i)] = 1 @@ -885,7 +885,7 @@ cdef class BooleanFunction(SageObject): """ d = {} for i in self.autocorrelation(): - if d.has_key(abs(i)): + if abs(i) in d: d[abs(i)] += 1 else: d[abs(i)] = 1 diff --git a/src/sage/doctest/forker.py b/src/sage/doctest/forker.py index bb2d9ae1f7b..ea250cd3433 100644 --- a/src/sage/doctest/forker.py +++ b/src/sage/doctest/forker.py @@ -791,7 +791,7 @@ def execute(self, example, compiled, globs): sage: filename = os.path.join(SAGE_SRC,'sage','doctest','forker.py') sage: FDS = FileDocTestSource(filename,DD) sage: globs = RecordingDict(globals()) - sage: globs.has_key('doctest_var') + sage: 'doctest_var' in globs False sage: doctests, extras = FDS.create_doctests(globs) sage: ex0 = doctests[0].examples[0] @@ -1285,7 +1285,7 @@ def update_results(self, D): [('cputime', [...]), ('err', None), ('failures', 0), ('walltime', [...])] """ for key in ["cputime","walltime"]: - if not D.has_key(key): + if key not in D: D[key] = [] if hasattr(self, key): D[key].append(self.__dict__[key]) diff --git a/src/sage/dynamics/interval_exchanges/constructors.py b/src/sage/dynamics/interval_exchanges/constructors.py index 1ef34c00824..9e9dc83370b 100644 --- a/src/sage/dynamics/interval_exchanges/constructors.py +++ b/src/sage/dynamics/interval_exchanges/constructors.py @@ -792,11 +792,11 @@ def RauzyDiagram(*args, **kargs): sage: w2[:20] == w1 True """ - if not kargs.has_key('reduced'): + if 'reduced' not in kargs: kargs['reduced'] = False - if not kargs.has_key('flips'): + if 'flips' not in kargs: kargs['flips'] = [] - if not kargs.has_key('alphabet'): + if 'alphabet' not in kargs: kargs['alphabet'] = None p = GeneralizedPermutation( @@ -805,15 +805,15 @@ def RauzyDiagram(*args, **kargs): flips = kargs['flips'], alphabet = kargs['alphabet']) - if not kargs.has_key('right_induction'): + if 'right_induction' not in kargs: kargs['right_induction'] = True - if not kargs.has_key('left_induction'): + if 'left_induction' not in kargs: kargs['left_induction'] = False - if not kargs.has_key('left_right_inversion'): + if 'left_right_inversion' not in kargs: kargs['left_right_inversion'] = False - if not kargs.has_key('top_bottom_inversion'): + if 'top_bottom_inversion' not in kargs: kargs['top_bottom_inversion'] = False - if not kargs.has_key('symmetric'): + if 'symmetric' not in kargs: kargs['symmetric'] = False return p.rauzy_diagram( diff --git a/src/sage/dynamics/interval_exchanges/labelled.py b/src/sage/dynamics/interval_exchanges/labelled.py index e52b583bd29..17760d30ff9 100644 --- a/src/sage/dynamics/interval_exchanges/labelled.py +++ b/src/sage/dynamics/interval_exchanges/labelled.py @@ -356,7 +356,7 @@ def _reversed(self): 3 2 1 2 1 3 """ - if self.__dict__.has_key('_twin'): + if '_twin' in self.__dict__: del self.__dict__['_twin'] if self._hash is not None: self._hash = None @@ -381,7 +381,7 @@ def _inversed(self): 3 1 2 1 2 3 """ - if self.__dict__.has_key('_twin'): + if '_twin' in self.__dict__: del self.__dict__['_twin'] if self._hash is not None: self._hash = None diff --git a/src/sage/env.py b/src/sage/env.py index e281e043e99..89dddc0be85 100644 --- a/src/sage/env.py +++ b/src/sage/env.py @@ -100,6 +100,7 @@ def _add_variable_or_fallback(key, fallback, force=False): _add_variable_or_fallback('SAGE_SPKG_INST', opj('$SAGE_LOCAL', 'var', 'lib', 'sage', 'installed')) _add_variable_or_fallback('SAGE_DOC', opj('$SAGE_SRC', 'doc')) _add_variable_or_fallback('DOT_SAGE', opj(os.environ.get('HOME','$SAGE_ROOT'), '.sage')) +_add_variable_or_fallback('PYTHON_EGG_CACHE',opj('$DOT_SAGE','.python-eggs')) _add_variable_or_fallback('SAGE_DOT_GIT', opj('$SAGE_ROOT', '.git')) # misc diff --git a/src/sage/ext/interactive_constructors_c.pyx b/src/sage/ext/interactive_constructors_c.pyx index a71dce92df6..7d564a501d7 100644 --- a/src/sage/ext/interactive_constructors_c.pyx +++ b/src/sage/ext/interactive_constructors_c.pyx @@ -93,7 +93,7 @@ cdef _inject(X, do): return X cdef _do_inject(kwds): - if kwds.has_key('inject'): + if 'inject' in kwds: s = kwds['inject'] del kwds['inject'] return s == True diff --git a/src/sage/functions/transcendental.py b/src/sage/functions/transcendental.py index 00de106782a..429652448ae 100644 --- a/src/sage/functions/transcendental.py +++ b/src/sage/functions/transcendental.py @@ -407,7 +407,7 @@ def _eval_(self, x): elif x <= 2: return 1 - x.log() n = x.floor() - if self._cur_prec < x.parent().prec() or not self._f.has_key(n): + if self._cur_prec < x.parent().prec() or n not in self._f: self._cur_prec = rel_prec = x.parent().prec() # Go a bit beyond so we're not constantly re-computing. max = x.parent()(1.1)*x + 10 diff --git a/src/sage/geometry/hyperplane_arrangement/plot.py b/src/sage/geometry/hyperplane_arrangement/plot.py index 43e5a709331..a6ea8ab836d 100644 --- a/src/sage/geometry/hyperplane_arrangement/plot.py +++ b/src/sage/geometry/hyperplane_arrangement/plot.py @@ -145,14 +145,14 @@ def plot(hyperplane_arrangement, **kwds): elif dim not in [1,2,3]: # revise to handle 4d return # silently # handle extra keywords - if kwds.has_key('hyperplane_colors'): + if 'hyperplane_colors' in kwds: hyp_colors = kwds.pop('hyperplane_colors') if not type(hyp_colors) == list: # we assume its a single color then hyp_colors = [hyp_colors] * N else: HSV_tuples = [(i*1.0/N, 0.8, 0.9) for i in range(N)] hyp_colors = map(lambda x: hsv_to_rgb(*x), HSV_tuples) - if kwds.has_key('hyperplane_labels'): + if 'hyperplane_labels' in kwds: hyp_labels = kwds.pop('hyperplane_labels') has_hyp_label = True if not type(hyp_labels) == list: # we assume its a boolean then @@ -166,27 +166,27 @@ def plot(hyperplane_arrangement, **kwds): hyp_labels = relabeled else: has_hyp_label = False - if kwds.has_key('label_colors'): + if 'label_colors' in kwds: label_colors = kwds.pop('label_colors') has_label_color = True if not type(label_colors) == list: # we assume its a single color then label_colors = [label_colors] * N else: has_label_color = False - if kwds.has_key('label_fontsize'): + if 'label_fontsize' in kwds: label_fontsize = kwds.pop('label_fontsize') has_label_fontsize = True if not type(label_fontsize) == list: # we assume its a single size then label_fontsize = [label_fontsize] * N else: has_label_fontsize = False - if kwds.has_key('label_offsets'): + if 'label_offsets' in kwds: has_offsets = True offsets = kwds.pop('label_offsets') else: has_offsets = False # give default values below hyperplane_legend = kwds.pop('hyperplane_legend', 'long' if dim < 3 else False) - if kwds.has_key('hyperplane_opacities'): + if 'hyperplane_opacities' in kwds: hyperplane_opacities = kwds.pop('hyperplane_opacities') has_opacity = True if not type(hyperplane_opacities) == list: # we assume a single number then @@ -196,7 +196,7 @@ def plot(hyperplane_arrangement, **kwds): point_sizes = kwds.pop('point_sizes', 50) if not type(point_sizes) == list: point_sizes = [point_sizes] * N - if kwds.has_key('ranges'): + if 'ranges' in kwds: ranges_set = True ranges = kwds.pop('ranges') if not type(ranges) in [list,tuple]: # ranges is a single number @@ -344,7 +344,7 @@ def plot_hyperplane(hyperplane, **kwds): elif hyperplane.dimension() not in [0, 1, 2]: # dimension of hyperplane, not ambient space raise ValueError('can only plot hyperplanes in dimensions 1, 2, 3') # handle extra keywords - if kwds.has_key('hyperplane_label'): + if 'hyperplane_label' in kwds: hyp_label = kwds.pop('hyperplane_label') if hyp_label == False: has_hyp_label = False @@ -361,24 +361,24 @@ def plot_hyperplane(hyperplane, **kwds): label = hyperplane._latex_() else: label = hyp_label # a string - if kwds.has_key('label_color'): + if 'label_color' in kwds: label_color = kwds.pop('label_color') else: label_color = 'black' - if kwds.has_key('label_fontsize'): + if 'label_fontsize' in kwds: label_fontsize = kwds.pop('label_fontsize') else: label_fontsize = 14 - if kwds.has_key('label_offset'): + if 'label_offset' in kwds: has_offset = True label_offset = kwds.pop('label_offset') else: has_offset = False # give default values below - if kwds.has_key('point_size'): + if 'point_size' in kwds: pt_size = kwds.pop('point_size') else: pt_size = 50 - if kwds.has_key('ranges'): + if 'ranges' in kwds: ranges_set = True ranges = kwds.pop('ranges') else: @@ -395,7 +395,7 @@ def plot_hyperplane(hyperplane, **kwds): p += text(label, (d/x,label_offset), color=label_color,fontsize=label_fontsize) p += text('',(d/x,label_offset+0.4)) # add space at top - if not kwds.has_key('ymax'): + if 'ymax' not in kwds: kwds['ymax'] = 0.5 elif hyperplane.dimension() == 1: # a line in the plane pnt = hyperplane.point() diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index be4ceb630b5..41d18925993 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -584,7 +584,7 @@ def __reduce__(self): state.pop('_desc') state.pop('_distances', None) state.pop('_skeleton', None) - if state.has_key('_points'): + if '_points' in state: state['_npoints'] = state.pop('_points').ncols() return (LatticePolytope, (self._vertices, self._desc, False, False), state) @@ -599,7 +599,7 @@ def __setstate__(self, state): True """ self.__dict__.update(state) - if state.has_key('_faces'): # Faces do not remember polytopes + if '_faces' in state: # Faces do not remember polytopes for d_faces in self._faces: for face in d_faces: face._polytope = self @@ -694,10 +694,10 @@ def _compute_faces(self): sage: o = lattice_polytope.octahedron(3) sage: v = o.__dict__.pop("_faces", None) # faces may be cached already - sage: o.__dict__.has_key("_faces") + sage: "_faces" in o.__dict__ False sage: o._compute_faces() - sage: o.__dict__.has_key("_faces") + sage: "_faces" in o.__dict__ True Check that Trac 8934 is fixed:: @@ -831,10 +831,10 @@ def _face_compute_points(self, face): sage: o = lattice_polytope.octahedron(3) sage: e = o.faces(dim=1)[0] sage: v = e.__dict__.pop("_points", None) # points may be cached already - sage: e.__dict__.has_key("_points") + sage: "_points" in e.__dict__ False sage: o._face_compute_points(e) - sage: e.__dict__.has_key("_points") + sage: "_points" in e.__dict__ True """ m = self.distances().matrix_from_rows(face._facets) @@ -853,10 +853,10 @@ def _face_split_points(self, face): sage: c = lattice_polytope.octahedron(3).polar() sage: f = c.facets()[0] sage: v = f.__dict__.pop("_interior_points", None) - sage: f.__dict__.has_key("_interior_points") + sage: "_interior_points" in f.__dict__ False sage: v = f.__dict__.pop("_boundary_points", None) - sage: f.__dict__.has_key("_boundary_points") + sage: "_boundary_points" in f.__dict__ False sage: c._face_split_points(f) sage: f._interior_points @@ -1082,7 +1082,7 @@ def _read_equations(self, data): 2 -1 -1 2 -1 -1 - sage: p.__dict__.has_key("_polar") + sage: "_polar" in p.__dict__ False sage: p._read_equations(s) sage: p._polar._vertices @@ -1095,9 +1095,9 @@ def _read_equations(self, data): sage: p.vertices() [ 1 0 -1] [ 0 2 -3] - sage: p.__dict__.has_key("_facet_normals") + sage: "_facet_normals" in p.__dict__ False - sage: p.__dict__.has_key("_facet_constants") + sage: "_facet_constants" in p.__dict__ False sage: s = p.poly_x("e") sage: print s @@ -1170,7 +1170,7 @@ def _read_faces(self, data): f[1]: 00000011 00000101 00010001 00001010 00100010 00001100 01000100 10001000 00110000 01010000 10100000 11000000 f[2]: 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000 sage: v = o.__dict__.pop("_faces", None) - sage: o.__dict__.has_key("_faces") + sage: "_faces" in o.__dict__ False sage: o._read_faces(s) sage: o._faces @@ -1267,7 +1267,7 @@ def _read_nef_partitions(self, data): destroy cache integrity and lead so strange effects in other doctests:: sage: o_copy = LatticePolytope(o.vertices()) - sage: o_copy.__dict__.has_key("_nef_partitions") + sage: "_nef_partitions" in o_copy.__dict__ False sage: o_copy._read_nef_partitions(s) sage: o_copy._nef_partitions @@ -3698,9 +3698,9 @@ def __reduce__(self): state.pop('_polytope') state.pop('_vertices') state.pop('_facets') - if state.has_key('_points'): + if '_points' in state: state['_npoints'] = len(state.pop('_points')) - if state.has_key('_interior_points'): + if '_interior_points' in state: state['_ninterior_points'] = len(state.pop('_interior_points')) state.pop('_boundary_points') # Reference to the polytope is not pickled - the polytope will restore it @@ -4624,7 +4624,7 @@ def octahedron(dim): sage: o is lattice_polytope.octahedron(4) True """ - if _octahedrons.has_key(dim): + if dim in _octahedrons: return _octahedrons[dim] else: _octahedrons[dim] = _create_octahedron(dim) diff --git a/src/sage/graphs/base/c_graph.pyx b/src/sage/graphs/base/c_graph.pyx index 140d7aba784..c345fd269be 100644 --- a/src/sage/graphs/base/c_graph.pyx +++ b/src/sage/graphs/base/c_graph.pyx @@ -2387,7 +2387,7 @@ class CGraphBackend(GenericGraphBackend): sage: g = 2*graphs.RandomGNP(20,.3) sage: paths = g._backend.shortest_path_all_vertices(0) - sage: all([ (not paths.has_key(v) and g.distance(0,v) == +Infinity) or len(paths[v])-1 == g.distance(0,v) for v in g]) + sage: all([ (v not in paths and g.distance(0,v) == +Infinity) or len(paths[v])-1 == g.distance(0,v) for v in g]) True """ cdef list current_layer @@ -3011,7 +3011,7 @@ cdef class Search_iterator: self.stack = [v_id] - if not self.graph.directed: + if not self.graph._directed: ignore_direction = False self.test_out = (not reverse) or ignore_direction diff --git a/src/sage/graphs/base/static_sparse_backend.pxd b/src/sage/graphs/base/static_sparse_backend.pxd index f1f45205fcd..2d9051057c7 100644 --- a/src/sage/graphs/base/static_sparse_backend.pxd +++ b/src/sage/graphs/base/static_sparse_backend.pxd @@ -7,7 +7,7 @@ include 'sage/ext/stdsage.pxi' cdef class StaticSparseCGraph(CGraph): cdef short_digraph g cdef short_digraph g_rev - cdef bint directed + cdef bint _directed cpdef bint has_vertex(self, int n) cdef int add_vertex_unsafe(self, int k) diff --git a/src/sage/graphs/base/static_sparse_backend.pyx b/src/sage/graphs/base/static_sparse_backend.pyx index 14c21c21960..85af27fc10b 100644 --- a/src/sage/graphs/base/static_sparse_backend.pyx +++ b/src/sage/graphs/base/static_sparse_backend.pyx @@ -63,10 +63,10 @@ cdef class StaticSparseCGraph(CGraph): sage: g = StaticSparseCGraph(graphs.PetersenGraph()) """ has_labels = any(not l is None for _,_,l in G.edge_iterator()) - self.directed = G.is_directed() + self._directed = G.is_directed() init_short_digraph(self.g, G, edge_labelled = has_labels) - if self.directed: + if self._directed: init_reverse(self.g_rev,self.g) # Defining the meaningless set of 'active' vertices. Because of CGraph. @@ -191,7 +191,7 @@ cdef class StaticSparseCGraph(CGraph): return -1 if size < degree else degree cdef int in_neighbors_unsafe(self, int u, int *neighbors, int size) except? -2: - if not self.directed: + if not self._directed: return self.out_neighbors_unsafe(u,neighbors,size) cdef int degree = self.g_rev.neighbors[u+1] - self.g_rev.neighbors[u] @@ -236,7 +236,7 @@ cdef class StaticSparseCGraph(CGraph): sage: g.in_neighbors(0) [1, 4, 5] """ - if not self.directed: + if not self._directed: return self.out_neighbors(u) if u<0 or u>self.g.n: @@ -283,7 +283,7 @@ cdef class StaticSparseCGraph(CGraph): if u<0 or u>self.g.n: raise LookupError("The vertex does not belong to the graph") - if not self.directed: + if not self._directed: return self.g.neighbors[u+1] - self.g.neighbors[u] else: return self.g_rev.neighbors[u+1] - self.g_rev.neighbors[u] @@ -364,12 +364,16 @@ class StaticSparseBackend(CGraphBackend): [1] sage: g.edges() [(1, 1, 1), (1, 1, 2), (1, 1, 3)] + + :trac:`15810` is fixed:: + + sage: DiGraph({1:{2:['a','b'], 3:['c']}, 2:{3:['d']}}, immutable=True).is_directed_acyclic() + True """ cdef StaticSparseCGraph cg = StaticSparseCGraph(G) self._cg = cg - # .directed and not ._directed. Because of CGraph. - self.directed = cg.directed + self._directed = cg._directed vertices = G.vertices() self._order = len(vertices) @@ -430,7 +434,7 @@ class StaticSparseBackend(CGraphBackend): sage: loads(dumps(gi)) == gi True """ - if self.directed: + if self._directed: from sage.graphs.digraph import DiGraph G = DiGraph(loops=self._loops, multiedges=self._multiedges) G.add_edges(list(self.iterator_out_edges(self.iterator_verts(None),True))) @@ -615,7 +619,7 @@ class StaticSparseBackend(CGraphBackend): [(1, 2, None)] """ cdef StaticSparseCGraph cg = self._cg - if not cg.directed: + if not cg._directed: for x in self.iterator_out_edges(vertices, labels): yield x return @@ -795,7 +799,7 @@ class StaticSparseBackend(CGraphBackend): cdef StaticSparseCGraph cg = self._cg if directed: - if cg.directed: + if cg._directed: # Returns the real number of directed arcs return int(cg.g.m) else: @@ -804,7 +808,7 @@ class StaticSparseBackend(CGraphBackend): # cg.g.neighbors[cg.g.n] in the array `cg.g.edges` return int(cg.g.neighbors[cg.g.n]-cg.g.edges) else: - if cg.directed: + if cg._directed: raise NotImplementedError("Sorry, I have no idea what is expected " "in this situation. I don't think " "that it is well-defined either, " @@ -892,12 +896,12 @@ class StaticSparseBackend(CGraphBackend): cdef StaticSparseCGraph cg = self._cg if directed: - if cg.directed: + if cg._directed: return cg.in_degree(v) + cg.out_degree(v) else: return 2*cg.out_degree(v) else: - if cg.directed: + if cg._directed: raise NotImplementedError("Sorry, I have no idea what is expected " "in this situation. I don't think " "that it is well-defined either, " @@ -926,7 +930,7 @@ class StaticSparseBackend(CGraphBackend): cdef StaticSparseCGraph cg = self._cg - if cg.directed: + if cg._directed: return cg.in_degree(v) else: return cg.out_degree(v) @@ -1026,7 +1030,7 @@ class StaticSparseBackend(CGraphBackend): cdef StaticSparseCGraph cg = self._cg cdef short_digraph g - if cg.directed: + if cg._directed: for i in range(out_degree(cg.g_rev,v)): yield self._vertex_to_labels[cg.g_rev.neighbors[v][i]] else: diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index f869bb07cfc..d95e96e8c95 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -919,7 +919,6 @@ def __init__(self, data=None, pos=None, loops=None, format=None, self._weighted = weighted self.allow_loops(loops, check=False) self.allow_multiple_edges(multiedges, check=False) - self._backend.directed = True else: raise NotImplementedError("Supported implementations: networkx, c_graph.") diff --git a/src/sage/graphs/generators/intersection.py b/src/sage/graphs/generators/intersection.py index b479d5b1354..0195f128c3a 100644 --- a/src/sage/graphs/generators/intersection.py +++ b/src/sage/graphs/generators/intersection.py @@ -110,38 +110,64 @@ def IntervalGraph(intervals, points_ordered = False): def PermutationGraph(second_permutation, first_permutation = None): r""" - Builds a permutation graph from one (or two) permutations. - - General definition - - A Permutation Graph can be encoded by a permutation `\sigma` - of `1, ..., n`. It is then built in the following way : - - Take two horizontal lines in the euclidean plane, and mark points `1, ..., - n` from left to right on the first of them. On the second one, still from - left to right, mark point in the order in which they appear in `\sigma`. - Now, link by a segment the two points marked with 1, then link together - the points marked with 2, and so on. The permutation graph defined by the - permutation is the intersection graph of those segments : there exists a - point in this graph for each element from `1` to `n`, two vertices `i, j` - being adjacent if the segments `i` and `j` cross each other. - - The set of edges of the resulting graph is equal to the set of inversions of - the inverse of the given permutation. + Build a permutation graph from one permutation or from two lists. + + Definition: + + If `\sigma` is a permutation of `\{ 1, 2, \ldots, n \}`, then the + permutation graph of `\sigma` is the graph on vertex set + `\{ 1, 2, \ldots, n \}` in which two vertices `i` and `j` satisfying + `i < j` are connected by an edge if and only if + `\sigma^{-1}(i) > \sigma^{-1}(j)`. A visual way to construct this + graph is as follows: + + Take two horizontal lines in the euclidean plane, and mark points + `1, ..., n` from left to right on the first of them. On the second + one, still from left to right, mark `n` points + `\sigma(1), \sigma(2), \ldots, \sigma(n)`. + Now, link by a segment the two points marked with `1`, then link + together the points marked with `2`, and so on. The permutation + graph of `\sigma` is the intersection graph of those segments: there + exists a vertex in this graph for each element from `1` to `n`, two + vertices `i, j` being adjacent if the segments `i` and `j` cross + each other. + + The set of edges of the permutation graph can thus be identified with + the set of inversions of the inverse of the given permutation + `\sigma`. + + A more general notion of permutation graph can be defined as + follows: If `S` is a set, and `(a_1, a_2, \ldots, a_n)` and + `(b_1, b_2, \ldots, b_n)` are two lists of elements of `S`, each of + which lists contains every element of `S` exactly once, then the + permutation graph defined by these two lists is the graph on the + vertex set `S` in which two vertices `i` and `j` are connected by an + edge if and only if the order in which these vertices appear in the + list `(a_1, a_2, \ldots, a_n)` is the opposite of the order in which + they appear in the list `(b_1, b_2, \ldots, b_n)`. When + `(a_1, a_2, \ldots, a_n) = (1, 2, \ldots, n)`, this graph is the + permutation graph of the permutation + `(b_1, b_2, \ldots, b_n) \in S_n`. Notice that `S` does not have to + be a set of integers here, but can be a set of strings, tuples, or + anything else. We can still use the above visual description to + construct the permutation graph, but now we have to mark points + `a_1, a_2, \ldots, a_n` from left to right on the first horizontal + line and points `b_1, b_2, \ldots, b_n` from left to right on the + second horizontal line. INPUT: - - ``second_permutation`` -- the permutation from which the graph should be - built. It corresponds to the ordering of the elements on the second line - (see previous definition) + - ``second_permutation`` -- the unique permutation/list defining the graph, + or the second of the two (if the graph is to be built from two + permutations/lists). - - ``first_permutation`` (optional) -- the ordering of the elements on the - *first* line. This is useful when the elements have no natural ordering, - for instance when they are strings, or tuples, or anything else. + - ``first_permutation`` (optional) -- the first of the two + permutations/lists from which the graph should be built, if it is to be + built from two permutations/lists. - When ``first_permutation == None`` (default), it is set to be equal to - ``sorted(second_permutation)``, which just yields the expected - ordering when the elements of the graph are integers. + When ``first_permutation is None`` (default), it is set to be equal to + ``sorted(second_permutation)``, which yields the expected ordering when + the elements of the graph are integers. .. SEEALSO: @@ -158,13 +184,61 @@ def PermutationGraph(second_permutation, first_permutation = None): - :meth:`~sage.combinat.permutation.Permutation.inversions` - EXAMPLE:: + EXAMPLES:: sage: p = Permutations(5).random_element() - sage: edges = graphs.PermutationGraph(p).edges(labels =False) + sage: PG = graphs.PermutationGraph(p) + sage: edges = PG.edges(labels=False) sage: set(edges) == set(p.inverse().inversions()) True + sage: PG = graphs.PermutationGraph([3,4,5,1,2]) + sage: sorted(PG.edges()) + [(1, 3, None), + (1, 4, None), + (1, 5, None), + (2, 3, None), + (2, 4, None), + (2, 5, None)] + sage: PG = graphs.PermutationGraph([3,4,5,1,2], [1,4,2,5,3]) + sage: sorted(PG.edges()) + [(1, 3, None), + (1, 4, None), + (1, 5, None), + (2, 3, None), + (2, 5, None), + (3, 4, None), + (3, 5, None)] + sage: PG = graphs.PermutationGraph([1,4,2,5,3], [3,4,5,1,2]) + sage: sorted(PG.edges()) + [(1, 3, None), + (1, 4, None), + (1, 5, None), + (2, 3, None), + (2, 5, None), + (3, 4, None), + (3, 5, None)] + + sage: PG = graphs.PermutationGraph(Permutation([1,3,2]), Permutation([1,2,3])) + sage: sorted(PG.edges()) + [(2, 3, None)] + + sage: graphs.PermutationGraph([]).edges() + [] + sage: graphs.PermutationGraph([], []).edges() + [] + + sage: PG = graphs.PermutationGraph("graph", "phrag") + sage: sorted(PG.edges()) + [('a', 'g', None), + ('a', 'h', None), + ('a', 'p', None), + ('g', 'h', None), + ('g', 'p', None), + ('g', 'r', None), + ('h', 'r', None), + ('p', 'r', None)] + TESTS:: sage: graphs.PermutationGraph([1, 2, 3], [4, 5, 6]) @@ -186,8 +260,6 @@ def PermutationGraph(second_permutation, first_permutation = None): from sage.combinat.permutation import Permutation p2 = Permutation(map(lambda x:vertex_to_index[x], second_permutation)) - p1 = Permutation(map(lambda x:vertex_to_index[x], first_permutation)) - p2 = p2 * p1.inverse() p2 = p2.inverse() g = Graph(name="Permutation graph for "+str(second_permutation)) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index b12e6215450..9b2a819f1de 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -4050,7 +4050,7 @@ def genus(self, set_embedding=True, on_embedding=None, minimal=True, maximal=Fal g += genus.simple_connected_graph_genus(H, set_embedding = True, check = False, minimal = True) emb = H.get_embedding() for v in emb: - if embedding.has_key(v): + if v in embedding: embedding[v] += emb[v] else: embedding[v] = emb[v] @@ -5289,7 +5289,7 @@ def edge_cut(self, s, t, value_only=True, use_edge_labels=False, vertices=False, l0 = [] l1 = [] for x in g.vertex_iterator(): - if v.has_key(x) and v[x] == 1: + if x in v and v[x] == 1: l1.append(x) else: l0.append(x) @@ -5410,8 +5410,8 @@ def vertex_cut(self, s, t, value_only=True, vertices=False, solver=None, verbose l1 = [] for x in g.vertex_iterator(): # if the vertex is not in the cut - if not (b.has_key(x) and b[x] == 1): - if (v.has_key(x) and v[x] == 1): + if not (x in b and b[x] == 1): + if (x in v and v[x] == 1): l1.append(x) else: l0.append(x) @@ -6309,7 +6309,7 @@ def traveling_salesman_problem(self, use_edge_labels = False, solver = None, con # the weights of the parallel edges # new value *if* ( none other *or* new==None and last > 1 *else* change nothing - e[(u,v)] = l if (not e.has_key((u,v)) or ( (l is None or l == {}) and e[(u,v)] > 1 )) else e[(u,v)] + e[(u,v)] = l if ((u,v) not in e or ( (l is None or l == {}) and e[(u,v)] > 1 )) else e[(u,v)] g.add_edges([(u,v) for (u,v),l in e.iteritems()]) @@ -15554,10 +15554,10 @@ def plot3d(self, bgcolor=(1,1,1), edge_colors = { (0,0,0) : self.edges() } # by default turn off the frame - if not kwds.has_key('frame'): + if 'frame' not in kwds: kwds['frame'] = False # by default make the background given by bgcolor - if not kwds.has_key('background'): + if 'background' not in kwds: kwds['background'] = bgcolor try: graphic = 0 @@ -17122,6 +17122,16 @@ def automorphism_group(self, partition=None, verbosity=0, Permutation Group with generators [()] sage: Graph({'a':['a'], 'b':[]}).automorphism_group().domain() {'a', 'b'} + + We can check that the subgroups are labelled correctly + (:trac:`15656`):: + + sage: G1 = Graph(':H`ECw@HGXGAGUG`e') + sage: G = G1.automorphism_group() + sage: G.subgroups() + [Subgroup of (Permutation Group with generators [(0,7)(1,4)(2,3)(6,8)]) generated by [()], + Subgroup of (Permutation Group with generators [(0,7)(1,4)(2,3)(6,8)]) generated by [(0,7)(1,4)(2,3)(6,8)]] + """ from sage.groups.perm_gps.partn_ref.refinement_graphs import search_tree from sage.groups.perm_gps.permgroup import PermutationGroup diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index a3f1dcdbcda..4d153051bbd 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -1542,7 +1542,6 @@ def __init__(self, data=None, pos=None, loops=None, format=None, self._weighted = weighted self.allow_loops(loops, check=False) self.allow_multiple_edges(multiedges, check=False) - self._backend.directed = False else: raise NotImplementedError("Supported implementations: networkx, c_graph.") diff --git a/src/sage/graphs/graph_coloring.py b/src/sage/graphs/graph_coloring.py index ad56304c9d4..52977df5a49 100644 --- a/src/sage/graphs/graph_coloring.py +++ b/src/sage/graphs/graph_coloring.py @@ -210,7 +210,7 @@ def all_graph_colorings(G,n,count_only=False, hex_colors=False, vertex_color_dic coloring = {} if vertex_color_dict: for x in a: - if colormap.has_key(x): + if x in colormap: v,c = colormap[x] if hex_colors: coloring[v] = colors[c] @@ -218,15 +218,15 @@ def all_graph_colorings(G,n,count_only=False, hex_colors=False, vertex_color_dic coloring[v] = color_dict[colors[c]] else: for x in a: - if colormap.has_key(x): + if x in colormap: v,c = colormap[x] if hex_colors: - if coloring.has_key(colors[c]): + if colors[c] in coloring: coloring[colors[c]].append(v) else: coloring[colors[c]] = [v] else: - if coloring.has_key(color_dict[colors[c]]): + if color_dict[colors[c]] in coloring: coloring[color_dict[colors[c]]].append(v) else: coloring[color_dict[colors[c]]] = [v] diff --git a/src/sage/graphs/graph_latex.py b/src/sage/graphs/graph_latex.py index 8dbd8e02715..ea818e34cba 100644 --- a/src/sage/graphs/graph_latex.py +++ b/src/sage/graphs/graph_latex.py @@ -1668,34 +1668,34 @@ def tkz_picture(self): for u in vertex_list: # c = dvc - if vertex_colors.has_key(u): + if u in vertex_colors: c = cc.to_rgb(vertex_colors[u]) v_color[ u ] = c # c = dvfc - if vertex_fill_colors.has_key(u): + if u in vertex_fill_colors: c = cc.to_rgb(vertex_fill_colors[u]) vf_color[u] = c # sh = dsh - if vertex_shapes.has_key(u): + if u in vertex_shapes: sh = vertex_shapes[u] v_shape[u] = sh # vs = dvs - if vertex_sizes.has_key(u): + if u in vertex_sizes: vs = vertex_sizes[u] v_size[u] = vs # if vertex_labels: # c = dvlc - if vertex_label_colors.has_key(u): + if u in vertex_label_colors: c = cc.to_rgb(vertex_label_colors[u]) vl_color[u] = c # vlp = dvlp - if vertex_label_placements.has_key(u): + if u in vertex_label_placements: vlp = vertex_label_placements[u] # test vlp here vl_placement[u] = vlp @@ -1760,8 +1760,8 @@ def tkz_picture(self): edge=(e[0],e[1]); reverse=(e[1],e[0]) # c = dec - if edge_colors.has_key(edge) or (not self._graph.is_directed() and edge_colors.has_key(reverse)): - if edge_colors.has_key(edge): + if edge in edge_colors or (not self._graph.is_directed() and reverse in edge_colors): + if edge in edge_colors: c = cc.to_rgb(edge_colors[edge]) else: c = cc.to_rgb(edge_colors[reverse]) @@ -1769,16 +1769,16 @@ def tkz_picture(self): # if edge_fills: c = defc - if edge_fill_colors.has_key(edge) or (not self._graph.is_directed() and edge_fill_colors.has_key(reverse)): - if edge_colors.has_key(edge): + if edge in edge_fill_colors or (not self._graph.is_directed() and reverse in edge_fill_colors): + if edge in edge_colors: c = cc.to_rgb(edge_fill_colors[edge]) else: c = cc.to_rgb(edge_fill_colors[reverse]) ef_color[edge] = c # et = det - if edge_thicknesses.has_key(edge) or (not self._graph.is_directed() and edge_thicknesses.has_key(reverse)): - if edge_thicknesses.has_key(edge): + if edge in edge_thicknesses or (not self._graph.is_directed() and reverse in edge_thicknesses): + if edge in edge_thicknesses: et = edge_thicknesses[edge] else: et = edge_thicknesses[reverse] @@ -1786,24 +1786,24 @@ def tkz_picture(self): # if edge_labels: c = delc - if edge_label_colors.has_key(edge) or (not self._graph.is_directed() and edge_label_colors.has_key(reverse)): - if edge_label_colors.has_key(edge): + if edge in edge_label_colors or (not self._graph.is_directed() and reverse in edge_label_colors): + if edge in edge_label_colors: c = cc.to_rgb(edge_label_colors[edge]) else: c = cc.to_rgb(edge_label_colors[reverse]) el_color[edge] = c # els = dels - if edge_label_slopes.has_key(edge) or (not self._graph.is_directed() and edge_label_slopes.has_key(reverse)): - if edge_label_slopes.has_key(edge): + if edge in edge_label_slopes or (not self._graph.is_directed() and reverse in edge_label_slopes): + if edge in edge_label_slopes: els = edge_label_slopes[edge] else: els = edge_label_slopes[reverse] el_slope[edge] = els # elp = delp - if edge_label_placements.has_key(edge) or (not self._graph.is_directed() and edge_label_placements.has_key(reverse)): - if edge_label_placements.has_key(edge): + if edge in edge_label_placements or (not self._graph.is_directed() and reverse in edge_label_placements): + if edge in edge_label_placements: elp = edge_label_placements[edge] else: elp = edge_label_placements[reverse] @@ -1827,7 +1827,7 @@ def tkz_picture(self): lp_placement = {} for u in vertex_list: lp = dlp - if loop_placements.has_key(u): + if u in loop_placements: lp = loop_placements[u] lp_placement[u] = lp diff --git a/src/sage/graphs/graph_list.py b/src/sage/graphs/graph_list.py index 584de63a7f8..7d4e43348c0 100644 --- a/src/sage/graphs/graph_list.py +++ b/src/sage/graphs/graph_list.py @@ -298,11 +298,11 @@ def to_graphics_arrays(list, **kwds): if ( isinstance( list[i], graph.GenericGraph ) ): pos = list[i].get_pos() if ( pos is None ): - if not kwds.has_key('layout'): + if 'layout' not in kwds: kwds['layout'] = 'circular' - if not kwds.has_key('vertex_size'): + if 'vertex_size' not in kwds: kwds['vertex_size'] = 50 - if not kwds.has_key('vertex_labels'): + if 'vertex_labels' not in kwds: kwds['vertex_labels'] = False kwds['graph_border'] = True plist.append(list[i].plot(**kwds)) diff --git a/src/sage/graphs/weakly_chordal.pyx b/src/sage/graphs/weakly_chordal.pyx index 334b59cb75a..3cf420e5972 100644 --- a/src/sage/graphs/weakly_chordal.pyx +++ b/src/sage/graphs/weakly_chordal.pyx @@ -171,7 +171,7 @@ def is_long_hole_free(g, certificate=False): else: return False, None - elif not VisitedP3.has_key((b,c,d)): + elif (b,c,d) not in VisitedP3: # search for another P_4 res, hole_vertices = process(b,c,d,i+1) if not res: @@ -187,7 +187,7 @@ def is_long_hole_free(g, certificate=False): InPath[u] = 0 # u is the first vertex at position 0 for vv,ww in g.edge_iterator(labels = False): for v,w in [(vv,ww),(ww,vv)]: - if has_edge(dense_graph,u,v,n) and u!=w and not has_edge(dense_graph,u,w,n) and not VisitedP3.has_key((u,v,w)): + if has_edge(dense_graph,u,v,n) and u!=w and not has_edge(dense_graph,u,w,n) and (u,v,w) not in VisitedP3: InPath[v] = 1 # v is the second vertex at position 1 res,hole = process(u, v, w, 2) if not res: @@ -302,7 +302,7 @@ def is_long_antihole_free(g, certificate = False): VisitedP3[c,a,b] = True for d in g.neighbor_iterator(b): if has_edge(dense_graph,d,a,n) and not has_edge(dense_graph,d,c,n): - if InPath.has_key(d): + if d in InPath: if certificate: #calculation of induced cycle in complement j = InPath[d] @@ -337,7 +337,7 @@ def is_long_antihole_free(g, certificate = False): else: return False, [] - elif not VisitedP3.has_key((b,d,c)): + elif (b,d,c) not in VisitedP3: r,antihole = process(b,c,d,k+1) if not r: return False, antihole @@ -351,7 +351,7 @@ def is_long_antihole_free(g, certificate = False): for u in g: InPath[u] = 1 for v,w in g.edge_iterator(labels = False): - if not has_edge(dense_graph,u,v,n) and not has_edge(dense_graph,u,w,n) and not VisitedP3.has_key((v,w,u)): + if not has_edge(dense_graph,u,v,n) and not has_edge(dense_graph,u,w,n) and (v,w,u) not in VisitedP3: InPath[v] = 0 r,antihole = process(v, u, w, 2) if not r: diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx index 402e38f1a42..63aa4ebb6ef 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx @@ -1009,7 +1009,7 @@ def get_orbits(list gens, int n): orbit_dict = {} for i from 0 <= i < n: j = OP_find(OP, i) - if orbit_dict.has_key(j): + if j in orbit_dict: orbit_dict[j].append(i) else: orbit_dict[j] = [i] diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index de6fd53668c..6113e0dc3a8 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -2920,19 +2920,19 @@ def subgroups(self): sage: G = SymmetricGroup(3) sage: G.subgroups() - [Permutation Group with generators [()], - Permutation Group with generators [(2,3)], - Permutation Group with generators [(1,2)], - Permutation Group with generators [(1,3)], - Permutation Group with generators [(1,2,3)], - Permutation Group with generators [(2,3), (1,2,3)]] + [Subgroup of (Symmetric group of order 3! as a permutation group) generated by [()], + Subgroup of (Symmetric group of order 3! as a permutation group) generated by [(2,3)], + Subgroup of (Symmetric group of order 3! as a permutation group) generated by [(1,2)], + Subgroup of (Symmetric group of order 3! as a permutation group) generated by [(1,3)], + Subgroup of (Symmetric group of order 3! as a permutation group) generated by [(1,2,3)], + Subgroup of (Symmetric group of order 3! as a permutation group) generated by [(2,3), (1,2,3)]] sage: G = CyclicPermutationGroup(14) sage: G.subgroups() - [Permutation Group with generators [()], - Permutation Group with generators [(1,8)(2,9)(3,10)(4,11)(5,12)(6,13)(7,14)], - Permutation Group with generators [(1,3,5,7,9,11,13)(2,4,6,8,10,12,14)], - Permutation Group with generators [(1,2,3,4,5,6,7,8,9,10,11,12,13,14)]] + [Subgroup of (Cyclic group of order 14 as a permutation group) generated by [()], + Subgroup of (Cyclic group of order 14 as a permutation group) generated by [(1,8)(2,9)(3,10)(4,11)(5,12)(6,13)(7,14)], + Subgroup of (Cyclic group of order 14 as a permutation group) generated by [(1,3,5,7,9,11,13)(2,4,6,8,10,12,14)], + Subgroup of (Cyclic group of order 14 as a permutation group) generated by [(1,2,3,4,5,6,7,8,9,10,11,12,13,14)]] AUTHOR: @@ -2942,7 +2942,7 @@ def subgroups(self): ccs = self._gap_().ConjugacyClassesSubgroups() for cc in ccs: for h in cc.Elements(): - all_sg.append(PermutationGroup(gap_group=h)) + all_sg.append(self.subgroup(gap_group=h)) return all_sg def blocks_all(self, representatives = True): diff --git a/src/sage/gsl/fft.pyx b/src/sage/gsl/fft.pyx index d3bd8ca846c..b3bf88221bc 100644 --- a/src/sage/gsl/fft.pyx +++ b/src/sage/gsl/fft.pyx @@ -59,7 +59,7 @@ def FastFourierTransform(size, base_ring=None): sage: a.forward_transform() sage: a #abs tol 1e-2 - [(36.0, 0.0), (-4.00, 9.65), (-4.0, 4.0), (-3.99, 1.65), (-4.0, 0.0), (-4.0, -1.65), (-4.0, -4.0), (-3.99, -9.65)] + [(36.0, 0.0), (-4.00, 9.65), (-4.0, 4.0), (-4.0, 1.65), (-4.0, 0.0), (-4.0, -1.65), (-4.0, -4.0), (-4.0, -9.65)] And backwards:: diff --git a/src/sage/interfaces/ecm.py b/src/sage/interfaces/ecm.py index dbbadf44bb3..0d4868392a6 100644 --- a/src/sage/interfaces/ecm.py +++ b/src/sage/interfaces/ecm.py @@ -1,171 +1,447 @@ r""" The Elliptic Curve Factorization Method -\sage includes GMP-ECM, which is a highly optimized implementation -of Lenstra's elliptic curve factorization method. See -\url{http://ecm.gforge.inria.fr/} -for more about GMP-ECM. +The elliptic curve factorization method (ECM) is the fastest way to +factor a **known composite** integer if one of the factors is +relatively small (up to approximately 80 bits / 25 decimal digits). To +factor an arbitrary integer it must be combined with a primality +test. The :meth:`ECM.factor` method is an example for how to combine +ECM with a primality test to compute the prime factorization of integers. + +Sage includes GMP-ECM, which is a highly optimized implementation of +Lenstra's elliptic curve factorization method. See +http://ecm.gforge.inria.fr for more about GMP-ECM. + +AUTHORS: + +These people wrote GMP-ECM: +Pierrick Gaudry, Jim Fougeron, +Laurent Fousse, Alexander Kruppa, +Dave Newman, Paul Zimmermann + +BUGS: + +Output from ecm is non-deterministic. Doctests should set the random +seed, but currently there is no facility to do so. """ -import os, pexpect +############################################################################### +# Copyright (C) 2006, William Stein +# Copyright (C) 2006, Robert Bradshaw +# Copyright (C) 2013, Volker Braun +# +# Distributed under the terms of the GNU General Public License (GPL) +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# http://www.gnu.org/licenses/ +############################################################################### + + +import os +import re from math import ceil, floor -from sage.rings.integer import Integer +from sage.structure.sage_object import SageObject +from sage.rings.integer_ring import ZZ from sage.misc.misc import verbose, tmp_filename from sage.misc.decorators import rename_keyword -import cleaner -import sage.misc.package -def nothing(): - pass +class ECM(SageObject): -class ECM: def __init__(self, B1=10, B2=None, **kwds): r""" Create an interface to the GMP-ECM elliptic curve method factorization program. - See \url{http://ecm.gforge.inria.fr/}. + See http://ecm.gforge.inria.fr - AUTHORS: - These people wrote GMP-ECM: - Pierrick Gaudry, Jim Fougeron, - Laurent Fousse, Alexander Kruppa, - Dave Newman, Paul Zimmermann + INPUT: - William Stein and Robert Bradshaw -- wrote the Sage interface to GMP-ECM + - ``B1`` -- integer. Stage 1 bound - INPUT: - B1 -- stage 1 bound - B2 -- stage 2 bound (or interval B2min-B2max) - - x0 -- x use x as initial point - sigma -- s use s as curve generator [ecm] - A -- a use a as curve parameter [ecm] - k -- n perform >= n steps in stage 2 - power -- n use x^n for Brent-Suyama's extension - dickson -- n use n-th Dickson's polynomial for Brent-Suyama's extension - c -- n perform n runs for each input - pm1 -- perform P-1 instead of ECM - pp1 -- perform P+1 instead of ECM - q -- quiet mode - v -- verbose mode - timestamp -- print a time stamp with each number - mpzmod -- use GMP's mpz_mod for mod reduction - modmuln -- use Montgomery's MODMULN for mod reduction - redc -- use Montgomery's REDC for mod reduction - nobase2 -- disable special base-2 code - base2 -- n force base 2 mode with 2^n+1 (n>0) or 2^n-1 (n<0) - save -- file save residues at end of stage 1 to file - savea -- file like -save, appends to existing files - resume -- file resume residues from file, reads from - stdin if file is "-" - primetest -- perform a primality test on input - treefile -- f store product tree of F in files f.0 f.1 ... - i -- n increment B1 by this constant on each run - I -- f auto-calculated increment for B1 multiplied by 'f' scale factor - inp -- file Use file as input (instead of redirecting stdin) - b -- Use breadth-first mode of file processing - d -- Use depth-first mode of file processing (default) - one -- Stop processing a candidate if a factor is found (looping mode) - n -- run ecm in 'nice' mode (below normal priority) - nn -- run ecm in 'very nice' mode (idle priority) - t -- n Trial divide candidates before P-1, P+1 or ECM up to n - ve -- n Verbosely show short (< n character) expressions on each loop - cofdec -- Force cofactor output in decimal (even if expressions are used) - B2scale -- f Multiplies the default B2 value by f - go -- val Preload with group order val, which can be a simple expression, - or can use N as a placeholder for the number being factored. - prp -- cmd use shell command cmd to do large primality tests - prplen -- n only candidates longer than this number of digits are 'large' - prpval -- n value>=0 which indicates the prp command foundnumber to be PRP. - prptmp -- file outputs n value to temp file prior to running (NB. gets deleted) - prplog -- file otherwise get PRP results from this file (NB. gets deleted) - prpyes -- str literal string found in prplog file when number is PRP - prpno -- str literal string found in prplog file when number is composite + - ``B2`` -- integer. Stage 2 bound (or interval B2min-B2max) + + In addition the following keyword arguments can be used: + + - ``x0`` -- integer `x`. use `x` as initial point + + - ``sigma`` -- integer `s`. Use s as curve generator [ecm] + + - ``A`` -- integer `a`. Use a as curve parameter [ecm] + + - ``k`` -- integer `n`. Perform `>= n` steps in stage 2 + + - ``power`` -- integer `n`. Use `x^n` for Brent-Suyama's + extension + + - ``dickson`` -- integer `n`. Use `n`-th Dickson's polynomial + for Brent-Suyama's extension + + - ``c`` -- integer `n`. Perform `n` runs for each input + + - ``pm1`` -- boolean. perform P-1 instead of ECM + + - ``pp1`` -- boolean. perform P+1 instead of ECM + + - ``q`` -- boolean. quiet mode + + - ``v`` -- boolean. verbose mode + + - ``timestamp`` -- boolean. print a time stamp with each number + + - ``mpzmod`` -- boolean. use GMP's mpz_mod for mod reduction + + - ``modmuln`` -- boolean. use Montgomery's MODMULN for mod reduction + + - ``redc`` -- boolean. use Montgomery's REDC for mod reduction + + - ``nobase2`` -- boolean. Disable special base-2 code + + - ``base2`` -- integer `n`. Force base 2 mode with 2^n+1 (n>0) + or 2^n-1 (n<0) + + - ``save`` -- string filename. Save residues at end of stage 1 + to file + + - ``savea`` -- string filename. Like -save, appends to + existing files + + - ``resume`` -- string filename. Resume residues from file, + reads from stdin if file is "-" + + - ``primetest`` -- boolean. Perform a primality test on input + + - ``treefile`` -- string. Store product tree of F in files f.0 + f.1 ... + + - ``i`` -- integer. increment B1 by this constant on each run + + - ``I`` -- integer `f`. auto-calculated increment for B1 + multiplied by `f` scale factor. + + - ``inp`` -- string. Use file as input (instead of redirecting + stdin) + + - ``b`` -- boolean. Use breadth-first mode of file processing + + - ``d`` -- boolean. Use depth-first mode of file processing + (default) + + - ``one`` -- boolean. Stop processing a candidate if a factor + is found (looping mode ) + + - ``n`` -- boolean. Run ecm in 'nice' mode (below normal + priority) + + - ``nn`` -- boolean. Run ecm in 'very nice' mode (idle + priority) + + - ``t`` -- integer `n`. Trial divide candidates before P-1, + P+1 or ECM up to `n`. + + - ``ve`` -- integer `n`. Verbosely show short (`< n` + character) expressions on each loop + + - ``cofdec`` -- boolean. Force cofactor output in decimal + (even if expressions are used ) + + - ``B2scale`` -- integer. Multiplies the default B2 value + + - ``go`` -- integer. Preload with group order val, which can + be a simple expression, or can use N as a placeholder for + the number being factored. + + - ``prp`` -- string. use shell command cmd to do large + primality tests + + - ``prplen`` -- integer. only candidates longer than this + number of digits are 'large' + + - ``prpval`` -- integer. value>=0 which indicates the prp + command foundnumber to be PRP. + + - ``prptmp`` -- file. outputs n value to temp file prior to + running (NB. gets deleted) + + - ``prplog`` -- file. otherwise get PRP results from this file + (NB. gets deleted) + + - ``prpyes`` -- string. Literal string found in prplog file + when number is PRP + + - ``prpno`` -- string. Literal string found in prplog file + when number is composite """ - self.__cmd = self.__startup_cmd(B1, B2, kwds) - - def __startup_cmd(self, B1, B2, kwds): - options = ' '.join(['-%s %s'%(x,v) for x, v in kwds.iteritems()]) - s = 'ecm %s %s '%(options, B1) - if not B2 is None: - s += str(B2) - return s - - def __call__(self, n, watch=False): - n = Integer(n) - self._validate(n) - cmd = 'echo "%s" | %s'%(n, self.__cmd) - if watch: - t = tmp_filename() - os.system('%s | tee %s'%(cmd, t)) - ou = open(t).read() - os.unlink(t) + self._cmd = self._make_cmd(B1, B2, kwds) + + def _make_cmd(self, B1, B2, kwds): + ecm = ['ecm'] + options = [] + for x, v in kwds.iteritems(): + if v is False: + continue + options.append('-{0}'.format(x)) + if (v is not True) and (v != ''): + options.append(str(v)) + if B2 is None: + args = [str(B1)] else: - from subprocess import Popen, PIPE - x = Popen(cmd, shell=True, - stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) - x.stdin.close() - ou = x.stderr.read() + '\n' + x.stdout.read() - if 'command not found' in ou: - err = ou + '\n' + 'You must install GMP-ECM.\n' - err += sage.misc.package.package_mesg('ecm-6.1.3') - raise RuntimeError, err - return ou + args = [str(B1), str(B2)] + return ecm + options + args + + def _run_ecm(self, cmd, n): + """ + Run ECM and return output as string. + + INPUT: + + - ``cmd`` -- list of strings. The command. + + - ``n`` -- integer suitable for ECM. No argument checking is + performed. + + OUTPUT: + + String. + + EXAMPLES:: + + sage: ecm._run_ecm(['cat'], 1234) + '1234' + """ + from subprocess import Popen, PIPE, STDOUT + p = Popen(cmd, stdout=PIPE, stdin=PIPE, stderr=PIPE) + out, err = p.communicate(input=str(n)) + if err != '': + raise ValueError(err) + return out + + def __call__(self, n): + """ + Call syntax. + + INPUT: + + - ``n`` -- integer. + + OUTPUT: + + String. The ECM output. + + EXAMPLES:: + + sage: print(ecm(3)) # random output + GMP-ECM 6.4.4 [configured with MPIR 2.6.0, --enable-asm-redc] [ECM] + Input number is 3 (1 digits) + ********** Factor found in step 1: 3 + Found input number N + """ + n = self._validate(n) + return self._run_ecm(self._cmd, n) def interact(self): """ Interactively interact with the ECM program. + + EXAMPLES:: + + sage: ecm.interact() # not tested """ print "Enter numbers to run ECM on them." print "Press control-C to exit." - os.system(self.__cmd) - + os.system(self._cmd) + # Recommended settings from + # http://www.mersennewiki.org/index.php/Elliptic_Curve_Method _recommended_B1_list = {15: 2000, - 20: 11000, - 25: 50000, - 30: 250000, - 35: 1000000, - 40: 3000000, - 45: 11000000, - 50: 44000000, - 55: 110000000, - 60: 260000000, - 65: 850000000, - 70: 2900000000 } - """Recommended settings from http://www.mersennewiki.org/index.php/Elliptic_Curve_Method.""" - - def __B1_table_value(self, factor_digits, min=15, max=70): - """Coerces to a key in _recommended_B1_list.""" - if factor_digits < min: factor_digits = min - if factor_digits > max: raise ValueError('Too many digits to be factored via the elliptic curve method.') - return 5*ceil(factor_digits/5) + 20: 11000, + 25: 50000, + 30: 250000, + 35: 1000000, + 40: 3000000, + 45: 11000000, + 50: 44000000, + 55: 110000000, + 60: 260000000, + 65: 850000000, + 70: 2900000000,} + + def _B1_table_value(self, factor_digits, min=15, max=70): + """ + Return key in ``_recommended_B1_list``. + + INPUT: + + - ``factor_digits`` -- integer. Number of digits. + + - ``min``, ``max`` -- integer. Min and max values. + + OUTPUT: + + Integer. A key in _recommended_B1_list. + + EXAMPLES:: + + sage: ecm._B1_table_value(33) + 35 + """ + if factor_digits < min: + factor_digits = min + if factor_digits > max: + raise ValueError('too many digits') + step = 5 + return ((factor_digits+step-1) // step) * step def recommended_B1(self, factor_digits): r""" - Recommended settings from \url{http://www.mersennewiki.org/index.php/Elliptic_Curve_Method}. + Return recommended ``B1`` setting. + + INPUT: + + - ``factor_digits`` -- integer. Number of digits. + + OUTPUT: + + Integer. Recommended settings from + http://www.mersennewiki.org/index.php/Elliptic_Curve_Method + + EXAMPLES:: + + sage: ecm.recommended_B1(33) + 1000000 """ - return self._recommended_B1_list[self.__B1_table_value(factor_digits)] + return self._recommended_B1_list[self._B1_table_value(factor_digits)] + + _parse_status_re = re.compile( + 'Using B1=(\d+), B2=(\d+), polynomial ([^,]+), sigma=(\d+)') + + _found_input_re = re.compile('Found input number N') + + _found_factor_re = re.compile( + 'Found (?P.*) factor of [\s]*(?P\d+) digits: (?P\d+)') + + _found_cofactor_re = re.compile( + '(?P.*) cofactor (?P\d+) has [\s]*(?P\d+) digits') + + def _parse_output(self, n, out): + """ + Parse the ECM output + + INPUT: + + - ``n`` -- integer. The ECM input number. + + - ``out`` -- string. The stdout from the ECM invocation. + + OUTPUT: + + List of pairs ``(integer, bool)`` consisting of factors of the + ECM input and whether they are deemed to be probable + prime. Note that ECM is not a good primality test, and there + is a sizeable probability that the "probable prime" is + actually composite. + + EXAMPLES:: + + sage: out = '\n'.join([ + ....: 'GMP-ECM 6.4.4 [configured with MPIR 2.6.0, --enable-asm-redc] [ECM]', + ....: 'Input number is 1632143 (7 digits)', + ....: 'Using B1=40, B2=480, polynomial x^1, sigma=3145777366', + ....: 'Step 1 took 0ms', + ....: 'Step 2 took 0ms', + ....: 'Run 2 out of 1000:', + ....: 'Using B1=40, B2=480, polynomial x^1, sigma=2101568373', + ....: 'Step 1 took 0ms', + ....: 'Step 2 took 0ms', + ....: '********** Factor found in step 2: 1632143', + ....: 'Found input number N']) + sage: ecm._parse_output(1632143, out) + [(1632143, True)] + sage: ecm.get_last_params()['sigma'] + '2101568373' + + sage: from sage.interfaces.ecm import TEST_ECM_OUTPUT_1 + sage: n1 = 508021860739623467191080372196682785441177798407961 + sage: ecm._parse_output(n1, TEST_ECM_OUTPUT_1) + [(79792266297612017, True), (6366805760909027985741435139224233, True)] + + sage: from sage.interfaces.ecm import TEST_ECM_OUTPUT_2 + sage: ecm._parse_output(32193213281156929, TEST_ECM_OUTPUT_2) + [(179424673, True), (179424673, True)] + + sage: from sage.interfaces.ecm import TEST_ECM_OUTPUT_3, TEST_ECM_OUTPUT_4 + sage: n3 = 66955751844124594814248420514215108438425124740949701470891 + sage: ecm._parse_output(n3, TEST_ECM_OUTPUT_3) + [(197002597249, True), + (339872432034468861533158743041639097889948066859, False)] + sage: ecm._parse_output(n3, TEST_ECM_OUTPUT_4) + [(265748496095531068869578877937, False), + (251951573867253012259144010843, True)] + """ + out_lines = out.lstrip().splitlines() + if not out_lines[0].startswith('GMP-ECM'): + raise ValueError('invalid output') + result = [] + for line in out_lines: + # print('parsing line >>{0}<<'.format(line)) + m = self._parse_status_re.match(line) + if m is not None: + group = m.groups() + self._last_params = {'B1' : group[0], 'B2' : group[1], + 'poly' : group[2], 'sigma' : group[3]} + continue + m = self._found_input_re.match(line) + if m is not None: + return [(n, True)] + m = self._found_factor_re.match(line) + if m is not None: + factor = m.group('factor') + primality = m.group('primality') + assert primality in ['probable prime', 'composite'] + result += [(ZZ(factor), primality == 'probable prime')] + continue # cofactor on the next line + m = self._found_cofactor_re.match(line) + if m is not None: + cofactor = m.group('cofactor') + primality = m.group('primality') + assert primality in ['Probable prime', 'Composite'] + result += [(ZZ(cofactor), primality == 'Probable prime')] + #assert len(result) == 2 + return result + raise ValueError('failed to parse ECM output') - @rename_keyword(deprecation=6094, method="algorithm") def one_curve(self, n, factor_digits=None, B1=2000, algorithm="ECM", **kwds): """ Run one single ECM (or P-1/P+1) curve on input n. + Note that trying a single curve is not particularly useful by + itself. One typically needs to run over thousands of trial + curves to factor `n`. + INPUT: - n -- a positive integer - factor_digits -- decimal digits estimate of the wanted factor - B1 -- stage 1 bound (default 2000) - algorithm -- either "ECM" (default), "P-1" or "P+1" + + - ``n`` -- a positive integer + + - ``factor_digits`` -- integer. Decimal digits estimate of the + wanted factor. + + - ``B1`` -- integer. Stage 1 bound (default 2000) + + - ``algorithm`` -- either "ECM" (default), "P-1" or "P+1" + OUTPUT: - a list [p,q] where p and q are integers and n = p * q. - If no factor was found, then p = 1 and q = n. - WARNING: neither p nor q is guaranteed to be prime. - EXAMPLES: + + a list ``[p, q]`` where p and q are integers and n = p * q. + If no factor was found, then p = 1 and q = n. + + .. WARNING:: + + Neither p nor q in the output is guaranteed to be prime. + + EXAMPLES:: + sage: f = ECM() sage: n = 508021860739623467191080372196682785441177798407961 sage: f.one_curve(n, B1=10000, sigma=11) @@ -179,312 +455,349 @@ def one_curve(self, n, factor_digits=None, B1=2000, algorithm="ECM", **kwds): sage: f.one_curve(n, B1=2000, algorithm="P+1", x0=5) [328006342451, 6366805760909027985741435139224233] """ - n = Integer(n) - self._validate(n) - if not factor_digits is None: + n = self._validate(n) + if factor_digits is not None: B1 = self.recommended_B1(factor_digits) if algorithm == "P-1": kwds['pm1'] = '' elif algorithm == "P+1": kwds['pp1'] = '' + elif algorithm == "ECM": + pass else: - if not algorithm == "ECM": - err = "unexpected algorithm: " + algorithm - raise ValueError, err - self.__cmd = self._ECM__startup_cmd(B1, None, kwds) - child = pexpect.spawn(self.__cmd) - cleaner.cleaner(child.pid, self.__cmd) - child.timeout = None - child.__del__ = nothing # work around stupid exception ignored error - child.expect('[ECM]') - child.sendline(str(n)) - child.sendline("bad") # child.sendeof() - while True: - try: - child.expect('(Using B1=(\d+), B2=(\d+), polynomial ([^,]+), sigma=(\d+)\D)|(Factor found in step \d:\s+(\d+)\D)|(Error - invalid number)') - info = child.match.groups() - # B1 is info[1], B2 is info[2], poly is info[3], sigma is info[4], - # step is info[5], factor is info[6], cofactor is info[7] - if not info[0] is None: - # got Using B1=... line - self.last_params = { 'B1' : child.match.groups()[1], - 'B2' : child.match.groups()[2], - 'poly' : child.match.groups()[3], - 'sigma' : child.match.groups()[4] } - elif info[7] != None: - # got Error - invalid number, which means the curve did - # end without finding any factor, and the next input 'bad' - # was given to GMP-ECM - child.kill(0) - return [1, n] - else: - # got Factor found... - p = Integer(info[6]) - child.kill(0) - return [p, n/p] - - except pexpect.EOF: - child.kill(0) - return [1, n] - child.kill(0) + raise ValueError('unknown algorithm') + cmd = self._make_cmd(B1, None, kwds) + out = self._run_ecm(cmd, n) + try: + factors = self._parse_output(n, out) + return [factors[0][0], factors[1][0]] + except ValueError: + # output does not end in factorization + return [ZZ(1), n] + + def _find_factor(self, n, factor_digits, B1, **kwds): + """ + Helper for :meth:`find_factor`. + + INPUT: + + See :meth:`find_factor`. + + OUTPUT: + List of pairs ``(integer, bool)`` consisting of factors of the + ECM input and whether they are probable prime. Note that ECM + is not a good primality test and there is a sizeable chance + that a "probable prime" is actually composite. + + EXAMPLES:: + + sage: f = ECM() + sage: n = 508021860739623467191080372196682785441177798407961 + sage: f._find_factor(n, None, 2000) + [(79792266297612017, True), + (6366805760909027985741435139224233, True)] + """ + n = self._validate(n) + kwds.setdefault('c', 1000000000) + kwds.setdefault('I', 1) + if factor_digits is not None: + B1 = self.recommended_B1(factor_digits) + kwds['one'] = True + kwds['cofdec'] = True + cmd = self._make_cmd(B1, None, kwds) + out = self._run_ecm(cmd, n) + return self._parse_output(n, out) def find_factor(self, n, factor_digits=None, B1=2000, **kwds): """ - Splits off a single factor of n. - See ECM.factor() + Return a factor of n. + + See also :meth:`factor` if you want a prime factorization of + `n`. + + INPUT: + + - ``n`` -- a positive integer, + + - ``factor_digits`` -- integer or ``None`` (default). Decimal + digits estimate of the wanted factor. + + - ``B1`` -- integer. Stage 1 bound (default 2000). This is + used as bound if ``factor_digits`` is not specified. + + - ``kwds`` -- optional keyword parameters. OUTPUT: - list of integers whose product is n - EXAMPLES: + List of integers whose product is n. For certain lengths of + the factor, this is the best algorithm to find a + factor. + + .. NOTE: + + ECM is not a good primality test. Not finding a + factorization is only weak evidence for `n` being + prime. You shoud run a **good** primality test before + calling this function. + + EXAMPLES:: + sage: f = ECM() sage: n = 508021860739623467191080372196682785441177798407961 sage: f.find_factor(n) [79792266297612017, 6366805760909027985741435139224233] - Note that the input number can't have more than 4095 digits: + Note that the input number can't have more than 4095 digits:: + sage: f=2^2^14+1 sage: ecm.find_factor(f) Traceback (most recent call last): ... ValueError: n must have at most 4095 digits """ - n = Integer(n) - self._validate(n) - if not 'c' in kwds: kwds['c'] = 1000000000 - if not 'I' in kwds: kwds['I'] = 1 - if not factor_digits is None: - B1 = self.recommended_B1(factor_digits) - kwds['one'] = '' - kwds['cofdec'] = '' - self.__cmd = self._ECM__startup_cmd(B1, None, kwds) - self.last_params = { 'B1' : B1 } - child = pexpect.spawn(self.__cmd) - cleaner.cleaner(child.pid, self.__cmd) - child.timeout = None - child.__del__ = nothing # program around stupid exception ignored error - child.expect('[ECM]') - child.sendline(str(n)) - child.sendline("bad") # child.sendeof() - while True: - - try: - child.expect('(Using B1=(\d+), B2=(\d+), polynomial ([^,]+), sigma=(\d+)\D)|(Factor found in step \d:\s+(\d+)\D)|(Error - invalid number)') - info = child.match.groups() - if not info[0] is None: - self.last_params = { 'B1' : child.match.groups()[1], - 'B2' : child.match.groups()[2], - 'poly' : child.match.groups()[3], - 'sigma' : child.match.groups()[4] } - elif info[7] != None: - child.kill(0) - self.primality = [False] - return [n] - else: - p = Integer(info[6]) - child.expect('(input number)|(prime factor)|(composite factor)') - if not child.match.groups()[0] is None: - child.kill(0) - return self.find_factor(n, B1=4+floor(float(B1)/2), **kwds) - else: - # primality testing is cheap compared to factoring, but has already been done - # return [p, n/p] - self.primality = [not child.match.groups()[1] is None] - child.expect('((prime cofactor)|(Composite cofactor)) (\d+)\D') - q = Integer(child.match.groups()[3]) - self.primality += [not child.match.groups()[1] is None] - child.kill(0) - return [p, q] - - - except pexpect.EOF: - child.kill(0) - self.primality = [False] - return [n] - child.kill(0) - - - def factor(self, n, factor_digits=None, B1=2000, **kwds): + factors = self._find_factor(n, factor_digits, B1, **kwds) + return [factor[0] for factor in factors] + + def factor(self, n, factor_digits=None, B1=2000, proof=False, **kwds): """ - Returns a list of integers whose product is n, computed using - GMP-ECM, and PARI for small factors. + Return a probable prime factorization of `n`. + + Combines GMP-ECM with a primality test, see + :meth:`~sage.rings.integer.Integer.is_prime`. The primality + test is provable or probabilistic depending on the `proof` + flag. + + Moreover, for small `n` PARI is used directly. - ** WARNING: There is no guarantee that the factors returned are - prime. ** + .. WARNING:: + + There is no mathematical guarantee that the factors + returned are actually prime if ``proof=False`` + (default). It is extremely likely, though. Currently, + there are no known examples where this fails. INPUT: - n -- a positive integer - factor_digits -- optional guess at how many digits are in the smallest factor. - B1 -- initial lower bound, defaults to 2000 (15 digit factors) - kwds -- arguments to pass to ecm-gmp. See help for ECM for more details. + + - ``n`` -- a positive integer + + - ``factor_digits`` -- integer or ``None`` (default). Optional + guess at how many digits are in the smallest factor. + + - ``B1`` -- initial lower bound, defaults to 2000 (15 digit + factors). Used if ``factor_digits`` is not specified. + + - ``proof`` -- boolean (default: ``False``). Whether to prove + that the factors are prime. + + - ``kwds`` -- keyword arguments to pass to ecm-gmp. See help + for :class:`ECM` for more details. OUTPUT: - a list of integers whose product is n - NOTE: - Trial division should typically be performed before using - this method. Also, if you suspect that n is the product - of two similarly-sized primes, other methods (such as a - quadratic sieve -- use the qsieve command) will usually be - faster. + A list of integers whose product is n. + + .. NOTE:: + + Trial division should typically be performed, but this is + not implemented (yet) in this method. + + If you suspect that n is the product of two + similarly-sized primes, other methods (such as a quadratic + sieve -- use the qsieve command) will usually be faster. + + The best known algorithm for factoring in the case where + all factors are large is the general number field + sieve. This is not implemented in Sage; You probably want + to use a cluster for problems of this size. + + EXAMPLES:: - EXAMPLES: sage: ecm.factor(602400691612422154516282778947806249229526581) [45949729863572179, 13109994191499930367061460439] - - sage: ecm.factor((2^197 + 1)/3) # takes a long time + sage: ecm.factor((2^197 + 1)/3) # long time [197002597249, 1348959352853811313, 251951573867253012259144010843] + sage: ecm.factor(179427217^13) == [179427217] * 13 + True """ - if B1 < 2000 or len(str(n)) < 15: - return sum([[p]*e for p, e in Integer(n).factor()], []) - - factors = self.find_factor(n, factor_digits, B1, **kwds) - factors.sort() - if len(factors) == 1: - return factors - assert len(factors) == 2 - _primality = [self.primality[0], self.primality[1]] - try: - last_B1 = self.last_params['B1'] - except AttributeError: - self.last_params = {} - self.last_params['B1'] = 10 - last_B1 = 10 - if not _primality[1]: - factors[1:2] = self.factor(factors[1], B1=last_B1, **kwds) - _primality[1:2] = self.primality - if not _primality[0]: - factors[0:1] = self.factor(factors[0], B1=last_B1, **kwds) - _primality[0:1] = self.primality - self.primality = _primality - factors.sort() - return factors - + n = self._validate(n) + factors = [n] # factors that need to be factorized futher + probable_prime_factors = [] # output prime factors + while len(factors) > 0: + n = factors.pop() + + # Step 0: Primality test + if n.is_prime(proof=proof): + probable_prime_factors.append(n) + continue + + # Step 1: Use PARI directly for small primes + if n.ndigits() < 15: + for p,e in n.factor(algorithm='pari'): + probable_prime_factors.extend([p]*e) + continue + + # Step 2: Deal with small factors efficiently + # Step 2+1/3: Determine if N is a perfect power + if n.is_perfect_power(): + base, exp = n.perfect_power() + factors.extend([base] * exp) + continue + + # Step 2+2/3: Do trial division to remove small prime + # factors, and maybe some other factorization algorithms + # that perform well on small ranges. This all depends on + # the kind of number you are trying to factor (todo) + + # Step 3: Call find_factor until a factorization is found + n_factorization = [n] + while len(n_factorization) == 1: + n_factorization = self.find_factor(n) + factors.extend(n_factorization) + + return sorted(probable_prime_factors) def get_last_params(self): """ - Returns the parameters (including the curve) of the last ecm run. - In the case that the number was factored successfully, this will return the parameters that yielded the factorization. + Return the parameters (including the curve) of the last ecm run. - INPUT: - none + In the case that the number was factored successfully, this + will return the parameters that yielded the factorization. OUTPUT: - The parameters for the most recent factorization. + + A dictionary containing the parameters for the most recent + factorization. + + EXAMPLES:: - EXAMPLES: sage: ecm.factor((2^197 + 1)/3) # long time [197002597249, 1348959352853811313, 251951573867253012259144010843] sage: ecm.get_last_params() # random output {'poly': 'x^1', 'sigma': '1785694449', 'B1': '8885', 'B2': '1002846'} + """ + return self._last_params + def time(self, n, factor_digits, verbose=False): """ - return self.last_params + Print a runtime estimate. + BUGS: + + This method should really return something and not just print + stuff on the screen. + INPUT: - def time(self, n, factor_digits, verbose=0): - """ - Gives an approximation for the amount of time it will take to find a factor - of size factor_digits in a single process on the current computer. - This estimate is provided by GMP-ECM's verbose option on a single run of a curve. + - ``n`` -- a positive integer - INPUT: - n -- a positive integer - factor_digits -- the (estimated) number of digits of the smallest factor + - ``factor_digits`` -- the (estimated) number of digits of the + smallest factor + + OUTPUT: + + An approximation for the amount of time it will take to find a + factor of size factor_digits in a single process on the + current computer. This estimate is provided by GMP-ECM's + verbose option on a single run of a curve. EXAMPLES:: sage: n = next_prime(11^23)*next_prime(11^37) + sage: ecm.time(n, 35) # random output + Expected curves: 910, Expected time: 23.95m - sage: ecm.time(n, 20) # not tested - Expected curves: 77 Expected time: 7.21s - sage: ecm.time(n, 25) # not tested - Expected curves: 206 Expected time: 1.56m - sage: ecm.time(n, 30, verbose=1) # not tested - GMP-ECM 6.1.3 [powered by GMP 4.2.1] [ECM] - + sage: ecm.time(n, 30, verbose=True) # random output + GMP-ECM 6.4.4 [configured with MPIR 2.6.0, --enable-asm-redc] [ECM] + Running on localhost.localdomain Input number is 304481639541418099574459496544854621998616257489887231115912293 (63 digits) - Using MODMULN - Using B1=250000, B2=128992510, polynomial Dickson(3), sigma=2307628716 + Using MODMULN [mulredc:0, sqrredc:0] + Using B1=250000, B2=128992510, polynomial Dickson(3), sigma=3244548117 dF=2048, k=3, d=19110, d2=11, i0=3 Expected number of curves to find a factor of n digits: - 20 25 30 35 40 45 50 55 60 65 - 8 50 430 4914 70293 1214949 2.5e+07 5.9e+08 1.6e+10 2.7e+13 - Step 1 took 6408ms - Using 16 small primes for NTT - Estimated memory usage: 3862K - Initializing tables of differences for F took 16ms - Computing roots of F took 128ms - Building F from its roots took 408ms - Computing 1/F took 608ms - Initializing table of differences for G took 12ms - Computing roots of G took 120ms - Building G from its roots took 404ms - Computing roots of G took 120ms - Building G from its roots took 412ms - Computing G * H took 328ms - Reducing G * H mod F took 348ms - Computing roots of G took 120ms - Building G from its roots took 408ms - Computing G * H took 328ms - Reducing G * H mod F took 348ms - Computing polyeval(F,G) took 1128ms - Step 2 took 5260ms + 35 40 45 50 55 60 65 70 75 80 + 4911 70940 1226976 2.5e+07 5.8e+08 1.6e+10 2.7e+13 4e+18 5.4e+23 Inf + Step 1 took 230ms + Using 10 small primes for NTT + Estimated memory usage: 4040K + Initializing tables of differences for F took 0ms + Computing roots of F took 9ms + Building F from its roots took 16ms + Computing 1/F took 9ms + Initializing table of differences for G took 0ms + Computing roots of G took 8ms + Building G from its roots took 16ms + Computing roots of G took 7ms + Building G from its roots took 16ms + Computing G * H took 6ms + Reducing G * H mod F took 5ms + Computing roots of G took 7ms + Building G from its roots took 17ms + Computing G * H took 5ms + Reducing G * H mod F took 5ms + Computing polyeval(F,G) took 34ms + Computing product of all F(g_i) took 0ms + Step 2 took 164ms Expected time to find a factor of n digits: - 20 25 30 35 40 45 50 55 60 65 - 1.58m 9.64m 1.39h 15.93h 9.49d 164.07d 9.16y 218.68y 5825y 1e+07y - Expected curves: 4914 Expected time: 1.39h - + 35 40 45 50 55 60 65 70 75 80 + 32.25m 7.76h 5.60d 114.21d 7.27y 196.42y 337811y 5e+10y 7e+15y Inf + + Expected curves: 4911, Expected time: 32.25m """ - self._validate(n) + title_curves = 'Expected number of curves to find a factor of n digits:' + title_time = 'Expected time to find a factor of n digits:' + n = self._validate(n) B1 = self.recommended_B1(factor_digits) - self.__cmd = self._ECM__startup_cmd(B1, None, {'v': ' '}) - child = pexpect.spawn(self.__cmd) - cleaner.cleaner(child.pid, self.__cmd) - child.timeout = None - child.expect('[ECM]') - child.sendline(str(n)) - try: - child.sendeof() - except Exception: - pass - child.expect('20\s+25\s+30\s+35\s+40\s+45\s+50\s+55\s+60\s+65') - if verbose: - print child.before, - print child.after, - child.expect('(\d\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s', timeout=None) - offset = (self.__B1_table_value(factor_digits, 20, 65)-20)/5 - curve_count = child.match.groups()[int(offset)] + cmd = self._make_cmd(B1, None, {'v': True}) + out = self._run_ecm(cmd, n) if verbose: - print child.before, - print child.after, - child.expect('20\s+25\s+30\s+35\s+40\s+45\s+50\s+55\s+60\s+65', timeout=None) - if verbose: - print child.before, - print child.after, - child.expect('(\d\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s', timeout=None) - if verbose: - print child.before, - print child.after - time = child.match.groups()[int(offset)] - child.kill(0) - print "Expected curves:", curve_count, "\tExpected time:", time + print(out) + if title_time not in out: + print('Unable to compute timing, factorized immediately') + return + + out_lines = iter(out.splitlines()) + while next(out_lines) != title_curves: + pass + header_curves = next(out_lines) + curve_count_table = next(out_lines) + + while next(out_lines) != title_time: + pass + header_time = next(out_lines) + time_table = next(out_lines) + + assert header_curves == header_time + assert header_curves.split() == [ + '35', '40', '45', '50', '55', '60', '65', '70', '75', '80'] + h_min = 35 + h_max = 80 + offset = (self._B1_table_value(factor_digits, h_min, h_max) - h_min) / 5 + print('offset', offset) + curve_count = curve_count_table.split()[offset] + time = time_table.split()[offset] + print 'Expected curves: {0}, Expected time: {1}'.format(curve_count, time) def _validate(self, n): """ Verify that n is positive and has at most 4095 digits. - INPUT: - n + INPUT:: - This function raises a ValueError if the two conditions listed above - are not both satisfied. It is here because GMP-ECM silently ignores - all digits of input after the 4095th! + - ``n`` -- integer. + + OUTPUT: + + The integer as a Sage integer. This function raises a + ValueError if the two conditions listed above are not both + satisfied. It is here because GMP-ECM silently ignores all + digits of input after the 4095th! + + EXAMPLES:: - EXAMPLES: sage: ecm = ECM() + sage: ecm._validate(3) + 3 sage: ecm._validate(0) Traceback (most recent call last): ... @@ -494,12 +807,81 @@ def _validate(self, n): ... ValueError: n must have at most 4095 digits """ - n = Integer(n) + n = ZZ(n) if n <= 0: - raise ValueError, "n must be positive" + raise ValueError("n must be positive") if n.ndigits() > 4095: - raise ValueError, "n must have at most 4095 digits" + raise ValueError("n must have at most 4095 digits") + return n # unique instance ecm = ECM() + + +# Tests +TEST_ECM_OUTPUT_1 = """ +GMP-ECM 6.4.4 [configured with MPIR 2.6.0, --enable-asm-redc] [ECM] +Input number is 508021860739623467191080372196682785441177798407961 (51 digits) +Using B1=2000, B2=147396, polynomial x^1, sigma=2005325688 +Step 1 took 1ms +Step 2 took 2ms +Run 2 out of 1000000000: +Using B1=2399, B2=2399-186156, polynomial x^1, sigma=3689070339 +Step 1 took 3ms +Step 2 took 2ms +[...] +Run 29 out of 1000000000: +Using B1=16578, B2=16578-3162402, polynomial x^1, sigma=2617498039 +Step 1 took 12ms +Step 2 took 17ms +********** Factor found in step 2: 79792266297612017 +Found probable prime factor of 17 digits: 79792266297612017 +Probable prime cofactor 6366805760909027985741435139224233 has 34 digits +""" + +TEST_ECM_OUTPUT_2 = """ +GMP-ECM 6.4.4 [configured with MPIR 2.6.0, --enable-asm-redc] [ECM] +Input number is 32193213281156929 (17 digits) +Using B1=2000, B2=147396, polynomial x^1, sigma=434130265 +Step 1 took 2ms +Step 2 took 3ms +********** Factor found in step 2: 179424673 +Found probable prime factor of 9 digits: 179424673 +Probable prime cofactor 179424673 has 9 digits +""" + +TEST_ECM_OUTPUT_3 = """ +GMP-ECM 6.4.4 [configured with MPIR 2.6.0, --enable-asm-redc] [ECM] +Input number is 66955751844124594814248420514215108438425124740949701470891 (59 digits) +Using B1=2000, B2=147396, polynomial x^1, sigma=553262339 +Step 1 took 3ms +Step 2 took 4ms +Run 2 out of 1000000000: +Using B1=2399, B2=2399-186156, polynomial x^1, sigma=557154369 +Step 1 took 5ms +Step 2 took 4ms +Run 3 out of 1000000000: +Using B1=2806, B2=2806-224406, polynomial x^1, sigma=478195111 +Step 1 took 5ms +Step 2 took 4ms +********** Factor found in step 2: 197002597249 +Found probable prime factor of 12 digits: 197002597249 +Composite cofactor 339872432034468861533158743041639097889948066859 has 48 digits +""" + +TEST_ECM_OUTPUT_4 = """ +GMP-ECM 6.4.4 [configured with MPIR 2.6.0, --enable-asm-redc] [ECM] +Input number is 66955751844124594814248420514215108438425124740949701470891 (59 digits) +Using B1=2000, B2=147396, polynomial x^1, sigma=1881424010\n +Step 1 took 4ms +Step 2 took 2ms +********** Factor found in step 2: 265748496095531068869578877937 +Found composite factor of 30 digits: 265748496095531068869578877937 +Probable prime cofactor 251951573867253012259144010843 has 30 digits +""" + + + + + diff --git a/src/sage/interfaces/gap.py b/src/sage/interfaces/gap.py index b16a766941d..3bbe373dd00 100644 --- a/src/sage/interfaces/gap.py +++ b/src/sage/interfaces/gap.py @@ -1508,6 +1508,7 @@ def gap_reset_workspace(max_workspace_size=None, verbose=False): # Create new workspace with filename WORKSPACE g = Gap(use_workspace_cache=False, max_workspace_size=None) + g.eval('SetUserPreference("HistoryMaxLines", 30)') for pkg in ['GAPDoc', 'ctbllib', 'sonata', 'guava', 'factint', \ 'gapdoc', 'grape', 'design', \ 'toric', 'laguna', 'braid']: diff --git a/src/sage/interfaces/magma.py b/src/sage/interfaces/magma.py index f092c504ab9..4082bd03c90 100644 --- a/src/sage/interfaces/magma.py +++ b/src/sage/interfaces/magma.py @@ -733,7 +733,7 @@ def __call__(self, x, gens=None): # of the objects in the Magma interface to work correctly. has_cache = hasattr(x, '_magma_cache') try: - if has_cache and x._magma_cache.has_key(self): + if has_cache and self in x._magma_cache: A = x._magma_cache[self] if A._session_number == self._session_number: return A @@ -742,7 +742,7 @@ def __call__(self, x, gens=None): x._magma_cache = {} try: - if self.__cache.has_key(x): + if x in self.__cache: A = self.__cache[x] if A._session_number == self._session_number: return A @@ -1640,7 +1640,7 @@ def __call__(self, *args, **kwds): """ nvals = 1 if len(kwds) > 0: - if kwds.has_key('nvals'): + if 'nvals' in kwds: nvals = kwds['nvals'] del kwds['nvals'] M = self._obj.parent() @@ -1751,7 +1751,7 @@ def __call__(self, *args, **kwds): """ nvals = 1 if len(kwds) > 0: - if kwds.has_key('nvals'): + if 'nvals' in kwds: nvals = kwds['nvals'] del kwds['nvals'] M = self._parent diff --git a/src/sage/interfaces/maxima.py b/src/sage/interfaces/maxima.py index f67aa08af13..aa330e2a041 100644 --- a/src/sage/interfaces/maxima.py +++ b/src/sage/interfaces/maxima.py @@ -756,7 +756,8 @@ def _eval_line(self, line, allow_use_file=False, line_echo = self._expect.readline() if not wait_for_prompt: return - assert line_echo.strip() == line.strip(), 'mismatch:\n' + line_echo + line + # line_echo sometimes has randomly inserted terminal echo in front #15811 + assert line_echo.strip().endswith(line.strip()), 'mismatch:\n' + line_echo + line self._expect_expr(self._display_prompt) out = self._before() # input echo + output prompt + output diff --git a/src/sage/interfaces/mwrank.py b/src/sage/interfaces/mwrank.py index 369837df26d..6f39f73e10a 100644 --- a/src/sage/interfaces/mwrank.py +++ b/src/sage/interfaces/mwrank.py @@ -178,7 +178,7 @@ def __init__(self, options="", server=None,server_tmpdir=None): sage: from sage.interfaces.mwrank import Mwrank_class sage: M = Mwrank_class('-v 0 -l') sage: M('0 -1 1 0 0') - 'Curve [0,-1,1,0,0] :\tRank = 0\n\n\nRegulator = 1\n' + 'Curve [0,-1,1,0,0] :...Rank = 0...Regulator = 1...' sage: from sage.interfaces.mwrank import Mwrank_class sage: TestSuite(Mwrank_class).run() @@ -231,7 +231,7 @@ def __call__(self, cmd): The input can be five integers separated by whitespace:: sage: mwrank('0 -1 1 0 0') - 'Curve [0,-1,1,0,0] :\tBasic pair: I=16, J=-304\n...' + 'Curve [0,-1,1,0,0] :...Basic pair: I=16, J=-304...' Or a list or tuple of exactly five integers:: diff --git a/src/sage/interfaces/psage.py b/src/sage/interfaces/psage.py index 0a07d3baced..d3bcfd0215a 100644 --- a/src/sage/interfaces/psage.py +++ b/src/sage/interfaces/psage.py @@ -50,7 +50,7 @@ class PSage(Sage): def __init__(self, **kwds): - if kwds.has_key('server'): + if 'server' in kwds: raise NotImplementedError, "PSage doesn't work on remote server yet." Sage.__init__(self, **kwds) import sage.misc.misc diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index 5d858ac7d9e..a8d22e17385 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -1026,7 +1026,7 @@ def cell(self, *index): True """ index_str = _format_cell_index(index) - if self._cell_cache.has_key(index_str): + if index_str in self._cell_cache: return self._cell_cache[index_str] else: c = self.make_cells(self.d_cell(index))[0] diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py index 68d1bda2c62..6cb90c3a69d 100644 --- a/src/sage/interfaces/singular.py +++ b/src/sage/interfaces/singular.py @@ -1682,7 +1682,7 @@ def sage_poly(self, R=None, kcache=None): sage_repr[ETuple(exp,ngens)]=k(singular_poly_list[coeff_start+i]) else: elem = singular_poly_list[coeff_start+i] - if not kcache.has_key(elem): + if elem not in kcache: kcache[elem] = k( elem ) sage_repr[ETuple(exp,ngens)]= kcache[elem] @@ -1711,7 +1711,7 @@ def sage_poly(self, R=None, kcache=None): sage_repr[exp]=k(singular_poly_list[coeff_start+i]) else: elem = singular_poly_list[coeff_start+i] - if not kcache.has_key(elem): + if elem not in kcache: kcache[elem] = k( elem ) sage_repr[ exp ]= kcache[elem] diff --git a/src/sage/lfunctions/dokchitser.py b/src/sage/lfunctions/dokchitser.py index e546e440d2d..649c8196a1c 100644 --- a/src/sage/lfunctions/dokchitser.py +++ b/src/sage/lfunctions/dokchitser.py @@ -187,7 +187,7 @@ def __init__(self, conductor, gammaV, weight, eps, \ def __reduce__(self): D = copy.copy(self.__dict__) - if D.has_key('_Dokchitser__gp'): + if '_Dokchitser__gp' in D: del D['_Dokchitser__gp'] return reduce_load_dokchitser, (D, ) diff --git a/src/sage/lfunctions/lcalc.py b/src/sage/lfunctions/lcalc.py index 2e11f15935e..5a02aec92bf 100644 --- a/src/sage/lfunctions/lcalc.py +++ b/src/sage/lfunctions/lcalc.py @@ -343,7 +343,7 @@ def twist_zeros(self, n, dmin, dmax, L=''): d, x = a.split() x = RR(x) d = Z(d) - if w.has_key(d): + if d in w: w[d].append(x) else: w[d] = [x] diff --git a/src/sage/libs/ntl/ntl_GF2EContext.pyx b/src/sage/libs/ntl/ntl_GF2EContext.pyx index db8d031db58..8ac70a7263f 100644 --- a/src/sage/libs/ntl/ntl_GF2EContext.pyx +++ b/src/sage/libs/ntl/ntl_GF2EContext.pyx @@ -114,7 +114,7 @@ def ntl_GF2EContext( v ): if (GF2X_deg((v).x) < 1): raise ValueError, "%s is not a valid modulus."%v key = hash(v) - if GF2EContextDict.has_key(key): + if key in GF2EContextDict: context = GF2EContextDict[key]() if context is not None: return context diff --git a/src/sage/libs/ntl/ntl_ZZ_pContext.pyx b/src/sage/libs/ntl/ntl_ZZ_pContext.pyx index 56966c53e47..5a46a17c687 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pContext.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pContext.pyx @@ -124,7 +124,7 @@ cdef class ntl_ZZ_pContext_factory: v -- an ntl_ZZ """ cdef ntl_ZZ_pContext_class context - if self.context_dict.has_key(v): + if v in self.context_dict: context = self.context_dict[v]() if context is not None: return context diff --git a/src/sage/libs/pari/gen.pyx b/src/sage/libs/pari/gen.pyx index 6c082c36214..8cffecfbef1 100644 --- a/src/sage/libs/pari/gen.pyx +++ b/src/sage/libs/pari/gen.pyx @@ -218,19 +218,49 @@ cdef class gen(sage.structure.element.RingElement): return P.new_gen(gaddsg(1, self.g)) def __mod__(self, other): - cdef gen selfgen - cdef gen othergen - if isinstance(other, gen) and isinstance(self, gen): - selfgen = self - othergen = other - pari_catch_sig_on() - return P.new_gen(gmod(selfgen.g, othergen.g)) - return sage.structure.element.bin_op(self, other, operator.mod) + """ + Return ``self`` modulo ``other``. - def __pow__(gen self, n, m): - cdef gen t0 = objtogen(n) + EXAMPLES:: + + sage: pari(15) % pari(6) + 3 + sage: pari("x^3+x^2+x+1") % pari("x^2") + x + 1 + sage: pari(-2) % int(3) + 1 + sage: int(-2) % pari(3) + 1 + """ + cdef gen selfgen = objtogen(self) + cdef gen othergen = objtogen(other) + pari_catch_sig_on() + return P.new_gen(gmod(selfgen.g, othergen.g)) + + def __pow__(self, n, m): + """ + Return ``self`` to the power ``n`` (if ``m`` is ``None``) or + ``Mod(self, m)^n`` if ``m`` is not ``None``. + + EXAMPLES:: + + sage: pari(5) ^ pari(3) + 125 + sage: pari("x-1") ^ 3 + x^3 - 3*x^2 + 3*x - 1 + sage: pow(pari(5), pari(28), int(29)) + Mod(1, 29) + sage: int(2) ^ pari(-5) + 1/32 + sage: pari(2) ^ int(-5) + 1/32 + """ + cdef gen t0 = objtogen(self) + cdef gen t1 = objtogen(n) + if m is not None: + t0 = t0.Mod(m) pari_catch_sig_on() - return P.new_gen(gpow(self.g, t0.g, prec_bits_to_words(0))) + return P.new_gen(gpow(t0.g, t1.g, prec_bits_to_words(0))) def __neg__(gen self): pari_catch_sig_on() @@ -240,13 +270,48 @@ cdef class gen(sage.structure.element.RingElement): raise RuntimeError, "Use ** for exponentiation, not '^', which means xor\n"+\ "in Python, and has the wrong precedence." - def __rshift__(gen self, long n): + def __rshift__(self, long n): + """ + Divide ``self`` by `2^n` (truncating or not, depending on the + input type). + + EXAMPLES:: + + sage: pari(25) >> 3 + 3 + sage: pari(25/2) >> 2 + 25/8 + sage: pari("x") >> 3 + 1/8*x + sage: pari(1.0) >> 100 + 7.88860905221012 E-31 + sage: int(33) >> pari(2) + 8 + """ + cdef gen t0 = objtogen(self) pari_catch_sig_on() - return P.new_gen(gshift(self.g, -n)) + return P.new_gen(gshift(t0.g, -n)) + + def __lshift__(self, long n): + """ + Multiply ``self`` by `2^n`. - def __lshift__(gen self, long n): + EXAMPLES:: + + sage: pari(25) << 3 + 200 + sage: pari(25/32) << 2 + 25/8 + sage: pari("x") << 3 + 8*x + sage: pari(1.0) << 100 + 1.26765060022823 E30 + sage: int(33) << pari(2) + 132 + """ + cdef gen t0 = objtogen(self) pari_catch_sig_on() - return P.new_gen(gshift(self.g, n)) + return P.new_gen(gshift(t0.g, n)) def __invert__(gen self): pari_catch_sig_on() diff --git a/src/sage/libs/pari/pari_instance.pyx b/src/sage/libs/pari/pari_instance.pyx index cc4050df5af..7991a62ba05 100644 --- a/src/sage/libs/pari/pari_instance.pyx +++ b/src/sage/libs/pari/pari_instance.pyx @@ -157,6 +157,9 @@ include 'pari_err.pxi' include 'sage/ext/stdsage.pxi' include 'sage/ext/interrupt.pxi' +cdef extern from 'c_lib/include/memory.h': + void init_memory_functions() + import sys cimport libc.stdlib @@ -438,6 +441,10 @@ cdef class PariInstance(sage.structure.parent_base.ParentWithBase): _pari_init_error_handling() + # pari_init_opts() overrides MPIR's memory allocation functions, + # so we need to reset them. + init_memory_functions() + num_primes = maxprime # Free the PARI stack and allocate our own (using Cython) diff --git a/src/sage/logic/logic.py b/src/sage/logic/logic.py index 4954f7a200d..e59aee812b2 100644 --- a/src/sage/logic/logic.py +++ b/src/sage/logic/logic.py @@ -272,10 +272,47 @@ def print_table(self, table): print line print - #TODO: implement the combine function which returns - # two statements or'd together def combine(self, statement1, statement2): - x = 0 + r""" + Return a new statement which contains the + two statements or'd together. + + INPUT: + + - ``statement1`` -- the first statement + - ``statement2`` -- the second statement + + OUTPUT: + + A new staement which or'd the given statements together. + + EXAMPLES:: + + sage: log = SymbolicLogic() + sage: s1 = log.statement("(a&b)") + sage: s2 = log.statement("b") + sage: log.combine(s1,s2) + [['OPAREN', + 'OPAREN', + 'OPAREN', + 'a', + 'AND', + 'b', + 'CPAREN', + 'CPAREN', + 'OR', + 'OPAREN', + 'b', + 'CPAREN', + 'CPAREN'], + {'a': 'False', 'b': 'False'}, + ['a', 'b', 'b']] + """ + toks = ['OPAREN'] + statement1[0] + ['OR'] + statement2[0] + ['CPAREN'] + variables = dict(statement1[1].items() + statement2[1].items()) + var_order = statement1[2] + statement2[2] + return [toks, variables, var_order] + #TODO: implement the simplify function which calls #a c++ implementation of the ESPRESSO algorithm diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index 55613b273c5..391e719fc3f 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -1784,7 +1784,7 @@ cdef class Matrix(sage.structure.element.Matrix): if callable(rep_mapping): rep = rep_mapping(x) # avoid hashing entries, especially algebraic numbers - elif rep_mapping and rep_mapping.has_key(x): + elif rep_mapping and x in rep_mapping: rep = rep_mapping.get(x) else: rep = repr(x) diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index 811759a1098..4a8461f77f6 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -5855,9 +5855,9 @@ cdef class Matrix(matrix1.Matrix): self.check_mutability() cdef Matrix d, a cdef Py_ssize_t r, c - cdef bint transformation = kwds.has_key('transformation') and kwds['transformation'] + cdef bint transformation = 'transformation' in kwds and kwds['transformation'] if self._base_ring == ZZ: - if kwds.has_key('include_zero_rows') and not kwds['include_zero_rows']: + if 'include_zero_rows' in kwds and not kwds['include_zero_rows']: raise ValueError, "cannot echelonize in place and delete zero rows" if transformation: d, a = self.dense_matrix().echelon_form(**kwds) @@ -6098,7 +6098,7 @@ cdef class Matrix(matrix1.Matrix): sage: T*D == E True """ - cdef bint transformation = (kwds.has_key('transformation') and kwds['transformation']) + cdef bint transformation = ('transformation' in kwds and kwds['transformation']) x = self.fetch('echelon_form') if x is not None: if not transformation: diff --git a/src/sage/matrix/misc.pyx b/src/sage/matrix/misc.pyx index 732d86e282a..c9e1140a993 100644 --- a/src/sage/matrix/misc.pyx +++ b/src/sage/matrix/misc.pyx @@ -370,7 +370,7 @@ def matrix_rational_echelon_form_multimodular(Matrix self, height_guess=None, pr for i in range(len(X)): if cmp_pivots(best_pivots, list(X[i].pivots())) <= 0: p = X[i].base_ring().order() - if not lifts.has_key(p): + if p not in lifts: t0 = verbose("Lifting a good matrix", level=2, caller_name = "multimod echelon") lift = X[i].lift() lifts[p] = (lift, p) diff --git a/src/sage/matroids/set_system.pyx b/src/sage/matroids/set_system.pyx index 3b42a17dec4..1499f6fcfbe 100644 --- a/src/sage/matroids/set_system.pyx +++ b/src/sage/matroids/set_system.pyx @@ -448,7 +448,10 @@ cdef class SetSystem: if E is None: E = xrange(self._len) if P is None: - P = SetSystem(self._groundset, [self._groundset], capacity=self._groundset_size) + if self._groundset: + P = SetSystem(self._groundset, [self._groundset], capacity=self._groundset_size) + else: + P = SetSystem([], []) cnt = self._incidence_count(E) self._groundset_partition(P, cnt) return P @@ -607,6 +610,9 @@ cdef class SetSystem: ....: ['a', 'c', 'd']]) sage: S._isomorphism(T) {1: 'c', 2: 'd', 3: 'b', 4: 'a'} + sage: S = SetSystem([], []) + sage: S._isomorphism(S) + {} """ cdef long l, p if SP is None or OP is None: diff --git a/src/sage/misc/cachefunc.pyx b/src/sage/misc/cachefunc.pyx index 7c0703e6e0c..be3be4c3f7f 100644 --- a/src/sage/misc/cachefunc.pyx +++ b/src/sage/misc/cachefunc.pyx @@ -2727,7 +2727,7 @@ class FileCache: keystr = kwdstr + argstr return self._dir + self._prefix + keystr - def has_key(self, key): + def __contains__(self, key): """ Returns ``True`` if ``self[key]`` is defined and False otherwise. @@ -2738,9 +2738,9 @@ class FileCache: sage: FC = FileCache(dir, memory_cache = False, prefix='foo') sage: k = ((),(('a',1),)) sage: FC[k] = True - sage: FC.has_key(k) + sage: k in FC True - sage: FC.has_key(((),())) + sage: ((),()) in FC False """ return os.path.exists(self._filename(key) + '.key.sobj') @@ -2771,7 +2771,7 @@ class FileCache: cache = self._cache if cache is not None: - if cache.has_key(key): + if key in cache: return cache[key] f = self._filename(key) + '.sobj' @@ -2830,12 +2830,12 @@ class FileCache: sage: t = randint(0, 1000) sage: FC1[k] = t sage: del FC2[k] - sage: FC1.has_key(k) + sage: k in FC1 False """ f = self._filename(key) cache = self._cache - if cache is not None and cache.has_key(key): + if cache is not None and key in cache: del self._cache[key] if os.path.exists(f + '.sobj'): os.remove(f + '.sobj') diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index 65fe49bc113..4afc9046c5c 100644 --- a/src/sage/misc/cython.py +++ b/src/sage/misc/cython.py @@ -35,7 +35,7 @@ def cblas(): sage: sage.misc.cython.cblas() # random -- depends on OS, etc. 'cblas' """ - if os.environ.has_key('SAGE_CBLAS'): + if 'SAGE_CBLAS' in os.environ: return os.environ['SAGE_CBLAS'] elif os.path.exists('/usr/lib/libcblas.dylib') or \ os.path.exists('/usr/lib/libcblas.so'): @@ -156,7 +156,7 @@ def environ_parse(s): else: j = i + j name = s[i+1:j] - if os.environ.has_key(name): + if name in os.environ: s = s[:i] + os.environ[name] + s[j:] else: return s @@ -425,7 +425,7 @@ def cython(filename, verbose=False, compile_message=False, name = base else: global sequence_number - if not sequence_number.has_key(base): + if base not in sequence_number: sequence_number[base] = 0 name = '%s_%s'%(base, sequence_number[base]) diff --git a/src/sage/misc/edit_module.py b/src/sage/misc/edit_module.py index 582c6e42c19..774995cedc4 100644 --- a/src/sage/misc/edit_module.py +++ b/src/sage/misc/edit_module.py @@ -206,7 +206,7 @@ def set_editor(editor_name,opts=''): 'vi -c ${line} ${file}' """ - if sage.misc.edit_module.template_defaults.has_key(editor_name): + if editor_name in sage.misc.edit_module.template_defaults: set_edit_template(Template(template_defaults[editor_name].safe_substitute(opts=opts))) else: raise ValueError, "editor_name not known. Try set_edit_template() instead." diff --git a/src/sage/misc/fpickle.pyx b/src/sage/misc/fpickle.pyx index 157f3639059..f05c8a3e4a1 100644 --- a/src/sage/misc/fpickle.pyx +++ b/src/sage/misc/fpickle.pyx @@ -125,7 +125,7 @@ def pickleModule(module): def unpickleModule(name): 'support function for copy_reg to unpickle module refs' - if oldModules.has_key(name): + if name in oldModules: name = oldModules[name] return __import__(name,{},{},'x') diff --git a/src/sage/misc/misc.py b/src/sage/misc/misc.py index 40ed951caf4..529f5c3ddd6 100644 --- a/src/sage/misc/misc.py +++ b/src/sage/misc/misc.py @@ -14,9 +14,9 @@ Check the fix from trac #8323:: - sage: globals().has_key('name') + sage: 'name' in globals() False - sage: globals().has_key('func') + sage: 'func' in globals() False """ @@ -910,7 +910,7 @@ def assert_attribute(x, attr, init=None): If the object x has the attribute attr, do nothing. If not, set x.attr to init. """ - if x.__dict__.has_key(attr): return + if attr in x.__dict__: return if attr[:2] == "__": z = str(x.__class__).split("'") if len(z) > 1: diff --git a/src/sage/misc/randstate.pyx b/src/sage/misc/randstate.pyx index 81e6edcfb5a..85c726e2fa5 100644 --- a/src/sage/misc/randstate.pyx +++ b/src/sage/misc/randstate.pyx @@ -756,7 +756,7 @@ cdef class randstate: if prev is not self: - if self._gp_saved_seeds is not None and self._gp_saved_seeds.has_key(gp): + if self._gp_saved_seeds is not None and gp in self._gp_saved_seeds: seed = self._gp_saved_seeds[gp] else: diff --git a/src/sage/misc/reset.pyx b/src/sage/misc/reset.pyx index a98eaef57ca..321d0b5dd44 100644 --- a/src/sage/misc/reset.pyx +++ b/src/sage/misc/reset.pyx @@ -119,7 +119,7 @@ def restore(vars=None): NameError: name 'ww' is not defined """ G = globals() # this is the reason the code must be in Cython. - if not G.has_key('sage_mode'): + if 'sage_mode' not in G: import sage.all D = sage.all.__dict__ else: @@ -148,7 +148,7 @@ def _restore(G, D, vars): else: vars = vars.split() for k in vars: - if D.has_key(k): + if k in D: G[k] = D[k] else: try: diff --git a/src/sage/misc/session.pyx b/src/sage/misc/session.pyx index 2fc8c6bae90..ab403366f97 100644 --- a/src/sage/misc/session.pyx +++ b/src/sage/misc/session.pyx @@ -152,11 +152,11 @@ def _is_new_var(x, v, hidden): return False # If a variable names was not there at init time then it is # definitely new. - if not state_at_init.has_key(x): + if x not in state_at_init: return True # A variable could also be new even if it was there at init, say if # its value changed. - return not (state_at_init.has_key(x) and state_at_init[x] is v) + return x not in state_at_init or state_at_init[x] is not v def show_identifiers(hidden=False): r""" diff --git a/src/sage/misc/weak_dict.pyx b/src/sage/misc/weak_dict.pyx index 289b103cc2b..055fe33524a 100644 --- a/src/sage/misc/weak_dict.pyx +++ b/src/sage/misc/weak_dict.pyx @@ -619,11 +619,11 @@ cdef class WeakValueDictionary(dict): For a non-existing key, the default value is stored and returned:: - sage: D.has_key(4) + sage: 4 in D False sage: D.setdefault(4, ZZ) Integer Ring - sage: D.has_key(4) + sage: 4 in D True sage: D[4] Integer Ring @@ -827,35 +827,6 @@ cdef class WeakValueDictionary(dict): raise KeyError(k) return out - def has_key(self, k): - """ - Returns True, if the key is known to the dictionary. - - EXAMPLES:: - - sage: import sage.misc.weak_dict - sage: class Vals(object): pass - sage: L = [Vals() for _ in range(10)] - sage: D = sage.misc.weak_dict.WeakValueDictionary(enumerate(L)) - sage: D.has_key(3) - True - - As usual, keys are compared by equality and not by identity:: - - sage: D.has_key(int(3)) - True - - This is a weak value dictionary. Hence, the existence of the - dictionary does not prevent the values from garbage collection, - thereby removing the corresponding key-value pairs:: - - sage: del L[3] - sage: D.has_key(3) - False - - """ - return k in self - def __contains__(self, k): """ Containment in the set of keys. diff --git a/src/sage/modular/abvar/constructor.py b/src/sage/modular/abvar/constructor.py index b1c833c22c6..42d882061b2 100644 --- a/src/sage/modular/abvar/constructor.py +++ b/src/sage/modular/abvar/constructor.py @@ -46,7 +46,7 @@ def _get(key): ... ValueError: element not in cache """ - if _cache.has_key(key): + if key in _cache: z = _cache[key]() if z is not None: return z diff --git a/src/sage/modular/arithgroup/arithgroup_element.pyx b/src/sage/modular/arithgroup/arithgroup_element.pyx index 6073c9f5dd8..f8d9deef1a0 100644 --- a/src/sage/modular/arithgroup/arithgroup_element.pyx +++ b/src/sage/modular/arithgroup/arithgroup_element.pyx @@ -108,9 +108,9 @@ cdef class ArithmeticSubgroupElement(MultiplicativeGroupElement): from all import SL2Z oldparent, kwdict = state self._set_parent(SL2Z) - if kwdict.has_key('_ArithmeticSubgroupElement__x'): + if '_ArithmeticSubgroupElement__x' in kwdict: self.__x = kwdict['_ArithmeticSubgroupElement__x'] - elif kwdict.has_key('_CongruenceSubgroupElement__x'): + elif '_CongruenceSubgroupElement__x' in kwdict: self.__x = kwdict['_CongruenceSubgroupElement__x'] else: raise ValueError, "Don't know how to unpickle %s" % repr(state) diff --git a/src/sage/modular/cusps_nf.py b/src/sage/modular/cusps_nf.py index 7dbeba2d533..34abe24d098 100644 --- a/src/sage/modular/cusps_nf.py +++ b/src/sage/modular/cusps_nf.py @@ -155,7 +155,7 @@ def list_of_representatives(N): Fractional ideal (37, a + 12), Fractional ideal (47, a - 9)) """ - if _list_reprs_cache.has_key(N): + if N in _list_reprs_cache: lreps = _list_reprs_cache[N] if not (lreps is None): return lreps lreps = NFCusps_ideal_reps_for_levelN(N)[0] @@ -230,7 +230,7 @@ def NFCusps(number_field, use_cache=True): """ if use_cache: key = number_field - if _nfcusps_cache.has_key(key): + if key in _nfcusps_cache: C = _nfcusps_cache[key] if not (C is None): return C diff --git a/src/sage/modular/dirichlet.py b/src/sage/modular/dirichlet.py index e3424032b84..3d480352f6b 100644 --- a/src/sage/modular/dirichlet.py +++ b/src/sage/modular/dirichlet.py @@ -594,7 +594,7 @@ def bernoulli(self, k, algorithm='recurrence', cache=True, **opts): self.__bernoulli except AttributeError: self.__bernoulli = {} - if self.__bernoulli.has_key(k): + if k in self.__bernoulli: return self.__bernoulli[k] N = self.modulus() K = self.base_ring() @@ -1762,7 +1762,7 @@ def DirichletGroup(modulus, base_ring=None, zeta=None, zeta_order=None, zeta_order = zeta.multiplicative_order() key = (base_ring, modulus, zeta, zeta_order) - if _cache.has_key(key): + if key in _cache: x = _cache[key]() if not x is None: return x diff --git a/src/sage/modular/etaproducts.py b/src/sage/modular/etaproducts.py index 80a302ea1a3..81983a9b131 100644 --- a/src/sage/modular/etaproducts.py +++ b/src/sage/modular/etaproducts.py @@ -66,7 +66,7 @@ def EtaGroup(level): ... ValueError: Level (=0) must be a positive integer """ - if _cache.has_key(level): + if level in _cache: G = _cache[level]() if not G is None: return G diff --git a/src/sage/modular/hecke/algebra.py b/src/sage/modular/hecke/algebra.py index fb6fa5b541f..cf4566f6033 100644 --- a/src/sage/modular/hecke/algebra.py +++ b/src/sage/modular/hecke/algebra.py @@ -98,7 +98,7 @@ def AnemicHeckeAlgebra(M): k = (M, M.basis_matrix()) except AttributeError: k = M - if _anemic_cache.has_key(k): + if k in _anemic_cache: T = _anemic_cache[k]() if not (T is None): return T @@ -134,7 +134,7 @@ def HeckeAlgebra(M): k = (M, M.basis_matrix()) except AttributeError: k = M - if _cache.has_key(k): + if k in _cache: T = _cache[k]() if not (T is None): return T diff --git a/src/sage/modular/hecke/ambient_module.py b/src/sage/modular/hecke/ambient_module.py index 7fac6a64f7a..ad5047b2684 100644 --- a/src/sage/modular/hecke/ambient_module.py +++ b/src/sage/modular/hecke/ambient_module.py @@ -411,7 +411,7 @@ def degeneracy_map(self, codomain, t=1): except AttributeError: self._degeneracy_maps = {} - if self._degeneracy_maps.has_key(key): + if key in self._degeneracy_maps: return self._degeneracy_maps[key] if M.rank() == 0: @@ -655,7 +655,7 @@ def is_new(self, p=None): True """ try: - if self.__is_new.has_key(p): + if p in self.__is_new: return self.__is_new[p] except AttributeError: pass @@ -674,7 +674,7 @@ def is_old(self, p=None): False """ try: - if self.__is_old.has_key(p): + if p in self.__is_old: return self.__is_old[p] except AttributeError: pass diff --git a/src/sage/modular/hecke/module.py b/src/sage/modular/hecke/module.py index f2f81d0bf99..f5b2c50df74 100644 --- a/src/sage/modular/hecke/module.py +++ b/src/sage/modular/hecke/module.py @@ -157,11 +157,11 @@ def _compute_hecke_matrix_prime_power(self, p, r, **kwds): raise ArithmeticError, "p must be a prime" # T_{p^r} := T_p * T_{p^{r-1}} - eps(p)p^{k-1} T_{p^{r-2}}. pow = p**(r-1) - if not self._hecke_matrices.has_key(pow): + if pow not in self._hecke_matrices: # The following will force computation of T_{p^s} # for all s<=r-1, except possibly s=0. self._hecke_matrices[pow] = self._compute_hecke_matrix(pow) - if not self._hecke_matrices.has_key(1): + if 1 not in self._hecke_matrices: self._hecke_matrices[1] = self._compute_hecke_matrix(1) Tp = self._hecke_matrices[p] Tpr1 = self._hecke_matrices[pow] @@ -188,7 +188,7 @@ def _compute_hecke_matrix_general_product(self, F, **kwds): prod = None for p, r in F: pow = int(p**r) - if not self._hecke_matrices.has_key(pow): + if pow not in self._hecke_matrices: self._hecke_matrices[pow] = self._compute_hecke_matrix(pow) if prod is None: prod = self._hecke_matrices[pow] @@ -1206,7 +1206,7 @@ def dual_hecke_matrix(self, n): self._dual_hecke_matrices except AttributeError: self._dual_hecke_matrices = {} - if not self._dual_hecke_matrices.has_key(n): + if n not in self._dual_hecke_matrices: T = self._compute_dual_hecke_matrix(n) self._dual_hecke_matrices[n] = T return self._dual_hecke_matrices[n] @@ -1292,7 +1292,7 @@ def eigenvalue(self, n, name='alpha'): for p, r in F: (p, r) = (int(p), int(r)) pow = p**r - if not (ev.has_key(pow) and ev[pow].has_key(name)): + if not (pow in ev and name in ev[pow]): # TODO: Optimization -- do something much more # intelligent in case character is not defined. For # example, compute it using the diamond operators @@ -1358,7 +1358,7 @@ def hecke_matrix(self, n): n = int(n) if n <= 0: raise IndexError, "n must be positive." - if not self._hecke_matrices.has_key(n): + if n not in self._hecke_matrices: T = self._compute_hecke_matrix(n) T.set_immutable() self._hecke_matrices[n] = T @@ -1416,7 +1416,7 @@ def diamond_bracket_matrix(self, d): [ 0 0 -1 0] """ d = int(d) % self.level() - if not self._diamond_matrices.has_key(d): + if d not in self._diamond_matrices: if self.character() is not None: D = matrix_space.MatrixSpace(self.base_ring(),self.rank())(self.character()(d)) else: @@ -1757,7 +1757,7 @@ def _dict_set(v, n, key, val): sage: _dict_set(v, 1, 3, 4); v {1: {2: 3, 3: 4}} """ - if v.has_key(n): + if n in v: v[n][key] = val else: v[n] = {key:val} diff --git a/src/sage/modular/modform/constructor.py b/src/sage/modular/modform/constructor.py index 76eddac956e..d3691eafc63 100644 --- a/src/sage/modular/modform/constructor.py +++ b/src/sage/modular/modform/constructor.py @@ -306,7 +306,7 @@ def ModularForms(group = 1, key = canonical_parameters(group, level, weight, base_ring) - if use_cache and _cache.has_key(key): + if use_cache and key in _cache: M = _cache[key]() if not (M is None): M.set_precision(prec) diff --git a/src/sage/modular/modform/eis_series.py b/src/sage/modular/modform/eis_series.py index 044466c1ebf..d7ee18cf6c4 100644 --- a/src/sage/modular/modform/eis_series.py +++ b/src/sage/modular/modform/eis_series.py @@ -265,7 +265,7 @@ def __find_eisen_chars(character, k): for e in G: m = Integer(e.conductor()) - if C.has_key(m): + if m in C: C[m].append(e) else: C[m] = [e] @@ -275,11 +275,11 @@ def __find_eisen_chars(character, k): params = [] for L in divisors(N): misc.verbose("divisor %s"%L) - if not C.has_key(L): + if L not in C: continue GL = C[L] for R in divisors(N/L): - if not C.has_key(R): + if R not in C: continue GR = C[R] for chi in GL: diff --git a/src/sage/modular/modsym/boundary.py b/src/sage/modular/modsym/boundary.py index 3cd3b9d5b33..6d2dd3196fc 100644 --- a/src/sage/modular/modsym/boundary.py +++ b/src/sage/modular/modsym/boundary.py @@ -204,7 +204,7 @@ def _add_(self, other): """ z = dict(other.__x) for i, c in self.__x.items(): - if z.has_key(i): + if i in z: z[i] += c else: z[i] = c @@ -225,7 +225,7 @@ def _sub_(self, other): """ z = dict(self.__x) for i, c in other.__x.items(): - if z.has_key(i): + if i in z: z[i] -= c else: z[i] = -c diff --git a/src/sage/modular/modsym/heilbronn.pyx b/src/sage/modular/modsym/heilbronn.pyx index f28af38c283..7aba4e23fde 100644 --- a/src/sage/modular/modsym/heilbronn.pyx +++ b/src/sage/modular/modsym/heilbronn.pyx @@ -259,7 +259,7 @@ cdef class Heilbronn: b = u*self.list.v[4*i+1] + v*self.list.v[4*i+3] export.c_p1_normalize_int(N, a, b, &c, &d, &s, 0) X = (c,d) - if M.has_key(X): + if X in M: M[X] = M[X] + 1 else: M[X] = 1 @@ -269,7 +269,7 @@ cdef class Heilbronn: b = (u * self.list.v[4*i+1])%N + (v * self.list.v[4*i+3])%N export.c_p1_normalize_int(N, a, b, &c, &d, &s, 0) X = (c,d) - if M.has_key(X): + if X in M: M[X] = M[X] + 1 else: M[X] = 1 @@ -279,7 +279,7 @@ cdef class Heilbronn: b = llong_prod_mod(u,self.list.v[4*i+1],N) + llong_prod_mod(v,self.list.v[4*i+3], N) export.c_p1_normalize_llong(N, a, b, &c, &d, &s, 0) X = (c,d) - if M.has_key(X): + if X in M: M[X] = M[X] + 1 else: M[X] = 1 diff --git a/src/sage/modular/modsym/manin_symbols.py b/src/sage/modular/modsym/manin_symbols.py index 8c016d153cf..eb40ec066e1 100644 --- a/src/sage/modular/modsym/manin_symbols.py +++ b/src/sage/modular/modsym/manin_symbols.py @@ -292,7 +292,7 @@ def index(self, x): sage: all([i == m.index(m[i]) for i in xrange(len(m))]) True """ - if self._index.has_key(x): + if x in self._index: return self._index[x] x = self.normalize(x) try: @@ -1266,7 +1266,7 @@ def index(self, x): (16, 1), (17, 1)] """ - if self._index.has_key(x): + if x in self._index: return self._index[x], 1 x, s= self.normalize(x) try: diff --git a/src/sage/modular/modsym/modsym.py b/src/sage/modular/modsym/modsym.py index d0bb2ff026f..f0a118d1b35 100644 --- a/src/sage/modular/modsym/modsym.py +++ b/src/sage/modular/modsym/modsym.py @@ -336,7 +336,7 @@ def ModularSymbols(group = 1, """ key = canonical_parameters(group, weight, sign, base_ring) - if use_cache and _cache.has_key(key): + if use_cache and key in _cache: M = _cache[key]() if not (M is None): return M diff --git a/src/sage/modular/modsym/p1list_nf.py b/src/sage/modular/modsym/p1list_nf.py index d5e1be9e775..d7cef23f8cd 100644 --- a/src/sage/modular/modsym/p1list_nf.py +++ b/src/sage/modular/modsym/p1list_nf.py @@ -427,7 +427,7 @@ def normalize(self, with_scalar=False): else: return MSymbol(N, 1, N.reduce(self.d*cinv)) - if _level_cache.has_key(N): + if N in _level_cache: Lfacs, Lxs = _level_cache[N] else: Lfacs = [p**e for p, e in N.factor()] diff --git a/src/sage/modular/modsym/relation_matrix.py b/src/sage/modular/modsym/relation_matrix.py index db14ba023ef..ce54ecfe361 100644 --- a/src/sage/modular/modsym/relation_matrix.py +++ b/src/sage/modular/modsym/relation_matrix.py @@ -207,7 +207,7 @@ def T_relation_matrix_wtk_g0(syms, mod, field, sparse): if w==2: already_seen.add(j) j0, s0 = mod[j] s0 = s*s0 - if v.has_key(j0): + if j0 in v: v[j0] += s0 else: v[j0] = s0 @@ -786,7 +786,7 @@ def sparse_2term_quotient(rels, n, F): ## iT_plus_iTT = M.apply_T(i) + M.apply_TT(i) ## v = {i:ONE} ## for j, s in iT_plus_iTT: -## if v.has_key(j): +## if j in v: ## v[j] += field(s) ## else: ## v[j] = field(s) diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index a91d00c64d3..6c1cc1286ac 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -246,7 +246,7 @@ def OverconvergentModularForms(prime, weight, radius, base_ring=QQ, prec = 20, c if int(prime) not in [2, 3, 5, 7, 13]: raise ValueError, "p must be one of {2, 3, 5, 7, 13}" key = (prime, weight, radius, base_ring, prec, char) - if __ocmfdict.has_key(key): + if key in __ocmfdict: w = __ocmfdict[key] M = w() if not (M is None): diff --git a/src/sage/modular/overconvergent/weightspace.py b/src/sage/modular/overconvergent/weightspace.py index 72bc963cb72..95f257abde8 100644 --- a/src/sage/modular/overconvergent/weightspace.py +++ b/src/sage/modular/overconvergent/weightspace.py @@ -97,7 +97,7 @@ def WeightSpace_constructor(p, base_ring=None): """ if base_ring is None: base_ring = Qp(p) - if _wscache.has_key((p, base_ring)): + if (p, base_ring) in _wscache: m = _wscache[(p, base_ring)]() if m is not None: return m diff --git a/src/sage/modular/quatalg/brandt.py b/src/sage/modular/quatalg/brandt.py index e8ba2257b49..5db911aba1c 100644 --- a/src/sage/modular/quatalg/brandt.py +++ b/src/sage/modular/quatalg/brandt.py @@ -309,7 +309,7 @@ def BrandtModule(N, M=1, weight=2, base_ring=QQ, use_cache=True): raise TypeError, "base_ring must be a commutative ring" key = (N, M, weight, base_ring) if use_cache: - if cache.has_key(key): # TODO: re-enable caching! + if key in cache: # TODO: re-enable caching! return cache[key] if weight != 2: raise NotImplementedError, "weight != 2 not yet implemented" @@ -830,7 +830,7 @@ def hecke_matrix(self, n, algorithm='default', sparse=False, B=None): n = ZZ(n) if n <= 0: raise IndexError, "n must be positive." - if not self._hecke_matrices.has_key(n): + if n not in self._hecke_matrices: if algorithm == 'default': try: pr = len(self.__brandt_series_vectors[0][0]) except (AttributeError, IndexError): pr = 0 diff --git a/src/sage/modular/ssmod/ssmod.py b/src/sage/modular/ssmod/ssmod.py index 2c88bcc8c9b..da59302c565 100644 --- a/src/sage/modular/ssmod/ssmod.py +++ b/src/sage/modular/ssmod/ssmod.py @@ -911,7 +911,7 @@ def supersingular_points(self): neighbors = Phi2_quad(X, ss_points[j_prev], ss_points[pos]).roots() for (xj,ej) in neighbors: - if not ss_points_dic.has_key(xj): + if xj not in ss_points_dic: j = len(ss_points) ss_points += [xj] ss_points_pre += [pos] @@ -1037,7 +1037,7 @@ def hecke_matrix(self,L): - Iftikhar Burhanuddin -- burhanud@usc.edu """ - if self.__hecke_matrices.has_key(L): + if L in self.__hecke_matrices: return self.__hecke_matrices[L] SS, II = self.supersingular_points() if L == 2: diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index 9f4bf9358b7..9780327b556 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -4101,7 +4101,7 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): cdef object v, e e = dict((right)._entries) for i, a in left._entries.iteritems(): - if e.has_key(i): + if i in e: sum = (a)._add_( e[i]) if sum: e[i] = sum @@ -4122,7 +4122,7 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): cdef object v, e e = dict(left._entries) # dict to make a copy for i, a in (right)._entries.iteritems(): - if e.has_key(i): + if i in e: diff = ( e[i])._sub_(a) if diff: e[i] = diff @@ -4182,7 +4182,7 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): e = dict((right)._entries) z = left.base_ring()(0) for i, a in left._entries.iteritems(): - if e.has_key(i): + if i in e: z += (a)._mul_( e[i]) return z @@ -4199,7 +4199,7 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): e = dict((right)._entries) v = PyDict_New() for i, a in left._entries.iteritems(): - if e.has_key(i): + if i in e: prod = (a)._mul_( e[i]) if prod: v[i] = prod @@ -4317,7 +4317,7 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): if i < 0 or i >= degree: raise IndexError("index must be between %s and %s"%(-degree, degree-1)) - if self._entries.has_key(i): + if i in self._entries: return self._entries[i] return self.base_ring()(0) # optimize this somehow @@ -4335,7 +4335,7 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): 0 """ i = int(i) - if self._entries.has_key(i): + if i in self._entries: return self._entries[i] return self.base_ring()(0) # optimize this somehow @@ -4366,7 +4366,7 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): raise ValueError("vector is immutable; please change a copy instead (use copy())") i = int(i) if x == 0: - if self._entries.has_key(i): + if i in self._entries: del self._entries[i] return self._entries[i] = x diff --git a/src/sage/modules/free_quadratic_module.py b/src/sage/modules/free_quadratic_module.py index 107d48bdd76..2d1e7cf1215 100644 --- a/src/sage/modules/free_quadratic_module.py +++ b/src/sage/modules/free_quadratic_module.py @@ -151,7 +151,7 @@ def FreeQuadraticModule( key = (base_ring, rank, inner_product_matrix, sparse) - if _cache.has_key(key): + if key in _cache: M = _cache[key]() if not (M is None): return M diff --git a/src/sage/monoids/string_monoid.py b/src/sage/monoids/string_monoid.py index e66e1e1935e..17b2e433a72 100644 --- a/src/sage/monoids/string_monoid.py +++ b/src/sage/monoids/string_monoid.py @@ -55,9 +55,6 @@ def BinaryStrings(): True """ # Here we cache the binary strings to make them unique - # if _cache.has_key(2): - # The method .has_key() has been deprecated since Python 2.2. Use - # "k in Dict" instead of "Dict.has_key(k)". if 2 in _cache: S = _cache[2]() if not S is None: @@ -87,9 +84,6 @@ def OctalStrings(): 033355556 """ # Here we cache the octal strings to make them unique - # if _cache.has_key(8): - # The method .has_key() has been deprecated since Python 2.2. Use - # "k in Dict" instead of "Dict.has_key(k)". if 8 in _cache: S = _cache[8]() if not S is None: @@ -120,9 +114,6 @@ def HexadecimalStrings(): 0aaaf """ # Here we cache the hexadecimal strings to make them unique - # if _cache.has_key(16): - # The method .has_key() has been deprecated since Python 2.2. Use - # "k in Dict" instead of "Dict.has_key(k)". if 16 in _cache: S = _cache[16]() if not S is None: @@ -158,9 +149,6 @@ def Radix64Strings(): / """ # Here we cache the radix-64 strings to make them unique - # if _cache.has_key(64): - # The method .has_key() has been deprecated since Python 2.2. Use - # "k in Dict" instead of "Dict.has_key(k)". if 64 in _cache: S = _cache[64]() if not S is None: @@ -189,9 +177,6 @@ def AlphabeticStrings(): Z """ # Here we cache the alphabetic strings to make them unique - # if _cache.has_key(26): - # The method .has_key() has been deprecated since Python 2.2. Use - # "k in Dict" instead of "Dict.has_key(k)". if 26 in _cache: S = _cache[26]() if not S is None: diff --git a/src/sage/monoids/string_monoid_element.py b/src/sage/monoids/string_monoid_element.py index 4a852074bae..f0734da2348 100644 --- a/src/sage/monoids/string_monoid_element.py +++ b/src/sage/monoids/string_monoid_element.py @@ -328,9 +328,6 @@ def coincidence_index(self, prec=0): RR = RealField(prec) char_dict = {} for i in self._element_list: - # if char_dict.has_key(i): - # The method .has_key() has been deprecated since Python 2.2. Use - # "k in Dict" instead of "Dict.has_key(k)". if i in char_dict: char_dict[i] += 1 else: @@ -508,9 +505,6 @@ def frequency_distribution(self, length=1, prec=0): eps = RR(Integer(1)/N) for i in range(N): c = self[i:i+length] - # if X.has_key(c): - # The method .has_key() has been deprecated since Python 2.2. Use - # "k in Dict" instead of "Dict.has_key(k)". if c in X: X[c] += eps else: diff --git a/src/sage/monoids/string_ops.py b/src/sage/monoids/string_ops.py index 3f71bad0522..b6f73862e21 100644 --- a/src/sage/monoids/string_ops.py +++ b/src/sage/monoids/string_ops.py @@ -43,7 +43,7 @@ def frequency_distribution(S, n=1, field=None): eps = field(1)/N for i in range(N): c = S[i] - if P.has_key(c): + if c in P: P[c] += eps else: P[c] = eps @@ -68,7 +68,7 @@ def coincidence_index(S,n=1): X = {} for i in range(N): c = S[i:i+n] - if X.has_key(c): + if c in X: X[c] += 1 else: X[c] = 1 diff --git a/src/sage/numerical/backends/glpk_graph_backend.pyx b/src/sage/numerical/backends/glpk_graph_backend.pyx index a49ebde3bfd..def16f931d9 100644 --- a/src/sage/numerical/backends/glpk_graph_backend.pyx +++ b/src/sage/numerical/backends/glpk_graph_backend.pyx @@ -601,11 +601,11 @@ cdef class GLPKGraphBackend(object): if params is not None: try: - if params.has_key("low"): + if "low" in params: (a.data).low = params["low"] - if params.has_key("cap"): + if "cap" in params: (a.data).cap = params["cap"] - if params.has_key("cost"): + if "cost" in params: (a.data).cost = params["cost"] except TypeError: glp_del_arc(self.graph, a) @@ -688,24 +688,24 @@ cdef class GLPKGraphBackend(object): a = glp_add_arc(self.graph, u, v) if isinstance(label, dict): - if label.has_key("cost"): + if "cost" in label: cost = label["cost"] (a.data).cost = cost - if label.has_key("cap"): + if "cap" in label: cap = label["cap"] (a.data).cap = cap - if label.has_key("low"): + if "low" in label: low = label["low"] (a.data).low = low if not isdirected: a = glp_add_arc(self.graph, v, u) if isinstance(label, dict): - if label.has_key("cost"): + if "cost" in label: (a.data).cost = cost - if label.has_key("cap"): + if "cap" in label: (a.data).cap = cap - if label.has_key("low"): + if "low" in label: (a.data).low = low cpdef tuple get_edge(self, char* u, char* v): @@ -946,13 +946,13 @@ cdef class GLPKGraphBackend(object): cdef double low, cap, cost, x if params is not None: - if params.has_key("low"): + if "low" in params: low = params["low"] - if params.has_key("cap"): + if "cap" in params: cap = params["cap"] - if params.has_key("cost"): + if "cost" in params: cost = params["cost"] - if params.has_key("x"): + if "x" in params: x = params["x"] while a is not NULL: @@ -961,16 +961,16 @@ cdef class GLPKGraphBackend(object): glp_del_arc(self.graph, a) elif a.head == vert_v: del_it = True - if params.has_key("low"): + if "low" in params: if (a.data).low != low: del_it = False - if params.has_key("cap"): + if "cap" in params: if (a.data).cap != cap: del_it = False - if params.has_key("cost"): + if "cost" in params: if (a.data).cost != cost: del_it = False - if params.has_key("x"): + if "x" in params: if (a.data).x != x: del_it = False if del_it: diff --git a/src/sage/numerical/linear_functions.pyx b/src/sage/numerical/linear_functions.pyx index 242566b9047..5fe81501b33 100644 --- a/src/sage/numerical/linear_functions.pyx +++ b/src/sage/numerical/linear_functions.pyx @@ -658,7 +658,7 @@ cdef class LinearFunction(ModuleElement): cdef bint first = True t = "" - if d.has_key(-1): + if -1 in d: coeff = d.pop(-1) if coeff!=0: t = self._coeff_formatter(coeff, constant_term=True) diff --git a/src/sage/numerical/mip.pyx b/src/sage/numerical/mip.pyx index d6dd3f2f660..e0fc1ef9f5d 100644 --- a/src/sage/numerical/mip.pyx +++ b/src/sage/numerical/mip.pyx @@ -1153,7 +1153,7 @@ cdef class MixedIntegerLinearProgram(SageObject): c = [] [c.append(self.get_values(ll)) for ll in l] val.append(c) - elif self._variables.has_key(l): + elif l in self._variables: #val.append(self._values[l]) val.append(self._backend.get_variable_value(self._variables[l])) @@ -1568,7 +1568,7 @@ cdef class MixedIntegerLinearProgram(SageObject): else: for v in e.keys(): self.set_binary(e[v]) - elif self._variables.has_key(e): + elif e in self._variables: self._backend.set_variable_type(self._variables[e],self.__BINARY) else: raise ValueError("e must be an instance of MIPVariable or one of its elements.") @@ -1637,7 +1637,7 @@ cdef class MixedIntegerLinearProgram(SageObject): else: for v in e.keys(): self.set_integer(e[v]) - elif self._variables.has_key(e): + elif e in self._variables: self._backend.set_variable_type(self._variables[e],self.__INTEGER) else: raise ValueError("e must be an instance of MIPVariable or one of its elements.") @@ -1706,7 +1706,7 @@ cdef class MixedIntegerLinearProgram(SageObject): else: for v in e.keys(): self.set_real(e[v]) - elif self._variables.has_key(e): + elif e in self._variables: self._backend.set_variable_type(self._variables[e],self.__REAL) else: raise ValueError("e must be an instance of MIPVariable or one of its elements.") @@ -2187,7 +2187,7 @@ cdef class MIPVariable(SageObject): cdef int j - if self._dict.has_key(i): + if i in self._dict: return self._dict[i] elif self._dim == 1: zero = self._p._backend.zero() diff --git a/src/sage/parallel/ncpus.py b/src/sage/parallel/ncpus.py index 7c5b3bbc899..81e6f980335 100644 --- a/src/sage/parallel/ncpus.py +++ b/src/sage/parallel/ncpus.py @@ -43,7 +43,7 @@ def ncpus(): """ #for Linux, Unix and MacOS if hasattr(os, "sysconf"): - if os.sysconf_names.has_key("SC_NPROCESSORS_ONLN"): + if "SC_NPROCESSORS_ONLN" in os.sysconf_names: #Linux and Unix ncpus = os.sysconf("SC_NPROCESSORS_ONLN") if isinstance(ncpus, int) and ncpus > 0: @@ -54,7 +54,7 @@ def ncpus(): process = subprocess.Popen("sysctl -n hw.ncpu", shell=True, stdin=subprocess.PIPE, stdout = subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) return int(process.stdout.read()) #for Windows - if os.environ.has_key("NUMBER_OF_PROCESSORS"): + if "NUMBER_OF_PROCESSORS" in os.environ: ncpus = int(os.environ["NUMBER_OF_PROCESSORS"]) if ncpus > 0: return ncpus diff --git a/src/sage/plot/contour_plot.py b/src/sage/plot/contour_plot.py index f677b74df69..d5ea7a8d67a 100644 --- a/src/sage/plot/contour_plot.py +++ b/src/sage/plot/contour_plot.py @@ -149,7 +149,7 @@ def _render_on_subplot(self, subplot): options = self.options() fill = options['fill'] contours = options['contours'] - if options.has_key('cmap'): + if 'cmap' in options: cmap = get_cmap(options['cmap']) elif fill or contours is None: cmap = get_cmap('gray') diff --git a/src/sage/plot/plot3d/base.pyx b/src/sage/plot/plot3d/base.pyx index 7b4debeb884..07ea20b0a75 100644 --- a/src/sage/plot/plot3d/base.pyx +++ b/src/sage/plot/plot3d/base.pyx @@ -1298,7 +1298,7 @@ end_scene""" % (render_params.antialiasing, opts['aspect_ratio'], opts['zoom'] ) - if ext == 'png': + if ext == '.png': # No conversion is necessary out_filename = filename else: @@ -1306,7 +1306,7 @@ end_scene""" % (render_params.antialiasing, out_filename = sage.misc.temporary_file.tmp_filename(ext=ext) tachyon_rt(T.tachyon(), out_filename, opts['verbosity'], True, '-res %s %s' % (opts['figsize'][0]*100, opts['figsize'][1]*100)) - if ext != 'png': + if ext != '.png': import PIL.Image as Image Image.open(out_filename).save(filename) else: @@ -1802,7 +1802,7 @@ cdef class PrimitiveObject(Graphics3d): This is the base class for the non-container 3d objects. """ def __init__(self, **kwds): - if kwds.has_key('texture'): + if 'texture' in kwds: self.texture = kwds['texture'] if not is_Texture(self.texture): self.texture = Texture(self.texture) diff --git a/src/sage/plot/plot3d/list_plot3d.py b/src/sage/plot/plot3d/list_plot3d.py index 1ecf72546cf..49f4a6e6e3d 100644 --- a/src/sage/plot/plot3d/list_plot3d.py +++ b/src/sage/plot/plot3d/list_plot3d.py @@ -164,7 +164,7 @@ def list_plot3d(v, interpolation_type='default', texture="automatic", point_list if texture == "automatic": texture = "lightblue" if is_Matrix(v): - if interpolation_type=='default' or interpolation_type=='linear' and not kwds.has_key('num_points'): + if interpolation_type=='default' or interpolation_type=='linear' and 'num_points' not in kwds: return list_plot3d_matrix(v, texture=texture, **kwds) else: l=[] @@ -399,7 +399,7 @@ def list_plot3d_tuples(v,interpolation_type, texture, **kwds): ymin=float(min(y)) ymax=float(max(y)) - num_points= kwds['num_points'] if kwds.has_key('num_points') else int(4*numpy.sqrt(len(x))) + num_points= kwds['num_points'] if 'num_points' in kwds else int(4*numpy.sqrt(len(x))) #arbitrary choice - assuming more or less a nxn grid of points # x should have n^2 entries. We sample 4 times that many points. @@ -446,13 +446,13 @@ def g(x,y): if interpolation_type =='spline': from plot3d import plot3d - kx=kwds['kx'] if kwds.has_key('kx') else 3 - ky=kwds['ky'] if kwds.has_key('ky') else 3 - if kwds.has_key('degree'): + kx=kwds['kx'] if 'kx' in kwds else 3 + ky=kwds['ky'] if 'ky' in kwds else 3 + if 'degree' in kwds: kx=kwds['degree'] ky=kwds['degree'] - s=kwds['smoothing'] if kwds.has_key('smoothing') else len(x)-numpy.sqrt(2*len(x)) + s=kwds['smoothing'] if 'smoothing' in kwds else len(x)-numpy.sqrt(2*len(x)) s=interpolate.bisplrep(x,y,z,[int(1)]*len(x),xmin,xmax,ymin,ymax,kx=kx,ky=ky,s=s) f=lambda x,y: interpolate.bisplev(x,y,s) return plot3d(f,(xmin,xmax),(ymin,ymax),texture=texture,plot_points=[num_points,num_points],**kwds) diff --git a/src/sage/plot/plot3d/platonic.py b/src/sage/plot/plot3d/platonic.py index e570c6c1cba..5bf16708d0c 100644 --- a/src/sage/plot/plot3d/platonic.py +++ b/src/sage/plot/plot3d/platonic.py @@ -84,12 +84,12 @@ def index_face_set(face_list, point_list, enclosed, **kwds): sage: icosahedron(center=(2,0,0),size=2,color='red') """ - if kwds.has_key('center'): + if 'center' in kwds: center = kwds['center'] del kwds['center'] else: center = (0,0,0) - if kwds.has_key('size'): + if 'size' in kwds: size = kwds['size'] del kwds['size'] else: diff --git a/src/sage/plot/plot3d/shapes2.py b/src/sage/plot/plot3d/shapes2.py index b320a06aae2..d0eef4610d8 100644 --- a/src/sage/plot/plot3d/shapes2.py +++ b/src/sage/plot/plot3d/shapes2.py @@ -144,7 +144,7 @@ def line3d(points, thickness=1, radius=None, arrow_head=False, **kwds): return L else: v = [] - if kwds.has_key('texture'): + if 'texture' in kwds: kwds = kwds.copy() texture = kwds.pop('texture') else: @@ -644,7 +644,7 @@ def text3d(txt, (x,y,z), **kwds): sage: text3d("Sage is...",(2,12,1), rgbcolor=(1,0,0)) + text3d("quite powerful!!",(4,10,0), rgbcolor=(0,0,1)) """ - if not kwds.has_key('color') and not kwds.has_key('rgbcolor'): + if 'color' not in kwds and 'rgbcolor' not in kwds: kwds['color'] = (0,0,0) G = Text(txt, **kwds).translate((x,y,z)) G._set_extra_kwds(kwds) diff --git a/src/sage/plot/plot_field.py b/src/sage/plot/plot_field.py index 115c9c4fec7..dbdd9783b1b 100644 --- a/src/sage/plot/plot_field.py +++ b/src/sage/plot/plot_field.py @@ -111,8 +111,30 @@ def _repr_(self): sage: P=plot_vector_field((sin(x), cos(y)), (x,-3,3), (y,-3,3)) sage: P[0] PlotField defined by a 20 x 20 vector grid + + TESTS: + We check that :trac:`15052` is fixed + (note that in general :trac:`15002` should be fixed):: + + sage: x,y=var('x,y') + sage: P=plot_vector_field((sin(x), cos(y)), (x,-3,3), (y,-3,3), wrong_option='nonsense') + sage: P[0].options()['plot_points'] + verbose 0 (...: primitive.py, options) WARNING: Ignoring option 'wrong_option'=nonsense + verbose 0 (...: primitive.py, options) + The allowed options for PlotField defined by a 20 x 20 vector grid are: + color The color of the arrows + headaxislength head length at shaft intersection, default is 4.5 + headlength head length as multiple of shaft width, default is 5 + headwidth Head width as multiple of shaft width, default is 3 + pivot Where the arrow should be placed in relation to the point (tail, middle, tip) + plot_points How many points to use for plotting precision + zorder The layer level in which to draw + + 20 + """ - return "PlotField defined by a %s x %s vector grid"%(self.options()['plot_points'], self.options()['plot_points']) + return "PlotField defined by a %s x %s vector grid"%( + self._options['plot_points'], self._options['plot_points']) def _render_on_subplot(self, subplot): """ diff --git a/src/sage/plot/primitive.py b/src/sage/plot/primitive.py index 7cc194c7e54..fee17eba974 100644 --- a/src/sage/plot/primitive.py +++ b/src/sage/plot/primitive.py @@ -180,7 +180,7 @@ def options(self): s = "\nThe allowed options for %s are:\n"%self K.sort() for k in K: - if A.has_key(k): + if k in A: s += " %-15s%-60s\n"%(k,A[k]) verbose(s, level=0) diff --git a/src/sage/rings/complex_field.py b/src/sage/rings/complex_field.py index 93222968bc5..d01d19dc4e4 100644 --- a/src/sage/rings/complex_field.py +++ b/src/sage/rings/complex_field.py @@ -106,7 +106,7 @@ def ComplexField(prec=53, names=None): -1.0000000000000000000000000000000000000000000000000000000000 """ global cache - if cache.has_key(prec): + if prec in cache: X = cache[prec] C = X() if not C is None: diff --git a/src/sage/rings/complex_interval_field.py b/src/sage/rings/complex_interval_field.py index b988c1cd30b..0b693acf47c 100644 --- a/src/sage/rings/complex_interval_field.py +++ b/src/sage/rings/complex_interval_field.py @@ -93,7 +93,7 @@ def ComplexIntervalField(prec=53, names=None): 0.207879576350761908546955619834978770033877841631769608075136? """ global cache - if cache.has_key(prec): + if prec in cache: X = cache[prec] C = X() if not C is None: diff --git a/src/sage/rings/complex_mpc.pyx b/src/sage/rings/complex_mpc.pyx index 13785c994dc..7c40486ac75 100644 --- a/src/sage/rings/complex_mpc.pyx +++ b/src/sage/rings/complex_mpc.pyx @@ -259,7 +259,7 @@ def MPComplexField(prec=53, rnd="RNDNN", names=None): """ global cache mykey = (prec, rnd) - if cache.has_key(mykey): + if mykey in cache: X = cache[mykey] C = X() if not C is None: diff --git a/src/sage/rings/finite_rings/constructor.py b/src/sage/rings/finite_rings/constructor.py index 64926a44606..082018cc799 100644 --- a/src/sage/rings/finite_rings/constructor.py +++ b/src/sage/rings/finite_rings/constructor.py @@ -410,15 +410,15 @@ def create_key_and_extra_args(self, order, name=None, modulus=None, names=None, # is no good place to store a specific choice of # pseudo-Conway polynomials. if name is None: - if not (kwds.has_key('conway') and kwds['conway']): + if not ('conway' in kwds and kwds['conway']): raise ValueError("parameter 'conway' is required if no name given") - if not kwds.has_key('prefix'): + if 'prefix' not in kwds: raise ValueError("parameter 'prefix' is required if no name given") name = kwds['prefix'] + str(n) - if kwds.has_key('conway') and kwds['conway']: + if 'conway' in kwds and kwds['conway']: from conway_polynomials import conway_polynomial - if not kwds.has_key('prefix'): + if 'prefix' not in kwds: raise ValueError("a prefix must be specified if conway=True") if modulus is not None: raise ValueError("no modulus may be specified if conway=True") @@ -506,7 +506,7 @@ def create_object(self, version, key, check_irreducible=True, elem_cache=None, else: impl = 'pari_ffelt' if impl == 'givaro': - if kwds.has_key('repr'): + if 'repr' in kwds: repr = kwds['repr'] else: repr = 'poly' @@ -525,7 +525,7 @@ def create_object(self, version, key, check_irreducible=True, elem_cache=None, raise ValueError("no such finite field implementation: %s" % impl) # Temporary; see create_key_and_extra_args() above. - if kwds.has_key('prefix'): + if 'prefix' in kwds: K._prefix = kwds['prefix'] return K diff --git a/src/sage/rings/finite_rings/conway_polynomials.py b/src/sage/rings/finite_rings/conway_polynomials.py index e29daef07aa..7d67556b329 100644 --- a/src/sage/rings/finite_rings/conway_polynomials.py +++ b/src/sage/rings/finite_rings/conway_polynomials.py @@ -195,7 +195,7 @@ def polynomial(self, n): sage: PCL.polynomial(60) x^60 + x^59 + x^58 + x^55 + x^54 + x^53 + x^52 + x^51 + x^48 + x^46 + x^45 + x^42 + x^41 + x^39 + x^38 + x^37 + x^35 + x^32 + x^31 + x^30 + x^28 + x^24 + x^22 + x^21 + x^18 + x^17 + x^16 + x^15 + x^14 + x^10 + x^8 + x^7 + x^5 + x^3 + x^2 + x + 1 """ - if self.nodes.has_key(n): + if n in self.nodes: return self.nodes[n] p = self.p @@ -444,7 +444,7 @@ def find_leveller(qindex, level, x, xleveled, searched, i): if crt[(i,j)][qindex][1] >= level: if xleveled[j]: return [j] - elif not searched.has_key(j): + elif j not in searched: crt_possibles.append(j) for j in crt_possibles: path = find_leveller(qindex, level, x, xleveled, searched, j) diff --git a/src/sage/rings/finite_rings/finite_field_ntl_gf2e.py b/src/sage/rings/finite_rings/finite_field_ntl_gf2e.py index 3059340fd4a..b7640fc2c13 100644 --- a/src/sage/rings/finite_rings/finite_field_ntl_gf2e.py +++ b/src/sage/rings/finite_rings/finite_field_ntl_gf2e.py @@ -19,7 +19,7 @@ def late_import(): sage: sage.rings.finite_rings.finite_field_ntl_gf2e.GF2 is None # indirect doctest False """ - if globals().has_key("GF2"): + if "GF2" in globals(): return global ResidueField_generic, is_FiniteField, exists_conway_polynomial, conway_polynomial, Cache_ntl_gf2e, GF, GF2, is_Polynomial import sage.rings.residue_field diff --git a/src/sage/rings/fraction_field_FpT.pyx b/src/sage/rings/fraction_field_FpT.pyx index ea8c24695ab..e0a4f5acf8b 100644 --- a/src/sage/rings/fraction_field_FpT.pyx +++ b/src/sage/rings/fraction_field_FpT.pyx @@ -1118,7 +1118,7 @@ cdef class Polyring_FpT_coerce(RingHomomorphism_coercion): nmod_poly_set(ans._denom, &((y).x)) else: raise ValueError, "FpT only supports two positional arguments" - if not (kwds.has_key('reduce') and not kwds['reduce']): + if 'reduce' not in kwds or kwds['reduce']: normalize(ans._numer, ans._denom, ans.p) ans.initalized = True return ans @@ -1314,7 +1314,7 @@ cdef class Fp_FpT_coerce(RingHomomorphism_coercion): nmod_poly_set(ans._denom, &((y).x)) else: raise ValueError, "FpT only supports two positional arguments" - if not (kwds.has_key('reduce') and not kwds['reduce']): + if 'reduce' not in kwds or kwds['reduce']: normalize(ans._numer, ans._denom, ans.p) ans.initalized = True return ans @@ -1523,7 +1523,7 @@ cdef class ZZ_FpT_coerce(RingHomomorphism_coercion): nmod_poly_set(ans._denom, &((y).x)) else: raise ValueError, "FpT only supports two positional arguments" - if not (kwds.has_key('reduce') and not kwds['reduce']): + if 'reduce' not in kwds or kwds['reduce']: normalize(ans._numer, ans._denom, ans.p) ans.initalized = True return ans diff --git a/src/sage/rings/infinity.py b/src/sage/rings/infinity.py index a353ccf8381..5074ed7a9f1 100644 --- a/src/sage/rings/infinity.py +++ b/src/sage/rings/infinity.py @@ -215,7 +215,7 @@ def __new__(cls, *args): sage: sage.rings.infinity.UnsignedInfinityRing_class() is sage.rings.infinity.UnsignedInfinityRing_class() True """ - if _obj.has_key(cls): + if cls in _obj: return _obj[cls] _obj[cls] = O = cls.__bases__[-1].__new__(cls, *args) return O diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index e1b50944fde..329def20604 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -3386,12 +3386,11 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): more information - ``'ecm'`` - use ECM-GMP, an implementation of Hendrik - Lenstra's elliptic curve method; WARNING: the factors - returned may not be prime, see ecm.factor? for more - information + Lenstra's elliptic curve method. - - ``proof`` - bool (default: True) whether or not to - prove primality of each factor (only applicable for PARI). + - ``proof`` - bool (default: True) whether or not to prove + primality of each factor (only applicable for ``'pari'`` + and ``'ecm'``). - ``limit`` - int or None (default: None) if limit is given it must fit in a signed int, and the factorization is done @@ -3458,8 +3457,6 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: q = next_prime(10^21) sage: n = p*q sage: n.factor(algorithm='ecm') - doctest:... RuntimeWarning: the factors returned by ecm - are not guaranteed to be prime; see ecm.factor? for details 1000000000000037 * 1000000000000000000117 TESTS:: @@ -3538,11 +3535,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): F = IntegerFactorization(res, unit) return F elif algorithm == 'ecm': - message = "the factors returned by ecm are not guaranteed to be prime; see ecm.factor? for details" - from warnings import warn - warn(message, RuntimeWarning, stacklevel=2) from sage.interfaces.ecm import ecm - res = [(p, 1) for p in ecm.factor(n)] + res = [(p, 1) for p in ecm.factor(n, proof=proof)] F = IntegerFactorization(res, unit) return F else: @@ -4495,11 +4489,12 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): def is_prime(self, proof=None): r""" - Returns ``True`` if ``self`` is prime. + Test whether ``self`` is prime. INPUT: - - ``proof`` -- If False, use a strong pseudo-primality test. + - ``proof`` -- Boolean or ``None`` (default). If False, use a + strong pseudo-primality test (see :meth:`is_pseudoprime`). If True, use a provable primality test. If unset, use the default arithmetic proof flag. @@ -4582,7 +4577,12 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): def is_pseudoprime(self): r""" - Returns ``True`` if self is a pseudoprime + Test whether self is a pseudoprime + + This uses PARI's Baillie-PSW probabilistic primality + test. Currently, there are no known pseudoprimes for + Baille-PSW that are not actually prime. However it is + conjectured that there are infinitely many. EXAMPLES:: diff --git a/src/sage/rings/laurent_series_ring.py b/src/sage/rings/laurent_series_ring.py index 541de2c40d5..962940ddfc8 100644 --- a/src/sage/rings/laurent_series_ring.py +++ b/src/sage/rings/laurent_series_ring.py @@ -84,7 +84,7 @@ def LaurentSeriesRing(base_ring, name=None, names=None, default_prec=20, sparse= global laurent_series key = (base_ring, name, default_prec, sparse) - if laurent_series.has_key(key): + if key in laurent_series: x = laurent_series[key]() if x != None: return x diff --git a/src/sage/rings/laurent_series_ring_element.pyx b/src/sage/rings/laurent_series_ring_element.pyx index bd42f7c7af6..1337e8cada7 100644 --- a/src/sage/rings/laurent_series_ring_element.pyx +++ b/src/sage/rings/laurent_series_ring_element.pyx @@ -1291,7 +1291,7 @@ cdef class LaurentSeries(AlgebraElement): """ if len(kwds) >= 1: name = self.parent().variable_name() - if kwds.has_key(name): # a keyword specifies the Laurent series generator + if name in kwds: # a keyword specifies the Laurent series generator if len(x) > 0: raise ValueError, "must not specify %s keyword and positional argument" % name a = self(kwds[name]) diff --git a/src/sage/rings/morphism.pyx b/src/sage/rings/morphism.pyx index 185d5eb7e91..c2cfc7a02be 100644 --- a/src/sage/rings/morphism.pyx +++ b/src/sage/rings/morphism.pyx @@ -657,7 +657,7 @@ cdef class RingHomomorphism(RingMap): self._lift = lift cdef _update_slots(self, _slots): - if _slots.has_key('_lift'): + if '_lift' in _slots: self._lift = _slots['_lift'] Morphism._update_slots(self, _slots) diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index c684a6f50f7..099ab941611 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -444,7 +444,7 @@ def NumberField(polynomial, name=None, check=True, names=None, cache=True, key = (polynomial, polynomial.base_ring(), name, latex_name, embedding, embedding.parent() if embedding is not None else None, assume_disc_small, None if maximize_at_primes is None else tuple(maximize_at_primes)) - if _nf_cache.has_key(key): + if key in _nf_cache: K = _nf_cache[key]() if not K is None: return K @@ -910,7 +910,7 @@ def CyclotomicField(n=0, names=None, bracket="()", embedding=True): if embedding is True: embedding = (2 * CLF.pi() * CLF.gen() / n).exp() key = (n, names, embedding) - if _cyclo_cache.has_key(key): + if key in _cyclo_cache: K = _cyclo_cache[key]() if not K is None: return K K = NumberField_cyclotomic(n, names, embedding=embedding) diff --git a/src/sage/rings/number_field/number_field_element.pyx b/src/sage/rings/number_field/number_field_element.pyx index 9f9657eb655..fb25be553e7 100644 --- a/src/sage/rings/number_field/number_field_element.pyx +++ b/src/sage/rings/number_field/number_field_element.pyx @@ -2463,7 +2463,7 @@ cdef class NumberFieldElement(FieldElement): if isinstance(self.number_field(), number_field.NumberField_cyclotomic): t = self.number_field()._multiplicative_order_table() f = self.polynomial() - if t.has_key(f): + if f in t: self.__multiplicative_order = t[f] return self.__multiplicative_order else: diff --git a/src/sage/rings/padics/common_conversion.pyx b/src/sage/rings/padics/common_conversion.pyx index b3a3fd3f7e8..fd901a3a6fd 100644 --- a/src/sage/rings/padics/common_conversion.pyx +++ b/src/sage/rings/padics/common_conversion.pyx @@ -229,7 +229,7 @@ cdef int _process_args_and_kwds(long *aprec, long *rprec, args, kwds, bint absol - error status """ - if kwds.has_key("empty"): + if "empty" in kwds: # For backward compatibility aprec[0] = 0 rprec[0] = 0 @@ -237,13 +237,13 @@ cdef int _process_args_and_kwds(long *aprec, long *rprec, args, kwds, bint absol if len(args) > 2: raise TypeError("too many positional arguments") if len(args) == 2: - if kwds.has_key("relprec"): + if "relprec" in kwds: raise TypeError("_call_with_args() got multiple values for keyword argument 'relprec'") relprec = args[1] else: relprec = kwds.get("relprec",infinity) if len(args) >= 1: - if kwds.has_key("absprec"): + if "absprec" in kwds: raise TypeError("_call_with_args() got multiple values for keyword argument 'absprec'") absprec = args[0] else: diff --git a/src/sage/rings/padics/factory.py b/src/sage/rings/padics/factory.py index f91a147066b..f464f4dac56 100644 --- a/src/sage/rings/padics/factory.py +++ b/src/sage/rings/padics/factory.py @@ -84,21 +84,21 @@ def get_key_base(p, prec, type, print_mode, halt, names, ram_name, print_pos, pr raise ValueError, "p must be prime" print_ram_name = ram_name if isinstance(print_mode, dict): - if print_mode.has_key('pos'): + if 'pos' in print_mode: print_pos = print_mode['pos'] - if print_mode.has_key('ram_name'): + if 'ram_name' in print_mode: print_ram_name = print_mode['ram_name'] - if print_mode.has_key('unram_name'): + if 'unram_name' in print_mode: print_unram_name = print_mode['unram_name'] - if print_mode.has_key('sep'): + if 'sep' in print_mode: print_sep = print_mode['sep'] - if print_mode.has_key('alphabet'): + if 'alphabet' in print_mode: print_alphabet = print_mode['alphabet'] - if print_mode.has_key('max_ram_terms'): + if 'max_ram_terms' in print_mode: print_max_terms = print_mode['max_ram_terms'] - if print_mode.has_key('max_terms'): + if 'max_terms' in print_mode: print_max_terms = print_mode['max_terms'] - if print_mode.has_key('mode'): + if 'mode' in print_mode: print_mode = print_mode['mode'] else: print_mode = None diff --git a/src/sage/rings/padics/padic_base_generic.py b/src/sage/rings/padics/padic_base_generic.py index bcd2f3d8ec6..b9b0bbc695b 100644 --- a/src/sage/rings/padics/padic_base_generic.py +++ b/src/sage/rings/padics/padic_base_generic.py @@ -356,7 +356,7 @@ def plot(self, max_points=2500, **args): sage: Zp(5).plot(max_points=625) sage: Zp(23).plot(rgbcolor=(1,0,0)) """ - if not args.has_key('pointsize'): + if 'pointsize' not in args: args['pointsize'] = 1 from sage.misc.mrange import cartesian_product_iterator from sage.rings.real_double import RDF diff --git a/src/sage/rings/padics/padic_generic.py b/src/sage/rings/padics/padic_generic.py index 743305274a9..fdb4cf8b5b7 100644 --- a/src/sage/rings/padics/padic_generic.py +++ b/src/sage/rings/padics/padic_generic.py @@ -94,7 +94,7 @@ def _modified_print_mode(self, print_mode): elif isinstance(print_mode, str): print_mode = {'mode': print_mode} for option in ['mode', 'pos', 'ram_name', 'unram_name', 'var_name', 'max_ram_terms', 'max_unram_terms', 'max_terse_terms', 'sep', 'alphabet']: - if not print_mode.has_key(option): + if option not in print_mode: print_mode[option] = self._printer.dict()[option] return print_mode @@ -476,17 +476,17 @@ def extension(self, modulus, prec = None, names = None, print_mode = None, halt if not isinstance(print_mode, dict): print_mode = dict(print_mode) for option in ['mode', 'pos', 'max_ram_terms', 'max_unram_terms', 'max_terse_terms', 'sep', 'alphabet']: - if print_mode.has_key(option): + if option in print_mode: print_mode["print_" + option] = print_mode[option] del print_mode[option] - elif not print_mode.has_key("print_" + option): - if kwds.has_key("print_" + option): + elif "print_" + option not in print_mode: + if "print_" + option in kwds: print_mode["print_" + option] = kwds["print_" + option] else: print_mode["print_" + option] = self._printer.dict()[option] for option in ['ram_name', 'unram_name', 'var_name']: - if not print_mode.has_key(option): - if kwds.has_key(option): + if option not in print_mode: + if option in kwds: print_mode[option] = kwds[option] else: print_mode[option] = self._printer.dict()[option] @@ -854,6 +854,6 @@ def local_print_mode(obj, print_options, pos = None, ram_name = None): if ram_name is not None: print_options['ram_name'] = ram_name for option in ['mode', 'pos', 'ram_name', 'unram_name', 'var_name', 'max_ram_terms', 'max_unram_terms', 'max_terse_terms', 'sep', 'alphabet']: - if not print_options.has_key(option): + if option not in print_options: print_options[option] = obj._printer.dict()[option] return pAdicPrinter(obj, print_options) diff --git a/src/sage/rings/padics/padic_printing.pyx b/src/sage/rings/padics/padic_printing.pyx index 80b1918177f..1ef01de4da3 100644 --- a/src/sage/rings/padics/padic_printing.pyx +++ b/src/sage/rings/padics/padic_printing.pyx @@ -60,7 +60,7 @@ def pAdicPrinter(ring, options={}): series printer for 5-adic Ring with capped relative precision 20 """ for option in ['mode', 'pos', 'ram_name', 'unram_name', 'var_name', 'max_ram_terms', 'max_unram_terms', 'max_terse_terms', 'sep', 'alphabet']: - if not options.has_key(option): + if option not in options: options[option] = None return pAdicPrinter_class(ring, **options) diff --git a/src/sage/rings/padics/pow_computer.pyx b/src/sage/rings/padics/pow_computer.pyx index 47c906bc8aa..def84543a3e 100644 --- a/src/sage/rings/padics/pow_computer.pyx +++ b/src/sage/rings/padics/pow_computer.pyx @@ -527,7 +527,7 @@ cdef PowComputer_base PowComputer_c(Integer m, Integer cache_limit, Integer prec raise ValueError, "cannot create p-adic parents with precision cap larger than (1 << (sizeof(long)*8 - 2))" key = (m, cache_limit, prec_cap, in_field) - if pow_comp_cache.has_key(key): + if key in pow_comp_cache: PC = pow_comp_cache[key]() if PC is not None: return PC diff --git a/src/sage/rings/padics/pow_computer_ext.pyx b/src/sage/rings/padics/pow_computer_ext.pyx index f17036dfe10..b46b86ecf71 100644 --- a/src/sage/rings/padics/pow_computer_ext.pyx +++ b/src/sage/rings/padics/pow_computer_ext.pyx @@ -2242,7 +2242,7 @@ cdef class PowComputer_ZZ_pX_big(PowComputer_ZZ_pX): elif n == self.prec_cap: return &self.top_mod else: - if self.modulus_dict.has_key(n): + if n in self.modulus_dict: return &((self.modulus_dict[n]).x) else: c = self.get_context(n) diff --git a/src/sage/rings/polynomial/infinite_polynomial_element.py b/src/sage/rings/polynomial/infinite_polynomial_element.py index 677675e27f7..31dd3d64007 100644 --- a/src/sage/rings/polynomial/infinite_polynomial_element.py +++ b/src/sage/rings/polynomial/infinite_polynomial_element.py @@ -952,7 +952,7 @@ def footprint(self): for t in L: n = t[0][0] # the variable *n*ame s = int(t[0][1]) # the variable *s*hift - if not self._footprint.has_key(s): + if s not in self._footprint: self._footprint[s] = [0]*l self._footprint[s][self.parent()._name_dict[n]] = t[1] # the exponent self._has_footprint = True @@ -1035,7 +1035,7 @@ def symmetric_cancellation_order(self,other): P = range(Lbig[-1]+1) gens = xrange(PARENT.ngens()) if Lsmall[0]==0: - if not Fbig.has_key(0): + if 0 not in Fbig: return (None,1,1) Lsmall.pop(0) Lbig.pop(0) diff --git a/src/sage/rings/polynomial/laurent_polynomial_ring.py b/src/sage/rings/polynomial/laurent_polynomial_ring.py index 395deb7e6d8..ed7d6ef2720 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ring.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ring.py @@ -293,7 +293,7 @@ def _get_from_cache(key): True """ try: - if _cache.has_key(key): + if key in _cache: return _cache[key] # put () here to re-enable weakrefs except TypeError, msg: raise TypeError, 'key = %s\n%s'%(key,msg) diff --git a/src/sage/rings/polynomial/multi_polynomial_element.py b/src/sage/rings/polynomial/multi_polynomial_element.py index 6da4dc0d834..ce5ec98bea5 100644 --- a/src/sage/rings/polynomial/multi_polynomial_element.py +++ b/src/sage/rings/polynomial/multi_polynomial_element.py @@ -989,9 +989,9 @@ def subs(self, fixed=None, **kw): """ variables = list(self.parent().gens()) for i in range(0,len(variables)): - if kw.has_key(str(variables[i])): + if str(variables[i]) in kw: variables[i]=kw[str(variables[i])] - elif fixed and fixed.has_key(variables[i]): + elif fixed and variables[i] in fixed: variables[i] = fixed[variables[i]] return self(tuple(variables)) diff --git a/src/sage/rings/polynomial/multi_polynomial_ring.py b/src/sage/rings/polynomial/multi_polynomial_ring.py index 7bdf69cb572..eac2e5c49aa 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ring.py +++ b/src/sage/rings/polynomial/multi_polynomial_ring.py @@ -525,7 +525,7 @@ def ideal(self, *gens, **kwds): do_coerce = True elif not isinstance(gens, (list, tuple)): gens = [gens] - if (kwds.has_key('coerce') and kwds['coerce']) or do_coerce: + if ('coerce' in kwds and kwds['coerce']) or do_coerce: gens = [self(x) for x in gens] # this will even coerce from singular ideals correctly! return multi_polynomial_ideal.MPolynomialIdeal(self, gens, **kwds) diff --git a/src/sage/rings/polynomial/pbori.pyx b/src/sage/rings/polynomial/pbori.pyx index ed29494e3cd..cac22852f75 100644 --- a/src/sage/rings/polynomial/pbori.pyx +++ b/src/sage/rings/polynomial/pbori.pyx @@ -2306,7 +2306,7 @@ cdef class BooleanMonomial(MonoidElement): """ res = 1 for i in self.iterindex(): - if d.has_key(i): + if i in d: res *= d[i] else: res *= (self._parent).gen(i) diff --git a/src/sage/rings/polynomial/polydict.pyx b/src/sage/rings/polynomial/polydict.pyx index 216d8938a98..d32991ea340 100644 --- a/src/sage/rings/polynomial/polydict.pyx +++ b/src/sage/rings/polynomial/polydict.pyx @@ -305,7 +305,7 @@ cdef class PolyDict: 4 """ K = mon.keys()[0] - if not self.__repn.has_key(K): + if K not in self.__repn: return 0 return self.__repn[K] diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 2b9f3bcd381..8300d16c94b 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -351,7 +351,7 @@ cdef class Polynomial(CommutativeAlgebraElement): """ if len(x) == 1 and isinstance(x[0], dict): g = self.parent().gen() - if x[0].has_key(g): + if g in x[0]: return self(x[0][g]) elif len(x[0]) > 0: raise TypeError("keys do not match self's parent") @@ -565,7 +565,7 @@ cdef class Polynomial(CommutativeAlgebraElement): if kwds: P = self.parent() name = P.variable_name() - if kwds.has_key(name): + if name in kwds: if len(x) > 0: raise ValueError("must not specify both a keyword and positional argument") a = self(kwds[name]) diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index e8594dc0037..6544b31beb0 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -212,7 +212,7 @@ def _derivative(self, var=None): d = {} for n, c in self.__coeffs.iteritems(): d[n-1] = n*c - if d.has_key(-1): + if -1 in d: del d[-1] return P(d) @@ -329,7 +329,7 @@ def __getitem__(self,n): P = self.parent() return P(v) else: - if not self.__coeffs.has_key(n): + if n not in self.__coeffs: return self.base_ring()(0) return self.__coeffs[n] @@ -359,7 +359,7 @@ def _unsafe_mutate(self, n, value): if n < 0: raise IndexError, "polynomial coefficient index must be nonnegative" if value == 0: - if x.has_key(n): + if n in x: del x[n] else: x[n] = value diff --git a/src/sage/rings/polynomial/real_roots.pyx b/src/sage/rings/polynomial/real_roots.pyx index 1d48506754f..0c59ad71b0a 100644 --- a/src/sage/rings/polynomial/real_roots.pyx +++ b/src/sage/rings/polynomial/real_roots.pyx @@ -2009,7 +2009,7 @@ def precompute_degree_reduction_cache(n): ) """ while True: - if dr_cache.has_key(n): return + if n in dr_cache: return next = degree_reduction_next_size(n) if next is None: dr_cache[n] = (None, None, 0) diff --git a/src/sage/rings/polynomial/term_order.py b/src/sage/rings/polynomial/term_order.py index 53d3107388e..105ff8773fd 100644 --- a/src/sage/rings/polynomial/term_order.py +++ b/src/sage/rings/polynomial/term_order.py @@ -547,7 +547,7 @@ def __setstate__(self, dict): sage: t2._weights is None True """ - if not dict.has_key('_weights'): + if '_weights' not in dict: name = dict['_TermOrder__name'] n = dict['_TermOrder__length'] t = TermOrder(name,n) diff --git a/src/sage/rings/power_series_poly.pyx b/src/sage/rings/power_series_poly.pyx index a7c511b86c5..b2153b5fb24 100644 --- a/src/sage/rings/power_series_poly.pyx +++ b/src/sage/rings/power_series_poly.pyx @@ -294,7 +294,7 @@ cdef class PowerSeries_poly(PowerSeries): if len(kwds) >= 1: name = P.variable_name() - if kwds.has_key(name): # a keyword specifies the power series generator + if name in kwds: # a keyword specifies the power series generator if len(x) > 0: raise ValueError, "must not specify %s keyword and positional argument" % name a = self(kwds[name]) diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index bd222aacc0a..972fc1c4980 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -5791,7 +5791,7 @@ def complex_roots(self, prec, multiplicity): -1.189207115002721?*I, 1.189207115002721?*I] """ - if self._roots_cache.has_key(multiplicity): + if multiplicity in self._roots_cache: roots = self._roots_cache[multiplicity] if roots[0] >= prec: return roots[1] diff --git a/src/sage/rings/quotient_ring.py b/src/sage/rings/quotient_ring.py index 04d9728e010..19b81a875b5 100644 --- a/src/sage/rings/quotient_ring.py +++ b/src/sage/rings/quotient_ring.py @@ -940,7 +940,7 @@ def ideal(self, *gens, **kwds): coerce = True elif not isinstance(gens, (list, tuple)): gens = [gens] - if kwds.has_key('coerce') and kwds['coerce']: + if 'coerce' in kwds and kwds['coerce']: gens = [self(x) for x in gens] # this will even coerce from singular ideals correctly! return sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal(self, gens, **kwds) diff --git a/src/sage/rings/rational_field.py b/src/sage/rings/rational_field.py index f28915ffcd9..384eaa2f348 100644 --- a/src/sage/rings/rational_field.py +++ b/src/sage/rings/rational_field.py @@ -62,7 +62,7 @@ _obj = {} class _uniq(object): def __new__(cls): - if _obj.has_key(0): + if 0 in _obj: return _obj[0] O = number_field_base.NumberField.__new__(cls) _obj[0] = O diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index 31584bd1ef3..2e5b89706fb 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -1804,6 +1804,23 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): '[0.26794919243112269 .. 0.26794919243112276]' sage: -v -0.2679491924311227? + + Check that :trac:`15166` is fixed:: + + sage: RIF(1.84e13).exp() + [2.0985787164673874e323228496 .. +infinity] # 32-bit + 6.817557048799520?e7991018467019 # 64-bit + sage: from sage.rings.real_mpfr import mpfr_get_exp_min, mpfr_get_exp_max + sage: v = RIF(1.0 << (mpfr_get_exp_max() - 1)); v + 1.0492893582336939?e323228496 # 32-bit + 2.9378268945557938?e1388255822130839282 # 64-bit + sage: -v + -1.0492893582336939?e323228496 # 32-bit + -2.9378268945557938?e1388255822130839282 # 64-bit + sage: v = RIF(1.0 >> -mpfr_get_exp_min()+1); v + 2.3825649048879511?e-323228497 # 32-bit + 8.5096913117408362?e-1388255822130839284 # 64-bit + """ if not(mpfr_number_p(&self.value.left) and mpfr_number_p(&self.value.right)): raise ValueError, "_str_question_style on NaN or infinity" @@ -1896,7 +1913,7 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): # the right of the last mantissa digit (that is, so the number # is mantissa*base^exponent, if you interpret mantissa as an integer). - cdef int digits + cdef long digits digits = strlen(lower_s) if lower_s[0] == '-': digits -= 1 @@ -1943,7 +1960,7 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): if mpfr_zero_p(&self.value.right): upper_expo = lower_expo - cdef int expo_delta + cdef mp_exp_t expo_delta if lower_expo < upper_expo: expo_delta = upper_expo - lower_expo @@ -1974,7 +1991,7 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): mpz_cdiv_q(upper_mpz, upper_mpz, tmp) upper_expo = lower_expo - cdef int expo = lower_expo + cdef mp_exp_t expo = lower_expo # Now the basic plan is to repeat # lower = floor(lower/base); upper = ceiling(upper/base) @@ -2014,8 +2031,8 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): # the internals of mpz_sizeinbase, or by writing our own # approximate logarithm.) - cdef int cur_error_digits = mpz_sizeinbase(cur_error, base) - cdef int max_error_digits = mpz_sizeinbase(max_error, base) + cdef long cur_error_digits = mpz_sizeinbase(cur_error, base) + cdef long max_error_digits = mpz_sizeinbase(max_error, base) # The GMP documentation claims that mpz_sizeinbase will be either # the true number of digits, or one too high. So @@ -2028,7 +2045,7 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): # k-1 = cur_error_digits-2-max_error_digits, and # k = cur_error_digits-1-max_error_digits. - cdef int k = cur_error_digits - 1 - max_error_digits + cdef long k = cur_error_digits - 1 - max_error_digits if k > 0: mpz_ui_pow_ui(tmp, base, k) @@ -2108,7 +2125,7 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): # If we use scientific notation, we put the radix point to the # right of the first digit; that would give us an exponent of: - cdef int sci_expo = expo + digits - 1 + cdef mp_exp_t sci_expo = expo + digits - 1 if abs(sci_expo) >= 6: scientific = True diff --git a/src/sage/rings/ring.pyx b/src/sage/rings/ring.pyx index 45414f5dbd3..dd7c6d61adb 100644 --- a/src/sage/rings/ring.pyx +++ b/src/sage/rings/ring.pyx @@ -500,7 +500,7 @@ cdef class Ring(ParentWithGens): sage: R.ideal() Principal ideal (0) of Univariate Polynomial Ring in x over Rational Field """ - if kwds.has_key('coerce'): + if 'coerce' in kwds: coerce = kwds['coerce'] del kwds['coerce'] else: @@ -548,7 +548,7 @@ cdef class Ring(ParentWithGens): for h in gens[1:]: g = g.gcd(h) gens = [g] - if kwds.has_key('ideal_class'): + if 'ideal_class' in kwds: C = kwds['ideal_class'] del kwds['ideal_class'] else: diff --git a/src/sage/sandpiles/sandpile.py b/src/sage/sandpiles/sandpile.py index 1b323cb417c..d518a1bf88d 100644 --- a/src/sage/sandpiles/sandpile.py +++ b/src/sage/sandpiles/sandpile.py @@ -356,7 +356,7 @@ def __getattr__(self, name): sage: S.__getattr__('_max_stable') {1: 3, 2: 3, 3: 3, 4: 3} """ - if not self.__dict__.has_key(name): + if name not in self.__dict__: if name == '_max_stable': self._set_max_stable() return deepcopy(self.__dict__[name]) @@ -2318,7 +2318,7 @@ def __getattr__(self, name): sage: C.__getattr__('_deg') 3 """ - if not self.__dict__.has_key(name): + if name not in self.__dict__: if name=='_deg': self._set_deg() return self.__dict__[name] @@ -3186,7 +3186,7 @@ def _set_is_recurrent(self): """ if '_recurrents' in self._sandpile.__dict__: self._is_recurrent = (self in self._sandpile._recurrents) - elif self.__dict__.has_key('_equivalent_recurrent'): + elif '_equivalent_recurrent' in self.__dict__: self._is_recurrent = (self._equivalent_recurrent == self) else: # add the burning configuration to config @@ -3297,7 +3297,7 @@ def _set_is_superstable(self): """ if '_superstables' in self._sandpile.__dict__: self._is_superstable = (self in self._sandpile._superstables) - elif self.__dict__.has_key('_equivalent_superstable'): + elif '_equivalent_superstable' in self.__dict__: self._is_superstable = (self._equivalent_superstable[0] == self) else: self._is_superstable = self.dualize().is_recurrent() @@ -3540,7 +3540,7 @@ def __getattr__(self, name): sage: D.__getattr__('_deg') 6 """ - if not self.__dict__.has_key(name): + if name not in self.__dict__: if name=='_deg': self._set_deg() return self.__dict__[name] diff --git a/src/sage/schemes/elliptic_curves/BSD.py b/src/sage/schemes/elliptic_curves/BSD.py index 18db346aee5..0b26f34d59d 100644 --- a/src/sage/schemes/elliptic_curves/BSD.py +++ b/src/sage/schemes/elliptic_curves/BSD.py @@ -618,7 +618,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, if verbosity > 1: print ' p = %d: Trying p_primary_bound'%p p_bound = BSD.Sha.p_primary_bound(p) - if BSD.proof.has_key(p): + if p in BSD.proof: BSD.proof[p].append(('Stein-Wuthrich', p_bound)) else: BSD.proof[p] = [('Stein-Wuthrich', p_bound)] @@ -627,7 +627,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, print 'True for p=%d by Stein-Wuthrich.'%p primes_to_remove.append(p) else: - if BSD.bounds.has_key(p): + if p in BSD.bounds: BSD.bounds[p][1] = min(BSD.bounds[p][1], p_bound) else: BSD.bounds[p] = (0, p_bound) @@ -652,7 +652,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, if D_K%p != 0 and BSD.N%(p**2) != 0 and galrep.is_irreducible(p): if verbosity > 0: print 'Kolyvagin\'s bound for p = %d applies by Cha.'%p - if BSD.proof.has_key(p): + if p in BSD.proof: BSD.proof[p].append('Cha') else: BSD.proof[p] = ['Cha'] @@ -668,7 +668,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, if verbosity > 0: print 'Kolyvagin\'s bound for p = %d applies by Stein et al.'%p kolyvagin_primes.append(p) - if BSD.proof.has_key(p): + if p in BSD.proof: BSD.proof[p].append('Stein et al.') else: BSD.proof[p] = ['Stein et al.'] @@ -689,7 +689,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, if m_max > 0: if verbosity > 0: print 'Jetchev\'s results apply (at p = %d) with m_max ='%p, m_max - if BSD.proof.has_key(p): + if p in BSD.proof: BSD.proof[p].append(('Jetchev',m_max)) else: BSD.proof[p] = [('Jetchev',m_max)] @@ -703,7 +703,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, # now ord_p_bound is one on I_K!!! ord_p_bound *= 2 # by Kolyvagin, now ord_p_bound is one on #Sha break - if BSD.proof.has_key(p): + if p in BSD.proof: BSD.proof[p].append(('Kolyvagin',ord_p_bound)) else: BSD.proof[p] = [('Kolyvagin',ord_p_bound)] @@ -714,7 +714,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, elif BSD.sha_an.ord(p) > ord_p_bound: raise RuntimeError("p = %d: ord_p_bound == %d, but sha_an.ord(p) == %d. This appears to be a counterexample to BSD, but is more likely a bug."%(p,ord_p_bound,BSD.sha_an.ord(p))) else: # BSD.sha_an.ord(p) <= ord_p_bound != 0: - if BSD.bounds.has_key(p): + if p in BSD.bounds: low = BSD.bounds[p][0] BSD.bounds[p] = (low, min(BSD.bounds[p][1], ord_p_bound)) else: @@ -734,7 +734,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, if verbosity > 0: print 'Kato further implies that #Sha[%d] is trivial.'%p primes_to_remove.append(p) - if BSD.proof.has_key(p): + if p in BSD.proof: BSD.proof[p].append(('Kato',0)) else: BSD.proof[p] = [('Kato',0)] @@ -743,11 +743,11 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, bd = L_over_Omega.valuation(p) if verbosity > 1: print 'Kato implies that ord_p(#Sha[%d]) <= %d '%(p,bd) - if BSD.proof.has_key(p): + if p in BSD.proof: BSD.proof[p].append(('Kato',bd)) else: BSD.proof[p] = [('Kato',bd)] - if BSD.bounds.has_key(p): + if p in BSD.bounds: low = BSD.bounds[p][0] BSD.bounds[p][1] = (low, min(BSD.bounds[p][1], bd)) else: @@ -766,7 +766,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, print 'True for p=%s by Mazur'%p for p in primes_to_remove: BSD.primes.remove(p) - if BSD.proof.has_key(p): + if p in BSD.proof: BSD.proof[p].append('Mazur') else: BSD.proof[p] = ['Mazur'] @@ -906,7 +906,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, s += 'non-split multiplicative' if BSD.curve.tamagawa_product()%p==0: s += ', divides a Tamagawa number' - if BSD.bounds.has_key(p): + if p in BSD.bounds: s += '\n (%d <= ord_p <= %d)'%BSD.bounds[p] else: s += '\n (no bounds found)' diff --git a/src/sage/schemes/elliptic_curves/cm.py b/src/sage/schemes/elliptic_curves/cm.py index 3769453a968..9a8415a1657 100644 --- a/src/sage/schemes/elliptic_curves/cm.py +++ b/src/sage/schemes/elliptic_curves/cm.py @@ -512,7 +512,7 @@ def classno(d): # optimize this inner loop a little.) if h <= hmax: z = (Integer(D), Integer(f)) - if T.has_key(h): + if h in T: T[h].append(z) else: T[h] = [z] diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index 950f8fcbb55..5cdbbdf8741 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -1744,7 +1744,7 @@ def __sort_kernel_list(self): self.__kernel_2tor[xQ] = (xQ,yQ,gxQ,gyQ,vQ,uQ) v = v + vQ w = w + (uQ + xQ*vQ) - elif (not self.__kernel_non2tor.has_key(xQ)): # Q is not a 2-torsion + elif xQ not in self.__kernel_non2tor: # Q is not a 2-torsion vQ = 2*gxQ - a1*gyQ self.__kernel_non2tor[xQ] = (xQ,yQ,gxQ,gyQ,vQ,uQ) v = v + vQ @@ -1858,7 +1858,7 @@ def __compute_via_velu_numeric(self, xP, yP): """ # first check if the point is in the kernel - if ( self.__kernel_2tor.has_key(xP) or self.__kernel_non2tor.has_key(xP) ) : + if xP in self.__kernel_2tor or xP in self.__kernel_non2tor: return self.__intermediate_codomain(0) outP = self.__compute_via_velu(xP,yP) diff --git a/src/sage/schemes/elliptic_curves/ell_rational_field.py b/src/sage/schemes/elliptic_curves/ell_rational_field.py index 857061b562f..81557627e9a 100644 --- a/src/sage/schemes/elliptic_curves/ell_rational_field.py +++ b/src/sage/schemes/elliptic_curves/ell_rational_field.py @@ -619,7 +619,7 @@ def pari_curve(self, prec=None, factor=1): sage: E = EllipticCurve(RationalField(), ['1/3', '2/3']) sage: e = E.pari_curve(prec=100) - sage: E._pari_curve.has_key(100) + sage: 100 in E._pari_curve True sage: e.type() 't_VEC' @@ -628,7 +628,7 @@ def pari_curve(self, prec=None, factor=1): This shows that the bug uncovered by trac:`3954` is fixed:: - sage: E._pari_curve.has_key(100) + sage: 100 in E._pari_curve True :: @@ -1689,7 +1689,7 @@ def rank(self, use_database=False, verbose=False, try: return self.__rank[proof] except KeyError: - if proof is False and self.__rank.has_key(True): + if proof is False and True in self.__rank: return self.__rank[True] if use_database: try: @@ -1856,7 +1856,7 @@ def gens(self, verbose=False, rank1_search=10, except AttributeError: pass except KeyError: - if proof is False and self.__gens.has_key(True): + if proof is False and True in self.__gens: return self.__gens[True] # At this point, either self.__gens does not exist, or @@ -1985,7 +1985,7 @@ def gens_certain(self): sage: E.gens_certain() True """ - return self.__gens.has_key(True) + return True in self.__gens def ngens(self, proof = None): """ @@ -2081,7 +2081,7 @@ def regulator(self, use_database=True, proof=None, precision=None, else: # Found regulator value but precision is too low pass except KeyError: - if proof is False and self.__regulator.has_key(True): + if proof is False and True in self.__regulator: reg = self.__regulator[True] if reg.parent().precision() >= precision: return RR(reg) @@ -2710,7 +2710,7 @@ def kodaira_type_old(self, p): except AttributeError: self.__kodaira_type = {} self.__tamagawa_number = {} - if not self.__kodaira_type.has_key(p): + if p not in self.__kodaira_type: v = self.pari_mincurve().elllocalred(p) from kodaira_symbol import KodairaSymbol self.__kodaira_type[p] = KodairaSymbol(v[1]) @@ -3825,7 +3825,7 @@ def has_cm(self): 1728 """ - return CMJ.has_key(self.j_invariant()) + return self.j_invariant() in CMJ def cm_discriminant(self): """ diff --git a/src/sage/schemes/elliptic_curves/kodaira_symbol.py b/src/sage/schemes/elliptic_curves/kodaira_symbol.py index ee504919a5a..eec3f2c5ca8 100644 --- a/src/sage/schemes/elliptic_curves/kodaira_symbol.py +++ b/src/sage/schemes/elliptic_curves/kodaira_symbol.py @@ -323,7 +323,7 @@ def KodairaSymbol(symbol): sage: all([KS(str(KS(n)))==KS(n) for n in range(-10,10) if n!=0]) True """ - if _ks_cache.has_key(symbol): + if symbol in _ks_cache: ks = _ks_cache[symbol]() if not ks is None: return ks diff --git a/src/sage/sets/family.py b/src/sage/sets/family.py index 2bae01e3672..ac89e6e7a06 100644 --- a/src/sage/sets/family.py +++ b/src/sage/sets/family.py @@ -582,7 +582,7 @@ def has_key(self, k): sage: Family({"a":1, "b":2, "c":3}).has_key("d") False """ - return self._dictionary.has_key(k) + return k in self._dictionary def __eq__(self, other): """ diff --git a/src/sage/sets/set_from_iterator.py b/src/sage/sets/set_from_iterator.py index deed5075b04..7fe4ee7ef00 100644 --- a/src/sage/sets/set_from_iterator.py +++ b/src/sage/sets/set_from_iterator.py @@ -436,7 +436,7 @@ def _sage_doc_(self): sage: d = Decorator() sage: d.f = Integer.is_prime sage: print sage_getdoc(d) # indirect doctest - Returns "True" if "self" is prime. + Test whether "self" is prime. ... IMPLEMENTATION: Calls the PARI "isprime" function. diff --git a/src/sage/stats/basic_stats.py b/src/sage/stats/basic_stats.py index 00f6e2012d1..a55217ec714 100644 --- a/src/sage/stats/basic_stats.py +++ b/src/sage/stats/basic_stats.py @@ -126,7 +126,7 @@ def mode(v): freq = {} for i in v: - if freq.has_key(i): + if i in freq: freq[i] += 1 else: freq[i] = 1 diff --git a/src/sage/structure/category_object.pyx b/src/sage/structure/category_object.pyx index 4764a93499a..2867496269c 100644 --- a/src/sage/structure/category_object.pyx +++ b/src/sage/structure/category_object.pyx @@ -247,7 +247,7 @@ cdef class CategoryObject(sage_object.SageObject): ############################################################################## def _populate_generators_(self, gens=None, names=None, normalize = True, category=None): - if self._generators.has_key(category): + if category in self._generators: raise ValueError, "Generators cannot be changed after object creation." if category is None: category = self._category diff --git a/src/sage/structure/dynamic_class.py b/src/sage/structure/dynamic_class.py index 03f66ee25ab..0979f62a2be 100644 --- a/src/sage/structure/dynamic_class.py +++ b/src/sage/structure/dynamic_class.py @@ -372,7 +372,7 @@ def dynamic_class_internal(name, bases, cls=None, reduction=None, doccls=None, p if cls is not None: methods = dict(cls.__dict__) # Anything else that should not be kept? - if methods.has_key("__dict__"): + if "__dict__" in methods: methods.__delitem__("__dict__") if prepend_cls_bases: bases = cls.__bases__ + bases @@ -385,7 +385,7 @@ def dynamic_class_internal(name, bases, cls=None, reduction=None, doccls=None, p assert bases != () doccls = bases[0] methods['_reduction'] = reduction - if not methods.has_key("_sage_src_lines_"): + if "_sage_src_lines_" not in methods: from sage.misc.sageinspect import sage_getsourcelines @staticmethod def _sage_src_lines(): @@ -393,7 +393,7 @@ def _sage_src_lines(): methods['_sage_src_lines_'] = _sage_src_lines methods['__doc__'] = doccls.__doc__ methods['__module__'] = doccls.__module__ - #if not methods.has_key("_sage_doc_"): + #if "_sage_doc_" not in methods: # from sage.misc.sageinspect import sage_getdoc # def _sage_getdoc(obj): # return sage_getdoc(cls) diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index bd783e53d36..da81c9d6d1b 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -620,9 +620,9 @@ cdef class Element(sage_object.SageObject): # required to have the latter for i in xrange(0,ngens): gen=parent.gen(i) - if kwds.has_key(str(gen)): + if str(gen) in kwds: variables.append(kwds[str(gen)]) - elif in_dict and in_dict.has_key(gen): + elif in_dict and gen in in_dict: variables.append(in_dict[gen]) else: variables.append(gen) diff --git a/src/sage/structure/global_options.py b/src/sage/structure/global_options.py index 526cd8b8c00..432940e3f67 100644 --- a/src/sage/structure/global_options.py +++ b/src/sage/structure/global_options.py @@ -692,7 +692,7 @@ def __getitem__(self, option): link,linked_opt=self._linked_value[option] return link[linked_opt] elif option in self._value: - if self._display_values.has_key(option): + if option in self._display_values: return self._display_values[option][self._value[option]] return self._value[option] @@ -826,7 +826,7 @@ def _add_option(self, option, specifications): for opt in self._values: self._display_values[option] = {val.lower():val for val in self._values[option]} self._values[option] = [val.lower() for val in self._values[option]] - if self._alias.has_key(option): + if option in self._alias: self._alias[option] = {k.lower():v.lower() for k,v in self._alias[option].iteritems()} self._case_sensitive[option] = bool(specifications[spec]) elif spec!='description': diff --git a/src/sage/structure/parent_gens.pyx b/src/sage/structure/parent_gens.pyx index eb0e17ca179..fd635bcdd18 100644 --- a/src/sage/structure/parent_gens.pyx +++ b/src/sage/structure/parent_gens.pyx @@ -366,7 +366,7 @@ cdef class ParentWithGens(parent_base.ParentWithBase): return d def __setstate__(self, d): - if d.has_key('_element_constructor'): + if '_element_constructor' in d: return parent.Parent.__setstate__(self, d) try: self.__dict__.update(d) diff --git a/src/sage/structure/sage_object.pyx b/src/sage/structure/sage_object.pyx index b585493a186..5dad7325645 100644 --- a/src/sage/structure/sage_object.pyx +++ b/src/sage/structure/sage_object.pyx @@ -1236,7 +1236,7 @@ def loads(s, compress=True): return unpickler.load() -cdef bint make_pickle_jar = os.environ.has_key('SAGE_PICKLE_JAR') +cdef bint make_pickle_jar = 'SAGE_PICKLE_JAR' in os.environ def picklejar(obj, dir=None): """ diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index f8ba06ae1a8..f3ac5edad07 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -9503,7 +9503,7 @@ cdef class Expression(CommutativeRingElement): from sage.plot.plot import plot # see if the user passed a variable in. - if kwds.has_key('param'): + if 'param' in kwds: param = kwds['param'] else: param = None diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index e3a3446012f..f3e803c9af3 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -718,7 +718,7 @@ cdef class GinacFunction(BuiltinFunction): raise ValueError, "cannot find GiNaC function with name %s and %s arguments"%(fname, self._nargs) global sfunction_serial_dict - return sfunction_serial_dict.has_key(self._serial) + return self._serial in sfunction_serial_dict cdef _register_function(self): # We don't need to add anything to GiNaC's function registry @@ -898,7 +898,7 @@ cdef class BuiltinFunction(Function): # if match, get operator from function table global sfunction_serial_dict - if serial != -1 and sfunction_serial_dict.has_key(self._name) and \ + if serial != -1 and self._name in sfunction_serial_dict and \ sfunction_serial_dict[self._name].__class__ == self.__class__: # if the returned function is of the same type self._serial = serial diff --git a/src/sage/symbolic/units.py b/src/sage/symbolic/units.py index 2052020b082..c36b83d5525 100644 --- a/src/sage/symbolic/units.py +++ b/src/sage/symbolic/units.py @@ -1131,7 +1131,7 @@ def __getattr__(self, name): True """ - if self.__units.has_key(name): + if name in self.__units: return self.__units[name] if len(unit_to_type) == 0: evalunitdict() @@ -1223,7 +1223,7 @@ def is_unit(s): sage: sage.symbolic.units.is_unit(var('meter')) True """ - return unit_to_type.has_key(str(s)) + return str(s) in unit_to_type def convert(expr, target): """ @@ -1352,13 +1352,13 @@ def base_units(unit): x """ from sage.misc.all import sage_eval - if not unit_to_type.has_key(str(unit)): + if str(unit) not in unit_to_type: return unit elif unit_to_type[str(unit)] == 'si_prefixes' or unit_to_type[str(unit)] == 'unit_multipliers': return sage_eval(unitdict[unit_to_type[str(unit)]][str(unit)]) else: v = SR.var(unit_to_type[str(unit)]) - if unit_derivations.has_key(str(v)): + if str(v) in unit_derivations: base = unit_derivations_expr(v) for i in base.variables(): base = base.subs({i:SR.var(value_to_unit[str(i)]['1'])}) diff --git a/src/sage/version.py b/src/sage/version.py index 487fbd3fb77..5fdba14fc04 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,4 +1,4 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '6.2.beta1' -date = '2014-02-07' +version = '6.2.beta2' +date = '2014-02-15'