diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-06-15 14:18:22 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-06-15 14:27:16 +0300 |
commit | b52a8ab5cd66952839ada0843539b5564108a052 (patch) | |
tree | 659c3387aee1dbb2629b3afd68f8d306d37b45c2 | |
parent | 7d673060f61f85b3e440fa45df26795d3653c8d2 (diff) | |
download | ydb-b52a8ab5cd66952839ada0843539b5564108a052.tar.gz |
Intermediate changes
43 files changed, 403 insertions, 180 deletions
diff --git a/contrib/python/fonttools/.dist-info/METADATA b/contrib/python/fonttools/.dist-info/METADATA index fa68def0d1..832b0598ab 100644 --- a/contrib/python/fonttools/.dist-info/METADATA +++ b/contrib/python/fonttools/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: fonttools -Version: 4.52.4 +Version: 4.53.0 Summary: Tools to manipulate font files Home-page: http://github.com/fonttools/fonttools Author: Just van Rossum @@ -375,6 +375,16 @@ Have fun! Changelog ~~~~~~~~~ +4.53.0 (released 2024-05-31) +---------------------------- + +- [ttLib.removeOverlaps] Support CFF table to aid in downconverting CFF2 fonts (#3528) +- [avar] Fix crash when accessing not-yet-existing attribute (#3550) +- [docs] Add buildMathTable to otlLib.builder documentation (#3540) +- [feaLib] Allow UTF-8 with BOM when reading features (#3495) +- [SVGPathPen] Revert rounding coordinates to two decimal places by default (#3543) +- [varLib.instancer] Refix output filename decision-making (#3545, #3544, #3548) + 4.52.4 (released 2024-05-27) ---------------------------- diff --git a/contrib/python/fonttools/fontTools/__init__.py b/contrib/python/fonttools/fontTools/__init__.py index 68138485de..0de5c155e3 100644 --- a/contrib/python/fonttools/fontTools/__init__.py +++ b/contrib/python/fonttools/fontTools/__init__.py @@ -3,6 +3,6 @@ from fontTools.misc.loggingTools import configLogger log = logging.getLogger(__name__) -version = __version__ = "4.52.4" +version = __version__ = "4.53.0" __all__ = ["version", "log", "configLogger"] diff --git a/contrib/python/fonttools/fontTools/feaLib/lexer.py b/contrib/python/fonttools/fontTools/feaLib/lexer.py index 5867f70b38..4b6499d06f 100644 --- a/contrib/python/fonttools/fontTools/feaLib/lexer.py +++ b/contrib/python/fonttools/fontTools/feaLib/lexer.py @@ -269,7 +269,7 @@ class IncludingLexer(object): fileobj, closing = file_or_path, False else: filename, closing = file_or_path, True - fileobj = open(filename, "r", encoding="utf-8") + fileobj = open(filename, "r", encoding="utf-8-sig") data = fileobj.read() filename = getattr(fileobj, "name", None) if closing: diff --git a/contrib/python/fonttools/fontTools/pens/svgPathPen.py b/contrib/python/fonttools/fontTools/pens/svgPathPen.py index 8231603f8a..29d41a8029 100644 --- a/contrib/python/fonttools/fontTools/pens/svgPathPen.py +++ b/contrib/python/fonttools/fontTools/pens/svgPathPen.py @@ -2,7 +2,7 @@ from typing import Callable from fontTools.pens.basePen import BasePen -def pointToString(pt, ntos): +def pointToString(pt, ntos=str): return " ".join(ntos(i) for i in pt) @@ -37,13 +37,7 @@ class SVGPathPen(BasePen): print(tpen.getCommands()) """ - def __init__( - self, - glyphSet, - ntos: Callable[[float], str] = ( - lambda x: ("%.2f" % x) if x != int(x) else str(int(x)) - ), - ): + def __init__(self, glyphSet, ntos: Callable[[float], str] = str): BasePen.__init__(self, glyphSet) self._commands = [] self._lastCommand = None diff --git a/contrib/python/fonttools/fontTools/ttLib/removeOverlaps.py b/contrib/python/fonttools/fontTools/ttLib/removeOverlaps.py index ea13d4734b..312b56b294 100644 --- a/contrib/python/fonttools/fontTools/ttLib/removeOverlaps.py +++ b/contrib/python/fonttools/fontTools/ttLib/removeOverlaps.py @@ -7,11 +7,14 @@ import itertools import logging from typing import Callable, Iterable, Optional, Mapping -from fontTools.misc.roundTools import otRound +from fontTools.cffLib import CFFFontSet from fontTools.ttLib import ttFont from fontTools.ttLib.tables import _g_l_y_f from fontTools.ttLib.tables import _h_m_t_x +from fontTools.misc.psCharStrings import T2CharString +from fontTools.misc.roundTools import otRound, noRound from fontTools.pens.ttGlyphPen import TTGlyphPen +from fontTools.pens.t2CharStringPen import T2CharStringPen import pathops @@ -81,6 +84,14 @@ def ttfGlyphFromSkPath(path: pathops.Path) -> _g_l_y_f.Glyph: return glyph +def _charString_from_SkPath( + path: pathops.Path, charString: T2CharString +) -> T2CharString: + t2Pen = T2CharStringPen(width=charString.width, glyphSet=None) + path.draw(t2Pen) + return t2Pen.getCharString(charString.private, charString.globalSubrs) + + def _round_path( path: pathops.Path, round: Callable[[float], float] = otRound ) -> pathops.Path: @@ -90,7 +101,12 @@ def _round_path( return rounded_path -def _simplify(path: pathops.Path, debugGlyphName: str) -> pathops.Path: +def _simplify( + path: pathops.Path, + debugGlyphName: str, + *, + round: Callable[[float], float] = otRound, +) -> pathops.Path: # skia-pathops has a bug where it sometimes fails to simplify paths when there # are float coordinates and control points are very close to one another. # Rounding coordinates to integers works around the bug. @@ -105,7 +121,7 @@ def _simplify(path: pathops.Path, debugGlyphName: str) -> pathops.Path: except pathops.PathOpsError: pass - path = _round_path(path) + path = _round_path(path, round=round) try: path = pathops.simplify(path, clockwise=path.clockwise) log.debug( @@ -124,6 +140,10 @@ def _simplify(path: pathops.Path, debugGlyphName: str) -> pathops.Path: raise AssertionError("Unreachable") +def _same_path(path1: pathops.Path, path2: pathops.Path) -> bool: + return {tuple(c) for c in path1.contours} == {tuple(c) for c in path2.contours} + + def removeTTGlyphOverlaps( glyphName: str, glyphSet: _TTGlyphMapping, @@ -144,7 +164,7 @@ def removeTTGlyphOverlaps( path2 = _simplify(path, glyphName) # replace TTGlyph if simplified path is different (ignoring contour order) - if {tuple(c) for c in path.contours} != {tuple(c) for c in path2.contours}: + if not _same_path(path, path2): glyfTable[glyphName] = glyph = ttfGlyphFromSkPath(path2) # simplified glyph is always unhinted assert not glyph.program @@ -159,42 +179,16 @@ def removeTTGlyphOverlaps( return False -def removeOverlaps( +def _remove_glyf_overlaps( + *, font: ttFont.TTFont, - glyphNames: Optional[Iterable[str]] = None, - removeHinting: bool = True, - ignoreErrors=False, + glyphNames: Iterable[str], + glyphSet: _TTGlyphMapping, + removeHinting: bool, + ignoreErrors: bool, ) -> None: - """Simplify glyphs in TTFont by merging overlapping contours. - - Overlapping components are first decomposed to simple contours, then merged. - - Currently this only works with TrueType fonts with 'glyf' table. - Raises NotImplementedError if 'glyf' table is absent. - - Note that removing overlaps invalidates the hinting. By default we drop hinting - from all glyphs whether or not overlaps are removed from a given one, as it would - look weird if only some glyphs are left (un)hinted. - - Args: - font: input TTFont object, modified in place. - glyphNames: optional iterable of glyph names (str) to remove overlaps from. - By default, all glyphs in the font are processed. - removeHinting (bool): set to False to keep hinting for unmodified glyphs. - ignoreErrors (bool): set to True to ignore errors while removing overlaps, - thus keeping the tricky glyphs unchanged (fonttools/fonttools#2363). - """ - try: - glyfTable = font["glyf"] - except KeyError: - raise NotImplementedError("removeOverlaps currently only works with TTFs") - + glyfTable = font["glyf"] hmtxTable = font["hmtx"] - # wraps the underlying glyf Glyphs, takes care of interfacing with drawing pens - glyphSet = font.getGlyphSet() - - if glyphNames is None: - glyphNames = font.getGlyphOrder() # process all simple glyphs first, then composites with increasing component depth, # so that by the time we test for component intersections the respective base glyphs @@ -225,27 +219,170 @@ def removeOverlaps( log.debug("Removed overlaps for %s glyphs:\n%s", len(modified), " ".join(modified)) -def main(args=None): - """Simplify glyphs in TTFont by merging overlapping contours.""" +def _remove_charstring_overlaps( + *, + glyphName: str, + glyphSet: _TTGlyphMapping, + cffFontSet: CFFFontSet, +) -> bool: + path = skPathFromGlyph(glyphName, glyphSet) + + # remove overlaps + path2 = _simplify(path, glyphName, round=noRound) + + # replace TTGlyph if simplified path is different (ignoring contour order) + if not _same_path(path, path2): + charStrings = cffFontSet[0].CharStrings + charStrings[glyphName] = _charString_from_SkPath(path2, charStrings[glyphName]) + return True - import sys + return False - if args is None: - args = sys.argv[1:] - if len(args) < 2: - print( - f"usage: fonttools ttLib.removeOverlaps INPUT.ttf OUTPUT.ttf [GLYPHS ...]" +def _remove_cff_overlaps( + *, + font: ttFont.TTFont, + glyphNames: Iterable[str], + glyphSet: _TTGlyphMapping, + removeHinting: bool, + ignoreErrors: bool, + removeUnusedSubroutines: bool = True, +) -> None: + cffFontSet = font["CFF "].cff + modified = set() + for glyphName in glyphNames: + try: + if _remove_charstring_overlaps( + glyphName=glyphName, + glyphSet=glyphSet, + cffFontSet=cffFontSet, + ): + modified.add(glyphName) + except RemoveOverlapsError: + if not ignoreErrors: + raise + log.error("Failed to remove overlaps for '%s'", glyphName) + + if not modified: + log.debug("No overlaps found in the specified CFF glyphs") + return + + if removeHinting: + cffFontSet.remove_hints() + + if removeUnusedSubroutines: + cffFontSet.remove_unused_subroutines() + + log.debug("Removed overlaps for %s glyphs:\n%s", len(modified), " ".join(modified)) + + +def removeOverlaps( + font: ttFont.TTFont, + glyphNames: Optional[Iterable[str]] = None, + removeHinting: bool = True, + ignoreErrors: bool = False, + *, + removeUnusedSubroutines: bool = True, +) -> None: + """Simplify glyphs in TTFont by merging overlapping contours. + + Overlapping components are first decomposed to simple contours, then merged. + + Currently this only works for fonts with 'glyf' or 'CFF ' tables. + Raises NotImplementedError if 'glyf' or 'CFF ' tables are absent. + + Note that removing overlaps invalidates the hinting. By default we drop hinting + from all glyphs whether or not overlaps are removed from a given one, as it would + look weird if only some glyphs are left (un)hinted. + + Args: + font: input TTFont object, modified in place. + glyphNames: optional iterable of glyph names (str) to remove overlaps from. + By default, all glyphs in the font are processed. + removeHinting (bool): set to False to keep hinting for unmodified glyphs. + ignoreErrors (bool): set to True to ignore errors while removing overlaps, + thus keeping the tricky glyphs unchanged (fonttools/fonttools#2363). + removeUnusedSubroutines (bool): set to False to keep unused subroutines + in CFF table after removing overlaps. Default is to remove them if + any glyphs are modified. + """ + + if "glyf" not in font and "CFF " not in font: + raise NotImplementedError( + "No outline data found in the font: missing 'glyf' or 'CFF ' table" ) - sys.exit(1) - src = args[0] - dst = args[1] - glyphNames = args[2:] or None + if glyphNames is None: + glyphNames = font.getGlyphOrder() + + # Wraps the underlying glyphs, takes care of interfacing with drawing pens + glyphSet = font.getGlyphSet() + + if "glyf" in font: + _remove_glyf_overlaps( + font=font, + glyphNames=glyphNames, + glyphSet=glyphSet, + removeHinting=removeHinting, + ignoreErrors=ignoreErrors, + ) + + if "CFF " in font: + _remove_cff_overlaps( + font=font, + glyphNames=glyphNames, + glyphSet=glyphSet, + removeHinting=removeHinting, + ignoreErrors=ignoreErrors, + removeUnusedSubroutines=removeUnusedSubroutines, + ) - with ttFont.TTFont(src) as f: - removeOverlaps(f, glyphNames) - f.save(dst) + +def main(args=None): + """Simplify glyphs in TTFont by merging overlapping contours.""" + + import argparse + + parser = argparse.ArgumentParser( + "fonttools ttLib.removeOverlaps", description=__doc__ + ) + + parser.add_argument("input", metavar="INPUT.ttf", help="Input font file") + parser.add_argument("output", metavar="OUTPUT.ttf", help="Output font file") + parser.add_argument( + "glyphs", + metavar="GLYPHS", + nargs="*", + help="Optional list of glyph names to remove overlaps from", + ) + parser.add_argument( + "--keep-hinting", + action="store_true", + help="Keep hinting for unmodified glyphs, default is to drop hinting", + ) + parser.add_argument( + "--ignore-errors", + action="store_true", + help="ignore errors while removing overlaps, " + "thus keeping the tricky glyphs unchanged", + ) + parser.add_argument( + "--keep-unused-subroutines", + action="store_true", + help="Keep unused subroutines in CFF table after removing overlaps, " + "default is to remove them if any glyphs are modified", + ) + args = parser.parse_args(args) + + with ttFont.TTFont(args.input) as font: + removeOverlaps( + font=font, + glyphNames=args.glyphs or None, + removeHinting=not args.keep_hinting, + ignoreErrors=args.ignore_errors, + removeUnusedSubroutines=not args.keep_unused_subroutines, + ) + font.save(args.output) if __name__ == "__main__": diff --git a/contrib/python/fonttools/fontTools/ttLib/tables/_a_v_a_r.py b/contrib/python/fonttools/fontTools/ttLib/tables/_a_v_a_r.py index 6ea4132b3d..19f4f2cda4 100644 --- a/contrib/python/fonttools/fontTools/ttLib/tables/_a_v_a_r.py +++ b/contrib/python/fonttools/fontTools/ttLib/tables/_a_v_a_r.py @@ -143,7 +143,9 @@ class table__a_v_a_r(BaseTTXConverter): def renormalizeLocation(self, location, font): - if self.majorVersion not in (1, 2): + majorVersion = getattr(self, "majorVersion", 1) + + if majorVersion not in (1, 2): raise NotImplementedError("Unknown avar table version") avarSegments = self.segments @@ -154,7 +156,7 @@ class table__a_v_a_r(BaseTTXConverter): value = piecewiseLinearMap(value, avarMapping) mappedLocation[axisTag] = value - if self.majorVersion < 2: + if majorVersion < 2: return mappedLocation # Version 2 diff --git a/contrib/python/fonttools/fontTools/varLib/instancer/__init__.py b/contrib/python/fonttools/fontTools/varLib/instancer/__init__.py index 0c5dd40ce1..82676d4190 100644 --- a/contrib/python/fonttools/fontTools/varLib/instancer/__init__.py +++ b/contrib/python/fonttools/fontTools/varLib/instancer/__init__.py @@ -1880,7 +1880,9 @@ def main(args=None): ) isFullInstance = { - axisTag for axisTag, limit in axisLimits.items() if limit[0] == limit[2] + axisTag + for axisTag, limit in axisLimits.items() + if limit is None or limit[0] == limit[2] }.issuperset(axis.axisTag for axis in varfont["fvar"].axes) instantiateVariableFont( diff --git a/contrib/python/fonttools/ya.make b/contrib/python/fonttools/ya.make index dc7430ebfe..27248ee094 100644 --- a/contrib/python/fonttools/ya.make +++ b/contrib/python/fonttools/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(4.52.4) +VERSION(4.53.0) LICENSE(MIT) diff --git a/contrib/python/ipython/py3/.dist-info/METADATA b/contrib/python/ipython/py3/.dist-info/METADATA index 70ae07325e..d1b7f3be7d 100644 --- a/contrib/python/ipython/py3/.dist-info/METADATA +++ b/contrib/python/ipython/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: ipython -Version: 8.24.0 +Version: 8.25.0 Summary: IPython: Productive Interactive Computing Author: The IPython Development Team Author-email: ipython-dev@python.org @@ -43,17 +43,18 @@ Requires-Dist: ipython[test,test_extra] ; extra == 'all' Provides-Extra: black Requires-Dist: black ; extra == 'black' Provides-Extra: doc +Requires-Dist: docrepr ; extra == 'doc' +Requires-Dist: exceptiongroup ; extra == 'doc' +Requires-Dist: intersphinx-registry ; extra == 'doc' Requires-Dist: ipykernel ; extra == 'doc' +Requires-Dist: ipython[test] ; extra == 'doc' +Requires-Dist: matplotlib ; extra == 'doc' Requires-Dist: setuptools >=18.5 ; extra == 'doc' -Requires-Dist: sphinx >=1.3 ; extra == 'doc' Requires-Dist: sphinx-rtd-theme ; extra == 'doc' +Requires-Dist: sphinx >=1.3 ; extra == 'doc' Requires-Dist: sphinxcontrib-jquery ; extra == 'doc' -Requires-Dist: docrepr ; extra == 'doc' -Requires-Dist: matplotlib ; extra == 'doc' -Requires-Dist: stack-data ; extra == 'doc' Requires-Dist: typing-extensions ; extra == 'doc' -Requires-Dist: exceptiongroup ; extra == 'doc' -Requires-Dist: ipython[test] ; extra == 'doc' +Requires-Dist: tomli ; (python_version < "3.11") and extra == 'doc' Provides-Extra: kernel Requires-Dist: ipykernel ; extra == 'kernel' Provides-Extra: matplotlib diff --git a/contrib/python/ipython/py3/IPython/core/completerlib.py b/contrib/python/ipython/py3/IPython/core/completerlib.py index de6c4249b0..05f39e5015 100644 --- a/contrib/python/ipython/py3/IPython/core/completerlib.py +++ b/contrib/python/ipython/py3/IPython/core/completerlib.py @@ -199,9 +199,14 @@ def get_root_modules(): return rootmodules -def is_importable(module, attr, only_modules): +def is_importable(module, attr: str, only_modules) -> bool: if only_modules: - return inspect.ismodule(getattr(module, attr)) + try: + mod = getattr(module, attr) + except ModuleNotFoundError: + # See gh-14434 + return False + return inspect.ismodule(mod) else: return not(attr[:2] == '__' and attr[-2:] == '__') diff --git a/contrib/python/ipython/py3/IPython/core/historyapp.py b/contrib/python/ipython/py3/IPython/core/historyapp.py index 85dd9c5c3b..d555447b5d 100644 --- a/contrib/python/ipython/py3/IPython/core/historyapp.py +++ b/contrib/python/ipython/py3/IPython/core/historyapp.py @@ -146,9 +146,11 @@ class HistoryApp(Application): def start(self): if self.subapp is None: - print("No subcommand specified. Must specify one of: %s" % \ - (self.subcommands.keys())) - print() + print( + "No subcommand specified. Must specify one of: " + + ", ".join(map(repr, self.subcommands)) + + ".\n" + ) self.print_description() self.print_subcommands() self.exit(1) diff --git a/contrib/python/ipython/py3/IPython/core/hooks.py b/contrib/python/ipython/py3/IPython/core/hooks.py index f73c565763..484ebe459a 100644 --- a/contrib/python/ipython/py3/IPython/core/hooks.py +++ b/contrib/python/ipython/py3/IPython/core/hooks.py @@ -19,7 +19,7 @@ example, you could use a startup file like this:: def calljed(self,filename, linenum): "My editor hook calls the jed editor directly." - print "Calling my own editor, jed ..." + print("Calling my own editor, jed ...") if os.system('jed +%d %s' % (linenum,filename)) != 0: raise TryNext() @@ -111,7 +111,7 @@ class CommandChainDispatcher: TryNext""" last_exc = TryNext() for prio,cmd in self.chain: - #print "prio",prio,"cmd",cmd #dbg + # print("prio",prio,"cmd",cmd) # dbg try: return cmd(*args, **kw) except TryNext as exc: diff --git a/contrib/python/ipython/py3/IPython/core/inputsplitter.py b/contrib/python/ipython/py3/IPython/core/inputsplitter.py index f1ebd96b69..af7a12e6e0 100644 --- a/contrib/python/ipython/py3/IPython/core/inputsplitter.py +++ b/contrib/python/ipython/py3/IPython/core/inputsplitter.py @@ -320,7 +320,7 @@ class InputSplitter(object): prompt = '>>> ' + indent line = indent + raw_input(prompt) isp.push(line) - print 'Input source was:\n', isp.source_reset(), + print('Input source was:\n', isp.source_reset()) """ # A cache for storing the current indentation # The first value stores the most recently processed source input diff --git a/contrib/python/ipython/py3/IPython/core/interactiveshell.py b/contrib/python/ipython/py3/IPython/core/interactiveshell.py index e9e649345f..86eb7191e8 100644 --- a/contrib/python/ipython/py3/IPython/core/interactiveshell.py +++ b/contrib/python/ipython/py3/IPython/core/interactiveshell.py @@ -909,7 +909,7 @@ class InteractiveShell(SingletonConfigurable): paths = self.get_path_links(p) # In Cygwin paths like "c:\..." and '\cygdrive\c\...' are possible - if p_venv.parts[1] == "cygdrive": + if len(p_venv.parts) > 2 and p_venv.parts[1] == "cygdrive": drive_name = p_venv.parts[2] p_venv = (drive_name + ":/") / Path(*p_venv.parts[3:]) diff --git a/contrib/python/ipython/py3/IPython/core/logger.py b/contrib/python/ipython/py3/IPython/core/logger.py index ab12d10e22..101665bcc2 100644 --- a/contrib/python/ipython/py3/IPython/core/logger.py +++ b/contrib/python/ipython/py3/IPython/core/logger.py @@ -191,7 +191,7 @@ which already exists. But you must first start the logging process with def log_write(self, data, kind='input'): """Write data to the log file, if active""" - #print 'data: %r' % data # dbg + # print('data: %r' % data) # dbg if self.log_active and data: write = self.logfile.write if kind=='input': diff --git a/contrib/python/ipython/py3/IPython/core/magics/code.py b/contrib/python/ipython/py3/IPython/core/magics/code.py index 65ba52b8bb..4f1574dcef 100644 --- a/contrib/python/ipython/py3/IPython/core/magics/code.py +++ b/contrib/python/ipython/py3/IPython/core/magics/code.py @@ -452,7 +452,7 @@ class CodeMagics(Magics): # Load the parameter given as a variable. If not a string, # process it as an object instead (below) - #print '*** args',args,'type',type(args) # dbg + # print('*** args',args,'type',type(args)) # dbg data = eval(args, shell.user_ns) if not isinstance(data, str): raise DataIsObject @@ -636,8 +636,8 @@ class CodeMagics(Magics): In [1]: edit Editing... done. Executing edited code... - Out[1]: 'def foo():\\n print "foo() was defined in an editing - session"\\n' + Out[1]: 'def foo():\\n print("foo() was defined in an editing + session")\\n' We can then call the function foo():: @@ -661,21 +661,21 @@ class CodeMagics(Magics): In [5]: edit Editing... done. Executing edited code... hello - Out[5]: "print 'hello'\\n" + Out[5]: "print('hello')\\n" Now we call it again with the previous output (stored in _):: In [6]: edit _ Editing... done. Executing edited code... hello world - Out[6]: "print 'hello world'\\n" + Out[6]: "print('hello world')\\n" Now we call it with the output #8 (stored in _8, also as Out[8]):: In [7]: edit _8 Editing... done. Executing edited code... hello again - Out[7]: "print 'hello again'\\n" + Out[7]: "print('hello again')\\n" Changing the default editor hook: diff --git a/contrib/python/ipython/py3/IPython/core/magics/execution.py b/contrib/python/ipython/py3/IPython/core/magics/execution.py index f3688f4eb0..abfc4cbda7 100644 --- a/contrib/python/ipython/py3/IPython/core/magics/execution.py +++ b/contrib/python/ipython/py3/IPython/core/magics/execution.py @@ -1256,7 +1256,7 @@ class ExecutionMagics(Magics): Wall time: 1.37 Out[3]: 499999500000L - In [4]: %time print 'hello world' + In [4]: %time print('hello world') hello world CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s Wall time: 0.00 @@ -1406,9 +1406,9 @@ class ExecutionMagics(Magics): 44: x=1 45: y=3 46: z=x+y - 47: print x + 47: print(x) 48: a=5 - 49: print 'x',x,'y',y + 49: print('x',x,'y',y) you can create a macro with lines 44 through 47 (included) and line 49 called my_macro with:: @@ -1428,7 +1428,7 @@ class ExecutionMagics(Magics): You can view a macro's contents by explicitly printing it with:: - print macro_name + print(macro_name) """ opts,args = self.parse_options(parameter_s,'rq',mode='list') @@ -1439,7 +1439,7 @@ class ExecutionMagics(Magics): "%macro insufficient args; usage '%macro name n1-n2 n3-4...") name, codefrom = args[0], " ".join(args[1:]) - #print 'rng',ranges # dbg + # print('rng',ranges) # dbg try: lines = self.shell.find_user_code(codefrom, 'r' in opts) except (ValueError, TypeError) as e: @@ -1592,17 +1592,17 @@ def _format_time(timespan, precision=3): break return " ".join(time) - - # Unfortunately the unicode 'micro' symbol can cause problems in - # certain terminals. + + # Unfortunately characters outside of range(128) can cause problems in + # certain terminals. # See bug: https://bugs.launchpad.net/ipython/+bug/348466 # Try to prevent crashes by being more secure than it needs to # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set. - units = [u"s", u"ms",u'us',"ns"] # the save value - if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding: + units = ["s", "ms", "us", "ns"] # the safe value + if hasattr(sys.stdout, "encoding") and sys.stdout.encoding: try: - u'\xb5'.encode(sys.stdout.encoding) - units = [u"s", u"ms",u'\xb5s',"ns"] + "μ".encode(sys.stdout.encoding) + units = ["s", "ms", "μs", "ns"] except: pass scaling = [1, 1e3, 1e6, 1e9] diff --git a/contrib/python/ipython/py3/IPython/core/magics/history.py b/contrib/python/ipython/py3/IPython/core/magics/history.py index faa4335faa..8343677451 100644 --- a/contrib/python/ipython/py3/IPython/core/magics/history.py +++ b/contrib/python/ipython/py3/IPython/core/magics/history.py @@ -128,7 +128,7 @@ class HistoryMagics(Magics): In [6]: %history -n 4-6 4:a = 12 - 5:print a**2 + 5:print(a**2) 6:%history -n 4-6 """ diff --git a/contrib/python/ipython/py3/IPython/core/magics/namespace.py b/contrib/python/ipython/py3/IPython/core/magics/namespace.py index 5da8f7161a..737a76507f 100644 --- a/contrib/python/ipython/py3/IPython/core/magics/namespace.py +++ b/contrib/python/ipython/py3/IPython/core/magics/namespace.py @@ -43,7 +43,7 @@ class NamespaceMagics(Magics): '%pinfo object' is just a synonym for object? or ?object.""" - #print 'pinfo par: <%s>' % parameter_s # dbg + # print('pinfo par: <%s>' % parameter_s) # dbg # detail_level: 0 -> obj? , 1 -> obj?? detail_level = 0 # We need to detect if we got called as 'pinfo pinfo foo', which can diff --git a/contrib/python/ipython/py3/IPython/core/oinspect.py b/contrib/python/ipython/py3/IPython/core/oinspect.py index 937e5a9d4b..8aa8429e5d 100644 --- a/contrib/python/ipython/py3/IPython/core/oinspect.py +++ b/contrib/python/ipython/py3/IPython/core/oinspect.py @@ -1196,7 +1196,7 @@ class Inspector(Colorable): - list_types(False): list all available object types for object matching. """ - #print 'ps pattern:<%r>' % pattern # dbg + # print('ps pattern:<%r>' % pattern) # dbg # defaults type_pattern = 'all' @@ -1225,7 +1225,7 @@ class Inspector(Colorable): raise ValueError('invalid namespace <%s>. Valid names: %s' % (name,ns_table.keys())) - #print 'type_pattern:',type_pattern # dbg + # print('type_pattern:',type_pattern) # dbg search_result, namespaces_seen = set(), set() for ns_name in ns_search: ns = ns_table[ns_name] diff --git a/contrib/python/ipython/py3/IPython/core/page.py b/contrib/python/ipython/py3/IPython/core/page.py index d3e6a9eef5..31b314ec46 100644 --- a/contrib/python/ipython/py3/IPython/core/page.py +++ b/contrib/python/ipython/py3/IPython/core/page.py @@ -122,8 +122,8 @@ def _detect_screen_size(screen_lines_def): termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags) # Now we have what we needed: the screen size in rows/columns return screen_lines_real - #print '***Screen size:',screen_lines_real,'lines x',\ - #screen_cols,'columns.' # dbg + # print('***Screen size:',screen_lines_real,'lines x', + # screen_cols,'columns.') # dbg def pager_page(strng, start=0, screen_lines=0, pager_cmd=None): """Display a string, piping through a pager after a certain length. @@ -179,9 +179,9 @@ def pager_page(strng, start=0, screen_lines=0, pager_cmd=None): print(str_toprint) return - #print 'numlines',numlines,'screenlines',screen_lines # dbg + # print('numlines',numlines,'screenlines',screen_lines) # dbg if numlines <= screen_lines : - #print '*** normal print' # dbg + # print('*** normal print') # dbg print(str_toprint) else: # Try to open pager and default to internal one if that fails. diff --git a/contrib/python/ipython/py3/IPython/core/prefilter.py b/contrib/python/ipython/py3/IPython/core/prefilter.py index 5b1b86c753..e611b4b834 100644 --- a/contrib/python/ipython/py3/IPython/core/prefilter.py +++ b/contrib/python/ipython/py3/IPython/core/prefilter.py @@ -240,7 +240,7 @@ class PrefilterManager(Configurable): This implements the checker/handler part of the prefilter pipe. """ - # print "prefilter_line_info: ", line_info + # print("prefilter_line_info: ", line_info) handler = self.find_handler(line_info) return handler.handle(line_info) @@ -267,7 +267,7 @@ class PrefilterManager(Configurable): transformers and then the checkers/handlers. """ - # print "prefilter_line: ", line, continue_prompt + # print("prefilter_line: ", line, continue_prompt) # All handlers *must* return a value, even if it's blank (''). # save the line away in case we crash, so the post-mortem handler can @@ -300,7 +300,7 @@ class PrefilterManager(Configurable): return normal_handler.handle(line_info) prefiltered = self.prefilter_line_info(line_info) - # print "prefiltered line: %r" % prefiltered + # print("prefiltered line: %r" % prefiltered) return prefiltered def prefilter_lines(self, lines, continue_prompt=False): @@ -544,7 +544,7 @@ class PrefilterHandler(Configurable): ) def handle(self, line_info): - # print "normal: ", line_info + # print("normal: ", line_info) """Handle normal input lines. Use as a template for handlers.""" # With autoindent on, we need some way to exit the input loop, and I diff --git a/contrib/python/ipython/py3/IPython/core/profileapp.py b/contrib/python/ipython/py3/IPython/core/profileapp.py index 94cc0352e8..e7538ff201 100644 --- a/contrib/python/ipython/py3/IPython/core/profileapp.py +++ b/contrib/python/ipython/py3/IPython/core/profileapp.py @@ -303,8 +303,11 @@ class ProfileApp(Application): def start(self): if self.subapp is None: - print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys())) - print() + print( + "No subcommand specified. Must specify one of: " + + ", ".join(map(repr, self.subcommands)) + + ".\n" + ) self.print_description() self.print_subcommands() self.exit(1) diff --git a/contrib/python/ipython/py3/IPython/core/pylabtools.py b/contrib/python/ipython/py3/IPython/core/pylabtools.py index 1f5a11f37e..5c926a9c10 100644 --- a/contrib/python/ipython/py3/IPython/core/pylabtools.py +++ b/contrib/python/ipython/py3/IPython/core/pylabtools.py @@ -14,7 +14,7 @@ from IPython.utils.decorators import flag_calls # Matplotlib backend resolution functionality moved from IPython to Matplotlib -# in IPython 8.24 and Matplotlib 3.9.1. Need to keep `backends` and `backend2gui` +# in IPython 8.24 and Matplotlib 3.9.0. Need to keep `backends` and `backend2gui` # here for earlier Matplotlib and for external backend libraries such as # mplcairo that might rely upon it. _deprecated_backends = { @@ -224,7 +224,7 @@ def mpl_runner(safe_execfile): import matplotlib import matplotlib.pyplot as plt - #print '*** Matplotlib runner ***' # dbg + # print('*** Matplotlib runner ***') # dbg # turn off rendering until end of script with matplotlib.rc_context({"interactive": False}): safe_execfile(fname, *where, **kw) @@ -345,8 +345,10 @@ def find_gui_and_backend(gui=None, gui_select=None): backend = matplotlib.rcParamsOrig["backend"] backend, gui = backend_registry.resolve_backend(backend) else: + gui = _convert_gui_to_matplotlib(gui) backend, gui = backend_registry.resolve_gui_or_backend(gui) + gui = _convert_gui_from_matplotlib(gui) return gui, backend # Fallback to previous behaviour (Matplotlib < 3.9) @@ -485,6 +487,10 @@ def _matplotlib_manages_backends() -> bool: matplotlib.backends.registry.backend_registry is available along with member functions resolve_gui_or_backend, resolve_backend, list_all, and list_gui_frameworks. + + This function can be removed as it will always return True when Python + 3.12, the latest version supported by Matplotlib < 3.9, reaches + end-of-life in late 2028. """ global _matplotlib_manages_backends_value if _matplotlib_manages_backends_value is None: @@ -509,10 +515,28 @@ def _list_matplotlib_backends_and_gui_loops() -> list[str]: if _matplotlib_manages_backends(): from matplotlib.backends.registry import backend_registry - ret = backend_registry.list_all() + backend_registry.list_gui_frameworks() + ret = backend_registry.list_all() + [ + _convert_gui_from_matplotlib(gui) + for gui in backend_registry.list_gui_frameworks() + ] else: from IPython.core import pylabtools ret = list(pylabtools.backends.keys()) return sorted(["auto"] + ret) + + +# Matplotlib and IPython do not always use the same gui framework name. +# Always use the approprate one of these conversion functions when passing a +# gui framework name to/from Matplotlib. +def _convert_gui_to_matplotlib(gui: str | None) -> str | None: + if gui and gui.lower() == "osx": + return "macosx" + return gui + + +def _convert_gui_from_matplotlib(gui: str | None) -> str | None: + if gui and gui.lower() == "macosx": + return "osx" + return gui diff --git a/contrib/python/ipython/py3/IPython/core/release.py b/contrib/python/ipython/py3/IPython/core/release.py index 3abbedef73..431ce99874 100644 --- a/contrib/python/ipython/py3/IPython/core/release.py +++ b/contrib/python/ipython/py3/IPython/core/release.py @@ -16,7 +16,7 @@ # release. 'dev' as a _version_extra string means this is a development # version _version_major = 8 -_version_minor = 24 +_version_minor = 25 _version_patch = 0 _version_extra = ".dev" # _version_extra = "rc1" diff --git a/contrib/python/ipython/py3/IPython/core/shellapp.py b/contrib/python/ipython/py3/IPython/core/shellapp.py index 99d1d8a9f4..3815a0ecb9 100644 --- a/contrib/python/ipython/py3/IPython/core/shellapp.py +++ b/contrib/python/ipython/py3/IPython/core/shellapp.py @@ -82,12 +82,14 @@ shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.") shell_flags['pylab'] = ( {'InteractiveShellApp' : {'pylab' : 'auto'}}, """Pre-load matplotlib and numpy for interactive use with - the default matplotlib backend.""" + the default matplotlib backend. The exact options available + depend on what Matplotlib provides at runtime.""", ) shell_flags['matplotlib'] = ( {'InteractiveShellApp' : {'matplotlib' : 'auto'}}, """Configure matplotlib for interactive use with - the default matplotlib backend.""" + the default matplotlib backend. The exact options available + depend on what Matplotlib provides at runtime.""", ) # it's possible we don't want short aliases for *all* of these: @@ -114,7 +116,7 @@ shell_aliases['cache-size'] = 'InteractiveShell.cache_size' class MatplotlibBackendCaselessStrEnum(CaselessStrEnum): """An enum of Matplotlib backend strings where the case should be ignored. - Prior to Matplotlib 3.9.1 the list of valid backends is hardcoded in + Prior to Matplotlib 3.9.0 the list of valid backends is hardcoded in pylabtools.backends. After that, Matplotlib manages backends. The list of valid backends is determined when it is first needed to avoid @@ -205,12 +207,14 @@ class InteractiveShellApp(Configurable): matplotlib = MatplotlibBackendCaselessStrEnum( allow_none=True, help="""Configure matplotlib for interactive use with - the default matplotlib backend.""", + the default matplotlib backend. The exact options available + depend on what Matplotlib provides at runtime.""", ).tag(config=True) pylab = MatplotlibBackendCaselessStrEnum( allow_none=True, help="""Pre-load matplotlib and numpy for interactive use, selecting a particular matplotlib backend and loop integration. + The exact options available depend on what Matplotlib provides at runtime. """, ).tag(config=True) pylab_import_all = Bool( diff --git a/contrib/python/ipython/py3/IPython/core/splitinput.py b/contrib/python/ipython/py3/IPython/core/splitinput.py index 5bc3e32542..0cd70ec910 100644 --- a/contrib/python/ipython/py3/IPython/core/splitinput.py +++ b/contrib/python/ipython/py3/IPython/core/splitinput.py @@ -63,19 +63,19 @@ def split_user_input(line, pattern=None): pattern = line_split match = pattern.match(line) if not match: - # print "match failed for line '%s'" % line + # print("match failed for line '%s'" % line) try: ifun, the_rest = line.split(None,1) except ValueError: - # print "split failed for line '%s'" % line + # print("split failed for line '%s'" % line) ifun, the_rest = line, u'' pre = re.match(r'^(\s*)(.*)',line).groups()[0] esc = "" else: pre, esc, ifun, the_rest = match.groups() - #print 'line:<%s>' % line # dbg - #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest) # dbg + # print('line:<%s>' % line) # dbg + # print('pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest)) # dbg return pre, esc or '', ifun.strip(), the_rest.lstrip() diff --git a/contrib/python/ipython/py3/IPython/extensions/storemagic.py b/contrib/python/ipython/py3/IPython/extensions/storemagic.py index f3bc8f6c13..1ab56f72ea 100644 --- a/contrib/python/ipython/py3/IPython/extensions/storemagic.py +++ b/contrib/python/ipython/py3/IPython/extensions/storemagic.py @@ -25,7 +25,7 @@ def restore_aliases(ip, alias=None): staliases = ip.db.get('stored_aliases', {}) if alias is None: for k,v in staliases.items(): - #print "restore alias",k,v # dbg + # print("restore alias",k,v) # dbg #self.alias_table[k] = v ip.alias_manager.define_alias(k,v) else: @@ -43,7 +43,7 @@ def refresh_variables(ip): print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey) print("The error was:", sys.exc_info()[0]) else: - #print "restored",justkey,"=",obj #dbg + # print("restored",justkey,"=",obj) # dbg ip.user_ns[justkey] = obj diff --git a/contrib/python/ipython/py3/IPython/lib/lexers.py b/contrib/python/ipython/py3/IPython/lib/lexers.py index 42d5b7a87c..9aa3433af7 100644 --- a/contrib/python/ipython/py3/IPython/lib/lexers.py +++ b/contrib/python/ipython/py3/IPython/lib/lexers.py @@ -456,13 +456,13 @@ class IPythonConsoleLexer(Lexer): # does not use the continuation marker cannot be detected. # For example, the 3 in the following is clearly output: # - # In [1]: print 3 + # In [1]: print(3) # 3 # # But the following second line is part of the input: # # In [2]: while True: - # print True + # print(True) # # In both cases, the 2nd line will be 'output'. # diff --git a/contrib/python/ipython/py3/IPython/sphinxext/ipython_directive.py b/contrib/python/ipython/py3/IPython/sphinxext/ipython_directive.py index 10257a6d69..88357a5113 100644 --- a/contrib/python/ipython/py3/IPython/sphinxext/ipython_directive.py +++ b/contrib/python/ipython/py3/IPython/sphinxext/ipython_directive.py @@ -300,7 +300,7 @@ def block_parser(part, rgxin, rgxout, fmtin, fmtout): nextline = lines[i] matchout = rgxout.match(nextline) - #print "nextline=%s, continuation=%s, starts=%s"%(nextline, continuation, nextline.startswith(continuation)) + # print("nextline=%s, continuation=%s, starts=%s"%(nextline, continuation, nextline.startswith(continuation))) if matchout or nextline.startswith('#'): break elif nextline.startswith(continuation): @@ -538,7 +538,7 @@ class EmbeddedSphinxShell(object): # When there is stdout from the input, it also has a '\n' at the # tail end, and so this ensures proper spacing as well. E.g.: # - # In [1]: print x + # In [1]: print(x) # 5 # # In [2]: x = 5 @@ -699,7 +699,7 @@ class EmbeddedSphinxShell(object): """ self.ensure_pyplot() command = 'plt.gcf().savefig("%s")'%image_file - #print 'SAVEFIG', command # dbg + # print('SAVEFIG', command) # dbg self.process_input_line('bookmark ipy_thisdir', store_history=False) self.process_input_line('cd -b ipy_savedir', store_history=False) self.process_input_line(command, store_history=False) diff --git a/contrib/python/ipython/py3/IPython/terminal/ipapp.py b/contrib/python/ipython/py3/IPython/terminal/ipapp.py index 55ff1da391..fff6bdf9d2 100644 --- a/contrib/python/ipython/py3/IPython/terminal/ipapp.py +++ b/contrib/python/ipython/py3/IPython/terminal/ipapp.py @@ -270,7 +270,7 @@ class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): if self.subapp is not None: # don't bother initializing further, starting subapp return - # print self.extra_args + # print(self.extra_args) if self.extra_args and not self.something_to_run: self.file_to_run = self.extra_args[0] self.init_path() diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/glut.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/glut.py index 835aadfc97..63d020b314 100644 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/glut.py +++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/glut.py @@ -127,11 +127,11 @@ def inputhook(context): # 0.05 0.5% used_time = clock() - t if used_time > 10.0: - # print 'Sleep for 1 s' # dbg + # print('Sleep for 1 s') # dbg time.sleep(1.0) elif used_time > 0.1: # Few GUI events coming in, so we can sleep longer - # print 'Sleep for 0.05 s' # dbg + # print('Sleep for 0.05 s') # dbg time.sleep(0.05) else: # Many GUI events coming in, so sleep only very little diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/pyglet.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/pyglet.py index 49ec86d223..43b2208d7e 100644 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/pyglet.py +++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/pyglet.py @@ -53,11 +53,11 @@ def inputhook(context): # 0.05 0.5% used_time = clock() - t if used_time > 10.0: - # print 'Sleep for 1 s' # dbg + # print('Sleep for 1 s') # dbg time.sleep(1.0) elif used_time > 0.1: # Few GUI events coming in, so we can sleep longer - # print 'Sleep for 0.05 s' # dbg + # print('Sleep for 0.05 s') # dbg time.sleep(0.05) else: # Many GUI events coming in, so sleep only very little diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/wx.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/wx.py index a0f4442c77..8666a3621f 100644 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/wx.py +++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/wx.py @@ -137,11 +137,11 @@ def inputhook_wx3(context): # 0.05 0.5% used_time = clock() - t if used_time > 10.0: - # print 'Sleep for 1 s' # dbg + # print('Sleep for 1 s') # dbg time.sleep(1.0) elif used_time > 0.1: # Few GUI events coming in, so we can sleep longer - # print 'Sleep for 0.05 s' # dbg + # print('Sleep for 0.05 s') # dbg time.sleep(0.05) else: # Many GUI events coming in, so sleep only very little diff --git a/contrib/python/ipython/py3/IPython/testing/ipunittest.py b/contrib/python/ipython/py3/IPython/testing/ipunittest.py index 4b107618b5..b10c8d2235 100644 --- a/contrib/python/ipython/py3/IPython/testing/ipunittest.py +++ b/contrib/python/ipython/py3/IPython/testing/ipunittest.py @@ -108,7 +108,7 @@ class IPython2PythonConverter(object): newline(line) newline('') # ensure a closing newline, needed by doctest - #print "PYSRC:", '\n'.join(out) # dbg + # print("PYSRC:", '\n'.join(out)) # dbg return '\n'.join(out) #return dnew diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/ipdoctest.py b/contrib/python/ipython/py3/IPython/testing/plugin/ipdoctest.py index e7edf9837f..0e6a7efa96 100644 --- a/contrib/python/ipython/py3/IPython/testing/plugin/ipdoctest.py +++ b/contrib/python/ipython/py3/IPython/testing/plugin/ipdoctest.py @@ -68,7 +68,7 @@ class IPDoctestOutputChecker(doctest.OutputChecker): ret = doctest.OutputChecker.check_output(self, want, got, optionflags) if not ret and self.random_re.search(want): - #print >> sys.stderr, 'RANDOM OK:',want # dbg + # print('RANDOM OK:',want, file=sys.stderr) # dbg return True return ret @@ -141,7 +141,7 @@ class IPDocTestParser(doctest.DocTestParser): used for error messages. """ - #print 'Parse string:\n',string # dbg + # print('Parse string:\n',string) # dbg string = string.expandtabs() # If all lines begin with the same indentation, then strip it. diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/pytest_ipdoctest.py b/contrib/python/ipython/py3/IPython/testing/plugin/pytest_ipdoctest.py index fc8af13b57..40a3ae92b4 100644 --- a/contrib/python/ipython/py3/IPython/testing/plugin/pytest_ipdoctest.py +++ b/contrib/python/ipython/py3/IPython/testing/plugin/pytest_ipdoctest.py @@ -38,7 +38,11 @@ from _pytest._io import TerminalWriter from _pytest.compat import safe_getattr from _pytest.config import Config from _pytest.config.argparsing import Parser -from _pytest.fixtures import FixtureRequest + +try: + from _pytest.fixtures import TopRequest as FixtureRequest +except ImportError: + from _pytest.fixtures import FixtureRequest from _pytest.nodes import Collector from _pytest.outcomes import OutcomeException from _pytest.pathlib import fnmatch_ex, import_path @@ -69,6 +73,8 @@ RUNNER_CLASS = None # Lazy definition of output checker class CHECKER_CLASS: Optional[Type["IPDoctestOutputChecker"]] = None +pytest_version = tuple([int(part) for part in pytest.__version__.split(".")]) + def pytest_addoption(parser: Parser) -> None: parser.addini( @@ -143,7 +149,7 @@ def pytest_collect_file( return None -if int(pytest.__version__.split(".")[0]) < 7: +if pytest_version[0] < 7: _collect_file = pytest_collect_file def pytest_collect_file( @@ -448,7 +454,7 @@ class IPDoctestItem(pytest.Item): assert self.dtest is not None return self.path, self.dtest.lineno, "[ipdoctest] %s" % self.name - if int(pytest.__version__.split(".")[0]) < 7: + if pytest_version[0] < 7: @property def path(self) -> Path: @@ -521,7 +527,7 @@ class IPDoctestTextfile(pytest.Module): self, name=test.name, runner=runner, dtest=test ) - if int(pytest.__version__.split(".")[0]) < 7: + if pytest_version[0] < 7: @property def path(self) -> Path: @@ -636,20 +642,26 @@ class IPDoctestModule(pytest.Module): ) if self.path.name == "conftest.py": - if int(pytest.__version__.split(".")[0]) < 7: + if pytest_version[0] < 7: module = self.config.pluginmanager._importconftest( self.path, self.config.getoption("importmode"), ) else: + kwargs = {"rootpath": self.config.rootpath} + if pytest_version >= (8, 1): + kwargs["consider_namespace_packages"] = False module = self.config.pluginmanager._importconftest( self.path, self.config.getoption("importmode"), - rootpath=self.config.rootpath, + **kwargs, ) else: try: - module = import_path(self.path, root=self.config.rootpath) + kwargs = {"root": self.config.rootpath} + if pytest_version >= (8, 1): + kwargs["consider_namespace_packages"] = False + module = import_path(self.path, **kwargs) except ImportError: if self.config.getvalue("ipdoctest_ignore_import_errors"): pytest.skip("unable to import module %r" % self.path) @@ -671,7 +683,7 @@ class IPDoctestModule(pytest.Module): self, name=test.name, runner=runner, dtest=test ) - if int(pytest.__version__.split(".")[0]) < 7: + if pytest_version[0] < 7: @property def path(self) -> Path: @@ -701,11 +713,15 @@ def _setup_fixtures(doctest_item: IPDoctestItem) -> FixtureRequest: doctest_item.funcargs = {} # type: ignore[attr-defined] fm = doctest_item.session._fixturemanager + kwargs = {"node": doctest_item, "func": func, "cls": None} + if pytest_version <= (8, 0): + kwargs["funcargs"] = False doctest_item._fixtureinfo = fm.getfixtureinfo( # type: ignore[attr-defined] - node=doctest_item, func=func, cls=None, funcargs=False + **kwargs ) fixture_request = FixtureRequest(doctest_item, _ispytest=True) - fixture_request._fillfixtures() + if pytest_version <= (8, 0): + fixture_request._fillfixtures() return fixture_request diff --git a/contrib/python/ipython/py3/IPython/testing/tools.py b/contrib/python/ipython/py3/IPython/testing/tools.py index 2ff63a6d4a..b030349048 100644 --- a/contrib/python/ipython/py3/IPython/testing/tools.py +++ b/contrib/python/ipython/py3/IPython/testing/tools.py @@ -245,8 +245,8 @@ def ipexec_validate(fname, expected_out, expected_err='', __tracebackhide__ = True out, err = ipexec(fname, options, commands) - #print 'OUT', out # dbg - #print 'ERR', err # dbg + # print('OUT', out) # dbg + # print('ERR', err) # dbg # If there are any errors, we must check those before stdout, as they may be # more informative than simply having an empty stdout. if err: diff --git a/contrib/python/ipython/py3/IPython/utils/_sysinfo.py b/contrib/python/ipython/py3/IPython/utils/_sysinfo.py index 44764aa4ae..e2e484d493 100644 --- a/contrib/python/ipython/py3/IPython/utils/_sysinfo.py +++ b/contrib/python/ipython/py3/IPython/utils/_sysinfo.py @@ -1,2 +1,2 @@ # GENERATED BY setup.py -commit = "9d06a304d" +commit = "40a5a37ca" diff --git a/contrib/python/ipython/py3/IPython/utils/path.py b/contrib/python/ipython/py3/IPython/utils/path.py index cb5be04195..3d8d10c984 100644 --- a/contrib/python/ipython/py3/IPython/utils/path.py +++ b/contrib/python/ipython/py3/IPython/utils/path.py @@ -308,8 +308,8 @@ def target_outdated(target,deps): for dep in deps: dep_time = os.path.getmtime(dep) if dep_time > target_time: - #print "For target",target,"Dep failed:",dep # dbg - #print "times (dep,tar):",dep_time,target_time # dbg + # print("For target",target,"Dep failed:",dep) # dbg + # print("times (dep,tar):",dep_time,target_time) # dbg return 1 return 0 diff --git a/contrib/python/ipython/py3/IPython/utils/strdispatch.py b/contrib/python/ipython/py3/IPython/utils/strdispatch.py index d6bf510535..6c90fe871e 100644 --- a/contrib/python/ipython/py3/IPython/utils/strdispatch.py +++ b/contrib/python/ipython/py3/IPython/utils/strdispatch.py @@ -48,7 +48,7 @@ class StrDispatch(object): if re.match(r, key): yield obj else: - #print "nomatch",key # dbg + # print("nomatch",key) # dbg pass def __repr__(self): diff --git a/contrib/python/ipython/py3/IPython/utils/text.py b/contrib/python/ipython/py3/IPython/utils/text.py index 51dcdae5dd..46b3bb0e46 100644 --- a/contrib/python/ipython/py3/IPython/utils/text.py +++ b/contrib/python/ipython/py3/IPython/utils/text.py @@ -10,12 +10,18 @@ Inheritance diagram: import os import re import string +import sys import textwrap import warnings from string import Formatter from pathlib import Path -from typing import List, Dict, Tuple, Optional, cast +from typing import List, Dict, Tuple, Optional, cast, Sequence, Mapping, Any + +if sys.version_info < (3, 12): + from typing_extensions import Self +else: + from typing import Self class LSString(str): @@ -34,7 +40,11 @@ class LSString(str): Such strings are very useful to efficiently interact with the shell, which typically only understands whitespace-separated options for commands.""" - def get_list(self): + __list: List[str] + __spstr: str + __paths: List[Path] + + def get_list(self) -> List[str]: try: return self.__list except AttributeError: @@ -43,7 +53,7 @@ class LSString(str): l = list = property(get_list) - def get_spstr(self): + def get_spstr(self) -> str: try: return self.__spstr except AttributeError: @@ -52,12 +62,12 @@ class LSString(str): s = spstr = property(get_spstr) - def get_nlstr(self): + def get_nlstr(self) -> Self: return self n = nlstr = property(get_nlstr) - def get_paths(self): + def get_paths(self) -> List[Path]: try: return self.__paths except AttributeError: @@ -72,8 +82,8 @@ class LSString(str): # def print_lsstring(arg): # """ Prettier (non-repr-like) and more informative printer for LSString """ -# print "LSString (.p, .n, .l, .s available). Value:" -# print arg +# print("LSString (.p, .n, .l, .s available). Value:") +# print(arg) # # # print_lsstring = result_display.register(LSString)(print_lsstring) @@ -92,12 +102,16 @@ class SList(list): Any values which require transformations are computed only once and cached.""" - def get_list(self): + __spstr: str + __nlstr: str + __paths: List[Path] + + def get_list(self) -> Self: return self l = list = property(get_list) - def get_spstr(self): + def get_spstr(self) -> str: try: return self.__spstr except AttributeError: @@ -106,7 +120,7 @@ class SList(list): s = spstr = property(get_spstr) - def get_nlstr(self): + def get_nlstr(self) -> str: try: return self.__nlstr except AttributeError: @@ -115,7 +129,7 @@ class SList(list): n = nlstr = property(get_nlstr) - def get_paths(self): + def get_paths(self) -> List[Path]: try: return self.__paths except AttributeError: @@ -231,7 +245,7 @@ class SList(list): # def print_slist(arg): # """ Prettier (non-repr-like) and more informative printer for SList """ -# print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):" +# print("SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):") # if hasattr(arg, 'hideonce') and arg.hideonce: # arg.hideonce = False # return @@ -538,7 +552,9 @@ class FullEvalFormatter(Formatter): """ # copied from Formatter._vformat with minor changes to allow eval # and replace the format_spec code with slicing - def vformat(self, format_string: str, args, kwargs) -> str: + def vformat( + self, format_string: str, args: Sequence[Any], kwargs: Mapping[str, Any] + ) -> str: result = [] conversion: Optional[str] for literal_text, field_name, format_spec, conversion in self.parse( @@ -559,7 +575,7 @@ class FullEvalFormatter(Formatter): # eval the contents of the field for the object # to be formatted - obj = eval(field_name, kwargs) + obj = eval(field_name, dict(kwargs)) # do any conversion on the resulting object # type issue in typeshed, fined in https://github.com/python/typeshed/pull/11377 @@ -629,7 +645,9 @@ def _col_chunks(l, max_rows, row_first=False): yield l[i:(i + max_rows)] -def _find_optimal(rlist, row_first: bool, separator_size: int, displaywidth: int): +def _find_optimal( + rlist: List[str], row_first: bool, separator_size: int, displaywidth: int +) -> Dict[str, Any]: """Calculate optimal info to columnize a list of string""" for max_rows in range(1, len(rlist) + 1): col_widths = list(map(max, _col_chunks(rlist, max_rows, row_first))) @@ -653,7 +671,12 @@ def _get_or_default(mylist, i, default=None): def compute_item_matrix( - items, row_first: bool = False, empty=None, *, separator_size=2, displaywidth=80 + items: List[str], + row_first: bool = False, + empty: Optional[str] = None, + *, + separator_size: int = 2, + displaywidth: int = 80, ) -> Tuple[List[List[int]], Dict[str, int]]: """Returns a nested list, and info to columnize items @@ -710,7 +733,7 @@ def compute_item_matrix( category=PendingDeprecationWarning, ) info = _find_optimal( - list(map(len, items)), + list(map(len, items)), # type: ignore[arg-type] row_first, separator_size=separator_size, displaywidth=displaywidth, @@ -728,7 +751,7 @@ def columnize( separator: str = " ", displaywidth: int = 80, spread: bool = False, -): +) -> str: """Transform a list of strings into a single string with columns. Parameters diff --git a/contrib/python/ipython/py3/ya.make b/contrib/python/ipython/py3/ya.make index aa0ae48ce9..5a192f5089 100644 --- a/contrib/python/ipython/py3/ya.make +++ b/contrib/python/ipython/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(8.24.0) +VERSION(8.25.0) LICENSE(BSD-3-Clause) |