Hello community, here is the log from the commit of package xonsh for openSUSE:Factory checked in at 2018-06-29 22:27:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/xonsh (Old) and /work/SRC/openSUSE:Factory/.xonsh.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "xonsh" Fri Jun 29 22:27:06 2018 rev:6 rq:617152 version:0.6.6 Changes: -------- --- /work/SRC/openSUSE:Factory/xonsh/xonsh.changes 2018-05-29 10:38:07.723532753 +0200 +++ /work/SRC/openSUSE:Factory/.xonsh.new/xonsh.changes 2018-06-29 22:27:08.406450056 +0200 @@ -1,0 +2,28 @@ +Sun Jun 10 20:20:03 UTC 2018 - [email protected] + +- update to version 0.6.6: + * Added: + * A multipurpose add method to EnvPath. + * Added ``pygments-cache`` project in order to reduce startup time. + * Changed: + * built_ins.py, corrected a typo. + * test/test_news.py + It now uses regex to verify the format of rst files + * Mercurial (``hg``) will no longer run in a threadable subprocess when + it is run in interactive mode. + * Fixed: + * issue 2313 + +------------------------------------------------------------------- +Thu May 31 21:20:01 UTC 2018 - [email protected] + +- update to version 0.6.5: + * Added: + * Wizard ``FileInsterter`` node class now has ``dumps()`` method for + converting a mapping to a string to insert in a file. + * Fixed: + * Fixed issue with ``xonfig wizard`` writer failing to write valid run control + files for environment variables that are containter types. In particular, + the storage of ``$XONSH_HISTORY_SIZE`` has been fixed. + +------------------------------------------------------------------- Old: ---- 0.6.4.tar.gz New: ---- 0.6.6.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ xonsh.spec ++++++ --- /var/tmp/diff_new_pack.NLVPom/_old 2018-06-29 22:27:08.986449617 +0200 +++ /var/tmp/diff_new_pack.NLVPom/_new 2018-06-29 22:27:08.990449615 +0200 @@ -17,7 +17,7 @@ Name: xonsh -Version: 0.6.4 +Version: 0.6.6 Release: 0 Summary: A general purpose, Python-ish shell License: BSD-3-Clause AND BSD-2-Clause ++++++ 0.6.4.tar.gz -> 0.6.6.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/.appveyor.yml new/xonsh-0.6.6/.appveyor.yml --- old/xonsh-0.6.4/.appveyor.yml 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/.appveyor.yml 2018-06-06 19:12:10.000000000 +0200 @@ -1,4 +1,4 @@ -version: 0.6.4.{build} +version: 0.6.6.{build} os: Windows Server 2012 R2 environment: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/.travis.yml new/xonsh-0.6.6/.travis.yml --- old/xonsh-0.6.4/.travis.yml 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/.travis.yml 2018-06-06 19:12:10.000000000 +0200 @@ -42,7 +42,7 @@ - if [[ $BUILD_DOCS = true ]]; then python setup.py install; pip install -r requirements-docs.txt; - pip install pygments prompt_toolkit ply psutil ipykernel matplotlib; + pip install pygments prompt_toolkit<2 ply psutil ipykernel matplotlib; pip install doctr; else pip install -r requirements-tests.txt; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/CHANGELOG.rst new/xonsh-0.6.6/CHANGELOG.rst --- old/xonsh-0.6.4/CHANGELOG.rst 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/CHANGELOG.rst 2018-06-06 19:12:10.000000000 +0200 @@ -4,6 +4,64 @@ .. current developments +v0.6.6 +==================== + +**Added:** + +* A multipurpose add method to EnvPath. For example: + + .. code-block:: xonshcon + + $ $PATH + EnvPath( + ['/usr/bin', '/usr/local/bin', '/bin'] + ) + $ $PATH.add('~/.local/bin', front=True); $PATH + EnvPath( + ['/home/user/.local/bin', '/usr/bin', '/usr/local/bin', '/bin'] + ) + $ $PATH.add('/usr/bin', front=True, replace=True); $PATH + EnvPath( + ['/usr/bin', '/home/user/.local/bin', '/usr/local/bin', '/bin'] + ) +* Added ``pygments-cache`` project in order to reduce startup time. + + +**Changed:** + +* built_ins.py, corrected a typo. +* test/test_news.py + It now uses regex to verify the format of rst files +* Mercurial (``hg``) will no longer run in a threadable subprocess when + it is run in interactive mode. + + +**Fixed:** + +* issue 2313 + + + + +v0.6.5 +==================== + +**Added:** + +* Wizard ``FileInsterter`` node class now has ``dumps()`` method for + converting a mapping to a string to insert in a file. + + +**Fixed:** + +* Fixed issue with ``xonfig wizard`` writer failing to write valid run control + files for environment variables that are containter types. In particular, + the storage of ``$XONSH_HISTORY_SIZE`` has been fixed. + + + + v0.6.4 ==================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/requirements-docs.txt new/xonsh-0.6.6/requirements-docs.txt --- old/xonsh-0.6.4/requirements-docs.txt 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/requirements-docs.txt 2018-06-06 19:12:10.000000000 +0200 @@ -1,4 +1,4 @@ cloud_sptheme numpydoc==0.5 Sphinx==1.5.6 -prompt_toolkit +prompt_toolkit<2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/requirements-tests.txt new/xonsh-0.6.6/requirements-tests.txt --- old/xonsh-0.6.4/requirements-tests.txt 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/requirements-tests.txt 2018-06-06 19:12:10.000000000 +0200 @@ -5,7 +5,7 @@ pytest-flake8==0.5 pytest-cov==2.3.0 pytest-timeout==1.0.0 -prompt-toolkit==1.0.3 +prompt-toolkit<2 pygments==2.1.3 codecov==2.0.5 flake8==2.6.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/setup.cfg new/xonsh-0.6.6/setup.cfg --- old/xonsh-0.6.4/setup.cfg 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/setup.cfg 2018-06-06 19:12:10.000000000 +0200 @@ -1,5 +1,7 @@ [pytest] flake8-max-line-length = 180 +flake8-exclude = + xonsh/pygments_cache.py flake8-ignore = *.py E122 *.py E402 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/tests/test_news.py new/xonsh-0.6.6/tests/test_news.py --- old/xonsh-0.6.4/tests/test_news.py 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/tests/test_news.py 2018-06-06 19:12:10.000000000 +0200 @@ -19,42 +19,41 @@ name = fname.name with open(fname.path) as f: lines = f.read().splitlines() - nlines = len(lines) - for i, line in enumerate(lines): - if line.startswith('**'): - cat, *_ = line[2:].rsplit(':') + form = "" + for i, l in enumerate(lines): + # search the graves + if '`' in l: + if single_grave_reg.search(l): + pytest.fail("{}:{}: single grave accents" + " are not valid rst".format(name, i+1), + pytrace=False) + + # determine the form of line + if l.startswith('**'): + cat = l[2:].rsplit(':')[0] if cat not in CATEGORIES: pytest.fail('{}:{}: {!r} not a proper category ' 'must be one of {}' ''.format(name, i+1, cat, list(CATEGORIES)), pytrace=False) - if i+1 == nlines: - continue - if not lines[i+1].strip() == '': - pytest.fail('{}:{}: empty line required after category' - ''.format(name, i+1), pytrace=False) - if i > 0 and not lines[i-1].strip() == '': - pytest.fail('{}:{}: empty line required before category' - ''.format(name, i+1), pytrace=False) - if line.endswith('None'): - if not lines[i+2].startswith('**'): - pytest.fail("{}:{}: can't have entries after None" - ''.format(name, i+1), pytrace=False) + if l.endswith('None'): + form += '3' else: - if lines[i+2].startswith('**'): - pytest.fail("{}:{}: must have entry if not None" - ''.format(name, i+1), pytrace=False) + form += '2' + elif l.startswith('* ') or l.startswith(' '): + form += '1' + elif l.strip() == '': + form += '0' else: - if not (line.startswith('* ') - or line.startswith(' ') - or (line.strip() == '')): - pytest.fail('{}:{}: invalid rst'.format(name, i+1), - pytrace=False) - if '`' in line: - if single_grave_reg.search(line): - pytest.fail("{}:{}: single grave accents" - " are not valid rst".format(name, i+1), - pytrace=False) + pytest.fail('{}:{}: invalid rst'.format(name, i+1), + pytrace=False) + # The file should have: + # empty lines around categories + # at least one content line in a non null category + reg = re.compile(r'^(3(0|$)|201(1|0)*0)+$') + if not reg.match(form): + pytest.fail('{}: invalid rst'.format(name), + pytrace=False) @pytest.mark.parametrize('fname', list(scandir(NEWSDIR))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/tests/test_wizard.py new/xonsh-0.6.6/tests/test_wizard.py --- old/xonsh-0.6.4/tests/test_wizard.py 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/tests/test_wizard.py 2018-06-06 19:12:10.000000000 +0200 @@ -6,7 +6,7 @@ import pytest from xonsh.wizard import (Node, Wizard, Pass, PrettyFormatter, - Message, Question, StateVisitor) + Message, Question, StateVisitor, FileInserter) TREE0 = Wizard(children=[Pass(), Message(message='yo')]) @@ -57,3 +57,26 @@ } flat_obs = sv.flatten() assert flat_exp == flat_obs + + +def dump_xonfig_env_mock(path, value): + name = os.path.basename(path.rstrip('/')) + return '${name} = {val!r}'.format(name=name, val=value) + + +def test_tuple_store_and_write(): + # setup + sv = StateVisitor() + sv.store('/env/XONSH_HISTORY_SIZE', (1073741824, 'b')) + dump_rules = {'/': None, '/env/': None, + '/env/*': dump_xonfig_env_mock, + '/env/*/[0-9]*': None} + fi = FileInserter(prefix='# XONSH WIZARD START', suffix='# XONSH WIZARD END', + dump_rules=dump_rules, default_file=None, + check=False, ask_filename=False) + # run test + exp = ("# XONSH WIZARD START\n" + "$XONSH_HISTORY_SIZE = (1073741824, 'b')\n" + "# XONSH WIZARD END\n") + obs = fi.dumps(sv.flatten()) + assert exp == obs diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/xonsh/__init__.py new/xonsh-0.6.6/xonsh/__init__.py --- old/xonsh-0.6.4/xonsh/__init__.py 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/xonsh/__init__.py 2018-06-06 19:12:10.000000000 +0200 @@ -1,8 +1,8 @@ -__version__ = '0.6.4' +__version__ = '0.6.6' # amalgamate exclude jupyter_kernel parser_table parser_test_table pyghooks -# amalgamate exclude winutils wizard pytest_plugin fs macutils +# amalgamate exclude winutils wizard pytest_plugin fs macutils pygments_cache import os as _os if _os.getenv('XONSH_DEBUG', ''): pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/xonsh/ansi_colors.py new/xonsh-0.6.6/xonsh/ansi_colors.py --- old/xonsh-0.6.4/xonsh/ansi_colors.py 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/xonsh/ansi_colors.py 2018-06-06 19:12:10.000000000 +0200 @@ -890,7 +890,7 @@ return ANSI_STYLES[name] elif not HAS_PYGMENTS: raise KeyError('could not find style {0!r}'.format(name)) - from pygments.styles import get_style_by_name + from xonsh.pygments_cache import get_style_by_name pstyle = get_style_by_name(name) palette = make_palette(pstyle.styles.values()) astyle = make_ansi_style(palette) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/xonsh/commands_cache.py new/xonsh-0.6.6/xonsh/commands_cache.py --- old/xonsh-0.6.4/xonsh/commands_cache.py 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/xonsh/commands_cache.py 2018-06-06 19:12:10.000000000 +0200 @@ -70,12 +70,21 @@ else: return [name] + @staticmethod + def remove_dups(p): + ret = list() + for e in p: + if e not in ret: + ret.append(e) + return ret + @property def all_commands(self): paths = builtins.__xonsh_env__.get('PATH', []) - pathset = frozenset(x for x in paths if os.path.isdir(x)) + paths = CommandsCache.remove_dups(paths) + path_immut = tuple(x for x in paths if os.path.isdir(x)) # did PATH change? - path_hash = hash(pathset) + path_hash = hash(path_immut) cache_valid = path_hash == self._path_checksum self._path_checksum = path_hash # did aliases change? @@ -85,7 +94,7 @@ self._alias_checksum = al_hash # did the contents of any directory in PATH change? max_mtime = 0 - for path in pathset: + for path in path_immut: mtime = os.stat(path).st_mtime if mtime > max_mtime: max_mtime = mtime @@ -94,7 +103,7 @@ if cache_valid: return self._cmds_cache allcmds = {} - for path in reversed(paths): + for path in reversed(path_immut): # iterate backwards so that entries at the front of PATH overwrite # entries at the back. for cmd in executables_in(path): @@ -332,6 +341,23 @@ return pred +@lazyobject +def HG_PREDICTOR_PARSER(): + p = argparse.ArgumentParser('hg', add_help=False) + p.add_argument('command') + p.add_argument('-i', '--interactive', action='store_true', default=False, + dest='interactive') + return p + + +def predict_hg(args): + """Predict if mercurial is about to be run in interactive mode. + If it is interactive, predict False. If it isn't, predict True. + """ + ns, _ = HG_PREDICTOR_PARSER.parse_known_args(args) + return not ns.interactive + + def default_threadable_predictors(): """Generates a new defaultdict for known threadable predictors. The default is to predict true. @@ -348,6 +374,7 @@ 'emacsclient': predict_false, 'fish': predict_shell, 'gvim': predict_help_ver, + 'hg': predict_hg, 'htop': predict_help_ver, 'ipython': predict_shell, 'ksh': predict_shell, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/xonsh/pyghooks.py new/xonsh-0.6.6/xonsh/pyghooks.py --- old/xonsh-0.6.4/xonsh/pyghooks.py 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/xonsh/pyghooks.py 2018-06-06 19:12:10.000000000 +0200 @@ -8,21 +8,12 @@ from collections import ChainMap from collections.abc import MutableMapping -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# DO NOT MOVE -# must come before pygments imports -from xonsh.lazyasd import load_module_in_background -load_module_in_background('pkg_resources', debug='XONSH_DEBUG', - replacements={'pygments.plugin': 'pkg_resources'}) -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - from pygments.lexer import inherit, bygroups, include from pygments.lexers.agile import PythonLexer from pygments.token import (Keyword, Name, Comment, String, Error, Number, Operator, Generic, Whitespace, Token, Punctuation, Text) from pygments.style import Style -from pygments.styles import get_style_by_name import pygments.util from xonsh.commands_cache import CommandsCache @@ -34,6 +25,7 @@ from xonsh.style_tools import norm_name from xonsh.lazyimps import terminal256 from xonsh.platform import os_environ +from xonsh.pygments_cache import get_style_by_name def _command_is_valid(cmd): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/xonsh/pygments_cache.py new/xonsh-0.6.6/xonsh/pygments_cache.py --- old/xonsh-0.6.4/xonsh/pygments_cache.py 1970-01-01 01:00:00.000000000 +0100 +++ new/xonsh-0.6.6/xonsh/pygments_cache.py 2018-06-06 19:12:10.000000000 +0200 @@ -0,0 +1,417 @@ +"""A fast, drop-in replacement for pygments ``get_*()`` and ``guess_*()`` funtions. + +The following pygments API functions are currently supplied here:: + + from pygments_cache import get_lexer_for_filename, guess_lexer_for_filename + from pygments_cache import get_formatter_for_filename, get_formatter_by_name + from pygments_cache import get_style_by_name + from pygments_cache import get_filter_by_name + +The cache itself is stored at the location given by the ``$PYGMENTS_CACHE_FILE`` +environment variable, or by default at ``~/.local/share/pygments-cache/cache.py``. +The cache file is created on first use, if it does not already exist. + + +""" +import os +import importlib + + +# Global storage variables +__version__ = '0.1.1' +CACHE = None +DEBUG = False + + +def _print_duplicate_message(duplicates): + import sys + for filename, vals in sorted(duplicates.items()): + msg = 'for {0} ambiquity between:\n '.format(filename) + vals = [m + ':' + c for m, c in vals] + msg += '\n '.join(sorted(vals)) + print(msg, file=sys.stderr) + + +def _discover_lexers(): + import inspect + from pygments.lexers import get_all_lexers, find_lexer_class + # maps file extension (and names) to (module, classname) tuples + default_exts = { + # C / C++ + '.h': ('pygments.lexers.c_cpp', 'CLexer'), + '.hh': ('pygments.lexers.c_cpp', 'CppLexer'), + '.cp': ('pygments.lexers.c_cpp', 'CppLexer'), + # python + '.py': ('pygments.lexers.python', 'Python3Lexer'), + '.pyw': ('pygments.lexers.python', 'Python3Lexer'), + '.sc': ('pygments.lexers.python', 'Python3Lexer'), + '.tac': ('pygments.lexers.python', 'Python3Lexer'), + 'SConstruct': ('pygments.lexers.python', 'Python3Lexer'), + 'SConscript': ('pygments.lexers.python', 'Python3Lexer'), + '.sage': ('pygments.lexers.python', 'Python3Lexer'), + '.pytb': ('pygments.lexers.python', 'Python3TracebackLexer'), + # perl + '.t': ('pygments.lexers.perl', 'Perl6Lexer'), + '.pl': ('pygments.lexers.perl', 'Perl6Lexer'), + '.pm': ('pygments.lexers.perl', 'Perl6Lexer'), + # asm + '.s': ('pygments.lexers.asm', 'GasLexer'), + '.S': ('pygments.lexers.asm', 'GasLexer'), + '.asm': ('pygments.lexers.asm', 'NasmLexer'), + '.ASM': ('pygments.lexers.asm', 'NasmLexer'), + # Antlr + '.g': ('pygments.lexers.parsers', 'AntlrCppLexer'), + '.G': ('pygments.lexers.parsers', 'AntlrCppLexer'), + # XML + '.xml': ('pygments.lexers.html', 'XmlLexer'), + '.xsl': ('pygments.lexers.html', 'XsltLexer'), + '.xslt': ('pygments.lexers.html', 'XsltLexer'), + # ASP + '.axd': ('pygments.lexers.dotnet', 'CSharpAspxLexer'), + '.asax': ('pygments.lexers.dotnet', 'CSharpAspxLexer'), + '.ascx': ('pygments.lexers.dotnet', 'CSharpAspxLexer'), + '.ashx': ('pygments.lexers.dotnet', 'CSharpAspxLexer'), + '.asmx': ('pygments.lexers.dotnet', 'CSharpAspxLexer'), + '.aspx': ('pygments.lexers.dotnet', 'CSharpAspxLexer'), + # misc + '.b': ('pygments.lexers.esoteric', 'BrainfuckLexer'), + '.j': ('pygments.lexers.jvm', 'JasminLexer'), + '.m': ('pygments.lexers.matlab', 'MatlabLexer'), + '.n': ('pygments.lexers.dotnet', 'NemerleLexer'), + '.p': ('pygments.lexers.pawn', 'PawnLexer'), + '.v': ('pygments.lexers.theorem', 'CoqLexer'), + '.as': ('pygments.lexers.actionscript', 'ActionScript3Lexer'), + '.fs': ('pygments.lexers.forth', 'ForthLexer'), + '.hy': ('pygments.lexers.lisp', 'HyLexer'), + '.ts': ('pygments.lexers.javascript', 'TypeScriptLexer'), + '.rl': ('pygments.lexers.parsers', 'RagelCppLexer'), + '.bas': ('pygments.lexers.basic', 'QBasicLexer'), + '.bug': ('pygments.lexers.modeling', 'BugsLexer'), + '.ecl': ('pygments.lexers.ecl', 'ECLLexer'), + '.inc': ('pygments.lexers.php', 'PhpLexer'), + '.inf': ('pygments.lexers.configs', 'IniLexer'), + '.pro': ('pygments.lexers.prolog', 'PrologLexer'), + '.sql': ('pygments.lexers.sql', 'SqlLexer'), + '.txt': ('pygments.lexers.special', 'TextLexer'), + '.html': ('pygments.lexers.html', 'HtmlLexer'), + } + exts = {} + lexers = {'exts': exts} + if DEBUG: + from collections import defaultdict + duplicates = defaultdict(set) + for longname, aliases, filenames, mimetypes in get_all_lexers(): + cls = find_lexer_class(longname) + mod = inspect.getmodule(cls) + val = (mod.__name__, cls.__name__) + for filename in filenames: + if filename.startswith('*.'): + filename = filename[1:] + if '*' in filename: + continue + if (DEBUG and filename in exts and exts[filename] != val + and filename not in default_exts): + duplicates[filename].add(val) + duplicates[filename].add(exts[filename]) + exts[filename] = val + # remove some ambiquity + exts.update(default_exts) + # print duplicate message + if DEBUG: + _print_duplicate_message(duplicates) + return lexers + + +def _discover_formatters(): + import inspect + from pygments.formatters import get_all_formatters + # maps file extension (and names) to (module, classname) tuples + default_exts = {} + exts = {} + # maps formatter 'name' (not the class name) and alias to (module, classname) tuples + default_names = {} + names = {} + formatters = {'exts': exts, 'names': names} + if DEBUG: + from collections import defaultdict + duplicates = defaultdict(set) + for cls in get_all_formatters(): + mod = inspect.getmodule(cls) + val = (mod.__name__, cls.__name__) + # add extentions + for filename in cls.filenames: + if filename.startswith('*.'): + filename = filename[1:] + if '*' in filename: + continue + if (DEBUG and filename in exts and exts[filename] != val + and filename not in default_exts): + duplicates[filename].add(val) + duplicates[filename].add(exts[filename]) + exts[filename] = val + # add names and aliases + names[cls.name] = val + for alias in cls.aliases: + if (DEBUG and alias in names and names[alias] != val + and alias not in default_names): + duplicates[alias].add(val) + duplicates[alias].add(names[alias]) + names[alias] = val + # remove some ambiquity + exts.update(default_exts) + names.update(default_names) + # print dumplicate message + if DEBUG: + _print_duplicate_message(duplicates) + return formatters + + +def _discover_styles(): + import inspect + from pygments.styles import get_all_styles, get_style_by_name + # maps style 'name' (not the class name) and aliases to (module, classname) tuples + default_names = {} + names = {} + styles = {'names': names} + if DEBUG: + from collections import defaultdict + duplicates = defaultdict(set) + for name in get_all_styles(): + cls = get_style_by_name(name) + mod = inspect.getmodule(cls) + val = (mod.__name__, cls.__name__) + if (DEBUG and name in names and names[name] != val + and name not in default_names): + duplicates[name].add(val) + duplicates[name].add(names[name]) + names[name] = val + # remove some ambiquity + names.update(default_names) + # print dumplicate message + if DEBUG: + _print_duplicate_message(duplicates) + return styles + + +def _discover_filters(): + import inspect + from pygments.filters import get_all_filters, get_filter_by_name + # maps filter 'name' (not the class name) to (module, classname) tuples + default_names = {} + names = {} + filters = {'names': names} + if DEBUG: + from collections import defaultdict + duplicates = defaultdict(set) + for name in get_all_filters(): + filter = get_filter_by_name(name) + cls = type(filter) + mod = inspect.getmodule(cls) + val = (mod.__name__, cls.__name__) + if (DEBUG and name in names and names[name] != val + and name not in default_names): + duplicates[name].add(val) + duplicates[name].add(names[name]) + names[name] = val + # remove some ambiquity + names.update(default_names) + # print dumplicate message + if DEBUG: + _print_duplicate_message(duplicates) + return filters + + +def build_cache(): + """Does the hard work of building a cache from nothing.""" + cache = {} + cache['lexers'] = _discover_lexers() + cache['formatters'] = _discover_formatters() + cache['styles'] = _discover_styles() + cache['filters'] = _discover_filters() + return cache + + +def cache_filename(): + """Gets the name of the cache file to use.""" + # Configuration variables read from the environment + if 'PYGMENTS_CACHE_FILE' in os.environ: + return os.environ['PYGMENTS_CACHE_FILE'] + else: + return os.path.join(os.environ.get('XDG_DATA_HOME', + os.path.join(os.path.expanduser('~'), + '.local', 'share')), + 'pygments-cache', + 'cache.py' + ) + + +def load(filename): + """Loads the cache from a filename.""" + global CACHE + with open(filename) as f: + s = f.read() + ctx = globals() + CACHE = eval(s, ctx, ctx) + return CACHE + + +def write_cache(filename): + """Writes the current cache to the file""" + from pprint import pformat + d = os.path.dirname(filename) + os.makedirs(d, exist_ok=True) + s = pformat(CACHE) + with open(filename, 'w') as f: + f.write(s) + + +def load_or_build(): + """Loads the cache from disk. If the cache does not exist, + this will build and write it out. + """ + global CACHE + fname = cache_filename() + if os.path.exists(fname): + load(fname) + else: + import sys + print('pygments cache not found, building...', file=sys.stderr) + CACHE = build_cache() + print('...writing cache to ' + fname, file=sys.stderr) + write_cache(fname) + + +# +# pygments interface +# + +def get_lexer_for_filename(filename, text='', **options): + """Gets a lexer from a filename (usually via the filename extension). + This mimics the behavior of ``pygments.lexers.get_lexer_for_filename()`` + and ``pygments.lexers.guess_lexer_for_filename()``. + """ + if CACHE is None: + load_or_build() + exts = CACHE['lexers']['exts'] + fname = os.path.basename(filename) + key = fname if fname in exts else os.path.splitext(fname)[1] + if key in exts: + modname, clsname = exts[key] + mod = importlib.import_module(modname) + cls = getattr(mod, clsname) + lexer = cls(**options) + else: + # couldn't find lexer in cache, fallback to the hard way + import inspect + from pygments.lexers import guess_lexer_for_filename + lexer = guess_lexer_for_filename(filename, text, **options) + # add this filename to the cache for future use + cls = type(lexer) + mod = inspect.getmodule(cls) + exts[fname] = (mod.__name__, cls.__name__) + write_cache(cache_filename()) + return lexer + + +guess_lexer_for_filename = get_lexer_for_filename + + +def get_formatter_for_filename(fn, **options): + """Gets a formatter instance from a filename (usually via the filename + extension). This mimics the behavior of + ``pygments.formatters.get_formatter_for_filename()``. + """ + if CACHE is None: + load_or_build() + exts = CACHE['formatters']['exts'] + fname = os.path.basename(fn) + key = fname if fname in exts else os.path.splitext(fname)[1] + if key in exts: + modname, clsname = exts[key] + mod = importlib.import_module(modname) + cls = getattr(mod, clsname) + formatter = cls(**options) + else: + # couldn't find formatter in cache, fallback to the hard way + import inspect + from pygments.formatters import get_formatter_for_filename + formatter = get_formatter_for_filename(fn, **options) + # add this filename to the cache for future use + cls = type(formatter) + mod = inspect.getmodule(cls) + exts[fname] = (mod.__name__, cls.__name__) + write_cache(cache_filename()) + return formatter + + +def get_formatter_by_name(alias, **options): + """Gets a formatter instance from its name or alias. + This mimics the behavior of ``pygments.formatters.get_formatter_by_name()``. + """ + if CACHE is None: + load_or_build() + names = CACHE['formatters']['names'] + if alias in names: + modname, clsname = names[alias] + mod = importlib.import_module(modname) + cls = getattr(mod, clsname) + formatter = cls(**options) + else: + # couldn't find formatter in cache, fallback to the hard way + import inspect + from pygments.formatters import get_formatter_by_name + formatter = get_formatter_by_name(alias, **options) + # add this filename to the cache for future use + cls = type(formatter) + mod = inspect.getmodule(cls) + names[alias] = (mod.__name__, cls.__name__) + write_cache(cache_filename()) + return formatter + + +def get_style_by_name(name): + """Gets a style class from its name or alias. + This mimics the behavior of ``pygments.styles.get_style_by_name()``. + """ + if CACHE is None: + load_or_build() + names = CACHE['styles']['names'] + if name in names: + modname, clsname = names[name] + mod = importlib.import_module(modname) + style = getattr(mod, clsname) + else: + # couldn't find style in cache, fallback to the hard way + import inspect + from pygments.styles import get_style_by_name + style = get_style_by_name(name) + # add this style to the cache for future use + mod = inspect.getmodule(style) + names[name] = (mod.__name__, style.__name__) + write_cache(cache_filename()) + return style + + +def get_filter_by_name(filtername, **options): + """Gets a filter instance from its name. This mimics the behavior of + ``pygments.filters.get_filtere_by_name()``. + """ + if CACHE is None: + load_or_build() + names = CACHE['filters']['names'] + if filtername in names: + modname, clsname = names[filtername] + mod = importlib.import_module(modname) + cls = getattr(mod, clsname) + filter = cls(**options) + else: + # couldn't find style in cache, fallback to the hard way + import inspect + from pygments.filters import get_filter_by_name + filter = get_filter_by_name(filtername, **options) + # add this filter to the cache for future use + cls = type(filter) + mod = inspect.getmodule(cls) + names[filtername] = (mod.__name__, cls.__name__) + write_cache(cache_filename()) + return filter diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/xonsh/tools.py new/xonsh-0.6.6/xonsh/tools.py --- old/xonsh-0.6.4/xonsh/tools.py 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/xonsh/tools.py 2018-06-06 19:12:10.000000000 +0200 @@ -228,6 +228,36 @@ other = other._l return EnvPath(other + self._l) + def add(self, data, front=False, replace=False): + """Add a value to this EnvPath, + + path.add(data, front=bool, replace=bool) -> ensures that path contains data, with position determined by kwargs + + Parameters + ---------- + data : string or bytes or pathlib.Path + value to be added + front : bool + whether the value should be added to the front, will be + ignored if the data already exists in this EnvPath and + replace is False + Default : False + replace : bool + If True, the value will be removed and added to the + start or end(depending on the value of front) + Default : False + + Returns + ------- + None + + """ + if data not in self._l: + self._l.insert(0 if front else len(self._l), data) + elif replace: + self._l.remove(data) + self._l.insert(0 if front else len(self._l), data) + class DefaultNotGivenType(object): """Singleton for representing when no default value is given.""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/xonsh/wizard.py new/xonsh-0.6.6/xonsh/wizard.py --- old/xonsh-0.6.4/xonsh/wizard.py 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/xonsh/wizard.py 2018-06-06 19:12:10.000000000 +0200 @@ -334,6 +334,11 @@ dr[r] = func self._dr = dr + @staticmethod + def _find_rule_key(x): + """Key function for sorting regular expression rules""" + return (x[0], len(x[1].pattern)) + def find_rule(self, path): """For a path, find the key and conversion function that should be used to dump a value. @@ -350,10 +355,25 @@ if len(len_funcs) == 0: # No dump rule function for path return path, None - len_funcs.sort(reverse=True) + len_funcs.sort(reverse=True, key=self._find_rule_key) _, rule, func = len_funcs[0] return rule, func + def dumps(self, flat): + """Dumps a flat mapping of (string path keys, values) pairs and returns + a formatted string. + """ + lines = [self.prefix] + for path, value in sorted(flat.items()): + rule, func = self.find_rule(path) + if func is None: + continue + line = func(path, value) + lines.append(line) + lines.append(self.suffix) + new = '\n'.join(lines) + '\n' + return new + def create_truefalse_cond(prompt='yes or no [default: no]? ', path=None): """This creates a basic condition function for use with nodes like While @@ -771,16 +791,7 @@ def visit_fileinserter(self, node): # perform the dumping operation. - lines = [node.prefix] - flat = self.flatten() - for path, value in sorted(flat.items()): - rule, func = node.find_rule(path) - if func is None: - continue - line = func(path, value) - lines.append(line) - lines.append(node.suffix) - new = '\n'.join(lines) + '\n' + new = node.dumps(self.flatten()) # check if we should write this out if node.check: msg = 'The current state to insert is:\n\n{0}\n' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.6.4/xonsh/xonfig.py new/xonsh-0.6.6/xonsh/xonfig.py --- old/xonsh-0.6.4/xonsh/xonfig.py 2018-05-17 19:50:38.000000000 +0200 +++ new/xonsh-0.6.6/xonsh/xonfig.py 2018-06-06 19:12:10.000000000 +0200 @@ -161,7 +161,7 @@ def _dump_xonfig_env(path, value): - name = os.path.basename(path) + name = os.path.basename(path.rstrip('/')) ensurer = builtins.__xonsh_env__.get_ensurer(name) dval = ensurer.detype(value) return '${name} = {val!r}'.format(name=name, val=dval) @@ -177,6 +177,7 @@ '/env/': None, '/foreign_shells/*/': _dump_xonfig_foreign_shell, '/env/*': _dump_xonfig_env, + '/env/*/[0-9]*': None, '/xontribs/': _dump_xonfig_xontribs, }
