From 3ea9e259c6d9b83d5cbf8b7c2cd4da8d3f4c0774 Mon Sep 17 00:00:00 2001 From: Lin Guo Date: Thu, 30 May 2024 22:50:42 -0700 Subject: [PATCH] Fix py11 and 12 support * Remove relevant usage of `six.moves` in ramble and vendored deps * Update `py` dep to the latest [head](https://github.com/pytest-dev/py/tree/6b219734fcd8d2f6489c2f50585a435b34c029c2/py), due to https://github.com/pytest-dev/py/issues/273. --- lib/ramble/external/py/__init__.py | 34 +-- lib/ramble/external/py/__init__.pyi | 20 ++ lib/ramble/external/py/_builtin.py | 123 +--------- lib/ramble/external/py/_code/_assertionnew.py | 25 +- lib/ramble/external/py/_code/_assertionold.py | 3 +- lib/ramble/external/py/_code/assertion.py | 6 +- lib/ramble/external/py/_code/code.py | 33 ++- lib/ramble/external/py/_code/source.py | 11 +- lib/ramble/external/py/_error.py | 6 +- lib/ramble/external/py/_io/capture.py | 6 +- lib/ramble/external/py/_io/terminalwriter.py | 84 ++++++- lib/ramble/external/py/_log/log.py | 42 +++- lib/ramble/external/py/_log/warning.py | 9 +- lib/ramble/external/py/_path/common.py | 24 +- lib/ramble/external/py/_path/local.py | 232 +++++++++++++----- lib/ramble/external/py/_path/svnwc.py | 10 +- lib/ramble/external/py/_std.py | 9 + .../py/_vendored_packages/__init__.py | 0 .../apipkg-2.0.0.dist-info/INSTALLER | 1 + .../apipkg-2.0.0.dist-info/LICENSE | 18 ++ .../apipkg-2.0.0.dist-info/METADATA | 125 ++++++++++ .../apipkg-2.0.0.dist-info/RECORD | 11 + .../apipkg-2.0.0.dist-info/REQUESTED | 0 .../apipkg-2.0.0.dist-info/WHEEL | 6 + .../apipkg/__init__.py} | 126 ++++++---- .../py/_vendored_packages/apipkg/version.py | 5 + .../iniconfig-1.1.1.dist-info/INSTALLER | 1 + .../iniconfig-1.1.1.dist-info/LICENSE | 19 ++ .../iniconfig-1.1.1.dist-info/METADATA | 78 ++++++ .../iniconfig-1.1.1.dist-info/RECORD | 11 + .../iniconfig-1.1.1.dist-info/REQUESTED | 0 .../iniconfig-1.1.1.dist-info/WHEEL | 6 + .../iniconfig/__init__.py} | 17 +- .../_vendored_packages/iniconfig/__init__.pyi | 31 +++ .../py/_vendored_packages/iniconfig/py.typed | 0 lib/ramble/external/py/error.pyi | 129 ++++++++++ lib/ramble/external/py/iniconfig.pyi | 31 +++ lib/ramble/external/py/io.pyi | 130 ++++++++++ lib/ramble/external/py/path.pyi | 197 +++++++++++++++ lib/ramble/external/py/py.typed | 0 lib/ramble/external/py/xml.pyi | 25 ++ lib/ramble/llnl/util/tty/__init__.py | 3 - lib/ramble/ramble/fetch_strategy.py | 6 +- lib/ramble/ramble/util/web.py | 4 +- lib/ramble/spack/fetch_strategy.py | 6 +- lib/ramble/spack/gcs_handler.py | 4 +- lib/ramble/spack/url.py | 2 +- lib/ramble/spack/util/environment.py | 4 +- lib/ramble/spack/util/path.py | 2 +- lib/ramble/spack/util/s3.py | 4 +- lib/ramble/spack/util/url.py | 16 +- lib/ramble/spack/util/web.py | 4 +- 52 files changed, 1343 insertions(+), 356 deletions(-) create mode 100644 lib/ramble/external/py/__init__.pyi create mode 100644 lib/ramble/external/py/_vendored_packages/__init__.py create mode 100644 lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/INSTALLER create mode 100644 lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/LICENSE create mode 100644 lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/METADATA create mode 100644 lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/RECORD create mode 100644 lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/REQUESTED create mode 100644 lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/WHEEL rename lib/ramble/external/py/{_apipkg.py => _vendored_packages/apipkg/__init__.py} (55%) create mode 100644 lib/ramble/external/py/_vendored_packages/apipkg/version.py create mode 100644 lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/INSTALLER create mode 100644 lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/LICENSE create mode 100644 lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/METADATA create mode 100644 lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/RECORD create mode 100644 lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/REQUESTED create mode 100644 lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/WHEEL rename lib/ramble/external/py/{_iniconfig.py => _vendored_packages/iniconfig/__init__.py} (92%) create mode 100644 lib/ramble/external/py/_vendored_packages/iniconfig/__init__.pyi create mode 100644 lib/ramble/external/py/_vendored_packages/iniconfig/py.typed create mode 100644 lib/ramble/external/py/error.pyi create mode 100644 lib/ramble/external/py/iniconfig.pyi create mode 100644 lib/ramble/external/py/io.pyi create mode 100644 lib/ramble/external/py/path.pyi create mode 100644 lib/ramble/external/py/py.typed create mode 100644 lib/ramble/external/py/xml.pyi diff --git a/lib/ramble/external/py/__init__.py b/lib/ramble/external/py/__init__.py index 85af650f5..b892ce1a2 100644 --- a/lib/ramble/external/py/__init__.py +++ b/lib/ramble/external/py/__init__.py @@ -8,21 +8,27 @@ (c) Holger Krekel and others, 2004-2014 """ -__version__ = '1.4.34' +from py._error import error -from py import _apipkg +try: + from py._vendored_packages import apipkg + lib_not_mangled_by_packagers = True + vendor_prefix = '._vendored_packages.' +except ImportError: + import apipkg + lib_not_mangled_by_packagers = False + vendor_prefix = '' -# so that py.error.* instances are picklable -import sys -sys.modules['py.error'] = _apipkg.AliasModule("py.error", "py._error", 'error') -import py.error # "Dereference" it now just to be safe (issue110) +try: + from ._version import version as __version__ +except ImportError: + # broken installation, we don't even try + __version__ = "unknown" -_apipkg.initpkg(__name__, attr={'_apipkg': _apipkg}, exportdefs={ +apipkg.initpkg(__name__, attr={'_apipkg': apipkg, 'error': error}, exportdefs={ # access to all standard lib modules 'std': '._std:std', - # access to all posix errno's as classes - 'error': '._error:error', '_pydir' : '.__metainfo:pydir', 'version': 'py:__version__', # backward compatibility @@ -30,8 +36,6 @@ # pytest-2.0 has a flat namespace, we use alias modules # to keep old references compatible 'test' : 'pytest', - 'test.collect' : 'pytest', - 'test.cmdline' : 'pytest', # hook into the top-level standard library 'process' : { @@ -42,13 +46,13 @@ }, 'apipkg' : { - 'initpkg' : '._apipkg:initpkg', - 'ApiModule' : '._apipkg:ApiModule', + 'initpkg' : vendor_prefix + 'apipkg:initpkg', + 'ApiModule' : vendor_prefix + 'apipkg:ApiModule', }, 'iniconfig' : { - 'IniConfig' : '._iniconfig:IniConfig', - 'ParseError' : '._iniconfig:ParseError', + 'IniConfig' : vendor_prefix + 'iniconfig:IniConfig', + 'ParseError' : vendor_prefix + 'iniconfig:ParseError', }, 'path' : { diff --git a/lib/ramble/external/py/__init__.pyi b/lib/ramble/external/py/__init__.pyi new file mode 100644 index 000000000..96859e310 --- /dev/null +++ b/lib/ramble/external/py/__init__.pyi @@ -0,0 +1,20 @@ +from typing import Any + +# py allows to use e.g. py.path.local even without importing py.path. +# So import implicitly. +from . import error +from . import iniconfig +from . import path +from . import io +from . import xml + +__version__: str + +# Untyped modules below here. +std: Any +test: Any +process: Any +apipkg: Any +code: Any +builtin: Any +log: Any diff --git a/lib/ramble/external/py/_builtin.py b/lib/ramble/external/py/_builtin.py index 52ee9d79c..ddc89fc7b 100644 --- a/lib/ramble/external/py/_builtin.py +++ b/lib/ramble/external/py/_builtin.py @@ -1,120 +1,21 @@ import sys -try: - reversed = reversed -except NameError: - def reversed(sequence): - """reversed(sequence) -> reverse iterator over values of the sequence - - Return a reverse iterator - """ - if hasattr(sequence, '__reversed__'): - return sequence.__reversed__() - if not hasattr(sequence, '__getitem__'): - raise TypeError("argument to reversed() must be a sequence") - return reversed_iterator(sequence) - - class reversed_iterator(object): - - def __init__(self, seq): - self.seq = seq - self.remaining = len(seq) - - def __iter__(self): - return self - - def next(self): - i = self.remaining - if i > 0: - i -= 1 - item = self.seq[i] - self.remaining = i - return item - raise StopIteration - - def __length_hint__(self): - return self.remaining - -try: - any = any -except NameError: - def any(iterable): - for x in iterable: - if x: - return True - return False - -try: - all = all -except NameError: - def all(iterable): - for x in iterable: - if not x: - return False - return True - -try: - sorted = sorted -except NameError: - builtin_cmp = cmp # need to use cmp as keyword arg - - def sorted(iterable, cmp=None, key=None, reverse=0): - use_cmp = None - if key is not None: - if cmp is None: - def use_cmp(x, y): - return builtin_cmp(x[0], y[0]) - else: - def use_cmp(x, y): - return cmp(x[0], y[0]) - l = [(key(element), element) for element in iterable] - else: - if cmp is not None: - use_cmp = cmp - l = list(iterable) - if use_cmp is not None: - l.sort(use_cmp) - else: - l.sort() - if reverse: - l.reverse() - if key is not None: - return [element for (_, element) in l] - return l - -try: - set, frozenset = set, frozenset -except NameError: - from sets import set, frozenset - -# pass through -enumerate = enumerate - -try: - BaseException = BaseException -except NameError: - BaseException = Exception - -try: - GeneratorExit = GeneratorExit -except NameError: - class GeneratorExit(Exception): - """ This exception is never raised, it is there to make it possible to - write code compatible with CPython 2.5 even in lower CPython - versions.""" - pass - GeneratorExit.__module__ = 'exceptions' +# Passthrough for builtins supported with py27. +BaseException = BaseException +GeneratorExit = GeneratorExit _sysex = (KeyboardInterrupt, SystemExit, MemoryError, GeneratorExit) +all = all +any = any +callable = callable +enumerate = enumerate +reversed = reversed +set, frozenset = set, frozenset +sorted = sorted -try: - callable = callable -except NameError: - def callable(obj): - return hasattr(obj, "__call__") if sys.version_info >= (3, 0): - exec ("print_ = print ; exec_=exec") + exec("print_ = print ; exec_=exec") import builtins # some backward compatibility helpers @@ -131,13 +32,13 @@ def _totext(obj, encoding=None, errors=None): def _isbytes(x): return isinstance(x, bytes) + def _istext(x): return isinstance(x, str) text = str bytes = bytes - def _getimself(function): return getattr(function, '__self__', None) diff --git a/lib/ramble/external/py/_code/_assertionnew.py b/lib/ramble/external/py/_code/_assertionnew.py index afb1b31ff..d03f29d87 100644 --- a/lib/ramble/external/py/_code/_assertionnew.py +++ b/lib/ramble/external/py/_code/_assertionnew.py @@ -10,27 +10,10 @@ from py._code.assertion import _format_explanation, BuiltinAssertionError -if sys.platform.startswith("java") and sys.version_info < (2, 5, 2): - # See http://bugs.jython.org/issue1497 - _exprs = ("BoolOp", "BinOp", "UnaryOp", "Lambda", "IfExp", "Dict", - "ListComp", "GeneratorExp", "Yield", "Compare", "Call", - "Repr", "Num", "Str", "Attribute", "Subscript", "Name", - "List", "Tuple") - _stmts = ("FunctionDef", "ClassDef", "Return", "Delete", "Assign", - "AugAssign", "Print", "For", "While", "If", "With", "Raise", - "TryExcept", "TryFinally", "Assert", "Import", "ImportFrom", - "Exec", "Global", "Expr", "Pass", "Break", "Continue") - _expr_nodes = set(getattr(ast, name) for name in _exprs) - _stmt_nodes = set(getattr(ast, name) for name in _stmts) - def _is_ast_expr(node): - return node.__class__ in _expr_nodes - def _is_ast_stmt(node): - return node.__class__ in _stmt_nodes -else: - def _is_ast_expr(node): - return isinstance(node, ast.expr) - def _is_ast_stmt(node): - return isinstance(node, ast.stmt) +def _is_ast_expr(node): + return isinstance(node, ast.expr) +def _is_ast_stmt(node): + return isinstance(node, ast.stmt) class Failure(Exception): diff --git a/lib/ramble/external/py/_code/_assertionold.py b/lib/ramble/external/py/_code/_assertionold.py index 4e81fb3ef..1bb70a875 100644 --- a/lib/ramble/external/py/_code/_assertionold.py +++ b/lib/ramble/external/py/_code/_assertionold.py @@ -2,6 +2,7 @@ import sys, inspect from compiler import parse, ast, pycodegen from py._code.assertion import BuiltinAssertionError, _format_explanation +import types passthroughex = py.builtin._sysex @@ -470,7 +471,7 @@ def check(s, frame=None): def interpret(source, frame, should_fail=False): module = Interpretable(parse(source, 'exec').node) #print "got module", module - if isinstance(frame, py.std.types.FrameType): + if isinstance(frame, types.FrameType): frame = py.code.Frame(frame) try: module.run(frame) diff --git a/lib/ramble/external/py/_code/assertion.py b/lib/ramble/external/py/_code/assertion.py index 4ce80c75b..ff1643799 100644 --- a/lib/ramble/external/py/_code/assertion.py +++ b/lib/ramble/external/py/_code/assertion.py @@ -87,8 +87,4 @@ def __init__(self, *args): reinterpret_old = "old reinterpretation not available for py3" else: from py._code._assertionold import interpret as reinterpret_old -if sys.version_info >= (2, 6) or (sys.platform.startswith("java")): - from py._code._assertionnew import interpret as reinterpret -else: - reinterpret = reinterpret_old - +from py._code._assertionnew import interpret as reinterpret diff --git a/lib/ramble/external/py/_code/code.py b/lib/ramble/external/py/_code/code.py index 20fd965c9..dad796283 100644 --- a/lib/ramble/external/py/_code/code.py +++ b/lib/ramble/external/py/_code/code.py @@ -1,6 +1,6 @@ import py import sys -from inspect import CO_VARARGS, CO_VARKEYWORDS +from inspect import CO_VARARGS, CO_VARKEYWORDS, isclass builtin_repr = repr @@ -11,6 +11,9 @@ else: from py._code._py2traceback import format_exception_only +import traceback + + class Code(object): """ wrapper around Python code objects """ def __init__(self, rawcode): @@ -21,7 +24,7 @@ def __init__(self, rawcode): self.firstlineno = rawcode.co_firstlineno - 1 self.name = rawcode.co_name except AttributeError: - raise TypeError("not a code object: %r" %(rawcode,)) + raise TypeError("not a code object: %r" % (rawcode,)) self.raw = rawcode def __eq__(self, other): @@ -106,7 +109,7 @@ def exec_(self, code, **vars): """ f_locals = self.f_locals.copy() f_locals.update(vars) - py.builtin.exec_(code, self.f_globals, f_locals ) + py.builtin.exec_(code, self.f_globals, f_locals) def repr(self, object): """ return a 'safe' (non-recursive, one-line) string repr for 'object' @@ -130,6 +133,7 @@ def getargs(self, var=False): pass # this can occur when using Psyco return retval + class TracebackEntry(object): """ a single entry in a traceback """ @@ -153,7 +157,7 @@ def relline(self): return self.lineno - self.frame.code.firstlineno def __repr__(self): - return "" %(self.frame.code.path, self.lineno+1) + return "" % (self.frame.code.path, self.lineno+1) @property def statement(self): @@ -237,17 +241,19 @@ def __str__(self): raise except: line = "???" - return " File %r:%d in %s\n %s\n" %(fn, self.lineno+1, name, line) + return " File %r:%d in %s\n %s\n" % (fn, self.lineno+1, name, line) def name(self): return self.frame.code.raw.co_name name = property(name, None, None, "co_name of underlaying code") + class Traceback(list): """ Traceback objects encapsulate and offer higher level access to Traceback entries. """ Entry = TracebackEntry + def __init__(self, tb): """ initialize from given python traceback object. """ if hasattr(tb, 'tb_next'): @@ -362,7 +368,8 @@ def __init__(self, tup=None, exprinfo=None): self.traceback = py.code.Traceback(self.tb) def __repr__(self): - return "" % (self.typename, len(self.traceback)) + return "" % ( + self.typename, len(self.traceback)) def exconly(self, tryshort=False): """ return the exception as a string @@ -391,7 +398,7 @@ def _getreprcrash(self): return ReprFileLocation(path, lineno+1, exconly) def getrepr(self, showlocals=False, style="long", - abspath=False, tbfilter=True, funcargs=False): + abspath=False, tbfilter=True, funcargs=False): """ return str()able representation of this exception info. showlocals: show locals per traceback entry style: long|short|no|native traceback style @@ -401,13 +408,14 @@ def getrepr(self, showlocals=False, style="long", """ if style == 'native': return ReprExceptionInfo(ReprTracebackNative( - py.std.traceback.format_exception( + traceback.format_exception( self.type, self.value, self.traceback[0]._rawentry, )), self._getreprcrash()) - fmt = FormattedExcinfo(showlocals=showlocals, style=style, + fmt = FormattedExcinfo( + showlocals=showlocals, style=style, abspath=abspath, tbfilter=tbfilter, funcargs=funcargs) return fmt.repr_excinfo(self) @@ -428,7 +436,8 @@ class FormattedExcinfo(object): flow_marker = ">" fail_marker = "E" - def __init__(self, showlocals=False, style="long", abspath=True, tbfilter=True, funcargs=False): + def __init__(self, showlocals=False, style="long", + abspath=True, tbfilter=True, funcargs=False): self.showlocals = showlocals self.style = style self.tbfilter = tbfilter @@ -521,7 +530,7 @@ def repr_locals(self, locals): #else: # self._line("%-10s =\\" % (name,)) # # XXX - # py.std.pprint.pprint(value, stream=self.excinfowriter) + # pprint.pprint(value, stream=self.excinfowriter) return ReprLocals(lines) def repr_traceback_entry(self, entry, excinfo=None): @@ -779,7 +788,7 @@ def getrawcode(obj, trycall=True): obj = getattr(obj, 'f_code', obj) obj = getattr(obj, '__code__', obj) if trycall and not hasattr(obj, 'co_firstlineno'): - if hasattr(obj, '__call__') and not py.std.inspect.isclass(obj): + if hasattr(obj, '__call__') and not isclass(obj): x = getrawcode(obj.__call__, trycall=False) if hasattr(x, 'co_firstlineno'): return x diff --git a/lib/ramble/external/py/_code/source.py b/lib/ramble/external/py/_code/source.py index c8b668b2f..7fc7b23a9 100644 --- a/lib/ramble/external/py/_code/source.py +++ b/lib/ramble/external/py/_code/source.py @@ -193,7 +193,8 @@ def compile(self, filename=None, mode='exec', if flag & _AST_FLAG: return co lines = [(x + "\n") for x in self.lines] - py.std.linecache.cache[filename] = (1, None, lines, filename) + import linecache + linecache.cache[filename] = (1, None, lines, filename) return co # @@ -224,8 +225,8 @@ def getfslineno(obj): code = py.code.Code(obj) except TypeError: try: - fn = (py.std.inspect.getsourcefile(obj) or - py.std.inspect.getfile(obj)) + fn = (inspect.getsourcefile(obj) or + inspect.getfile(obj)) except TypeError: return "", -1 @@ -248,7 +249,7 @@ def getfslineno(obj): def findsource(obj): try: - sourcelines, lineno = py.std.inspect.findsource(obj) + sourcelines, lineno = inspect.findsource(obj) except py.builtin._sysex: raise except: @@ -334,8 +335,6 @@ def get_statement_startend2(lineno, node): def getstatementrange_ast(lineno, source, assertion=False, astnode=None): if astnode is None: content = str(source) - if sys.version_info < (2,7): - content += "\n" try: astnode = compile(content, "source", "exec", 1024) # 1024 for AST except ValueError: diff --git a/lib/ramble/external/py/_error.py b/lib/ramble/external/py/_error.py index 8ca339beb..a6375de9f 100644 --- a/lib/ramble/external/py/_error.py +++ b/lib/ramble/external/py/_error.py @@ -2,6 +2,7 @@ create errno-specific classes for IO or os calls. """ +from types import ModuleType import sys, os, errno class Error(EnvironmentError): @@ -31,7 +32,7 @@ def __str__(self): 5: errno.EACCES, # anything better? } -class ErrorMaker(object): +class ErrorMaker(ModuleType): """ lazily provides Exception classes for each possible POSIX errno (as defined per the 'errno' module). All such instances subclass EnvironmentError. @@ -86,4 +87,5 @@ def checked_call(self, func, *args, **kwargs): __tracebackhide__ = True -error = ErrorMaker() +error = ErrorMaker('py.error') +sys.modules[error.__name__] = error \ No newline at end of file diff --git a/lib/ramble/external/py/_io/capture.py b/lib/ramble/external/py/_io/capture.py index bc157ed97..cacf2fa71 100644 --- a/lib/ramble/external/py/_io/capture.py +++ b/lib/ramble/external/py/_io/capture.py @@ -13,7 +13,7 @@ class TextIO(StringIO): def write(self, data): if not isinstance(data, unicode): data = unicode(data, getattr(self, '_encoding', 'UTF-8'), 'replace') - StringIO.write(self, data) + return StringIO.write(self, data) else: TextIO = StringIO @@ -24,7 +24,7 @@ class BytesIO(StringIO): def write(self, data): if isinstance(data, unicode): raise TypeError("not a byte value: %r" %(data,)) - StringIO.write(self, data) + return StringIO.write(self, data) patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'} @@ -266,7 +266,7 @@ def readouterr(self): err = self._readsnapshot(self.err.tmpfile) else: err = "" - return [out, err] + return out, err def _readsnapshot(self, f): f.seek(0) diff --git a/lib/ramble/external/py/_io/terminalwriter.py b/lib/ramble/external/py/_io/terminalwriter.py index 390e8ca7b..442ca2395 100644 --- a/lib/ramble/external/py/_io/terminalwriter.py +++ b/lib/ramble/external/py/_io/terminalwriter.py @@ -5,9 +5,10 @@ """ -import sys, os +import sys, os, unicodedata import py py3k = sys.version_info[0] >= 3 +py33 = sys.version_info >= (3, 3) from py.builtin import text, bytes win32_and_ctypes = False @@ -24,16 +25,21 @@ def _getdimensions(): - import termios,fcntl,struct - call = fcntl.ioctl(1,termios.TIOCGWINSZ,"\000"*8) - height,width = struct.unpack( "hhhh", call ) [:2] - return height, width + if py33: + import shutil + size = shutil.get_terminal_size() + return size.lines, size.columns + else: + import termios, fcntl, struct + call = fcntl.ioctl(1, termios.TIOCGWINSZ, "\000" * 8) + height, width = struct.unpack("hhhh", call)[:2] + return height, width def get_terminal_width(): - height = width = 0 + width = 0 try: - height, width = _getdimensions() + _, width = _getdimensions() except py.builtin._sysex: raise except: @@ -53,6 +59,21 @@ def get_terminal_width(): terminal_width = get_terminal_width() +char_width = { + 'A': 1, # "Ambiguous" + 'F': 2, # Fullwidth + 'H': 1, # Halfwidth + 'N': 1, # Neutral + 'Na': 1, # Narrow + 'W': 2, # Wide +} + + +def get_line_width(text): + text = unicodedata.normalize('NFC', text) + return sum(char_width.get(unicodedata.east_asian_width(c), 1) for c in text) + + # XXX unify with _escaped func below def ansi_print(text, esc, file=None, newline=True, flush=False): if file is None: @@ -112,6 +133,8 @@ def should_do_markup(file): return True if os.environ.get('PY_COLORS') == '0': return False + if 'NO_COLOR' in os.environ: + return False return hasattr(file, 'isatty') and file.isatty() \ and os.environ.get('TERM') != 'dumb' \ and not (sys.platform.startswith('java') and os._name == 'nt') @@ -129,7 +152,7 @@ def __init__(self, file=None, stringio=False, encoding=None): if stringio: self.stringio = file = py.io.TextIO() else: - file = py.std.sys.stdout + from sys import stdout as file elif py.builtin.callable(file) and not ( hasattr(file, "write") and hasattr(file, "flush")): file = WriteFile(file, encoding=encoding) @@ -139,6 +162,8 @@ def __init__(self, file=None, stringio=False, encoding=None): self._file = file self.hasmarkup = should_do_markup(file) self._lastlen = 0 + self._chars_on_current_line = 0 + self._width_of_current_line = 0 @property def fullwidth(self): @@ -150,6 +175,29 @@ def fullwidth(self): def fullwidth(self, value): self._terminal_width = value + @property + def chars_on_current_line(self): + """Return the number of characters written so far in the current line. + + Please note that this count does not produce correct results after a reline() call, + see #164. + + .. versionadded:: 1.5.0 + + :rtype: int + """ + return self._chars_on_current_line + + @property + def width_of_current_line(self): + """Return an estimate of the width so far in the current line. + + .. versionadded:: 1.6.0 + + :rtype: int + """ + return self._width_of_current_line + def _escaped(self, text, esc): if esc and self.hasmarkup: text = (''.join(['\x1b[%sm' % cod for cod in esc]) + @@ -181,7 +229,7 @@ def sep(self, sepchar, title=None, fullwidth=None, **kw): # i.e. 2 + 2*len(sepchar)*N + len(title) <= fullwidth # 2*len(sepchar)*N <= fullwidth - len(title) - 2 # N <= (fullwidth - len(title) - 2) // (2*len(sepchar)) - N = (fullwidth - len(title) - 2) // (2*len(sepchar)) + N = max((fullwidth - len(title) - 2) // (2*len(sepchar)), 1) fill = sepchar * N line = "%s %s %s" % (fill, title, fill) else: @@ -200,12 +248,27 @@ def write(self, msg, **kw): if msg: if not isinstance(msg, (bytes, text)): msg = text(msg) + + self._update_chars_on_current_line(msg) + if self.hasmarkup and kw: markupmsg = self.markup(msg, **kw) else: markupmsg = msg write_out(self._file, markupmsg) + def _update_chars_on_current_line(self, text_or_bytes): + newline = b'\n' if isinstance(text_or_bytes, bytes) else '\n' + current_line = text_or_bytes.rsplit(newline, 1)[-1] + if isinstance(current_line, bytes): + current_line = current_line.decode('utf-8', errors='replace') + if newline in text_or_bytes: + self._chars_on_current_line = len(current_line) + self._width_of_current_line = get_line_width(current_line) + else: + self._chars_on_current_line += len(current_line) + self._width_of_current_line += get_line_width(current_line) + def line(self, s='', **kw): self.write(s, **kw) self._checkfill(s) @@ -229,6 +292,9 @@ def write(self, msg, **kw): if msg: if not isinstance(msg, (bytes, text)): msg = text(msg) + + self._update_chars_on_current_line(msg) + oldcolors = None if self.hasmarkup and kw: handle = GetStdHandle(STD_OUTPUT_HANDLE) diff --git a/lib/ramble/external/py/_log/log.py b/lib/ramble/external/py/_log/log.py index ce47e8c75..56969bcb5 100644 --- a/lib/ramble/external/py/_log/log.py +++ b/lib/ramble/external/py/_log/log.py @@ -14,7 +14,9 @@ debug=py.log.STDOUT, command=None) """ -import py, sys +import py +import sys + class Message(object): def __init__(self, keywords, args): @@ -70,6 +72,7 @@ def __init__(self): def getstate(self): return self.keywords2consumer.copy() + def setstate(self, state): self.keywords2consumer.clear() self.keywords2consumer.update(state) @@ -104,17 +107,22 @@ def setconsumer(self, keywords, consumer): consumer = File(consumer) self.keywords2consumer[keywords] = consumer + def default_consumer(msg): """ the default consumer, prints the message to stdout (using 'print') """ sys.stderr.write(str(msg)+"\n") default_keywordmapper = KeywordMapper() + def setconsumer(keywords, consumer): default_keywordmapper.setconsumer(keywords, consumer) + def setstate(state): default_keywordmapper.setstate(state) + + def getstate(): return default_keywordmapper.getstate() @@ -122,11 +130,12 @@ def getstate(): # Consumers # + class File(object): """ log consumer wrapping a file(-like) object """ def __init__(self, f): assert hasattr(f, 'write') - #assert isinstance(f, file) or not hasattr(f, 'open') + # assert isinstance(f, file) or not hasattr(f, 'open') self._file = f def __call__(self, msg): @@ -135,6 +144,7 @@ def __call__(self, msg): if hasattr(self._file, 'flush'): self._file.flush() + class Path(object): """ log consumer that opens and writes to a Path """ def __init__(self, filename, append=False, @@ -158,29 +168,39 @@ def __call__(self, msg): if not self._buffering: self._file.flush() + def STDOUT(msg): """ consumer that writes to sys.stdout """ sys.stdout.write(str(msg)+"\n") + def STDERR(msg): """ consumer that writes to sys.stderr """ sys.stderr.write(str(msg)+"\n") + class Syslog: """ consumer that writes to the syslog daemon """ - def __init__(self, priority = None): + def __init__(self, priority=None): if priority is None: priority = self.LOG_INFO self.priority = priority def __call__(self, msg): """ write a message to the log """ - py.std.syslog.syslog(self.priority, str(msg)) - -for _prio in "EMERG ALERT CRIT ERR WARNING NOTICE INFO DEBUG".split(): - _prio = "LOG_" + _prio - try: - setattr(Syslog, _prio, getattr(py.std.syslog, _prio)) - except AttributeError: - pass + import syslog + syslog.syslog(self.priority, str(msg)) + + +try: + import syslog +except ImportError: + pass +else: + for _prio in "EMERG ALERT CRIT ERR WARNING NOTICE INFO DEBUG".split(): + _prio = "LOG_" + _prio + try: + setattr(Syslog, _prio, getattr(syslog, _prio)) + except AttributeError: + pass diff --git a/lib/ramble/external/py/_log/warning.py b/lib/ramble/external/py/_log/warning.py index 722e31e91..6ef20d98a 100644 --- a/lib/ramble/external/py/_log/warning.py +++ b/lib/ramble/external/py/_log/warning.py @@ -32,9 +32,11 @@ def _apiwarn(startversion, msg, stacklevel=2, function=None): msg = "%s (since version %s)" %(msg, startversion) warn(msg, stacklevel=stacklevel+1, function=function) + def warn(msg, stacklevel=1, function=None): if function is not None: - filename = py.std.inspect.getfile(function) + import inspect + filename = inspect.getfile(function) lineno = py.code.getrawcode(function).co_firstlineno else: try: @@ -67,10 +69,11 @@ def warn(msg, stacklevel=1, function=None): filename = module path = py.path.local(filename) warning = DeprecationWarning(msg, path, lineno) - py.std.warnings.warn_explicit(warning, category=Warning, + import warnings + warnings.warn_explicit(warning, category=Warning, filename=str(warning.path), lineno=warning.lineno, - registry=py.std.warnings.__dict__.setdefault( + registry=warnings.__dict__.setdefault( "__warningsregistry__", {}) ) diff --git a/lib/ramble/external/py/_path/common.py b/lib/ramble/external/py/_path/common.py index 5512e51ef..2364e5fef 100644 --- a/lib/ramble/external/py/_path/common.py +++ b/lib/ramble/external/py/_path/common.py @@ -1,12 +1,21 @@ """ """ -import os, sys, posixpath +import warnings +import os +import sys +import posixpath import fnmatch import py # Moved from local.py. iswin32 = sys.platform == "win32" or (getattr(os, '_name', False) == 'nt') +try: + # FileNotFoundError might happen in py34, and is not available with py27. + import_errors = (ImportError, FileNotFoundError) +except NameError: + import_errors = (ImportError,) + try: from os import fspath except ImportError: @@ -32,7 +41,7 @@ def fspath(path): raise try: import pathlib - except ImportError: + except import_errors: pass else: if isinstance(path, pathlib.PurePath): @@ -189,14 +198,16 @@ def load(self): """ (deprecated) return object unpickled from self.read() """ f = self.open('rb') try: - return py.error.checked_call(py.std.pickle.load, f) + import pickle + return py.error.checked_call(pickle.load, f) finally: f.close() def move(self, target): """ move this path to target. """ if target.relto(self): - raise py.error.EINVAL(target, + raise py.error.EINVAL( + target, "cannot move path into a subdirectory of itself") try: self.rename(target) @@ -226,7 +237,7 @@ def check(self, **kw): path.check(file=1, link=1) # a link pointing to a file """ if not kw: - kw = {'exists' : 1} + kw = {'exists': 1} return self.Checkers(self)._evaluate(kw) def fnmatch(self, pattern): @@ -375,6 +386,9 @@ def visit(self, fil=None, rec=None, ignore=NeverRaised, bf=False, sort=False): def _sortlist(self, res, sort): if sort: if hasattr(sort, '__call__'): + warnings.warn(DeprecationWarning( + "listdir(sort=callable) is deprecated and breaks on python3" + ), stacklevel=3) res.sort(sort) else: res.sort() diff --git a/lib/ramble/external/py/_path/local.py b/lib/ramble/external/py/_path/local.py index 2ffdaddf0..1385a0398 100644 --- a/lib/ramble/external/py/_path/local.py +++ b/lib/ramble/external/py/_path/local.py @@ -4,13 +4,13 @@ from __future__ import with_statement from contextlib import contextmanager -import sys, os, re, atexit, io +import sys, os, atexit, io, uuid import py from py._path import common from py._path.common import iswin32, fspath from stat import S_ISLNK, S_ISDIR, S_ISREG -from os.path import abspath, normcase, normpath, isabs, exists, isdir, isfile, islink, dirname +from os.path import abspath, normpath, isabs, exists, isdir, isfile, islink, dirname if sys.version_info > (3,0): def map_as_list(func, iter): @@ -18,6 +18,11 @@ def map_as_list(func, iter): else: map_as_list = map +ALLOW_IMPORTLIB_MODE = sys.version_info > (3,5) +if ALLOW_IMPORTLIB_MODE: + import importlib + + class Stat(object): def __getattr__(self, name): return getattr(self._osstatresult, "st_" + name) @@ -158,7 +163,10 @@ def __init__(self, path=None, expanduser=False): self.strpath = abspath(path) def __hash__(self): - return hash(self.strpath) + s = self.strpath + if iswin32: + s = s.lower() + return hash(s) def __eq__(self, other): s1 = fspath(self) @@ -191,8 +199,8 @@ def samefile(self, other): other = abspath(other) if self == other: return True - if iswin32: - return False # there is no samefile + if not hasattr(os.path, "samefile"): + return False return py.error.checked_call( os.path.samefile, self.strpath, other) @@ -206,7 +214,9 @@ def remove(self, rec=1, ignore_errors=False): # force remove of readonly files on windows if iswin32: self.chmod(0o700, rec=1) - py.error.checked_call(py.std.shutil.rmtree, self.strpath, + import shutil + py.error.checked_call( + shutil.rmtree, self.strpath, ignore_errors=ignore_errors) else: py.error.checked_call(os.rmdir, self.strpath) @@ -333,13 +343,16 @@ def join(self, *args, **kwargs): strargs = newargs break newargs.insert(0, arg) + # special case for when we have e.g. strpath == "/" + actual_sep = "" if strpath.endswith(sep) else sep for arg in strargs: arg = arg.strip(sep) if iswin32: # allow unix style paths even on windows. arg = arg.strip('/') arg = arg.replace('/', sep) - strpath = strpath + sep + arg + strpath = strpath + actual_sep + arg + actual_sep = sep obj = object.__new__(self.__class__) obj.strpath = normpath(strpath) return obj @@ -448,8 +461,9 @@ def rename(self, target): def dump(self, obj, bin=1): """ pickle object into path location""" f = self.open('wb') + import pickle try: - py.error.checked_call(py.std.pickle.dump, obj, f, bin) + py.error.checked_call(pickle.dump, obj, f, bin) finally: f.close() @@ -568,14 +582,17 @@ def chdir(self): @contextmanager def as_cwd(self): - """ return context manager which changes to current dir during the - managed "with" context. On __enter__ it returns the old dir. + """ + Return a context manager, which changes to the path's dir during the + managed "with" context. + On __enter__ it returns the old dir, which might be ``None``. """ old = self.chdir() try: yield old finally: - old.chdir() + if old is not None: + old.chdir() def realpath(self): """ return a new path which contains no symbolic links.""" @@ -641,10 +658,35 @@ def pyimport(self, modname=None, ensuresyspath=True): If ensuresyspath=="append" the root dir will be appended if it isn't already contained in sys.path. if ensuresyspath is False no modification of syspath happens. + + Special value of ensuresyspath=="importlib" is intended + purely for using in pytest, it is capable only of importing + separate .py files outside packages, e.g. for test suite + without any __init__.py file. It effectively allows having + same-named test modules in different places and offers + mild opt-in via this option. Note that it works only in + recent versions of python. """ if not self.check(): raise py.error.ENOENT(self) + if ensuresyspath == 'importlib': + if modname is None: + modname = self.purebasename + if not ALLOW_IMPORTLIB_MODE: + raise ImportError( + "Can't use importlib due to old version of Python") + spec = importlib.util.spec_from_file_location( + modname, str(self)) + if spec is None: + raise ImportError( + "Can't find module %s at location %s" % + (modname, str(self)) + ) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod + pkgpath = None if modname is None: pkgpath = self.pypkgpath() @@ -663,7 +705,7 @@ def pyimport(self, modname=None, ensuresyspath=True): mod = sys.modules[modname] if self.basename == "__init__.py": return mod # we don't check anything as we might - # we in a namespace package ... too icky to check + # be in a namespace package ... too icky to check modfile = mod.__file__ if modfile[-4:] in ('.pyc', '.pyo'): modfile = modfile[:-1] @@ -677,14 +719,17 @@ def pyimport(self, modname=None, ensuresyspath=True): except py.error.ENOENT: issame = False if not issame: - raise self.ImportMismatchError(modname, modfile, self) + ignore = os.getenv('PY_IGNORE_IMPORTMISMATCH') + if ignore != '1': + raise self.ImportMismatchError(modname, modfile, self) return mod else: try: return sys.modules[modname] except KeyError: # we have a custom modname, do a pseudo-import - mod = py.std.types.ModuleType(modname) + import types + mod = types.ModuleType(modname) mod.__file__ = str(self) sys.modules[modname] = mod try: @@ -729,7 +774,7 @@ def sysfind(cls, name, checker=None, paths=None): else: if paths is None: if iswin32: - paths = py.std.os.environ['Path'].split(';') + paths = os.environ['Path'].split(';') if '' not in paths and '.' not in paths: paths.append('.') try: @@ -737,10 +782,10 @@ def sysfind(cls, name, checker=None, paths=None): except KeyError: pass else: - paths = [re.sub('%SystemRoot%', systemroot, path) + paths = [path.replace('%SystemRoot%', systemroot) for path in paths] else: - paths = py.std.os.environ['PATH'].split(':') + paths = os.environ['PATH'].split(':') tryadd = [] if iswin32: tryadd += os.environ['PATHEXT'].split(os.pathsep) @@ -771,16 +816,18 @@ def _gethomedir(cls): return cls(x) _gethomedir = classmethod(_gethomedir) - #""" - #special class constructors for local filesystem paths - #""" + # """ + # special class constructors for local filesystem paths + # """ + @classmethod def get_temproot(cls): """ return the system's temporary directory (where tempfiles are usually created in) """ - return py.path.local(py.std.tempfile.gettempdir()) - get_temproot = classmethod(get_temproot) + import tempfile + return py.path.local(tempfile.gettempdir()) + @classmethod def mkdtemp(cls, rootdir=None): """ return a Path object pointing to a fresh new temporary directory (which we created ourself). @@ -789,59 +836,43 @@ def mkdtemp(cls, rootdir=None): if rootdir is None: rootdir = cls.get_temproot() return cls(py.error.checked_call(tempfile.mkdtemp, dir=str(rootdir))) - mkdtemp = classmethod(mkdtemp) def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3, - lock_timeout = 172800): # two days + lock_timeout=172800): # two days """ return unique directory with a number greater than the current maximum one. The number is assumed to start directly after prefix. if keep is true directories with a number less than (maxnum-keep) - will be removed. + will be removed. If .lock files are used (lock_timeout non-zero), + algorithm is multi-process safe. """ if rootdir is None: rootdir = cls.get_temproot() - nprefix = normcase(prefix) + nprefix = prefix.lower() def parse_num(path): """ parse the number out of a path (if it matches the prefix) """ - nbasename = normcase(path.basename) + nbasename = path.basename.lower() if nbasename.startswith(nprefix): try: return int(nbasename[len(nprefix):]) except ValueError: pass - # compute the maximum number currently in use with the - # prefix - lastmax = None - while True: - maxnum = -1 - for path in rootdir.listdir(): - num = parse_num(path) - if num is not None: - maxnum = max(maxnum, num) - - # make the new directory - try: - udir = rootdir.mkdir(prefix + str(maxnum+1)) - except py.error.EEXIST: - # race condition: another thread/process created the dir - # in the meantime. Try counting again - if lastmax == maxnum: - raise - lastmax = maxnum - continue - break - - # put a .lock file in the new directory that will be removed at - # process exit - if lock_timeout: - lockfile = udir.join('.lock') + def create_lockfile(path): + """ exclusively create lockfile. Throws when failed """ mypid = os.getpid() + lockfile = path.join('.lock') if hasattr(lockfile, 'mksymlinkto'): lockfile.mksymlinkto(str(mypid)) else: - lockfile.write(str(mypid)) + fd = py.error.checked_call(os.open, str(lockfile), os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644) + with os.fdopen(fd, 'w') as f: + f.write(str(mypid)) + return lockfile + + def atexit_remove_lockfile(lockfile): + """ ensure lockfile is removed at process exit """ + mypid = os.getpid() def try_remove_lockfile(): # in a fork() situation, only the last process should # remove the .lock, otherwise the other processes run the @@ -856,19 +887,82 @@ def try_remove_lockfile(): pass atexit.register(try_remove_lockfile) + # compute the maximum number currently in use with the prefix + lastmax = None + while True: + maxnum = -1 + for path in rootdir.listdir(): + num = parse_num(path) + if num is not None: + maxnum = max(maxnum, num) + + # make the new directory + try: + udir = rootdir.mkdir(prefix + str(maxnum+1)) + if lock_timeout: + lockfile = create_lockfile(udir) + atexit_remove_lockfile(lockfile) + except (py.error.EEXIST, py.error.ENOENT, py.error.EBUSY): + # race condition (1): another thread/process created the dir + # in the meantime - try again + # race condition (2): another thread/process spuriously acquired + # lock treating empty directory as candidate + # for removal - try again + # race condition (3): another thread/process tried to create the lock at + # the same time (happened in Python 3.3 on Windows) + # https://ci.appveyor.com/project/pytestbot/py/build/1.0.21/job/ffi85j4c0lqwsfwa + if lastmax == maxnum: + raise + lastmax = maxnum + continue + break + + def get_mtime(path): + """ read file modification time """ + try: + return path.lstat().mtime + except py.error.Error: + pass + + garbage_prefix = prefix + 'garbage-' + + def is_garbage(path): + """ check if path denotes directory scheduled for removal """ + bn = path.basename + return bn.startswith(garbage_prefix) + # prune old directories - if keep: + udir_time = get_mtime(udir) + if keep and udir_time: for path in rootdir.listdir(): num = parse_num(path) if num is not None and num <= (maxnum - keep): - lf = path.join('.lock') try: - t1 = lf.lstat().mtime - t2 = lockfile.lstat().mtime - if not lock_timeout or abs(t2-t1) < lock_timeout: - continue # skip directories still locked - except py.error.Error: - pass # assume that it means that there is no 'lf' + # try acquiring lock to remove directory as exclusive user + if lock_timeout: + create_lockfile(path) + except (py.error.EEXIST, py.error.ENOENT, py.error.EBUSY): + path_time = get_mtime(path) + if not path_time: + # assume directory doesn't exist now + continue + if abs(udir_time - path_time) < lock_timeout: + # assume directory with lockfile exists + # and lock timeout hasn't expired yet + continue + + # path dir locked for exclusive use + # and scheduled for removal to avoid another thread/process + # treating it as a new directory or removal candidate + garbage_path = rootdir.join(garbage_prefix + str(uuid.uuid4())) + try: + path.rename(garbage_path) + garbage_path.remove(rec=1) + except KeyboardInterrupt: + raise + except: # this might be py.error.Error, WindowsError ... + pass + if is_garbage(path): try: path.remove(rec=1) except KeyboardInterrupt: @@ -902,14 +996,19 @@ def try_remove_lockfile(): def copymode(src, dest): """ copy permission from src to dst. """ - py.std.shutil.copymode(src, dest) + import shutil + shutil.copymode(src, dest) + def copystat(src, dest): - """ copy permission, last modification time, last access time, and flags from src to dst.""" - py.std.shutil.copystat(str(src), str(dest)) + """ copy permission, last modification time, + last access time, and flags from src to dst.""" + import shutil + shutil.copystat(str(src), str(dest)) + def copychunked(src, dest): - chunksize = 524288 # half a meg of bytes + chunksize = 524288 # half a meg of bytes fsrc = src.open('rb') try: fdest = dest.open('wb') @@ -924,6 +1023,7 @@ def copychunked(src, dest): finally: fsrc.close() + def isimportable(name): if name and (name[0].isalpha() or name[0] == '_'): name = name.replace("_", '') diff --git a/lib/ramble/external/py/_path/svnwc.py b/lib/ramble/external/py/_path/svnwc.py index 992223c04..b5b9d8d54 100644 --- a/lib/ramble/external/py/_path/svnwc.py +++ b/lib/ramble/external/py/_path/svnwc.py @@ -94,7 +94,7 @@ def _getsvnversion(ver=[]): def _escape_helper(text): text = str(text) - if py.std.sys.platform != 'win32': + if sys.platform != 'win32': text = str(text).replace('$', '\\$') return text @@ -354,7 +354,7 @@ def path_to_fspath(path, addat=True): def url_from_path(path): fspath = path_to_fspath(path, False) - quote = py.std.urllib.quote + from urllib import quote if ISWINDOWS: match = _reg_allow_disk.match(fspath) fspath = fspath.replace('\\', '/') @@ -396,7 +396,7 @@ def makecmdoptions(self): def __str__(self): return "" %(self.username,) -rex_blame = re.compile(r'\s*(\d+)\s*(\S+) (.*)') +rex_blame = re.compile(r'\s*(\d+)\s+(\S+) (.*)') class SvnWCCommandPath(common.PathBase): """ path implementation offering access/modification to svn working copies. @@ -504,7 +504,7 @@ def checkout(self, url=None, rev=None): if url is None: url = self.url if rev is None or rev == -1: - if (py.std.sys.platform != 'win32' and + if (sys.platform != 'win32' and _getsvnversion() == '1.3'): url += "@HEAD" else: @@ -785,7 +785,7 @@ def info(self, usecache=1): info = InfoSvnWCCommand(output) # Can't reliably compare on Windows without access to win32api - if py.std.sys.platform != 'win32': + if sys.platform != 'win32': if info.path != self.localpath: raise py.error.ENOENT(self, "not a versioned resource:" + " %s != %s" % (info.path, self.localpath)) diff --git a/lib/ramble/external/py/_std.py b/lib/ramble/external/py/_std.py index 97a985332..66adb7b02 100644 --- a/lib/ramble/external/py/_std.py +++ b/lib/ramble/external/py/_std.py @@ -1,4 +1,10 @@ import sys +import warnings + + +class PyStdIsDeprecatedWarning(DeprecationWarning): + pass + class Std(object): """ makes top-level python modules available as an attribute, @@ -9,6 +15,9 @@ def __init__(self): self.__dict__ = sys.modules def __getattr__(self, name): + warnings.warn("py.std is deprecated, please import %s directly" % name, + category=PyStdIsDeprecatedWarning, + stacklevel=2) try: m = __import__(name) except ImportError: diff --git a/lib/ramble/external/py/_vendored_packages/__init__.py b/lib/ramble/external/py/_vendored_packages/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/INSTALLER b/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/INSTALLER new file mode 100644 index 000000000..a1b589e38 --- /dev/null +++ b/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/LICENSE b/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/LICENSE new file mode 100644 index 000000000..ff33b8f7c --- /dev/null +++ b/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/LICENSE @@ -0,0 +1,18 @@ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. diff --git a/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/METADATA b/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/METADATA new file mode 100644 index 000000000..7eea770a0 --- /dev/null +++ b/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/METADATA @@ -0,0 +1,125 @@ +Metadata-Version: 2.1 +Name: apipkg +Version: 2.0.0 +Summary: apipkg: namespace control and lazy-import mechanism +Home-page: https://github.com/pytest-dev/apipkg +Author: holger krekel +Maintainer: Ronny Pfannschmidt +Maintainer-email: opensource@ronnypfannschmidt.de +License: MIT +Platform: unix +Platform: linux +Platform: osx +Platform: cygwin +Platform: win32 +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: POSIX +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Topic :: Software Development :: Libraries +Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7 +Description-Content-Type: text/x-rst +License-File: LICENSE + +Welcome to apipkg ! +------------------- + +With apipkg you can control the exported namespace of a Python package and +greatly reduce the number of imports for your users. +It is a `small pure Python module`_ that works on CPython 2.7 and 3.4+, +Jython and PyPy. It cooperates well with Python's ``help()`` system, +custom importers (PEP302) and common command-line completion tools. + +Usage is very simple: you can require 'apipkg' as a dependency or you +can copy paste the ~200 lines of code into your project. + + +Tutorial example +------------------- + +Here is a simple ``mypkg`` package that specifies one namespace +and exports two objects imported from different modules:: + + + # mypkg/__init__.py + import apipkg + apipkg.initpkg(__name__, { + 'path': { + 'Class1': "_mypkg.somemodule:Class1", + 'clsattr': "_mypkg.othermodule:Class2.attr", + } + } + +The package is initialized with a dictionary as namespace. + +You need to create a ``_mypkg`` package with a ``somemodule.py`` +and ``othermodule.py`` containing the respective classes. +The ``_mypkg`` is not special - it's a completely +regular Python package. + +Namespace dictionaries contain ``name: value`` mappings +where the value may be another namespace dictionary or +a string specifying an import location. On accessing +an namespace attribute an import will be performed:: + + >>> import mypkg + >>> mypkg.path + + >>> mypkg.path.Class1 # '_mypkg.somemodule' gets imported now + + >>> mypkg.path.clsattr # '_mypkg.othermodule' gets imported now + 4 # the value of _mypkg.othermodule.Class2.attr + +The ``mypkg.path`` namespace and its two entries are +loaded when they are accessed. This means: + +* lazy loading - only what is actually needed is ever loaded + +* only the root "mypkg" ever needs to be imported to get + access to the complete functionality + +* the underlying modules are also accessible, for example:: + + from mypkg.sub import Class1 + + +Including apipkg in your package +-------------------------------------- + +If you don't want to add an ``apipkg`` dependency to your package you +can copy the `apipkg.py`_ file somewhere to your own package, +for example ``_mypkg/apipkg.py`` in the above example. You +then import the ``initpkg`` function from that new place and +are good to go. + +.. _`small pure Python module`: +.. _`apipkg.py`: https://github.com/pytest-dev/apipkg/blob/master/src/apipkg/__init__.py + +Feedback? +----------------------- + +If you have questions you are welcome to + +* join the **#pytest** channel on irc.libera.chat_ + (using an IRC client, via webchat_, or via Matrix_). +* create an issue on the bugtracker_ + +.. _irc.libera.chat: ircs://irc.libera.chat:6697/#pytest +.. _webchat: https://web.libera.chat/#pytest +.. _matrix: https://matrix.to/#/%23pytest:libera.chat +.. _bugtracker: https://github.com/pytest-dev/apipkg/issues + + diff --git a/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/RECORD b/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/RECORD new file mode 100644 index 000000000..357b8b9c7 --- /dev/null +++ b/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/RECORD @@ -0,0 +1,11 @@ +apipkg-2.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +apipkg-2.0.0.dist-info/LICENSE,sha256=6J7tEHTTqUMZi6E5uAhE9bRFuGC7p0qK6twGEFZhZOo,1054 +apipkg-2.0.0.dist-info/METADATA,sha256=GqNwkxraK5UTxObLVXTLc2UqktOPwZnKqdk2ThzHX0A,4292 +apipkg-2.0.0.dist-info/RECORD,, +apipkg-2.0.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +apipkg-2.0.0.dist-info/WHEEL,sha256=WzZ8cwjh8l0jtULNjYq1Hpr-WCqCRgPr--TX4P5I1Wo,110 +apipkg-2.0.0.dist-info/top_level.txt,sha256=3TGS6nmN7kjxhUK4LpPCB3QkQI34QYGrT0ZQGWajoZ8,7 +apipkg/__init__.py,sha256=gpbD3O57S9f-LsO2e-XwI6IGISayicfnCq3B5y_8frg,6978 +apipkg/__pycache__/__init__.cpython-39.pyc,, +apipkg/__pycache__/version.cpython-39.pyc,, +apipkg/version.py,sha256=bgZFg-f3UKhgE-z2w8RoFrwqRBzJBZkM4_jKFiYB9eU,142 diff --git a/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/REQUESTED b/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/REQUESTED new file mode 100644 index 000000000..e69de29bb diff --git a/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/WHEEL b/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/WHEEL new file mode 100644 index 000000000..b733a60d3 --- /dev/null +++ b/lib/ramble/external/py/_vendored_packages/apipkg-2.0.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/lib/ramble/external/py/_apipkg.py b/lib/ramble/external/py/_vendored_packages/apipkg/__init__.py similarity index 55% rename from lib/ramble/external/py/_apipkg.py rename to lib/ramble/external/py/_vendored_packages/apipkg/__init__.py index a73b8f6d0..350d8c4b0 100644 --- a/lib/ramble/external/py/_apipkg.py +++ b/lib/ramble/external/py/_vendored_packages/apipkg/__init__.py @@ -1,7 +1,7 @@ """ -apipkg: control the exported namespace of a python package. +apipkg: control the exported namespace of a Python package. -see http://pypi.python.org/pypi/apipkg +see https://pypi.python.org/pypi/apipkg (c) holger krekel, 2009 - MIT license """ @@ -9,43 +9,70 @@ import sys from types import ModuleType -__version__ = '1.3.dev' +from .version import version as __version__ # NOQA:F401 + def _py_abspath(path): """ special version of abspath that will leave paths from jython jars alone """ - if path.startswith('__pyclasspath__'): + if path.startswith("__pyclasspath__"): return path else: return os.path.abspath(path) -def initpkg(pkgname, exportdefs, attr=dict()): + +def distribution_version(name): + """try to get the version of the named distribution, + returs None on failure""" + from pkg_resources import get_distribution, DistributionNotFound + + try: + dist = get_distribution(name) + except DistributionNotFound: + pass + else: + return dist.version + + +def initpkg(pkgname, exportdefs, attr=None, eager=False): """ initialize given package from the export definitions. """ + attr = attr or {} oldmod = sys.modules.get(pkgname) d = {} - f = getattr(oldmod, '__file__', None) + f = getattr(oldmod, "__file__", None) if f: f = _py_abspath(f) - d['__file__'] = f - if hasattr(oldmod, '__version__'): - d['__version__'] = oldmod.__version__ - if hasattr(oldmod, '__loader__'): - d['__loader__'] = oldmod.__loader__ - if hasattr(oldmod, '__path__'): - d['__path__'] = [_py_abspath(p) for p in oldmod.__path__] - if '__doc__' not in exportdefs and getattr(oldmod, '__doc__', None): - d['__doc__'] = oldmod.__doc__ + d["__file__"] = f + if hasattr(oldmod, "__version__"): + d["__version__"] = oldmod.__version__ + if hasattr(oldmod, "__loader__"): + d["__loader__"] = oldmod.__loader__ + if hasattr(oldmod, "__path__"): + d["__path__"] = [_py_abspath(p) for p in oldmod.__path__] + if hasattr(oldmod, "__package__"): + d["__package__"] = oldmod.__package__ + if "__doc__" not in exportdefs and getattr(oldmod, "__doc__", None): + d["__doc__"] = oldmod.__doc__ + d["__spec__"] = getattr(oldmod, "__spec__", None) d.update(attr) if hasattr(oldmod, "__dict__"): oldmod.__dict__.update(d) mod = ApiModule(pkgname, exportdefs, implprefix=pkgname, attr=d) sys.modules[pkgname] = mod + # eagerload in bypthon to avoid their monkeypatching breaking packages + if "bpython" in sys.modules or eager: + for module in list(sys.modules.values()): + if isinstance(module, ApiModule): + module.__dict__ + return mod + def importobj(modpath, attrname): - module = __import__(modpath, None, None, ['__doc__']) + """imports a module, then resolves the attrname on it""" + module = __import__(modpath, None, None, ["__doc__"]) if not attrname: return module @@ -55,20 +82,25 @@ def importobj(modpath, attrname): retval = getattr(retval, x) return retval + class ApiModule(ModuleType): + """the magical lazy-loading module standing""" + def __docget(self): try: return self.__doc except AttributeError: - if '__doc__' in self.__map__: - return self.__makeattr('__doc__') + if "__doc__" in self.__map__: + return self.__makeattr("__doc__") + def __docset(self, value): self.__doc = value + __doc__ = property(__docget, __docset) def __init__(self, name, importspec, implprefix=None, attr=None): self.__name__ = name - self.__all__ = [x for x in importspec if x != '__onfirstaccess__'] + self.__all__ = [x for x in importspec if x != "__onfirstaccess__"] self.__map__ = {} self.__implprefix__ = implprefix or name if attr: @@ -77,47 +109,47 @@ def __init__(self, name, importspec, implprefix=None, attr=None): setattr(self, name, val) for name, importspec in importspec.items(): if isinstance(importspec, dict): - subname = '%s.%s' % (self.__name__, name) + subname = "{}.{}".format(self.__name__, name) apimod = ApiModule(subname, importspec, implprefix) sys.modules[subname] = apimod setattr(self, name, apimod) else: - parts = importspec.split(':') + parts = importspec.split(":") modpath = parts.pop(0) attrname = parts and parts[0] or "" - if modpath[0] == '.': + if modpath[0] == ".": modpath = implprefix + modpath if not attrname: - subname = '%s.%s' % (self.__name__, name) + subname = "{}.{}".format(self.__name__, name) apimod = AliasModule(subname, modpath) sys.modules[subname] = apimod - if '.' not in name: + if "." not in name: setattr(self, name, apimod) else: self.__map__[name] = (modpath, attrname) def __repr__(self): - l = [] - if hasattr(self, '__version__'): - l.append("version=" + repr(self.__version__)) - if hasattr(self, '__file__'): - l.append('from ' + repr(self.__file__)) - if l: - return '' % (self.__name__, " ".join(l)) - return '' % (self.__name__,) + repr_list = [] + if hasattr(self, "__version__"): + repr_list.append("version=" + repr(self.__version__)) + if hasattr(self, "__file__"): + repr_list.append("from " + repr(self.__file__)) + if repr_list: + return "".format(self.__name__, " ".join(repr_list)) + return "".format(self.__name__) def __makeattr(self, name): """lazily compute value for name or raise AttributeError if unknown.""" # print "makeattr", self.__name__, name target = None - if '__onfirstaccess__' in self.__map__: - target = self.__map__.pop('__onfirstaccess__') + if "__onfirstaccess__" in self.__map__: + target = self.__map__.pop("__onfirstaccess__") importobj(*target)() try: modpath, attrname = self.__map__[name] except KeyError: - if target is not None and name != '__onfirstaccess__': + if target is not None and name != "__onfirstaccess__": # retry, onfirstaccess might have set attrs return getattr(self, name) raise AttributeError(name) @@ -132,19 +164,20 @@ def __makeattr(self, name): __getattr__ = __makeattr + @property def __dict__(self): - # force all the content of the module to be loaded when __dict__ is read - dictdescr = ModuleType.__dict__['__dict__'] + # force all the content of the module + # to be loaded when __dict__ is read + dictdescr = ModuleType.__dict__["__dict__"] dict = dictdescr.__get__(self) if dict is not None: - hasattr(self, 'some') + hasattr(self, "some") for name in self.__all__: try: self.__makeattr(name) except AttributeError: pass return dict - __dict__ = property(__dict__) def AliasModule(modname, modpath, attrname=None): @@ -158,19 +191,22 @@ def getmod(): mod.append(x) return mod[0] - class AliasModule(ModuleType): + x = modpath + ("." + attrname if attrname else "") + repr_result = "".format(modname, x) + class AliasModule(ModuleType): def __repr__(self): - x = modpath - if attrname: - x += "." + attrname - return '' % (modname, x) + return repr_result def __getattribute__(self, name): try: return getattr(getmod(), name) except ImportError: - return None + if modpath == "pytest" and attrname is None: + # hack for pylibs py.test + return None + else: + raise def __setattr__(self, name, value): setattr(getmod(), name, value) diff --git a/lib/ramble/external/py/_vendored_packages/apipkg/version.py b/lib/ramble/external/py/_vendored_packages/apipkg/version.py new file mode 100644 index 000000000..c5b4e0e79 --- /dev/null +++ b/lib/ramble/external/py/_vendored_packages/apipkg/version.py @@ -0,0 +1,5 @@ +# coding: utf-8 +# file generated by setuptools_scm +# don't change, don't track in version control +version = '2.0.0' +version_tuple = (2, 0, 0) diff --git a/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/INSTALLER b/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/INSTALLER new file mode 100644 index 000000000..a1b589e38 --- /dev/null +++ b/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/LICENSE b/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/LICENSE new file mode 100644 index 000000000..31ecdfb1d --- /dev/null +++ b/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/LICENSE @@ -0,0 +1,19 @@ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + diff --git a/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/METADATA b/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/METADATA new file mode 100644 index 000000000..c078a7532 --- /dev/null +++ b/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/METADATA @@ -0,0 +1,78 @@ +Metadata-Version: 2.1 +Name: iniconfig +Version: 1.1.1 +Summary: iniconfig: brain-dead simple config-ini parsing +Home-page: http://github.com/RonnyPfannschmidt/iniconfig +Author: Ronny Pfannschmidt, Holger Krekel +Author-email: opensource@ronnypfannschmidt.de, holger.krekel@gmail.com +License: MIT License +Platform: unix +Platform: linux +Platform: osx +Platform: cygwin +Platform: win32 +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: POSIX +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Topic :: Software Development :: Libraries +Classifier: Topic :: Utilities +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 + +iniconfig: brain-dead simple parsing of ini files +======================================================= + +iniconfig is a small and simple INI-file parser module +having a unique set of features: + +* tested against Python2.4 across to Python3.2, Jython, PyPy +* maintains order of sections and entries +* supports multi-line values with or without line-continuations +* supports "#" comments everywhere +* raises errors with proper line-numbers +* no bells and whistles like automatic substitutions +* iniconfig raises an Error if two sections have the same name. + +If you encounter issues or have feature wishes please report them to: + + http://github.com/RonnyPfannschmidt/iniconfig/issues + +Basic Example +=================================== + +If you have an ini file like this:: + + # content of example.ini + [section1] # comment + name1=value1 # comment + name1b=value1,value2 # comment + + [section2] + name2= + line1 + line2 + +then you can do:: + + >>> import iniconfig + >>> ini = iniconfig.IniConfig("example.ini") + >>> ini['section1']['name1'] # raises KeyError if not exists + 'value1' + >>> ini.get('section1', 'name1b', [], lambda x: x.split(",")) + ['value1', 'value2'] + >>> ini.get('section1', 'notexist', [], lambda x: x.split(",")) + [] + >>> [x.name for x in list(ini)] + ['section1', 'section2'] + >>> list(list(ini)[0].items()) + [('name1', 'value1'), ('name1b', 'value1,value2')] + >>> 'section1' in ini + True + >>> 'inexistendsection' in ini + False + + diff --git a/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/RECORD b/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/RECORD new file mode 100644 index 000000000..168233330 --- /dev/null +++ b/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/RECORD @@ -0,0 +1,11 @@ +iniconfig-1.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +iniconfig-1.1.1.dist-info/LICENSE,sha256=KvaAw570k_uCgwNW0dPfGstaBgM8ui3sehniHKp3qGY,1061 +iniconfig-1.1.1.dist-info/METADATA,sha256=_4-oFKpRXuZv5rzepScpXRwhq6DzqsgbnA5ZpgMUMcs,2405 +iniconfig-1.1.1.dist-info/RECORD,, +iniconfig-1.1.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +iniconfig-1.1.1.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110 +iniconfig-1.1.1.dist-info/top_level.txt,sha256=7KfM0fugdlToj9UW7enKXk2HYALQD8qHiyKtjhSzgN8,10 +iniconfig/__init__.py,sha256=-pBe5AF_6aAwo1CxJQ8i_zJq6ejc6IxHta7qk2tNJhY,5208 +iniconfig/__init__.pyi,sha256=-4KOctzq28ohRmTZsqlH6aylyFqsNKxYqtk1dteypi4,1205 +iniconfig/__pycache__/__init__.cpython-39.pyc,, +iniconfig/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/REQUESTED b/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/REQUESTED new file mode 100644 index 000000000..e69de29bb diff --git a/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/WHEEL b/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/WHEEL new file mode 100644 index 000000000..6d38aa060 --- /dev/null +++ b/lib/ramble/external/py/_vendored_packages/iniconfig-1.1.1.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.35.1) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/lib/ramble/external/py/_iniconfig.py b/lib/ramble/external/py/_vendored_packages/iniconfig/__init__.py similarity index 92% rename from lib/ramble/external/py/_iniconfig.py rename to lib/ramble/external/py/_vendored_packages/iniconfig/__init__.py index 92b50bd85..6ad9eaf86 100644 --- a/lib/ramble/external/py/_iniconfig.py +++ b/lib/ramble/external/py/_vendored_packages/iniconfig/__init__.py @@ -1,12 +1,11 @@ """ brain-dead simple parser for ini-style files. (C) Ronny Pfannschmidt, Holger Krekel -- MIT licensed """ -__version__ = "0.2.dev2" - __all__ = ['IniConfig', 'ParseError'] COMMENTCHARS = "#;" + class ParseError(Exception): def __init__(self, path, lineno, msg): Exception.__init__(self, path, lineno, msg) @@ -15,7 +14,8 @@ def __init__(self, path, lineno, msg): self.msg = msg def __str__(self): - return "%s:%s: %s" %(self.path, self.lineno+1, self.msg) + return "%s:%s: %s" % (self.path, self.lineno+1, self.msg) + class SectionWrapper(object): def __init__(self, config, name): @@ -26,13 +26,15 @@ def lineof(self, name): return self.config.lineof(self.name, name) def get(self, key, default=None, convert=str): - return self.config.get(self.name, key, convert=convert, default=default) + return self.config.get(self.name, key, + convert=convert, default=default) def __getitem__(self, key): return self.config.sections[self.name][key] def __iter__(self): section = self.config.sections.get(self.name, []) + def lineof(key): return self.config.lineof(self.name, key) for name in sorted(section, key=lineof): @@ -45,7 +47,7 @@ def items(self): class IniConfig(object): def __init__(self, path, data=None): - self.path = str(path) # convenience + self.path = str(path) # convenience if data is None: f = open(self.path) try: @@ -64,11 +66,11 @@ def __init__(self, path, data=None): self._sources[section, name] = lineno if name is None: if section in self.sections: - self._raise(lineno, 'duplicate section %r'%(section, )) + self._raise(lineno, 'duplicate section %r' % (section, )) self.sections[section] = {} else: if name in self.sections[section]: - self._raise(lineno, 'duplicate name %r'%(name, )) + self._raise(lineno, 'duplicate name %r' % (name, )) self.sections[section][name] = value def _raise(self, lineno, msg): @@ -157,6 +159,7 @@ def __iter__(self): def __contains__(self, arg): return arg in self.sections + def iscommentline(line): c = line.lstrip()[:1] return c in COMMENTCHARS diff --git a/lib/ramble/external/py/_vendored_packages/iniconfig/__init__.pyi b/lib/ramble/external/py/_vendored_packages/iniconfig/__init__.pyi new file mode 100644 index 000000000..b6284bec3 --- /dev/null +++ b/lib/ramble/external/py/_vendored_packages/iniconfig/__init__.pyi @@ -0,0 +1,31 @@ +from typing import Callable, Iterator, Mapping, Optional, Tuple, TypeVar, Union +from typing_extensions import Final + +_D = TypeVar('_D') +_T = TypeVar('_T') + +class ParseError(Exception): + # Private __init__. + path: Final[str] + lineno: Final[int] + msg: Final[str] + +class SectionWrapper: + # Private __init__. + config: Final[IniConfig] + name: Final[str] + def __getitem__(self, key: str) -> str: ... + def __iter__(self) -> Iterator[str]: ... + def get(self, key: str, default: _D = ..., convert: Callable[[str], _T] = ...) -> Union[_T, _D]: ... + def items(self) -> Iterator[Tuple[str, str]]: ... + def lineof(self, name: str) -> Optional[int]: ... + +class IniConfig: + path: Final[str] + sections: Final[Mapping[str, Mapping[str, str]]] + def __init__(self, path: str, data: Optional[str] = None): ... + def __contains__(self, arg: str) -> bool: ... + def __getitem__(self, name: str) -> SectionWrapper: ... + def __iter__(self) -> Iterator[SectionWrapper]: ... + def get(self, section: str, name: str, default: _D = ..., convert: Callable[[str], _T] = ...) -> Union[_T, _D]: ... + def lineof(self, section: str, name: Optional[str] = ...) -> Optional[int]: ... diff --git a/lib/ramble/external/py/_vendored_packages/iniconfig/py.typed b/lib/ramble/external/py/_vendored_packages/iniconfig/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/lib/ramble/external/py/error.pyi b/lib/ramble/external/py/error.pyi new file mode 100644 index 000000000..034eba609 --- /dev/null +++ b/lib/ramble/external/py/error.pyi @@ -0,0 +1,129 @@ +from typing import Any, Callable, TypeVar + +_T = TypeVar('_T') + +def checked_call(func: Callable[..., _T], *args: Any, **kwargs: Any) -> _T: ... +class Error(EnvironmentError): ... +class EPERM(Error): ... +class ENOENT(Error): ... +class ESRCH(Error): ... +class EINTR(Error): ... +class EIO(Error): ... +class ENXIO(Error): ... +class E2BIG(Error): ... +class ENOEXEC(Error): ... +class EBADF(Error): ... +class ECHILD(Error): ... +class EAGAIN(Error): ... +class ENOMEM(Error): ... +class EACCES(Error): ... +class EFAULT(Error): ... +class ENOTBLK(Error): ... +class EBUSY(Error): ... +class EEXIST(Error): ... +class EXDEV(Error): ... +class ENODEV(Error): ... +class ENOTDIR(Error): ... +class EISDIR(Error): ... +class EINVAL(Error): ... +class ENFILE(Error): ... +class EMFILE(Error): ... +class ENOTTY(Error): ... +class ETXTBSY(Error): ... +class EFBIG(Error): ... +class ENOSPC(Error): ... +class ESPIPE(Error): ... +class EROFS(Error): ... +class EMLINK(Error): ... +class EPIPE(Error): ... +class EDOM(Error): ... +class ERANGE(Error): ... +class EDEADLCK(Error): ... +class ENAMETOOLONG(Error): ... +class ENOLCK(Error): ... +class ENOSYS(Error): ... +class ENOTEMPTY(Error): ... +class ELOOP(Error): ... +class EWOULDBLOCK(Error): ... +class ENOMSG(Error): ... +class EIDRM(Error): ... +class ECHRNG(Error): ... +class EL2NSYNC(Error): ... +class EL3HLT(Error): ... +class EL3RST(Error): ... +class ELNRNG(Error): ... +class EUNATCH(Error): ... +class ENOCSI(Error): ... +class EL2HLT(Error): ... +class EBADE(Error): ... +class EBADR(Error): ... +class EXFULL(Error): ... +class ENOANO(Error): ... +class EBADRQC(Error): ... +class EBADSLT(Error): ... +class EDEADLOCK(Error): ... +class EBFONT(Error): ... +class ENOSTR(Error): ... +class ENODATA(Error): ... +class ETIME(Error): ... +class ENOSR(Error): ... +class ENONET(Error): ... +class ENOPKG(Error): ... +class EREMOTE(Error): ... +class ENOLINK(Error): ... +class EADV(Error): ... +class ESRMNT(Error): ... +class ECOMM(Error): ... +class EPROTO(Error): ... +class EMULTIHOP(Error): ... +class EDOTDOT(Error): ... +class EBADMSG(Error): ... +class EOVERFLOW(Error): ... +class ENOTUNIQ(Error): ... +class EBADFD(Error): ... +class EREMCHG(Error): ... +class ELIBACC(Error): ... +class ELIBBAD(Error): ... +class ELIBSCN(Error): ... +class ELIBMAX(Error): ... +class ELIBEXEC(Error): ... +class EILSEQ(Error): ... +class ERESTART(Error): ... +class ESTRPIPE(Error): ... +class EUSERS(Error): ... +class ENOTSOCK(Error): ... +class EDESTADDRREQ(Error): ... +class EMSGSIZE(Error): ... +class EPROTOTYPE(Error): ... +class ENOPROTOOPT(Error): ... +class EPROTONOSUPPORT(Error): ... +class ESOCKTNOSUPPORT(Error): ... +class ENOTSUP(Error): ... +class EOPNOTSUPP(Error): ... +class EPFNOSUPPORT(Error): ... +class EAFNOSUPPORT(Error): ... +class EADDRINUSE(Error): ... +class EADDRNOTAVAIL(Error): ... +class ENETDOWN(Error): ... +class ENETUNREACH(Error): ... +class ENETRESET(Error): ... +class ECONNABORTED(Error): ... +class ECONNRESET(Error): ... +class ENOBUFS(Error): ... +class EISCONN(Error): ... +class ENOTCONN(Error): ... +class ESHUTDOWN(Error): ... +class ETOOMANYREFS(Error): ... +class ETIMEDOUT(Error): ... +class ECONNREFUSED(Error): ... +class EHOSTDOWN(Error): ... +class EHOSTUNREACH(Error): ... +class EALREADY(Error): ... +class EINPROGRESS(Error): ... +class ESTALE(Error): ... +class EUCLEAN(Error): ... +class ENOTNAM(Error): ... +class ENAVAIL(Error): ... +class EISNAM(Error): ... +class EREMOTEIO(Error): ... +class EDQUOT(Error): ... diff --git a/lib/ramble/external/py/iniconfig.pyi b/lib/ramble/external/py/iniconfig.pyi new file mode 100644 index 000000000..b6284bec3 --- /dev/null +++ b/lib/ramble/external/py/iniconfig.pyi @@ -0,0 +1,31 @@ +from typing import Callable, Iterator, Mapping, Optional, Tuple, TypeVar, Union +from typing_extensions import Final + +_D = TypeVar('_D') +_T = TypeVar('_T') + +class ParseError(Exception): + # Private __init__. + path: Final[str] + lineno: Final[int] + msg: Final[str] + +class SectionWrapper: + # Private __init__. + config: Final[IniConfig] + name: Final[str] + def __getitem__(self, key: str) -> str: ... + def __iter__(self) -> Iterator[str]: ... + def get(self, key: str, default: _D = ..., convert: Callable[[str], _T] = ...) -> Union[_T, _D]: ... + def items(self) -> Iterator[Tuple[str, str]]: ... + def lineof(self, name: str) -> Optional[int]: ... + +class IniConfig: + path: Final[str] + sections: Final[Mapping[str, Mapping[str, str]]] + def __init__(self, path: str, data: Optional[str] = None): ... + def __contains__(self, arg: str) -> bool: ... + def __getitem__(self, name: str) -> SectionWrapper: ... + def __iter__(self) -> Iterator[SectionWrapper]: ... + def get(self, section: str, name: str, default: _D = ..., convert: Callable[[str], _T] = ...) -> Union[_T, _D]: ... + def lineof(self, section: str, name: Optional[str] = ...) -> Optional[int]: ... diff --git a/lib/ramble/external/py/io.pyi b/lib/ramble/external/py/io.pyi new file mode 100644 index 000000000..d377e2405 --- /dev/null +++ b/lib/ramble/external/py/io.pyi @@ -0,0 +1,130 @@ +from io import StringIO as TextIO +from io import BytesIO as BytesIO +from typing import Any, AnyStr, Callable, Generic, IO, List, Optional, Text, Tuple, TypeVar, Union, overload +from typing_extensions import Final +import sys + +_T = TypeVar("_T") + +class FDCapture(Generic[AnyStr]): + def __init__(self, targetfd: int, tmpfile: Optional[IO[AnyStr]] = ..., now: bool = ..., patchsys: bool = ...) -> None: ... + def start(self) -> None: ... + def done(self) -> IO[AnyStr]: ... + def writeorg(self, data: AnyStr) -> None: ... + +class StdCaptureFD: + def __init__( + self, + out: Union[bool, IO[str]] = ..., + err: Union[bool, IO[str]] = ..., + mixed: bool = ..., + in_: bool = ..., + patchsys: bool = ..., + now: bool = ..., + ) -> None: ... + @classmethod + def call(cls, func: Callable[..., _T], *args: Any, **kwargs: Any) -> Tuple[_T, str, str]: ... + def reset(self) -> Tuple[str, str]: ... + def suspend(self) -> Tuple[str, str]: ... + def startall(self) -> None: ... + def resume(self) -> None: ... + def done(self, save: bool = ...) -> Tuple[IO[str], IO[str]]: ... + def readouterr(self) -> Tuple[str, str]: ... + +class StdCapture: + def __init__( + self, + out: Union[bool, IO[str]] = ..., + err: Union[bool, IO[str]] = ..., + in_: bool = ..., + mixed: bool = ..., + now: bool = ..., + ) -> None: ... + @classmethod + def call(cls, func: Callable[..., _T], *args: Any, **kwargs: Any) -> Tuple[_T, str, str]: ... + def reset(self) -> Tuple[str, str]: ... + def suspend(self) -> Tuple[str, str]: ... + def startall(self) -> None: ... + def resume(self) -> None: ... + def done(self, save: bool = ...) -> Tuple[IO[str], IO[str]]: ... + def readouterr(self) -> Tuple[IO[str], IO[str]]: ... + +# XXX: The type here is not exactly right. If f is IO[bytes] and +# encoding is not None, returns some weird hybrid, not exactly IO[bytes]. +def dupfile( + f: IO[AnyStr], + mode: Optional[str] = ..., + buffering: int = ..., + raising: bool = ..., + encoding: Optional[str] = ..., +) -> IO[AnyStr]: ... +def get_terminal_width() -> int: ... +def ansi_print( + text: Union[str, Text], + esc: Union[Union[str, Text], Tuple[Union[str, Text], ...]], + file: Optional[IO[Any]] = ..., + newline: bool = ..., + flush: bool = ..., +) -> None: ... +def saferepr(obj, maxsize: int = ...) -> str: ... + +class TerminalWriter: + stringio: TextIO + encoding: Final[str] + hasmarkup: bool + def __init__(self, file: Optional[IO[str]] = ..., stringio: bool = ..., encoding: Optional[str] = ...) -> None: ... + @property + def fullwidth(self) -> int: ... + @fullwidth.setter + def fullwidth(self, value: int) -> None: ... + @property + def chars_on_current_line(self) -> int: ... + @property + def width_of_current_line(self) -> int: ... + def markup( + self, + text: str, + *, + black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ..., + cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ..., + Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ..., + blink: int = ..., invert: int = ..., + ) -> str: ... + def sep( + self, + sepchar: str, + title: Optional[str] = ..., + fullwidth: Optional[int] = ..., + *, + black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ..., + cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ..., + Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ..., + blink: int = ..., invert: int = ..., + ) -> None: ... + def write( + self, + msg: str, + *, + black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ..., + cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ..., + Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ..., + blink: int = ..., invert: int = ..., + ) -> None: ... + def line( + self, + s: str = ..., + *, + black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ..., + cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ..., + Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ..., + blink: int = ..., invert: int = ..., + ) -> None: ... + def reline( + self, + line: str, + *, + black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ..., + cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ..., + Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ..., + blink: int = ..., invert: int = ..., + ) -> None: ... diff --git a/lib/ramble/external/py/path.pyi b/lib/ramble/external/py/path.pyi new file mode 100644 index 000000000..1ddab9601 --- /dev/null +++ b/lib/ramble/external/py/path.pyi @@ -0,0 +1,197 @@ +from typing import Any, AnyStr, Callable, ContextManager, Generic, IO, Iterable, Iterator, List, Optional, Text, Type, Union +from typing_extensions import Final, Literal +import os +import sys + +class _FNMatcher(Generic[AnyStr]): + pattern: AnyStr = ... + def __init__(self, pattern: AnyStr) -> None: ... + def __call__(self, path: local) -> bool: ... + +class _Stat: + path: Final[local] = ... + mode: Final[int] + ino: Final[int] + dev: Final[int] + nlink: Final[int] + uid: Final[int] + gid: Final[int] + size: Final[int] + atime: Final[float] + mtime: Final[float] + ctime: Final[float] + atime_ns: Final[int] + mtime_ns: Final[int] + ctime_ns: Final[int] + if sys.version_info >= (3, 8) and sys.platform == "win32": + reparse_tag: Final[int] + blocks: Final[int] + blksize: Final[int] + rdev: Final[int] + flags: Final[int] + gen: Final[int] + birthtime: Final[int] + rsize: Final[int] + creator: Final[int] + type: Final[int] + if sys.platform != 'win32': + @property + def owner(self) -> str: ... + @property + def group(self) -> str: ... + def isdir(self) -> bool: ... + def isfile(self) -> bool: ... + def islink(self) -> bool: ... + + +if sys.version_info >= (3, 6): + _PathLike = os.PathLike +else: + class _PathLike(Generic[AnyStr]): + def __fspath__(self) -> AnyStr: ... +_PathType = Union[bytes, Text, _PathLike[str], _PathLike[bytes], local] + +class local(_PathLike[str]): + class ImportMismatchError(ImportError): ... + + sep: Final[str] + strpath: Final[str] + + def __init__(self, path: _PathType = ..., expanduser: bool = ...) -> None: ... + def __hash__(self) -> int: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... + def __lt__(self, other: object) -> bool: ... + def __gt__(self, other: object) -> bool: ... + def __add__(self, other: object) -> local: ... + def __cmp__(self, other: object) -> int: ... + def __div__(self, other: _PathType) -> local: ... + def __truediv__(self, other: _PathType) -> local: ... + def __fspath__(self) -> str: ... + + @classmethod + def get_temproot(cls) -> local: ... + @classmethod + def make_numbered_dir( + cls, + prefix: str = ..., + rootdir: Optional[local] = ..., + keep: Optional[int] = ..., + lock_timeout: int = ..., + ) -> local: ... + @classmethod + def mkdtemp(cls, rootdir: Optional[local] = ...) -> local: ... + @classmethod + def sysfind( + cls, + name: _PathType, + checker: Optional[Callable[[local], bool]] = ..., + paths: Optional[Iterable[_PathType]] = ..., + ) -> Optional[local]: ... + + @property + def basename(self) -> str: ... + @property + def dirname(self) -> str: ... + @property + def purebasename(self) -> str: ... + @property + def ext(self) -> str: ... + + def as_cwd(self) -> ContextManager[Optional[local]]: ... + def atime(self) -> float: ... + def bestrelpath(self, dest: local) -> str: ... + def chdir(self) -> local: ... + def check( + self, + *, + basename: int = ..., notbasename: int = ..., + basestarts: int = ..., notbasestarts: int = ..., + dir: int = ..., notdir: int = ..., + dotfile: int = ..., notdotfile: int = ..., + endswith: int = ..., notendswith: int = ..., + exists: int = ..., notexists: int = ..., + ext: int = ..., notext: int = ..., + file: int = ..., notfile: int = ..., + fnmatch: int = ..., notfnmatch: int = ..., + link: int = ..., notlink: int = ..., + relto: int = ..., notrelto: int = ..., + ) -> bool: ... + def chmod(self, mode: int, rec: Union[int, str, Text, Callable[[local], bool]] = ...) -> None: ... + if sys.platform != 'win32': + def chown(self, user: Union[int, str], group: Union[int, str], rec: int = ...) -> None: ... + def common(self, other: local) -> Optional[local]: ... + def computehash(self, hashtype: str = ..., chunksize: int = ...) -> str: ... + def copy(self, target: local, mode: bool = ..., stat: bool = ...) -> None: ... + def dirpath(self, *args: _PathType, abs: int = ...) -> local: ... + def dump(self, obj: Any, bin: Optional[int] = ...) -> None: ... + def ensure(self, *args: _PathType, dir: int = ...) -> local: ... + def ensure_dir(self, *args: _PathType) -> local: ... + def exists(self) -> bool: ... + def fnmatch(self, pattern: str): _FNMatcher + def isdir(self) -> bool: ... + def isfile(self) -> bool: ... + def islink(self) -> bool: ... + def join(self, *args: _PathType, abs: int = ...) -> local: ... + def listdir( + self, + fil: Optional[Union[str, Text, Callable[[local], bool]]] = ..., + sort: Optional[bool] = ..., + ) -> List[local]: ... + def load(self) -> Any: ... + def lstat(self) -> _Stat: ... + def mkdir(self, *args: _PathType) -> local: ... + if sys.platform != 'win32': + def mklinkto(self, oldname: Union[str, local]) -> None: ... + def mksymlinkto(self, value: local, absolute: int = ...) -> None: ... + def move(self, target: local) -> None: ... + def mtime(self) -> float: ... + def new( + self, + *, + drive: str = ..., + dirname: str = ..., + basename: str = ..., + purebasename: str = ..., + ext: str = ..., + ) -> local: ... + def open(self, mode: str = ..., ensure: bool = ..., encoding: Optional[str] = ...) -> IO[Any]: ... + def parts(self, reverse: bool = ...) -> List[local]: ... + def pyimport( + self, + modname: Optional[str] = ..., + ensuresyspath: Union[bool, Literal["append", "importlib"]] = ..., + ) -> Any: ... + def pypkgpath(self) -> Optional[local]: ... + def read(self, mode: str = ...) -> Union[Text, bytes]: ... + def read_binary(self) -> bytes: ... + def read_text(self, encoding: str) -> Text: ... + def readlines(self, cr: int = ...) -> List[str]: ... + if sys.platform != 'win32': + def readlink(self) -> str: ... + def realpath(self) -> local: ... + def relto(self, relpath: Union[str, local]) -> str: ... + def remove(self, rec: int = ..., ignore_errors: bool = ...) -> None: ... + def rename(self, target: _PathType) -> None: ... + def samefile(self, other: _PathType) -> bool: ... + def setmtime(self, mtime: Optional[float] = ...) -> None: ... + def size(self) -> int: ... + def stat(self, raising: bool = ...) -> _Stat: ... + def sysexec(self, *argv: Any, **popen_opts: Any) -> Text: ... + def visit( + self, + fil: Optional[Union[str, Text, Callable[[local], bool]]] = ..., + rec: Optional[Union[Literal[1, True], str, Text, Callable[[local], bool]]] = ..., + ignore: Type[Exception] = ..., + bf: bool = ..., + sort: bool = ..., + ) -> Iterator[local]: ... + def write(self, data: Any, mode: str = ..., ensure: bool = ...) -> None: ... + def write_binary(self, data: bytes, ensure: bool = ...) -> None: ... + def write_text(self, data: Union[str, Text], encoding: str, ensure: bool = ...) -> None: ... + + +# Untyped types below here. +svnwc: Any +svnurl: Any +SvnAuth: Any diff --git a/lib/ramble/external/py/py.typed b/lib/ramble/external/py/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/lib/ramble/external/py/xml.pyi b/lib/ramble/external/py/xml.pyi new file mode 100644 index 000000000..9c44480a5 --- /dev/null +++ b/lib/ramble/external/py/xml.pyi @@ -0,0 +1,25 @@ +from typing import ClassVar, Generic, Iterable, Text, Type, Union +from typing_extensions import Final + +class raw: + uniobj: Final[Text] + def __init__(self, uniobj: Text) -> None: ... + +class _NamespaceMetaclass(type): + def __getattr__(self, name: str) -> Type[Tag]: ... + +class Namespace(metaclass=_NamespaceMetaclass): ... + +class Tag(list): + class Attr: + def __getattr__(self, attr: str) -> Text: ... + attr: Final[Attr] + def __init__(self, *args: Union[Text, raw, Tag, Iterable[Tag]], **kwargs: Union[Text, raw]) -> None: ... + def unicode(self, indent: int = ...) -> Text: ... + +class html(Namespace): + class Style: + def __init__(self, **kw: Union[str, Text]) -> None: ... + style: ClassVar[Style] + +def escape(ustring: Union[str, Text]) -> Text: ... diff --git a/lib/ramble/llnl/util/tty/__init__.py b/lib/ramble/llnl/util/tty/__init__.py index 893819699..6cadcc3a3 100644 --- a/lib/ramble/llnl/util/tty/__init__.py +++ b/lib/ramble/llnl/util/tty/__init__.py @@ -19,7 +19,6 @@ import six from six import StringIO -from six.moves import input if _platform != "win32": import fcntl @@ -295,7 +294,6 @@ def get_number(prompt, **kwargs): number = None while number is None: msg(prompt, newline=False) - ans = input() if ans == six.text_type(abort): return None @@ -328,7 +326,6 @@ def get_yes_or_no(prompt, **kwargs): result = None while result is None: msg(prompt, newline=False) - ans = input().lower() if not ans: result = default_value if result is None: diff --git a/lib/ramble/ramble/fetch_strategy.py b/lib/ramble/ramble/fetch_strategy.py index 23ac6855b..0098ccc69 100644 --- a/lib/ramble/ramble/fetch_strategy.py +++ b/lib/ramble/ramble/fetch_strategy.py @@ -35,7 +35,7 @@ import llnl.util.tty as tty import six -import six.moves.urllib.parse as urllib_parse +import urllib.parse import spack.error import spack.util.crypto as crypto import spack.util.pattern as pattern @@ -311,7 +311,7 @@ def candidate_urls(self): # This must be skipped on Windows due to URL encoding # of ':' characters on filepaths on Windows if sys.platform != "win32" and url.startswith("file://"): - path = urllib_parse.quote(url[len("file://") :]) + path = urllib.parse.quote(url[len("file://") :]) url = "file://" + path urls.append(url) @@ -1652,7 +1652,7 @@ def from_url_scheme(url, *args, **kwargs): in the given url.""" url = kwargs.get("url", url) - parsed_url = urllib_parse.urlparse(url, scheme="file") + parsed_url = urllib.parse.urlparse(url, scheme="file") scheme_mapping = kwargs.get("scheme_mapping") or { "file": "url", diff --git a/lib/ramble/ramble/util/web.py b/lib/ramble/ramble/util/web.py index f19cfb543..4b60ceec1 100644 --- a/lib/ramble/ramble/util/web.py +++ b/lib/ramble/ramble/util/web.py @@ -20,8 +20,8 @@ import traceback import six -from six.moves.urllib.error import URLError -from six.moves.urllib.request import Request, urlopen +from urllib.error import URLError +from urllib.request import Request, urlopen import llnl.util.lang from llnl.util.filesystem import mkdirp, rename diff --git a/lib/ramble/spack/fetch_strategy.py b/lib/ramble/spack/fetch_strategy.py index 378209308..abc089b69 100644 --- a/lib/ramble/spack/fetch_strategy.py +++ b/lib/ramble/spack/fetch_strategy.py @@ -32,7 +32,7 @@ from typing import List, Optional # novm import six -import six.moves.urllib.parse as urllib_parse +import urllib.parse import llnl.util import llnl.util.tty as tty @@ -308,7 +308,7 @@ def candidate_urls(self): # This must be skipped on Windows due to URL encoding # of ':' characters on filepaths on Windows if sys.platform != "win32" and url.startswith('file://'): - path = urllib_parse.quote(url[len('file://'):]) + path = urllib.parse.quote(url[len('file://'):]) url = 'file://' + path urls.append(url) @@ -1650,7 +1650,7 @@ def from_url_scheme(url, *args, **kwargs): in the given url.""" url = kwargs.get('url', url) - parsed_url = urllib_parse.urlparse(url, scheme='file') + parsed_url = urllib.parse.urlparse(url, scheme='file') scheme_mapping = ( kwargs.get('scheme_mapping') or diff --git a/lib/ramble/spack/gcs_handler.py b/lib/ramble/spack/gcs_handler.py index de35511ce..83fbdc07d 100644 --- a/lib/ramble/spack/gcs_handler.py +++ b/lib/ramble/spack/gcs_handler.py @@ -3,7 +3,7 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) -import six.moves.urllib.response as urllib_response +import urllib.response import spack.util.url as url_util import spack.util.web as web_util @@ -23,4 +23,4 @@ def gcs_open(req, *args, **kwargs): stream = gcsblob.get_blob_byte_stream() headers = gcsblob.get_blob_headers() - return urllib_response.addinfourl(stream, headers, url) + return urllib.response.addinfourl(stream, headers, url) diff --git a/lib/ramble/spack/url.py b/lib/ramble/spack/url.py index 8ad7b196a..cef2a90eb 100644 --- a/lib/ramble/spack/url.py +++ b/lib/ramble/spack/url.py @@ -29,7 +29,7 @@ import re from six import StringIO -from six.moves.urllib.parse import urlsplit, urlunsplit +from urllib.parse import urlsplit, urlunsplit import llnl.util.tty as tty from llnl.util.tty.color import cescape, colorize diff --git a/lib/ramble/spack/util/environment.py b/lib/ramble/spack/util/environment.py index c2870c17b..fc0de53b9 100644 --- a/lib/ramble/spack/util/environment.py +++ b/lib/ramble/spack/util/environment.py @@ -9,13 +9,13 @@ import json import os import os.path +import pickle import platform import re import socket import sys import six -from six.moves import cPickle import llnl.util.tty as tty from llnl.util.lang import dedupe @@ -170,7 +170,7 @@ def dump_environment(path, environment=None): @system_path_filter(arg_slice=slice(1)) def pickle_environment(path, environment=None): """Pickle an environment dictionary to a file.""" - cPickle.dump(dict(environment if environment else os.environ), + pickle.dump(dict(environment if environment else os.environ), open(path, 'wb'), protocol=2) diff --git a/lib/ramble/spack/util/path.py b/lib/ramble/spack/util/path.py index cd14cb433..a8135b2b0 100644 --- a/lib/ramble/spack/util/path.py +++ b/lib/ramble/spack/util/path.py @@ -15,7 +15,7 @@ import sys import tempfile -from six.moves.urllib.parse import urlparse +from urllib.parse import urlparse import llnl.util.tty as tty from llnl.util.lang import memoized diff --git a/lib/ramble/spack/util/s3.py b/lib/ramble/spack/util/s3.py index b52a879e2..c1ac80b43 100644 --- a/lib/ramble/spack/util/s3.py +++ b/lib/ramble/spack/util/s3.py @@ -5,7 +5,7 @@ import os -import six.moves.urllib.parse as urllib_parse +import urllib.parse import spack import spack.util.url as url_util @@ -21,7 +21,7 @@ def get_mirror_connection(url, url_type="push"): def _parse_s3_endpoint_url(endpoint_url): - if not urllib_parse.urlparse(endpoint_url, scheme='').scheme: + if not urllib.parse.urlparse(endpoint_url, scheme='').scheme: endpoint_url = '://'.join(('https', endpoint_url)) return endpoint_url diff --git a/lib/ramble/spack/util/url.py b/lib/ramble/spack/util/url.py index 824b5fed5..fd1a38ea8 100644 --- a/lib/ramble/spack/util/url.py +++ b/lib/ramble/spack/util/url.py @@ -12,7 +12,7 @@ import re import sys -import six.moves.urllib.parse as urllib_parse +import urllib.parse from six import string_types from spack.util.path import ( @@ -79,7 +79,7 @@ def parse(url, scheme='file'): require_url_format(url) url = escape_file_url(url) url_obj = ( - urllib_parse.urlparse(url, scheme=scheme, allow_fragments=False) + urllib.parse.urlparse(url, scheme=scheme, allow_fragments=False) if isinstance(url, string_types) else url) (scheme, netloc, path, params, query, _) = url_obj @@ -106,7 +106,7 @@ def parse(url, scheme='file'): if sys.platform == "win32": path = convert_to_posix_path(path) - return urllib_parse.ParseResult(scheme=scheme, + return urllib.parse.ParseResult(scheme=scheme, netloc=netloc, path=path, params=params, @@ -189,7 +189,7 @@ def join(base_url, path, *extra, **kwargs): last_abs_component = None scheme = '' for i in range(n - 1, -1, -1): - obj = urllib_parse.urlparse( + obj = urllib.parse.urlparse( paths[i], scheme='', allow_fragments=False) scheme = obj.scheme @@ -200,7 +200,7 @@ def join(base_url, path, *extra, **kwargs): # Without a scheme, we have to go back looking for the # next-last component that specifies a scheme. for j in range(i - 1, -1, -1): - obj = urllib_parse.urlparse( + obj = urllib.parse.urlparse( paths[j], scheme='', allow_fragments=False) if obj.scheme: @@ -218,14 +218,14 @@ def join(base_url, path, *extra, **kwargs): if last_abs_component is not None: paths = paths[last_abs_component:] if len(paths) == 1: - result = urllib_parse.urlparse( + result = urllib.parse.urlparse( paths[0], scheme='file', allow_fragments=False) # another subtlety: If the last argument to join() is an absolute # file:// URL component with a relative path, the relative path # needs to be resolved. if result.scheme == 'file' and result.netloc: - result = urllib_parse.ParseResult( + result = urllib.parse.ParseResult( scheme=result.scheme, netloc='', path=posixpath.abspath(result.netloc + result.path), @@ -281,7 +281,7 @@ def _join(base_url, path, *extra, **kwargs): if sys.platform == "win32": base_path = convert_to_posix_path(base_path) - return format(urllib_parse.ParseResult(scheme=scheme, + return format(urllib.parse.ParseResult(scheme=scheme, netloc=netloc, path=base_path, params=params, diff --git a/lib/ramble/spack/util/web.py b/lib/ramble/spack/util/web.py index 4bd0d9258..5ef35d6f2 100644 --- a/lib/ramble/spack/util/web.py +++ b/lib/ramble/spack/util/web.py @@ -17,8 +17,8 @@ import traceback import six -from six.moves.urllib.error import URLError -from six.moves.urllib.request import Request, urlopen +from urllib.error import URLError +from urllib.request import Request, urlopen import llnl.util.lang import llnl.util.tty as tty