Source code for sagenb.misc.misc

# -*- coding: utf-8 -*-
"""
Miscellaneous Notebook Functions

TESTS:

Check that github issue #195 is fixed::

    sage: from sagenb.misc.misc import mathjax_macros
    sage: type(mathjax_macros)
    <type 'list'>

"""

#############################################################################
#       Copyright (C) 2006, 2007 William Stein <wstein@gmail.com>
#  Distributed under the terms of the GNU General Public License (GPL)
#  The full text of the GPL is available at:
#                  http://www.gnu.org/licenses/
#############################################################################
import sys
from six import text_type, binary_type
from pkg_resources import resource_filename

PYTHON_VERSION = sys.version[0]

if PYTHON_VERSION == '3':
    CRE = ConnectionRefusedError
else:
    CRE = tuple


[docs]def stub(f): def g(*args, **kwds): print("Stub: {}".format(f.func_name)) return f(*args, **kwds) return g
min_password_length = 6 import os import socket import sys try: import cPickle as pickle except ImportError: import pickle
[docs]def find_next_available_port(interface, start, max_tries=100, verbose=False): """ Find the next available port at a given interface, that is, a port for which a current connection attempt returns a 'Connection refused' error message. If no port is found, raise a RuntimeError exception. INPUT: - ``interface`` - address to check - ``start`` - an int; the starting port number for the scan - ``max_tries`` - an int (default: 100); how many ports to scan - ``verbose`` - a bool (default: True); whether to print information about the scan OUTPUT: - an int - the port number EXAMPLES:: sage: from sagenb.misc.misc import find_next_available_port sage: find_next_available_port('127.0.0.1', 9000, verbose=False) # random output -- depends on network 9002 """ from signal import alarm alarm_count = 0 for port in range(start, start+max_tries+1): try: try: alarm(5) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((interface, port)) finally: alarm(0) # cancel alarm except socket.error as msg: if ((PYTHON_VERSION == '2' and msg[1] == 'Connection refused') or (PYTHON_VERSION == '3' and isinstance(msg, CRE))): if verbose: print("Using port = %s" % port) return port except KeyboardInterrupt: if verbose: print("alarm") alarm_count += 1 if alarm_count >= 10: break if verbose: print("Port %s is already in use." % port) print("Trying next port...") raise RuntimeError("no available port.")
[docs]def open_page(address, port, secure, path=""): if secure: rsrc = 'https' else: rsrc = 'http' os.system('%s %s://%s:%s%s 1>&2 > /dev/null &'%(browser(), rsrc, address, port, path))
[docs]def pad_zeros(s, size=3): """ EXAMPLES:: sage: pad_zeros(100) '100' sage: pad_zeros(10) '010' sage: pad_zeros(10, 5) '00010' sage: pad_zeros(389, 5) '00389' sage: pad_zeros(389, 10) '0000000389' """ return "0"*(size-len(str(s))) + str(s)
SAGENB_ROOT = os.path.split(resource_filename(__name__, ''))[0] DATA = os.path.join(SAGENB_ROOT, 'data') if 'DOT_SAGENB' in os.environ: DOT_SAGENB = os.environ['DOT_SAGENB'] elif 'DOT_SAGE' in os.environ: DOT_SAGENB = os.environ['DOT_SAGE'] else: DOT_SAGENB = os.path.join(os.environ['HOME'], '.sagenb') try: from sage.env import SAGE_URL except ImportError: SAGE_URL = 'http://sagemath.org' # TODO: Get macros from server and user settings. try: import sage.all from sage.misc.latex_macros import sage_mathjax_macros mathjax_macros = sage_mathjax_macros() except ImportError: mathjax_macros = [ "ZZ : '{\\\\Bold{Z}}'", "RR : '{\\\\Bold{R}}'", "CC : '{\\\\Bold{C}}'", "QQ : '{\\\\Bold{Q}}'", "QQbar : '{\\\\overline{\\\\QQ}}'", "GF : ['{\\\\Bold{F}_{#1}}', 1]", "Zp : ['{\\\\ZZ_{#1}}', 1]", "Qp : ['{\\\\QQ_{#1}}', 1]", "Zmod : ['{\\\\ZZ/#1\\\\ZZ}', 1]", "CIF : '{\\\\Bold{C}}'", "CLF : '{\\\\Bold{C}}'", "RDF : '{\\\\Bold{R}}'", "RIF : '{\\\\Bold{I} \\\\Bold{R}}'", "RLF : '{\\\\Bold{R}}'", "CFF : '{\\\\Bold{CFF}}'", "Bold : ['{\\\\mathbf{#1}}', 1]" ] except Exception: sage_mathjax_macros_easy = [] raise try: from sage.misc.session import init as session_init except ImportError: @stub def session_init(*args, **kwds): pass try: from sage.misc.sage_eval import sage_eval except ImportError: def sage_eval(value, globs): # worry about ^ and preparser -- this gets used in interact.py, # which is a bit weird, but heh. return eval(value, globs) try: from sage.misc.package import is_package_installed except ImportError: def is_package_installed(name, *args, **kwds): return False try: from sage.misc.viewer import browser except ImportError: @stub def browser(): return "open" try: from sage.structure.sage_object import loads, dumps, load, save except ImportError: loads = pickle.loads dumps = pickle.dumps def load(filename): return pickle.loads(open(filename).read()) def save(obj, filename): s = pickle.dumps(obj, protocol=2) open(filename, 'wb').write(s) try: from sage.misc.all import verbose except ImportError: # TODO! @stub def verbose(*args, **kwds): pass ################################ # clocks -- easy to implement ################################ import time, resource
[docs]def cputime(t=0): try: t = float(t) except TypeError: t = 0.0 u, s = resource.getrusage(resource.RUSAGE_SELF)[:2] return u + s - t
[docs]def walltime(t=0): return time.time() - t
[docs]def word_wrap(s, ncols=85): t = [] if ncols == 0: return s for x in s.split('\n'): if len(x) == 0 or x.lstrip()[:5] == 'sage:': t.append(x) continue while len(x) > ncols: k = ncols while k > 0 and x[k] != ' ': k -= 1 if k == 0: k = ncols end = '\\' else: end = '' t.append(x[:k] + end) x = x[k:] k=0 while k < len(x) and x[k] == ' ': k += 1 x = x[k:] t.append(x) return '\n'.join(t)
try: from sage.repl.preparse import strip_string_literals except ImportError: def strip_string_literals(code, state=None): # todo -- do we need this? return code try: from pkg_resources import Requirement, working_set SAGENB_VERSION = working_set.find(Requirement.parse('sagenb')).version except AttributeError: SAGENB_VERSION = "" try: import sage.version SAGE_VERSION=sage.version.version except ImportError: SAGE_VERSION="" try: from sage.plot.colors import Color except ImportError: class Color: def __init__(self, *args, **kwds): pass ######################################## # this is needed for @interact: # Color, sage_eval and is_Matrix # are imported from here in notebook/interact.py ########################################
[docs]def is_Matrix(x): try: from sage.structure.element import is_Matrix except ImportError: return False return is_Matrix(x)
[docs]def register_with_cleaner(pid): try: import sage.interfaces.cleaner sage.interfaces.cleaner.cleaner(pid) # register pid of forked process with cleaner except ImportError: print("generic cleaner needs to be written")
try: from sage.misc.all import tmp_filename, tmp_dir except ImportError: def tmp_filename(name='tmp'): # We use mktemp instead of mkstemp since the semantics of the # tmp_filename function simply don't allow for what mkstemp # provides. import tempfile return tempfile.mktemp() def tmp_dir(name='dir'): import tempfile return tempfile.mkdtemp() try: from sage.misc.inline_fortran import InlineFortran except ImportError: @stub def InlineFortran(*args, **kwds): pass try: from sage.misc.cython import cython except ImportError:
[docs] @stub def cython(*args, **kwds): # TODO raise NotImplementedError("Curently %cython mode requires Sage.")
############################################################# # File permissions # May need some changes on Windows. ############################################################# import stat
[docs]def set_restrictive_permissions(filename, allow_execute=False): x = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR if allow_execute: x = x | stat.S_IXGRP | stat.S_IXOTH os.chmod(filename, x)
[docs]def set_permissive_permissions(filename): os.chmod(filename, stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH | \ stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | \ stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP)
[docs]def encoded_str(obj, encoding='utf-8'): r""" Takes an object and returns an encoded str human-readable representation. string to bytes EXAMPLES:: sage: from sagenb.misc.misc import encoded_str sage: encoded_str(u'\u011b\u0161\u010d\u0159\u017e\xfd\xe1\xed\xe9\u010f\u010e') == 'ěščřžýáíéďĎ' True sage: encoded_str(u'abc') 'abc' sage: encoded_str(123) '123' """ if isinstance(obj, text_type): return obj.encode(encoding, 'ignore') return binary_type(obj)
[docs]def unicode_str(obj, encoding='utf-8'): r""" Takes an object and returns a unicode human-readable representation. (bytes or string) to string EXAMPLES:: sage: from sagenb.misc.misc import unicode_str sage: unicode_str('ěščřžýáíéďĎ') == u'\u011b\u0161\u010d\u0159\u017e\xfd\xe1\xed\xe9\u010f\u010e' True sage: unicode_str('abc') u'abc' sage: unicode_str(123) u'123' """ if isinstance(obj, binary_type): return obj.decode(encoding, 'ignore') elif isinstance(obj, text_type): return obj return text_type(obj)
[docs]def ignore_nonexistent_files(curdir, dirlist): """ Returns a list of non-existent files, given a directory and its contents. The returned list includes broken symbolic links. Use this, e.g., with :func:`shutil.copytree`, as shown below. INPUT: - ``curdir`` - a string; the name of the current directory - ``dirlist`` - a list of strings; names of ``curdir``'s contents OUTPUT: - a list of strings; names of ``curdir``'s non-existent files EXAMPLES:: sage: import os, shutil sage: from sagenb.misc.misc import ignore_nonexistent_files sage: opj = os.path.join; ope = os.path.exists; t = tmp_dir() sage: s = opj(t, 'src'); t = opj(t, 'trg'); hi = opj(s, 'hi.txt'); sage: os.makedirs(s) sage: f = open(hi, 'w'); f.write('hi'); f.close() sage: os.symlink(hi, opj(s, 'good.txt')) sage: os.symlink(opj(s, 'bad'), opj(s, 'bad.txt')) sage: slist = sorted(os.listdir(s)); slist ['bad.txt', 'good.txt', 'hi.txt'] sage: [ope(opj(s, x)) for x in slist] [False, True, True] sage: [os.path.islink(opj(s, x)) for x in slist] [True, True, False] sage: shutil.copytree(s, t) Traceback (most recent call last): ... Error: [('.../src/bad.txt', '.../trg/bad.txt', "[Errno 2] No such file or directory: '.../src/bad.txt'")] sage: shutil.rmtree(t); ope(t) False sage: shutil.copytree(s, t, ignore = ignore_nonexistent_files) sage: tlist = sorted(os.listdir(t)); tlist ['good.txt', 'hi.txt'] sage: [ope(opj(t, x)) for x in tlist] [True, True] sage: [os.path.islink(opj(t, x)) for x in tlist] # Note! [False, False] """ ignore = [] for x in dirlist: if not os.path.exists(os.path.join(curdir, x)): ignore.append(x) return ignore
[docs]def translations_path(): return os.path.join(SAGENB_ROOT, 'translations')
[docs]def get_languages(): from babel import Locale from babel.core import UnknownLocaleError langs = [] dir_names = [lang for lang in os.listdir(translations_path()) if lang != 'en_US'] for name in dir_names: try: Locale.parse(name) except UnknownLocaleError: pass else: langs.append(name) langs.sort() langs.insert(0, 'en_US') return langs
[docs]def N_(message): return message
[docs]def nN_(message_singular, message_plural): return [message_singular, message_plural]