From beb99322412889c01e812e0db39ed777a8afb2cc Mon Sep 17 00:00:00 2001 From: Alexandre Detiste Date: Wed, 20 Mar 2024 14:39:16 +0100 Subject: [PATCH 1/8] remove usage of six.print_() --- samples/printing/printing.py | 29 +++++++-------- samples/roses/clroses.py | 11 +++--- samples/roses/wxroses.py | 39 +++++++++++---------- samples/simple/events.py | 14 ++++---- wx/lib/pubsub/utils/misc.py | 5 +-- wx/lib/pubsub/utils/xmltopicdefnprovider.py | 4 ++- wx/tools/pywxrc.py | 24 +++++++------ 7 files changed, 67 insertions(+), 59 deletions(-) diff --git a/samples/printing/printing.py b/samples/printing/printing.py index 638d5cde..8af9a05e 100644 --- a/samples/printing/printing.py +++ b/samples/printing/printing.py @@ -1,5 +1,6 @@ +from __future__ import print_function + import wx -from six import print_ import os FONTSIZE = 10 @@ -180,7 +181,7 @@ class PrintFrameworkSample(wx.Frame): data = dlg.GetPageSetupData() self.pdata = wx.PrintData(data.GetPrintData()) # force a copy self.pdata.SetPaperId(data.GetPaperId()) - #print_("paperID %r, paperSize %r" % (self.pdata.GetPaperId(), self.pdata.GetPaperSize())) + #print("paperID %r, paperSize %r" % (self.pdata.GetPaperId(), self.pdata.GetPaperSize())) self.margins = (data.GetMarginTopLeft(), data.GetMarginBottomRight()) dlg.Destroy() @@ -226,20 +227,20 @@ class PrintFrameworkSample(wx.Frame): dlg = wx.PrintDialog(self, data) if dlg.ShowModal() == wx.ID_OK: data = dlg.GetPrintDialogData() - print_() - print_("GetFromPage:", data.GetFromPage()) - print_("GetToPage:", data.GetToPage()) - print_("GetMinPage:", data.GetMinPage()) - print_("GetMaxPage:", data.GetMaxPage()) - print_("GetNoCopies:", data.GetNoCopies()) - print_("GetAllPages:", data.GetAllPages()) - print_("GetSelection:", data.GetSelection()) - print_("GetCollate:", data.GetCollate()) - print_("GetPrintToFile:", data.GetPrintToFile()) + print() + print("GetFromPage:", data.GetFromPage()) + print("GetToPage:", data.GetToPage()) + print("GetMinPage:", data.GetMinPage()) + print("GetMaxPage:", data.GetMaxPage()) + print("GetNoCopies:", data.GetNoCopies()) + print("GetAllPages:", data.GetAllPages()) + print("GetSelection:", data.GetSelection()) + print("GetCollate:", data.GetCollate()) + print("GetPrintToFile:", data.GetPrintToFile()) self.pdata = wx.PrintData(data.GetPrintData()) - print_() - print_("GetPrinterName:", self.pdata.GetPrinterName()) + print() + print("GetPrinterName:", self.pdata.GetPrinterName()) dlg.Destroy() diff --git a/samples/roses/clroses.py b/samples/roses/clroses.py index a5a87866..f25ac93b 100644 --- a/samples/roses/clroses.py +++ b/samples/roses/clroses.py @@ -36,8 +36,9 @@ # ideal Roses program should be, however, callers are welcome to assert their # independence, override defaults, ignore features, etc. +from __future__ import print_function + from math import sin, cos, pi -from six import print_ # Rose class knows about: # > Generating points and vectors (returning data as a list of points) @@ -151,7 +152,7 @@ class rose: # update parameters or stop. def restart(self): if self.verbose: - print_('restart: int_state', self.int_state, 'cmd_state', self.cmd_state) + print('restart: int_state', self.int_state, 'cmd_state', self.cmd_state) try: tmp = self.sin_table[0] except: @@ -192,7 +193,7 @@ class rose: # before initialization is done. def repaint(self, delay): if self.int_state != self.INT_RESIZE: - # print_('repaint after', delay) + # print('repaint after', delay) self.int_state = self.INT_RESIZE self.AppCancelTimer() self.AppAfter(delay, self.clock) @@ -264,7 +265,7 @@ class rose: # roses is 0.) def clock(self): if self.int_state == self.INT_IDLE: - # print_('clock called in idle state') + # print('clock called in idle state') delay = 0 elif self.int_state == self.INT_DRAW: line, run = self.roselet() @@ -295,7 +296,7 @@ class rose: if delay == 0: if self.verbose: - print_('clock: going idle from state', self.int_state) + print('clock: going idle from state', self.int_state) else: self.AppAfter(delay, self.clock) diff --git a/samples/roses/wxroses.py b/samples/roses/wxroses.py index 7f8e3a7e..645f56aa 100644 --- a/samples/roses/wxroses.py +++ b/samples/roses/wxroses.py @@ -68,10 +68,11 @@ # control the display (without blocking the user's control) would be pretty # straightforward. +from __future__ import print_function + import wx import clroses import wx.lib.colourselect as cs -from six import print_ # Class SpinPanel creates a control that includes both a StaticText widget # which holds the the name of a parameter and a SpinCtrl widget which @@ -109,7 +110,7 @@ class SpinPanel(wx.Panel): name = self.st.GetLabel() value = self.sc.GetValue() if verbose: - print_('OnSpin', name, '=', value) + print('OnSpin', name, '=', value) self.callback(name, value) # Call MyFrame.OnSpinback to call clroses @@ -372,10 +373,10 @@ class MyFrame(wx.Frame, clroses.rose): h = max(600, fh) # Change 600 to desired minimum size w = h + fw - rw if verbose: - print_('rose panel size', (rw, rh)) - print_('side panel size', (sw, sh)) - print_(' frame size', (fw, fh)) - print_('Want size', (w,h)) + print('rose panel size', (rw, rh)) + print('side panel size', (sw, sh)) + print(' frame size', (fw, fh)) + print('Want size', (w,h)) self.SetSize((w, h)) self.SupplyControlValues() # Ask clroses to tell us all the defaults self.Show() @@ -386,25 +387,25 @@ class MyFrame(wx.Frame, clroses.rose): # Go/Stop button def OnGoStop(self, event): if verbose: - print_('OnGoStop') + print('OnGoStop') self.cmd_go_stop() # Redraw/Redraw def OnRedraw(self, event): if verbose: - print_('OnRedraw') + print('OnRedraw') self.cmd_redraw() # Backward/Reverse def OnBackward(self, event): if verbose: - print_('OnBackward') + print('OnBackward') self.cmd_backward() # Forward/Skip def OnForward(self, event): if verbose: - print_('OnForward') + print('OnForward') self.cmd_step() @@ -415,7 +416,7 @@ class MyFrame(wx.Frame, clroses.rose): def AppClear(self): if verbose: - print_('AppClear: clear screen') + print('AppClear: clear screen') self.rose_panel.Clear() def AppCreateLine(self, line): @@ -467,8 +468,8 @@ class MyFrame(wx.Frame, clroses.rose): # Method to provide a single callback after some amount of time. def AppAfter(self, msec, callback): if self.timer_callback: - print_('AppAfter: timer_callback already set!') - # print_('AppAfter:', callback) + print('AppAfter: timer_callback already set!') + # print('AppAfter:', callback) self.timer_callback = callback self.timer.Start(msec, True) @@ -476,14 +477,14 @@ class MyFrame(wx.Frame, clroses.rose): # interest in. def AppCancelTimer(self): self.timer.Stop() - # print_('AppCancelTimer') + # print('AppCancelTimer') self.timer_callback = None # When the timer happens, we come here and jump off to clroses internal code. def OnTimer(self, evt): callback = self.timer_callback self.timer_callback = None - # print_('OnTimer,', callback) + # print('OnTimer,', callback) if callback: callback() # Often calls AppAfter() and sets the callback else: @@ -502,7 +503,7 @@ class MyFrame(wx.Frame, clroses.rose): # Called when data in spin boxes changes. def OnSpinback(self, name, value): if verbose: - print_('OnSpinback', name, value) + print('OnSpinback', name, value) if name == 'Style': self.SetStyle(value) elif name == 'Sincr': @@ -530,7 +531,7 @@ class MyFrame(wx.Frame, clroses.rose): elif name == 'Delay': self.SetWaitDelay(value) else: - print_('OnSpinback: Don\'t recognize', name) + print('OnSpinback: Don\'t recognize', name) verbose = 0 # Need some command line options... spin_panels = {} # Hooks to get from rose to panel labels @@ -539,6 +540,6 @@ ctrl_buttons = {} # Button widgets for command (NE) panel app = wx.App(False) MyFrame() if verbose: - print_('spin_panels', list(spin_panels)) - print_('ctrl_buttons', list(ctrl_buttons)) + print('spin_panels', list(spin_panels)) + print('ctrl_buttons', list(ctrl_buttons)) app.MainLoop() diff --git a/samples/simple/events.py b/samples/simple/events.py index af58312a..112875bd 100644 --- a/samples/simple/events.py +++ b/samples/simple/events.py @@ -1,9 +1,9 @@ +from __future__ import print_function import wx -from six import print_ -print_(wx.version()) -#import os; print_('PID:', os.getpid()); raw_input('Ready to start, press enter...') +print(wx.version()) +#import os; print('PID:', os.getpid()); raw_input('Ready to start, press enter...') class MyFrame(wx.Frame): @@ -13,21 +13,21 @@ class MyFrame(wx.Frame): wx.CallAfter(self.after, 1, 2, 3) def after(self, a, b, c): - print_('Called via wx.CallAfter:', a, b, c) + print('Called via wx.CallAfter:', a, b, c) def onSize(self, evt): - print_(repr(evt.Size)) + print(repr(evt.Size)) evt.Skip() class MyApp(wx.App): def OnInit(self): - print_('OnInit') + print('OnInit') frm = MyFrame(None, title="Hello with Events", size=(480,360)) frm.Show() return True def OnExit(self): - print_('OnExit') + print('OnExit') return 0 app = MyApp() diff --git a/wx/lib/pubsub/utils/misc.py b/wx/lib/pubsub/utils/misc.py index 7d772746..29a4b931 100644 --- a/wx/lib/pubsub/utils/misc.py +++ b/wx/lib/pubsub/utils/misc.py @@ -6,8 +6,9 @@ printTreeDocs and printTreeSpec. :license: BSD, see LICENSE_BSD_Simple.txt for details. """ +from __future__ import print_function + import sys -from .. import py2and3 __all__ = ('printImported', 'StructMsg', 'Callback', 'Enum' ) @@ -16,7 +17,7 @@ def printImported(): """Output a list of pubsub modules imported so far""" ll = sorted([mod for mod in sys.modules if mod.find('pubsub') >= 0]) - py2and3.print_('\n'.join(ll)) + print('\n'.join(ll)) class StructMsg: diff --git a/wx/lib/pubsub/utils/xmltopicdefnprovider.py b/wx/lib/pubsub/utils/xmltopicdefnprovider.py index 20954cc5..e9b4ea34 100644 --- a/wx/lib/pubsub/utils/xmltopicdefnprovider.py +++ b/wx/lib/pubsub/utils/xmltopicdefnprovider.py @@ -45,6 +45,8 @@ of the XML tree. :license: BSD, see LICENSE_BSD_Simple.txt for details. """ +from __future__ import print_function + __author__ = 'Joshua R English' __revision__ = 6 __date__ = '2013-07-27' @@ -80,7 +82,7 @@ def _get_elem(elem): try: elem = ET.fromstring(elem) except: - py2and3.print_("Value Error", elem) + print("Value Error", elem) raise ValueError("Cannot convert to element") return elem diff --git a/wx/tools/pywxrc.py b/wx/tools/pywxrc.py index 8596940d..552fcba1 100644 --- a/wx/tools/pywxrc.py +++ b/wx/tools/pywxrc.py @@ -31,9 +31,11 @@ Usage: python pywxrc.py -h -o, --output output filename, or - for stdout """ +from __future__ import print_function + import sys, os, getopt, glob, re import xml.dom.minidom as minidom -from six import print_, byte2int +from six import byte2int #---------------------------------------------------------------------- @@ -286,7 +288,7 @@ class XmlResourceCompiler: gettextStrings += self.FindStringsInNode(resourceDocument.firstChild) # now write it all out - print_(self.templates.FILE_HEADER, file=outputFile) + print(self.templates.FILE_HEADER, file=outputFile) # Note: Technically it is not legal to have anything other # than ascii for class and variable names, but since the user @@ -295,23 +297,23 @@ class XmlResourceCompiler: # later when they try to run the program. if subclasses: subclasses = self.ReplaceBlocks(u"\n".join(subclasses)) - print_(subclasses, file=outputFile) + print(subclasses, file=outputFile) if classes: classes = self.ReplaceBlocks(u"\n".join(classes)) - print_(classes, file=outputFile) + print(classes, file=outputFile) - print_(self.templates.INIT_RESOURE_HEADER, file=outputFile) + print(self.templates.INIT_RESOURE_HEADER, file=outputFile) if embedResources: - print_(self.templates.PREPARE_MEMFS, file=outputFile) + print(self.templates.PREPARE_MEMFS, file=outputFile) resources = u"\n".join(resources) - print_(resources, file=outputFile) + print(resources, file=outputFile) if generateGetText: # gettextStrings is a list of unicode strings as returned by ConvertText conversions = [u' _("%s")' % s for s in gettextStrings] conversion_block = u"\n".join(conversions) conversion_func = self.templates.GETTEXT_DUMMY_FUNC % conversion_block - print_(conversion_func, file=outputFile) + print(conversion_func, file=outputFile) #------------------------------------------------------------------- @@ -327,7 +329,7 @@ class XmlResourceCompiler: strings = self.FindStringsInNode(resource) # strings is a list of unicode strings as returned by ConvertText strings = ['_("%s");' % s for s in strings] - print_("\n".join(strings), file=outputFile) + print("\n".join(strings), file=outputFile) #------------------------------------------------------------------- @@ -940,10 +942,10 @@ def main(args=None): except IOError as exc: - print_("%s." % str(exc), file=sys.stderr) + print("%s." % str(exc), file=sys.stderr) else: if outputFilename != "-": - print_("Resources written to %s." % outputFilename, file=sys.stderr) + print("Resources written to %s." % outputFilename, file=sys.stderr) if __name__ == "__main__": main(sys.argv[1:]) From 0257f755cf753126ea68733f69ec148698f6e63a Mon Sep 17 00:00:00 2001 From: Alexandre Detiste Date: Fri, 22 Mar 2024 00:06:03 +0100 Subject: [PATCH 2/8] remove most of Python2 compatibility code --- build.py | 2 - buildtools/backports/six.py | 952 ------------------ demo/AUI_DockingWindowMgr.py | 2 +- demo/ArtProvider.py | 2 +- demo/ImageFromStream.py | 2 +- demo/Main.py | 22 +- demo/MimeTypesManager.py | 3 +- demo/PropertyGrid.py | 5 +- demo/RichTextCtrl.py | 2 +- demo/SVGImage_Bitmap.py | 3 - demo/SVGImage_Render.py | 3 - demo/agw/FoldPanelBar.py | 3 +- demo/agw/HyperTreeList.py | 6 +- demo/agw/Windows7Explorer_Contents.py | 6 - etg/config.py | 3 - etg/listctrl.py | 5 +- etg/wxdatetime.py | 4 - samples/doodle/superdoodle.py | 3 +- samples/floatcanvas/DrawBot.py | 3 +- samples/html2/webview_sample.py | 2 +- samples/printing/printing.py | 2 - samples/roses/clroses.py | 2 - samples/roses/wxroses.py | 2 - samples/simple/events.py | 2 - sphinxtools/modulehunter.py | 11 +- unittests/test_arraystring.py | 14 +- unittests/test_bitmap.py | 6 +- unittests/test_cmndata.py | 12 +- unittests/test_cursor.py | 6 +- unittests/test_image.py | 43 +- unittests/test_lib_cdate.py | 1 - unittests/test_lib_pubsub_defaultlog.py | 2 +- unittests/test_lib_pubsub_listener.py | 4 - unittests/test_lib_pubsub_notify.py | 2 +- unittests/test_lib_pubsub_notify4.py | 3 +- unittests/test_lib_pubsub_topicmgr.py | 2 +- unittests/test_pgvariant.py | 2 - unittests/test_stream.py | 3 +- unittests/test_string.py | 52 - unittests/test_variant.py | 4 +- unittests/test_window.py | 3 +- unittests/test_wxdatetime.py | 9 +- unittests/wtc.py | 15 +- wx/lib/CDate.py | 1 - wx/lib/agw/artmanager.py | 2 +- wx/lib/agw/aui/auibar.py | 7 +- wx/lib/agw/aui/auibook.py | 9 +- wx/lib/agw/aui/framemanager.py | 14 +- wx/lib/agw/customtreectrl.py | 5 - wx/lib/agw/flatmenu.py | 8 +- wx/lib/agw/flatnotebook.py | 4 +- wx/lib/agw/floatspin.py | 7 +- wx/lib/agw/fmcustomizedlg.py | 7 +- wx/lib/agw/hypertreelist.py | 7 +- wx/lib/agw/persist/persist_constants.py | 5 +- wx/lib/agw/persist/persistencemanager.py | 7 +- wx/lib/agw/ribbon/bar.py | 4 +- wx/lib/agw/ribbon/buttonbar.py | 4 +- wx/lib/agw/rulerctrl.py | 6 +- wx/lib/agw/scrolledthumbnail.py | 13 +- wx/lib/agw/ultimatelistctrl.py | 11 +- wx/lib/agw/xlsgrid.py | 8 +- wx/lib/colourchooser/__init__.py | 2 - wx/lib/colourchooser/pycolourchooser.py | 2 - wx/lib/colourchooser/pycolourslider.py | 2 - wx/lib/colourchooser/pypalette.py | 2 - wx/lib/embeddedimage.py | 4 +- wx/lib/fancytext.py | 15 +- wx/lib/floatcanvas/FCObjects.py | 21 +- wx/lib/floatcanvas/FloatCanvas.py | 3 - wx/lib/floatcanvas/Resources.py | 2 +- wx/lib/floatcanvas/ScreenShot.py | 2 +- wx/lib/graphics.py | 3 +- wx/lib/inspection.py | 3 +- wx/lib/intctrl.py | 20 +- wx/lib/masked/combobox.py | 4 +- wx/lib/masked/ipaddrctrl.py | 3 +- wx/lib/masked/maskededit.py | 39 +- wx/lib/masked/numctrl.py | 3 +- wx/lib/masked/timectrl.py | 7 +- wx/lib/mixins/listctrl.py | 11 +- wx/lib/multisash.py | 5 +- wx/lib/pdfviewer/viewer.py | 6 +- wx/lib/printout.py | 10 +- wx/lib/pubsub/core/callables.py | 8 +- wx/lib/pubsub/core/imp2.py | 3 +- wx/lib/pubsub/core/kwargs/publisher.py | 6 +- wx/lib/pubsub/core/kwargs/topicargspecimpl.py | 7 +- wx/lib/pubsub/core/publisherbase.py | 4 +- wx/lib/pubsub/core/topicdefnprovider.py | 15 +- wx/lib/pubsub/core/topicmgr.py | 6 +- wx/lib/pubsub/core/topicobj.py | 22 +- wx/lib/pubsub/core/topicutils.py | 11 +- wx/lib/pubsub/py2and3.py | 608 ----------- wx/lib/pubsub/utils/misc.py | 2 - wx/lib/pubsub/utils/xmltopicdefnprovider.py | 7 +- wx/lib/rcsizer.py | 4 +- wx/lib/softwareupdate.py | 10 +- wx/lib/wxcairo/wx_pycairo.py | 15 +- wx/py/filling.py | 22 +- wx/py/images.py | 2 +- wx/py/interpreter.py | 11 +- wx/py/introspect.py | 17 +- wx/py/shell.py | 12 +- wx/py/sliceshell.py | 8 +- wx/tools/pywxrc.py | 2 - wx/tools/wxget.py | 13 +- wx/tools/wxget_docs_demo.py | 16 +- 108 files changed, 220 insertions(+), 2144 deletions(-) delete mode 100644 buildtools/backports/six.py delete mode 100644 wx/lib/pubsub/py2and3.py diff --git a/build.py b/build.py index ca27710e..420df995 100755 --- a/build.py +++ b/build.py @@ -13,8 +13,6 @@ # License: wxWindows License #---------------------------------------------------------------------- -from __future__ import absolute_import - import sys import glob import hashlib diff --git a/buildtools/backports/six.py b/buildtools/backports/six.py deleted file mode 100644 index 89b2188f..00000000 --- a/buildtools/backports/six.py +++ /dev/null @@ -1,952 +0,0 @@ -# Copyright (c) 2010-2018 Benjamin Peterson -# -# 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. - -"""Utilities for writing code that runs on Python 2 and 3""" - -from __future__ import absolute_import - -import functools -import itertools -import operator -import sys -import types - -__author__ = "Benjamin Peterson " -__version__ = "1.12.0" - - -# Useful for very coarse version differentiation. -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 -PY34 = sys.version_info[0:2] >= (3, 4) - -if PY3: - string_types = str, - integer_types = int, - class_types = type, - text_type = str - binary_type = bytes - - MAXSIZE = sys.maxsize -else: - string_types = basestring, - integer_types = (int, long) - class_types = (type, types.ClassType) - text_type = unicode - binary_type = str - - if sys.platform.startswith("java"): - # Jython always uses 32 bits. - MAXSIZE = int((1 << 31) - 1) - else: - # It's possible to have sizeof(long) != sizeof(Py_ssize_t). - class X(object): - - def __len__(self): - return 1 << 31 - try: - len(X()) - except OverflowError: - # 32-bit - MAXSIZE = int((1 << 31) - 1) - else: - # 64-bit - MAXSIZE = int((1 << 63) - 1) - del X - - -def _add_doc(func, doc): - """Add documentation to a function.""" - func.__doc__ = doc - - -def _import_module(name): - """Import module, returning the module after the last dot.""" - __import__(name) - return sys.modules[name] - - -class _LazyDescr(object): - - def __init__(self, name): - self.name = name - - def __get__(self, obj, tp): - result = self._resolve() - setattr(obj, self.name, result) # Invokes __set__. - try: - # This is a bit ugly, but it avoids running this again by - # removing this descriptor. - delattr(obj.__class__, self.name) - except AttributeError: - pass - return result - - -class MovedModule(_LazyDescr): - - def __init__(self, name, old, new=None): - super(MovedModule, self).__init__(name) - if PY3: - if new is None: - new = name - self.mod = new - else: - self.mod = old - - def _resolve(self): - return _import_module(self.mod) - - def __getattr__(self, attr): - _module = self._resolve() - value = getattr(_module, attr) - setattr(self, attr, value) - return value - - -class _LazyModule(types.ModuleType): - - def __init__(self, name): - super(_LazyModule, self).__init__(name) - self.__doc__ = self.__class__.__doc__ - - def __dir__(self): - attrs = ["__doc__", "__name__"] - attrs += [attr.name for attr in self._moved_attributes] - return attrs - - # Subclasses should override this - _moved_attributes = [] - - -class MovedAttribute(_LazyDescr): - - def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): - super(MovedAttribute, self).__init__(name) - if PY3: - if new_mod is None: - new_mod = name - self.mod = new_mod - if new_attr is None: - if old_attr is None: - new_attr = name - else: - new_attr = old_attr - self.attr = new_attr - else: - self.mod = old_mod - if old_attr is None: - old_attr = name - self.attr = old_attr - - def _resolve(self): - module = _import_module(self.mod) - return getattr(module, self.attr) - - -class _SixMetaPathImporter(object): - - """ - A meta path importer to import six.moves and its submodules. - - This class implements a PEP302 finder and loader. It should be compatible - with Python 2.5 and all existing versions of Python3 - """ - - def __init__(self, six_module_name): - self.name = six_module_name - self.known_modules = {} - - def _add_module(self, mod, *fullnames): - for fullname in fullnames: - self.known_modules[self.name + "." + fullname] = mod - - def _get_module(self, fullname): - return self.known_modules[self.name + "." + fullname] - - def find_module(self, fullname, path=None): - if fullname in self.known_modules: - return self - return None - - def __get_module(self, fullname): - try: - return self.known_modules[fullname] - except KeyError: - raise ImportError("This loader does not know module " + fullname) - - def load_module(self, fullname): - try: - # in case of a reload - return sys.modules[fullname] - except KeyError: - pass - mod = self.__get_module(fullname) - if isinstance(mod, MovedModule): - mod = mod._resolve() - else: - mod.__loader__ = self - sys.modules[fullname] = mod - return mod - - def is_package(self, fullname): - """ - Return true, if the named module is a package. - - We need this method to get correct spec objects with - Python 3.4 (see PEP451) - """ - return hasattr(self.__get_module(fullname), "__path__") - - def get_code(self, fullname): - """Return None - - Required, if is_package is implemented""" - self.__get_module(fullname) # eventually raises ImportError - return None - get_source = get_code # same as get_code - -_importer = _SixMetaPathImporter(__name__) - - -class _MovedItems(_LazyModule): - - """Lazy loading of moved objects""" - __path__ = [] # mark as package - - -_moved_attributes = [ - MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), - MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), - MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), - MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), - MovedAttribute("intern", "__builtin__", "sys"), - MovedAttribute("map", "itertools", "builtins", "imap", "map"), - MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), - MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), - MovedAttribute("getoutput", "commands", "subprocess"), - MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), - MovedAttribute("reduce", "__builtin__", "functools"), - MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), - MovedAttribute("StringIO", "StringIO", "io"), - MovedAttribute("UserDict", "UserDict", "collections"), - MovedAttribute("UserList", "UserList", "collections"), - MovedAttribute("UserString", "UserString", "collections"), - MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), - MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), - MovedModule("builtins", "__builtin__"), - MovedModule("configparser", "ConfigParser"), - MovedModule("copyreg", "copy_reg"), - MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), - MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), - MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), - MovedModule("http_cookies", "Cookie", "http.cookies"), - MovedModule("html_entities", "htmlentitydefs", "html.entities"), - MovedModule("html_parser", "HTMLParser", "html.parser"), - MovedModule("http_client", "httplib", "http.client"), - MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), - MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"), - MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), - MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), - MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), - MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), - MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), - MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), - MovedModule("cPickle", "cPickle", "pickle"), - MovedModule("queue", "Queue"), - MovedModule("reprlib", "repr"), - MovedModule("socketserver", "SocketServer"), - MovedModule("_thread", "thread", "_thread"), - MovedModule("tkinter", "Tkinter"), - MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), - MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), - MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), - MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), - MovedModule("tkinter_tix", "Tix", "tkinter.tix"), - MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), - MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), - MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), - MovedModule("tkinter_colorchooser", "tkColorChooser", - "tkinter.colorchooser"), - MovedModule("tkinter_commondialog", "tkCommonDialog", - "tkinter.commondialog"), - MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), - MovedModule("tkinter_font", "tkFont", "tkinter.font"), - MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), - MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", - "tkinter.simpledialog"), - MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), - MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), - MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), - MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), - MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), - MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), -] -# Add windows specific modules. -if sys.platform == "win32": - _moved_attributes += [ - MovedModule("winreg", "_winreg"), - ] - -for attr in _moved_attributes: - setattr(_MovedItems, attr.name, attr) - if isinstance(attr, MovedModule): - _importer._add_module(attr, "moves." + attr.name) -del attr - -_MovedItems._moved_attributes = _moved_attributes - -moves = _MovedItems(__name__ + ".moves") -_importer._add_module(moves, "moves") - - -class Module_six_moves_urllib_parse(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_parse""" - - -_urllib_parse_moved_attributes = [ - MovedAttribute("ParseResult", "urlparse", "urllib.parse"), - MovedAttribute("SplitResult", "urlparse", "urllib.parse"), - MovedAttribute("parse_qs", "urlparse", "urllib.parse"), - MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), - MovedAttribute("urldefrag", "urlparse", "urllib.parse"), - MovedAttribute("urljoin", "urlparse", "urllib.parse"), - MovedAttribute("urlparse", "urlparse", "urllib.parse"), - MovedAttribute("urlsplit", "urlparse", "urllib.parse"), - MovedAttribute("urlunparse", "urlparse", "urllib.parse"), - MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), - MovedAttribute("quote", "urllib", "urllib.parse"), - MovedAttribute("quote_plus", "urllib", "urllib.parse"), - MovedAttribute("unquote", "urllib", "urllib.parse"), - MovedAttribute("unquote_plus", "urllib", "urllib.parse"), - MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"), - MovedAttribute("urlencode", "urllib", "urllib.parse"), - MovedAttribute("splitquery", "urllib", "urllib.parse"), - MovedAttribute("splittag", "urllib", "urllib.parse"), - MovedAttribute("splituser", "urllib", "urllib.parse"), - MovedAttribute("splitvalue", "urllib", "urllib.parse"), - MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), - MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), - MovedAttribute("uses_params", "urlparse", "urllib.parse"), - MovedAttribute("uses_query", "urlparse", "urllib.parse"), - MovedAttribute("uses_relative", "urlparse", "urllib.parse"), -] -for attr in _urllib_parse_moved_attributes: - setattr(Module_six_moves_urllib_parse, attr.name, attr) -del attr - -Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes - -_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), - "moves.urllib_parse", "moves.urllib.parse") - - -class Module_six_moves_urllib_error(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_error""" - - -_urllib_error_moved_attributes = [ - MovedAttribute("URLError", "urllib2", "urllib.error"), - MovedAttribute("HTTPError", "urllib2", "urllib.error"), - MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), -] -for attr in _urllib_error_moved_attributes: - setattr(Module_six_moves_urllib_error, attr.name, attr) -del attr - -Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes - -_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), - "moves.urllib_error", "moves.urllib.error") - - -class Module_six_moves_urllib_request(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_request""" - - -_urllib_request_moved_attributes = [ - MovedAttribute("urlopen", "urllib2", "urllib.request"), - MovedAttribute("install_opener", "urllib2", "urllib.request"), - MovedAttribute("build_opener", "urllib2", "urllib.request"), - MovedAttribute("pathname2url", "urllib", "urllib.request"), - MovedAttribute("url2pathname", "urllib", "urllib.request"), - MovedAttribute("getproxies", "urllib", "urllib.request"), - MovedAttribute("Request", "urllib2", "urllib.request"), - MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), - MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), - MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), - MovedAttribute("BaseHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), - MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), - MovedAttribute("FileHandler", "urllib2", "urllib.request"), - MovedAttribute("FTPHandler", "urllib2", "urllib.request"), - MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), - MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), - MovedAttribute("urlretrieve", "urllib", "urllib.request"), - MovedAttribute("urlcleanup", "urllib", "urllib.request"), - MovedAttribute("URLopener", "urllib", "urllib.request"), - MovedAttribute("FancyURLopener", "urllib", "urllib.request"), - MovedAttribute("proxy_bypass", "urllib", "urllib.request"), - MovedAttribute("parse_http_list", "urllib2", "urllib.request"), - MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"), -] -for attr in _urllib_request_moved_attributes: - setattr(Module_six_moves_urllib_request, attr.name, attr) -del attr - -Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes - -_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), - "moves.urllib_request", "moves.urllib.request") - - -class Module_six_moves_urllib_response(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_response""" - - -_urllib_response_moved_attributes = [ - MovedAttribute("addbase", "urllib", "urllib.response"), - MovedAttribute("addclosehook", "urllib", "urllib.response"), - MovedAttribute("addinfo", "urllib", "urllib.response"), - MovedAttribute("addinfourl", "urllib", "urllib.response"), -] -for attr in _urllib_response_moved_attributes: - setattr(Module_six_moves_urllib_response, attr.name, attr) -del attr - -Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes - -_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), - "moves.urllib_response", "moves.urllib.response") - - -class Module_six_moves_urllib_robotparser(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_robotparser""" - - -_urllib_robotparser_moved_attributes = [ - MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), -] -for attr in _urllib_robotparser_moved_attributes: - setattr(Module_six_moves_urllib_robotparser, attr.name, attr) -del attr - -Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes - -_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), - "moves.urllib_robotparser", "moves.urllib.robotparser") - - -class Module_six_moves_urllib(types.ModuleType): - - """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" - __path__ = [] # mark as package - parse = _importer._get_module("moves.urllib_parse") - error = _importer._get_module("moves.urllib_error") - request = _importer._get_module("moves.urllib_request") - response = _importer._get_module("moves.urllib_response") - robotparser = _importer._get_module("moves.urllib_robotparser") - - def __dir__(self): - return ['parse', 'error', 'request', 'response', 'robotparser'] - -_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), - "moves.urllib") - - -def add_move(move): - """Add an item to six.moves.""" - setattr(_MovedItems, move.name, move) - - -def remove_move(name): - """Remove item from six.moves.""" - try: - delattr(_MovedItems, name) - except AttributeError: - try: - del moves.__dict__[name] - except KeyError: - raise AttributeError("no such move, %r" % (name,)) - - -if PY3: - _meth_func = "__func__" - _meth_self = "__self__" - - _func_closure = "__closure__" - _func_code = "__code__" - _func_defaults = "__defaults__" - _func_globals = "__globals__" -else: - _meth_func = "im_func" - _meth_self = "im_self" - - _func_closure = "func_closure" - _func_code = "func_code" - _func_defaults = "func_defaults" - _func_globals = "func_globals" - - -try: - advance_iterator = next -except NameError: - def advance_iterator(it): - return it.next() -next = advance_iterator - - -try: - callable = callable -except NameError: - def callable(obj): - return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) - - -if PY3: - def get_unbound_function(unbound): - return unbound - - create_bound_method = types.MethodType - - def create_unbound_method(func, cls): - return func - - Iterator = object -else: - def get_unbound_function(unbound): - return unbound.im_func - - def create_bound_method(func, obj): - return types.MethodType(func, obj, obj.__class__) - - def create_unbound_method(func, cls): - return types.MethodType(func, None, cls) - - class Iterator(object): - - def next(self): - return type(self).__next__(self) - - callable = callable -_add_doc(get_unbound_function, - """Get the function out of a possibly unbound function""") - - -get_method_function = operator.attrgetter(_meth_func) -get_method_self = operator.attrgetter(_meth_self) -get_function_closure = operator.attrgetter(_func_closure) -get_function_code = operator.attrgetter(_func_code) -get_function_defaults = operator.attrgetter(_func_defaults) -get_function_globals = operator.attrgetter(_func_globals) - - -if PY3: - def iterkeys(d, **kw): - return iter(d.keys(**kw)) - - def itervalues(d, **kw): - return iter(d.values(**kw)) - - def iteritems(d, **kw): - return iter(d.items(**kw)) - - def iterlists(d, **kw): - return iter(d.lists(**kw)) - - viewkeys = operator.methodcaller("keys") - - viewvalues = operator.methodcaller("values") - - viewitems = operator.methodcaller("items") -else: - def iterkeys(d, **kw): - return d.iterkeys(**kw) - - def itervalues(d, **kw): - return d.itervalues(**kw) - - def iteritems(d, **kw): - return d.iteritems(**kw) - - def iterlists(d, **kw): - return d.iterlists(**kw) - - viewkeys = operator.methodcaller("viewkeys") - - viewvalues = operator.methodcaller("viewvalues") - - viewitems = operator.methodcaller("viewitems") - -_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") -_add_doc(itervalues, "Return an iterator over the values of a dictionary.") -_add_doc(iteritems, - "Return an iterator over the (key, value) pairs of a dictionary.") -_add_doc(iterlists, - "Return an iterator over the (key, [values]) pairs of a dictionary.") - - -if PY3: - def b(s): - return s.encode("latin-1") - - def u(s): - return s - unichr = chr - import struct - int2byte = struct.Struct(">B").pack - del struct - byte2int = operator.itemgetter(0) - indexbytes = operator.getitem - iterbytes = iter - import io - StringIO = io.StringIO - BytesIO = io.BytesIO - _assertCountEqual = "assertCountEqual" - if sys.version_info[1] <= 1: - _assertRaisesRegex = "assertRaisesRegexp" - _assertRegex = "assertRegexpMatches" - else: - _assertRaisesRegex = "assertRaisesRegex" - _assertRegex = "assertRegex" -else: - def b(s): - return s - # Workaround for standalone backslash - - def u(s): - return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") - unichr = unichr - int2byte = chr - - def byte2int(bs): - return ord(bs[0]) - - def indexbytes(buf, i): - return ord(buf[i]) - iterbytes = functools.partial(itertools.imap, ord) - import StringIO - StringIO = BytesIO = StringIO.StringIO - _assertCountEqual = "assertItemsEqual" - _assertRaisesRegex = "assertRaisesRegexp" - _assertRegex = "assertRegexpMatches" -_add_doc(b, """Byte literal""") -_add_doc(u, """Text literal""") - - -def assertCountEqual(self, *args, **kwargs): - return getattr(self, _assertCountEqual)(*args, **kwargs) - - -def assertRaisesRegex(self, *args, **kwargs): - return getattr(self, _assertRaisesRegex)(*args, **kwargs) - - -def assertRegex(self, *args, **kwargs): - return getattr(self, _assertRegex)(*args, **kwargs) - - -if PY3: - exec_ = getattr(moves.builtins, "exec") - - def reraise(tp, value, tb=None): - try: - if value is None: - value = tp() - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - finally: - value = None - tb = None - -else: - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - - exec_("""def reraise(tp, value, tb=None): - try: - raise tp, value, tb - finally: - tb = None -""") - - -if sys.version_info[:2] == (3, 2): - exec_("""def raise_from(value, from_value): - try: - if from_value is None: - raise value - raise value from from_value - finally: - value = None -""") -elif sys.version_info[:2] > (3, 2): - exec_("""def raise_from(value, from_value): - try: - raise value from from_value - finally: - value = None -""") -else: - def raise_from(value, from_value): - raise value - - -print_ = getattr(moves.builtins, "print", None) -if print_ is None: - def print_(*args, **kwargs): - """The new-style print function for Python 2.4 and 2.5.""" - fp = kwargs.pop("file", sys.stdout) - if fp is None: - return - - def write(data): - if not isinstance(data, basestring): - data = str(data) - # If the file has an encoding, encode unicode with it. - if (isinstance(fp, file) and - isinstance(data, unicode) and - fp.encoding is not None): - errors = getattr(fp, "errors", None) - if errors is None: - errors = "strict" - data = data.encode(fp.encoding, errors) - fp.write(data) - want_unicode = False - sep = kwargs.pop("sep", None) - if sep is not None: - if isinstance(sep, unicode): - want_unicode = True - elif not isinstance(sep, str): - raise TypeError("sep must be None or a string") - end = kwargs.pop("end", None) - if end is not None: - if isinstance(end, unicode): - want_unicode = True - elif not isinstance(end, str): - raise TypeError("end must be None or a string") - if kwargs: - raise TypeError("invalid keyword arguments to print()") - if not want_unicode: - for arg in args: - if isinstance(arg, unicode): - want_unicode = True - break - if want_unicode: - newline = unicode("\n") - space = unicode(" ") - else: - newline = "\n" - space = " " - if sep is None: - sep = space - if end is None: - end = newline - for i, arg in enumerate(args): - if i: - write(sep) - write(arg) - write(end) -if sys.version_info[:2] < (3, 3): - _print = print_ - - def print_(*args, **kwargs): - fp = kwargs.get("file", sys.stdout) - flush = kwargs.pop("flush", False) - _print(*args, **kwargs) - if flush and fp is not None: - fp.flush() - -_add_doc(reraise, """Reraise an exception.""") - -if sys.version_info[0:2] < (3, 4): - def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, - updated=functools.WRAPPER_UPDATES): - def wrapper(f): - f = functools.wraps(wrapped, assigned, updated)(f) - f.__wrapped__ = wrapped - return f - return wrapper -else: - wraps = functools.wraps - - -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - # This requires a bit of explanation: the basic idea is to make a dummy - # metaclass for one level of class instantiation that replaces itself with - # the actual metaclass. - class metaclass(type): - - def __new__(cls, name, this_bases, d): - return meta(name, bases, d) - - @classmethod - def __prepare__(cls, name, this_bases): - return meta.__prepare__(name, bases) - return type.__new__(metaclass, 'temporary_class', (), {}) - - -def add_metaclass(metaclass): - """Class decorator for creating a class with a metaclass.""" - def wrapper(cls): - orig_vars = cls.__dict__.copy() - slots = orig_vars.get('__slots__') - if slots is not None: - if isinstance(slots, str): - slots = [slots] - for slots_var in slots: - orig_vars.pop(slots_var) - orig_vars.pop('__dict__', None) - orig_vars.pop('__weakref__', None) - if hasattr(cls, '__qualname__'): - orig_vars['__qualname__'] = cls.__qualname__ - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper - - -def ensure_binary(s, encoding='utf-8', errors='strict'): - """Coerce **s** to six.binary_type. - - For Python 2: - - `unicode` -> encoded to `str` - - `str` -> `str` - - For Python 3: - - `str` -> encoded to `bytes` - - `bytes` -> `bytes` - """ - if isinstance(s, text_type): - return s.encode(encoding, errors) - elif isinstance(s, binary_type): - return s - else: - raise TypeError("not expecting type '%s'" % type(s)) - - -def ensure_str(s, encoding='utf-8', errors='strict'): - """Coerce *s* to `str`. - - For Python 2: - - `unicode` -> encoded to `str` - - `str` -> `str` - - For Python 3: - - `str` -> `str` - - `bytes` -> decoded to `str` - """ - if not isinstance(s, (text_type, binary_type)): - raise TypeError("not expecting type '%s'" % type(s)) - if PY2 and isinstance(s, text_type): - s = s.encode(encoding, errors) - elif PY3 and isinstance(s, binary_type): - s = s.decode(encoding, errors) - return s - - -def ensure_text(s, encoding='utf-8', errors='strict'): - """Coerce *s* to six.text_type. - - For Python 2: - - `unicode` -> `unicode` - - `str` -> `unicode` - - For Python 3: - - `str` -> `str` - - `bytes` -> decoded to `str` - """ - if isinstance(s, binary_type): - return s.decode(encoding, errors) - elif isinstance(s, text_type): - return s - else: - raise TypeError("not expecting type '%s'" % type(s)) - - - -def python_2_unicode_compatible(klass): - """ - A decorator that defines __unicode__ and __str__ methods under Python 2. - Under Python 3 it does nothing. - - To support Python 2 and 3 with a single code base, define a __str__ method - returning text and apply this decorator to the class. - """ - if PY2: - if '__str__' not in klass.__dict__: - raise ValueError("@python_2_unicode_compatible cannot be applied " - "to %s because it doesn't define __str__()." % - klass.__name__) - klass.__unicode__ = klass.__str__ - klass.__str__ = lambda self: self.__unicode__().encode('utf-8') - return klass - - -# Complete the moves implementation. -# This code is at the end of this module to speed up module loading. -# Turn this module into a package. -__path__ = [] # required for PEP 302 and PEP 451 -__package__ = __name__ # see PEP 366 @ReservedAssignment -if globals().get("__spec__") is not None: - __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable -# Remove other six meta path importers, since they cause problems. This can -# happen if six is removed from sys.modules and then reloaded. (Setuptools does -# this for some reason.) -if sys.meta_path: - for i, importer in enumerate(sys.meta_path): - # Here's some real nastiness: Another "instance" of the six module might - # be floating around. Therefore, we can't use isinstance() to check for - # the six meta path importer, since the other six instance will have - # inserted an importer with different class. - if (type(importer).__name__ == "_SixMetaPathImporter" and - importer.name == __name__): - del sys.meta_path[i] - break - del i, importer -# Finally, add the importer to the meta path import hook. -sys.meta_path.append(_importer) diff --git a/demo/AUI_DockingWindowMgr.py b/demo/AUI_DockingWindowMgr.py index 0faca4f7..7b62face 100644 --- a/demo/AUI_DockingWindowMgr.py +++ b/demo/AUI_DockingWindowMgr.py @@ -5,7 +5,7 @@ import wx.grid import wx.html import wx.aui as aui -from six import BytesIO +from io import BytesIO ID_CreateTree = wx.NewIdRef() ID_CreateGrid = wx.NewIdRef() diff --git a/demo/ArtProvider.py b/demo/ArtProvider.py index b890894e..b5a8fa1f 100644 --- a/demo/ArtProvider.py +++ b/demo/ArtProvider.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Tags: phoenix-port, py3-port -from six import BytesIO +from io import BytesIO import wx diff --git a/demo/ImageFromStream.py b/demo/ImageFromStream.py index f428265e..5a490c5f 100644 --- a/demo/ImageFromStream.py +++ b/demo/ImageFromStream.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Tags: phoenix-port, py3-port -from six import BytesIO +from io import BytesIO import wx diff --git a/demo/Main.py b/demo/Main.py index db956362..0c5ea6ee 100644 --- a/demo/Main.py +++ b/demo/Main.py @@ -54,6 +54,7 @@ import sys, os, time, traceback import re import shutil +from io import BytesIO from threading import Thread @@ -66,8 +67,6 @@ from wx.adv import TaskBarIcon as TaskBarIcon from wx.adv import SplashScreen as SplashScreen import wx.lib.mixins.inspection -import six -from six import exec_, BytesIO from six.moves import cPickle from six.moves import urllib @@ -417,10 +416,7 @@ class InternetThread(Thread): try: url = _docsURL % ReplaceCapitals(self.selectedClass) with urllib.request.urlopen(url) as fid: - if six.PY2: - originalText = fid.read() - else: - originalText = fid.read().decode("utf-8") + originalText = fid.read().decode("utf-8") text = RemoveHTMLTags(originalText).split("\n") data = FindWindowStyles(text, originalText, self.selectedClass) @@ -962,9 +958,6 @@ def SearchDemo(name, keyword): with open(GetOriginalFilename(name), "rt") as fid: fullText = fid.read() - if six.PY2: - fullText = fullText.decode("iso-8859-1") - if fullText.find(keyword) >= 0: return True @@ -1075,10 +1068,9 @@ class DemoModules(object): self.modules = [[dict(), "" , "" , "" , None], [dict(), "" , "" , "" , None]] - getcwd = os.getcwd if six.PY3 else os.getcwdu for i in [modOriginal, modModified]: self.modules[i][0]['__file__'] = \ - os.path.join(getcwd(), GetOriginalFilename(name)) + os.path.join(os.getcwd(), GetOriginalFilename(name)) # load original module self.LoadFromFile(modOriginal, GetOriginalFilename(name)) @@ -1102,12 +1094,10 @@ class DemoModules(object): if self.name != __name__: source = self.modules[modID][1] description = self.modules[modID][2] - if six.PY2: - description = description.encode(sys.getfilesystemencoding()) try: code = compile(source, description, "exec") - exec_(code, self.modules[modID][0]) + exec(code, self.modules[modID][0]) except: self.modules[modID][4] = DemoError(sys.exc_info()) self.modules[modID][0] = None @@ -2228,10 +2218,6 @@ class wxPythonDemo(wx.Frame): self.pickledData[itemText] = data - if six.PY2: - # TODO: verify that this encoding is correct - text = text.decode('iso8859_1') - self.StopDownload() self.ovr.SetPage(text) #print("load time: ", time.time() - start) diff --git a/demo/MimeTypesManager.py b/demo/MimeTypesManager.py index 79bc3abe..ca14ff10 100644 --- a/demo/MimeTypesManager.py +++ b/demo/MimeTypesManager.py @@ -18,8 +18,7 @@ import images # helper function to make sure we don't convert unicode objects to strings # or vice versa when converting lists and None values to text. -import six -convert = six.text_type +convert = str #---------------------------------------------------------------------------- diff --git a/demo/PropertyGrid.py b/demo/PropertyGrid.py index fbef29e3..3e87798c 100644 --- a/demo/PropertyGrid.py +++ b/demo/PropertyGrid.py @@ -9,7 +9,6 @@ import wx import wx.adv import wx.propgrid as wxpg -from six import exec_ _ = wx.GetTranslation @@ -870,7 +869,7 @@ class TestPanel( wx.Panel ): sandbox = {'obj':ValueObject(), 'wx':wx, 'datetime':datetime} - exec_(dlg.tc.GetValue(), sandbox) + exec(dlg.tc.GetValue(), sandbox) t_start = time.time() #print(sandbox['obj'].__dict__) self.pg.SetPropertyValues(sandbox['obj']) @@ -917,7 +916,7 @@ class TestPanel( wx.Panel ): with MemoDialog(self,"Enter Content for Object Used for AutoFill",default_object_content1) as dlg: if dlg.ShowModal() == wx.ID_OK: sandbox = {'object':ValueObject(),'wx':wx} - exec_(dlg.tc.GetValue(), sandbox) + exec(dlg.tc.GetValue(), sandbox) t_start = time.time() self.pg.AutoFill(sandbox['object']) t_end = time.time() diff --git a/demo/RichTextCtrl.py b/demo/RichTextCtrl.py index 7ac6b1cb..b88502af 100644 --- a/demo/RichTextCtrl.py +++ b/demo/RichTextCtrl.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from six import BytesIO +from io import BytesIO import wx import wx.richtext as rt diff --git a/demo/SVGImage_Bitmap.py b/demo/SVGImage_Bitmap.py index 5284291d..0b7c51d4 100644 --- a/demo/SVGImage_Bitmap.py +++ b/demo/SVGImage_Bitmap.py @@ -2,7 +2,6 @@ import sys import os import glob -import six import wx from wx.svg import SVGimage @@ -26,8 +25,6 @@ class SVGBitmapDisplay(wx.Panel): def UpdateSVG(self, svg_filename): - if six.PY2 and isinstance(svg_filename, unicode): - svg_filename = svg_filename.encode(sys.getfilesystemencoding()) img = SVGimage.CreateFromFile(svg_filename) bmp = img.ConvertToScaledBitmap(self.bmp_size, self) self.statbmp.SetBitmap(bmp) diff --git a/demo/SVGImage_Render.py b/demo/SVGImage_Render.py index 579eb5f2..5c21cf22 100644 --- a/demo/SVGImage_Render.py +++ b/demo/SVGImage_Render.py @@ -2,7 +2,6 @@ import sys import os import glob -import six import wx from wx.svg import SVGimage @@ -26,8 +25,6 @@ class SVGRenderPanel(wx.Panel): def SetSVGFile(self, svg_filename): - if six.PY2 and isinstance(svg_filename, unicode): - svg_filename = svg_filename.encode(sys.getfilesystemencoding()) self._img = SVGimage.CreateFromFile(svg_filename) self.Refresh() diff --git a/demo/agw/FoldPanelBar.py b/demo/agw/FoldPanelBar.py index 7d191bc5..62201e5c 100644 --- a/demo/agw/FoldPanelBar.py +++ b/demo/agw/FoldPanelBar.py @@ -5,8 +5,7 @@ import wx import wx.adv import os import sys - -from six import BytesIO +from io import BytesIO try: dirName = os.path.dirname(os.path.abspath(__file__)) diff --git a/demo/agw/HyperTreeList.py b/demo/agw/HyperTreeList.py index c88e6729..c00a8125 100644 --- a/demo/agw/HyperTreeList.py +++ b/demo/agw/HyperTreeList.py @@ -4,15 +4,13 @@ import os import string import random +import sys +from io import BytesIO import wx import wx.lib.colourselect as csel import wx.lib.colourutils as cutils -import sys - -from six import BytesIO - try: dirName = os.path.dirname(os.path.abspath(__file__)) except: diff --git a/demo/agw/Windows7Explorer_Contents.py b/demo/agw/Windows7Explorer_Contents.py index b23df0e1..c24db908 100644 --- a/demo/agw/Windows7Explorer_Contents.py +++ b/demo/agw/Windows7Explorer_Contents.py @@ -3,7 +3,6 @@ import sys import os import wx -import six import time import datetime import operator @@ -27,12 +26,7 @@ except ImportError: # if it's not there locally, try the wxPython lib. bitmapDir = os.path.join(dirName, 'bitmaps') sys.path.append(os.path.split(dirName)[0]) -# helper function to make sure we don't convert unicode objects to strings -# or vice versa when converting lists and None values to text. convert = str -if six.PY2: - if 'unicode' in wx.PlatformInfo: - convert = unicode def FormatFileSize(size): diff --git a/etg/config.py b/etg/config.py index 6a012223..c2bc87c8 100644 --- a/etg/config.py +++ b/etg/config.py @@ -62,10 +62,7 @@ def run(): return rv; """) c.addPyMethod('ReadInt', '(self, key, defaultVal=0)', body="""\ - import six rv = self._cpp_ReadInt(key, defaultVal) - if six.PY2: - rv = int(rv) return rv """) diff --git a/etg/listctrl.py b/etg/listctrl.py index dc531a3e..2c76b003 100644 --- a/etg/listctrl.py +++ b/etg/listctrl.py @@ -316,10 +316,9 @@ def run(): sequence with an item for each column''', body="""\ if len(entry): - from six import text_type - pos = self.InsertItem(self.GetItemCount(), text_type(entry[0])) + pos = self.InsertItem(self.GetItemCount(), str(entry[0])) for i in range(1, len(entry)): - self.SetItem(pos, i, text_type(entry[i])) + self.SetItem(pos, i, str(entry[i])) return pos """) diff --git a/etg/wxdatetime.py b/etg/wxdatetime.py index 709f60f6..eb18c8ed 100644 --- a/etg/wxdatetime.py +++ b/etg/wxdatetime.py @@ -254,20 +254,16 @@ def run(): c.addPyMethod('__repr__', '(self)', """\ - from six import PY2 if self.IsValid(): f = self.Format() - if PY2: f = f.encode('utf-8') return '' % f else: return '' """) c.addPyMethod('__str__', '(self)', """\ - from six import PY2 if self.IsValid(): f = self.Format() - if PY2: f = f.encode('utf-8') return f else: return "INVALID DateTime" diff --git a/samples/doodle/superdoodle.py b/samples/doodle/superdoodle.py index 0b3d0932..feff7ff2 100644 --- a/samples/doodle/superdoodle.py +++ b/samples/doodle/superdoodle.py @@ -11,8 +11,7 @@ implemented using an wx.html.HtmlWindow. import sys import os - -from six.moves import cPickle as pickle +import pickle import wx import wx.html diff --git a/samples/floatcanvas/DrawBot.py b/samples/floatcanvas/DrawBot.py index 52ea41e0..5bb2a539 100644 --- a/samples/floatcanvas/DrawBot.py +++ b/samples/floatcanvas/DrawBot.py @@ -14,7 +14,6 @@ I think it's easier with FloatCavnas, and you get zoomign and scrolling to boot! """ import wx -from six import moves from math import * try: # see if there is a local FloatCanvas to use @@ -54,7 +53,7 @@ class DrawFrame(wx.Frame): Canvas = self.Canvas phi = (sqrt(5) + 1)/2 - 1 oradius = 10.0 - for i in moves.xrange(720): + for i in range(720): radius = 1.5 * oradius * sin(i * pi/720) Color = (255*(i / 720.), 255*( i / 720.), 255 * 0.25) x = oradius + 0.25*i*cos(phi*i*2*pi) diff --git a/samples/html2/webview_sample.py b/samples/html2/webview_sample.py index 22b6489c..61fbf776 100644 --- a/samples/html2/webview_sample.py +++ b/samples/html2/webview_sample.py @@ -1,6 +1,6 @@ import sys import os -from six import BytesIO +from io import BytesIO import wx import wx.html2 as webview diff --git a/samples/printing/printing.py b/samples/printing/printing.py index 8af9a05e..bc63744c 100644 --- a/samples/printing/printing.py +++ b/samples/printing/printing.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import wx import os diff --git a/samples/roses/clroses.py b/samples/roses/clroses.py index f25ac93b..b6a9ca64 100644 --- a/samples/roses/clroses.py +++ b/samples/roses/clroses.py @@ -36,8 +36,6 @@ # ideal Roses program should be, however, callers are welcome to assert their # independence, override defaults, ignore features, etc. -from __future__ import print_function - from math import sin, cos, pi # Rose class knows about: diff --git a/samples/roses/wxroses.py b/samples/roses/wxroses.py index 645f56aa..d6426bff 100644 --- a/samples/roses/wxroses.py +++ b/samples/roses/wxroses.py @@ -68,8 +68,6 @@ # control the display (without blocking the user's control) would be pretty # straightforward. -from __future__ import print_function - import wx import clroses import wx.lib.colourselect as cs diff --git a/samples/simple/events.py b/samples/simple/events.py index 112875bd..06ecb0d3 100644 --- a/samples/simple/events.py +++ b/samples/simple/events.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import wx print(wx.version()) diff --git a/sphinxtools/modulehunter.py b/sphinxtools/modulehunter.py index 6224c896..f53ad678 100644 --- a/sphinxtools/modulehunter.py +++ b/sphinxtools/modulehunter.py @@ -22,18 +22,11 @@ from .librarydescription import Method, Property, Attribute from . import inheritance -from .utilities import isPython3, PickleFile +from .utilities import PickleFile from .constants import object_types, EXCLUDED_ATTRS, MODULE_TO_ICON from .constants import CONSTANT_RE -if sys.version_info < (3,): - reload(sys) - sys.setdefaultencoding('utf-8') - -if isPython3(): - MethodTypes = (classmethod, types.MethodType, types.ClassMethodDescriptorType) -else: - MethodTypes = (classmethod, types.MethodType) +MethodTypes = (classmethod, types.MethodType, types.ClassMethodDescriptorType) try: import wx diff --git a/unittests/test_arraystring.py b/unittests/test_arraystring.py index bb7a80c9..cdbb4728 100644 --- a/unittests/test_arraystring.py +++ b/unittests/test_arraystring.py @@ -1,24 +1,16 @@ import unittest import wx -import six #--------------------------------------------------------------------------- -if not six.PY3: - alt = unicode -else: - def alt(s): - return bytes(s, 'utf-8') - - class ArrayString(unittest.TestCase): if hasattr(wx, 'testArrayStringTypemap'): def test_ArrayStringTypemaps(self): # basic conversion of list or tuples of strings - seqList = ['a', alt('b'), 'hello world'] + seqList = ['a', b'b', 'hello world'] self.assertEqual(wx.testArrayStringTypemap(seqList), ['a', 'b', 'hello world']) - seqTuple = ('a', alt('b'), 'hello world') + seqTuple = ('a', b'b', 'hello world') self.assertEqual(wx.testArrayStringTypemap(seqTuple), ['a', 'b', 'hello world']) def test_ArrayStringTypemapErrors(self): @@ -26,7 +18,7 @@ class ArrayString(unittest.TestCase): with self.assertRaises(TypeError): wx.testArrayStringTypemap("STRING sequence") with self.assertRaises(TypeError): - wx.testArrayStringTypemap(alt("ALT sequence")) + wx.testArrayStringTypemap(b"ALT sequence") with self.assertRaises(TypeError): wx.testArrayStringTypemap(["list", "with", "non-string", "items", 123]) diff --git a/unittests/test_bitmap.py b/unittests/test_bitmap.py index 72132e31..4cab3d0f 100644 --- a/unittests/test_bitmap.py +++ b/unittests/test_bitmap.py @@ -2,7 +2,6 @@ import unittest from unittests import wtc import wx import os -import six pngFile = os.path.join(os.path.dirname(__file__), 'toucan.png') @@ -58,10 +57,7 @@ class BitmapTests(wtc.WidgetTestCase): self.assertTrue( not b1.IsOk() ) b2 = wx.Bitmap(5, 10, 24) self.assertTrue( b2.IsOk() ) - if six.PY3: - self.assertTrue( b2.__bool__() == b2.IsOk() ) - else: - self.assertTrue( b2.__nonzero__() == b2.IsOk() ) + self.assertTrue( b2.__bool__() == b2.IsOk() ) # check that the __nonzero__ method can be used with if statements nzcheck = False diff --git a/unittests/test_cmndata.py b/unittests/test_cmndata.py index 8bba2b77..c8d13c68 100644 --- a/unittests/test_cmndata.py +++ b/unittests/test_cmndata.py @@ -1,7 +1,6 @@ import unittest from unittests import wtc import wx -import six #--------------------------------------------------------------------------- @@ -37,14 +36,9 @@ class cmndata_tests(wtc.WidgetTestCase): pd = wx.PrintData() pdd = wx.PrintDialogData() - if six.PY3: - psdd.__bool__() - pd.__bool__() - pdd.__bool__() - else: - psdd.__nonzero__() - pd.__nonzero__() - pdd.__nonzero__() + psdd.__bool__() + pd.__bool__() + pdd.__bool__() def test_PD_PaperSize(self): diff --git a/unittests/test_cursor.py b/unittests/test_cursor.py index 6bc10026..63852b3e 100644 --- a/unittests/test_cursor.py +++ b/unittests/test_cursor.py @@ -1,7 +1,6 @@ import unittest from unittests import wtc import wx -import six import os pngFile = os.path.join(os.path.dirname(__file__), 'pointy.png') @@ -70,10 +69,7 @@ class CursorTests(wtc.WidgetTestCase): c2 = wx.Cursor(wx.CURSOR_ARROW) self.assertTrue( c2.IsOk() ) - if six.PY3: - self.assertTrue( c2.__bool__() == c2.IsOk() ) - else: - self.assertTrue( c2.__nonzero__() == c2.IsOk() ) + self.assertTrue( c2.__bool__() == c2.IsOk() ) # check that the __nonzero__ method can be used with if statements nzcheck = False diff --git a/unittests/test_image.py b/unittests/test_image.py index fb3f6202..eaf28257 100644 --- a/unittests/test_image.py +++ b/unittests/test_image.py @@ -1,8 +1,7 @@ import unittest from unittests import wtc import wx -import six -from six import BytesIO as FileLikeObject +from io import BytesIO as FileLikeObject import os @@ -136,20 +135,12 @@ class image_Tests(wtc.WidgetTestCase): self.assertTrue(img.IsOk()) data = img.GetDataBuffer() self.assertTrue(isinstance(data, memoryview)) - if six.PY2: - data[0] = b'1' - data[1] = b'2' - data[2] = b'3' - self.assertEqual(ord('1'), img.GetRed(0,0)) - self.assertEqual(ord('2'), img.GetGreen(0,0)) - self.assertEqual(ord('3'), img.GetBlue(0,0)) - else: - data[0] = 1 - data[1] = 2 - data[2] = 3 - self.assertEqual(1, img.GetRed(0,0)) - self.assertEqual(2, img.GetGreen(0,0)) - self.assertEqual(3, img.GetBlue(0,0)) + data[0] = 1 + data[1] = 2 + data[2] = 3 + self.assertEqual(1, img.GetRed(0,0)) + self.assertEqual(2, img.GetGreen(0,0)) + self.assertEqual(3, img.GetBlue(0,0)) def test_imageGetAlphaDataBuffer(self): @@ -159,20 +150,12 @@ class image_Tests(wtc.WidgetTestCase): self.assertTrue(img.IsOk()) data = img.GetAlphaBuffer() self.assertTrue(isinstance(data, memoryview)) - if six.PY2: - data[0] = b'1' - data[1] = b'2' - data[2] = b'3' - self.assertEqual(ord('1'), img.GetAlpha(0,0)) - self.assertEqual(ord('2'), img.GetAlpha(1,0)) - self.assertEqual(ord('3'), img.GetAlpha(2,0)) - else: - data[0] = 1 - data[1] = 2 - data[2] = 3 - self.assertEqual(1, img.GetAlpha(0,0)) - self.assertEqual(2, img.GetAlpha(1,0)) - self.assertEqual(3, img.GetAlpha(2,0)) + data[0] = 1 + data[1] = 2 + data[2] = 3 + self.assertEqual(1, img.GetAlpha(0,0)) + self.assertEqual(2, img.GetAlpha(1,0)) + self.assertEqual(3, img.GetAlpha(2,0)) def test_imageSetDataBuffer1(self): diff --git a/unittests/test_lib_cdate.py b/unittests/test_lib_cdate.py index 02acd124..c7825ee6 100644 --- a/unittests/test_lib_cdate.py +++ b/unittests/test_lib_cdate.py @@ -1,7 +1,6 @@ import unittest from unittests import wtc import wx.lib.CDate as cdate -import six import datetime class lib_cdate_Tests(wtc.WidgetTestCase): diff --git a/unittests/test_lib_pubsub_defaultlog.py b/unittests/test_lib_pubsub_defaultlog.py index 6d952568..f8208870 100644 --- a/unittests/test_lib_pubsub_defaultlog.py +++ b/unittests/test_lib_pubsub_defaultlog.py @@ -7,10 +7,10 @@ """ import unittest +from io import StringIO from unittests import wtc from wx.lib.pubsub.utils import notification -from six import StringIO #--------------------------------------------------------------------------- diff --git a/unittests/test_lib_pubsub_listener.py b/unittests/test_lib_pubsub_listener.py index 2f71fe7c..95e17ab5 100644 --- a/unittests/test_lib_pubsub_listener.py +++ b/unittests/test_lib_pubsub_listener.py @@ -5,7 +5,6 @@ """ -import six import unittest from unittests import wtc @@ -195,9 +194,6 @@ class lib_pubsub_ArgsInfo(wtc.PubsubTestCase): def tmpFn(self): pass Listener( DOA.tmpFn, ArgsInfoMock() ) - # Py3 doesn't have unbound methods so this won't throw a ValueError - if not six.PY3: - self.assertRaises(ValueError, getListener1) # test DOA of tmp callable: def getListener2(): diff --git a/unittests/test_lib_pubsub_notify.py b/unittests/test_lib_pubsub_notify.py index 5128ca3f..4e7bd1df 100644 --- a/unittests/test_lib_pubsub_notify.py +++ b/unittests/test_lib_pubsub_notify.py @@ -22,7 +22,7 @@ class lib_pubsub_Notify(wtc.PubsubTestCase): from wx.lib.pubsub.utils.notification import useNotifyByWriteFile def captureStdout(): - from six import StringIO + from io import StringIO capture = StringIO() useNotifyByWriteFile( fileObj = capture ) return capture diff --git a/unittests/test_lib_pubsub_notify4.py b/unittests/test_lib_pubsub_notify4.py index 8d79ba8c..11d11149 100644 --- a/unittests/test_lib_pubsub_notify4.py +++ b/unittests/test_lib_pubsub_notify4.py @@ -9,7 +9,6 @@ import unittest from unittests import wtc -import six from difflib import ndiff, unified_diff, context_diff @@ -45,7 +44,7 @@ class lib_pubsub_NotifyN(wtc.PubsubTestCase): self.pub.setNotificationFlags(all=True) def verify(**ref): - for key, val in six.iteritems(notifiee.counts): + for key, val in notifiee.counts.items(): if key in ref: self.assertEqual(val, ref[key], "\n%s\n%s" % (notifiee.counts, ref) ) else: diff --git a/unittests/test_lib_pubsub_topicmgr.py b/unittests/test_lib_pubsub_topicmgr.py index da0da080..9ccdec55 100644 --- a/unittests/test_lib_pubsub_topicmgr.py +++ b/unittests/test_lib_pubsub_topicmgr.py @@ -359,7 +359,7 @@ r'''\-- Topic "a2" topicMgr.getOrCreateTopic('a2.b.a') topicMgr.getOrCreateTopic('a2.b.b') - from six import StringIO + from io import StringIO buffer = StringIO() printTreeDocs(rootTopic=root, width=70, fileObj=buffer) self.assertEqual( buffer.getvalue(), self.expectedOutput ) diff --git a/unittests/test_pgvariant.py b/unittests/test_pgvariant.py index 686698c1..2ca2de31 100644 --- a/unittests/test_pgvariant.py +++ b/unittests/test_pgvariant.py @@ -3,8 +3,6 @@ from unittests import wtc import wx import wx.propgrid as pg -import six - #--------------------------------------------------------------------------- class pgvariant_Tests(wtc.WidgetTestCase): diff --git a/unittests/test_stream.py b/unittests/test_stream.py index e19042d5..18751a8c 100644 --- a/unittests/test_stream.py +++ b/unittests/test_stream.py @@ -1,8 +1,7 @@ import unittest from unittests import wtc import wx -import six -from six import BytesIO as FileLikeObject +from io import BytesIO as FileLikeObject import os diff --git a/unittests/test_string.py b/unittests/test_string.py index e75dc2bf..a2406ed6 100644 --- a/unittests/test_string.py +++ b/unittests/test_string.py @@ -1,6 +1,5 @@ import unittest import wx -import six from unittests import wtc #--------------------------------------------------------------------------- @@ -10,57 +9,6 @@ from unittests import wtc class String(unittest.TestCase): if hasattr(wx, 'testStringTypemap'): - if not six.PY3: - def test_StringTypemapsPy2(self): - utf = '\xc3\xa9l\xc3\xa9phant' # utf-8 string - uni = utf.decode('utf-8') # convert to unicode - iso = uni.encode('iso-8859-1') # make a string with a different encoding - - - # wx.testStringTypemap() will accept a parameter that - # is a Unicode object or an 'ascii' or 'utf-8' string object, - # which will then be converted to a wxString. The return - # value is a Unicode object that has been converted from a - # wxString that is a copy of the wxString created for the - # parameter. - - # ascii - result = wx.testStringTypemap('hello') - self.assertTrue(type(result) == unicode) - self.assertTrue(result == unicode('hello')) - - # unicode should pass through unmodified - result = wx.testStringTypemap(uni) - self.assertTrue(result == uni) - - # utf-8 is converted - result = wx.testStringTypemap(utf) - self.assertTrue(result == uni) - - # can't auto-convert this - with self.assertRaises(UnicodeDecodeError): - result = wx.testStringTypemap(iso) - - # utf-16-be - val = "\x00\xe9\x00l\x00\xe9\x00p\x00h\x00a\x00n\x00t" - with self.assertRaises(UnicodeDecodeError): - result = wx.testStringTypemap(val) - result = wx.testStringTypemap( val.decode('utf-16-be')) - self.assertTrue(result == uni) - - # utf-32-be - val = "\x00\x00\x00\xe9\x00\x00\x00l\x00\x00\x00\xe9\x00\x00\x00p\x00\x00\x00h\x00\x00\x00a\x00\x00\x00n\x00\x00\x00t" - with self.assertRaises(UnicodeDecodeError): - result = wx.testStringTypemap(val) - result = wx.testStringTypemap(val.decode('utf-32-be')) - self.assertTrue(result == uni) - - # utf-8 with BOM - #val = "\xef\xbb\xbfHello" - #result = wx.testStringTypemap(val) - #self.assertTrue(result == u'\ufeffHello') - - else: def test_StringTypemapsPy3(self): utf = b'\xc3\xa9l\xc3\xa9phant' # utf-8 bytes uni = utf.decode('utf-8') # convert to unicode diff --git a/unittests/test_variant.py b/unittests/test_variant.py index d4f9563c..d7b2f51d 100644 --- a/unittests/test_variant.py +++ b/unittests/test_variant.py @@ -2,8 +2,6 @@ import unittest from unittests import wtc import wx -import six - #--------------------------------------------------------------------------- class variant_Tests(wtc.WidgetTestCase): @@ -11,7 +9,7 @@ class variant_Tests(wtc.WidgetTestCase): @unittest.skipIf(not hasattr(wx, 'testVariantTypemap'), '') def test_variant1(self): n = wx.testVariantTypemap(123) - self.assertTrue(isinstance(n, six.integer_types)) + self.assertTrue(isinstance(n, int)) self.assertEqual(n, 123) diff --git a/unittests/test_window.py b/unittests/test_window.py index b8132b8e..fa466969 100644 --- a/unittests/test_window.py +++ b/unittests/test_window.py @@ -1,7 +1,6 @@ import unittest from unittests import wtc import wx -import six #--------------------------------------------------------------------------- @@ -15,7 +14,7 @@ class WindowTests(wtc.WidgetTestCase): def test_windowHandle(self): w = wx.Window(self.frame, -1, (10,10), (50,50)) hdl = w.GetHandle() - self.assertTrue(isinstance(hdl, six.integer_types)) + self.assertTrue(isinstance(hdl, int)) def test_windowProperties(self): diff --git a/unittests/test_wxdatetime.py b/unittests/test_wxdatetime.py index 62e7d141..ef56c912 100644 --- a/unittests/test_wxdatetime.py +++ b/unittests/test_wxdatetime.py @@ -1,6 +1,5 @@ import unittest import wx -import six from unittests import wtc import datetime import time @@ -45,12 +44,8 @@ class datetime_Tests(wtc.WidgetTestCase): def test_datetimeGetAmPm(self): am, pm = wx.DateTime.GetAmPmStrings() - if six.PY3: - base = str - else: - base = unicode - self.assertTrue(isinstance(am, base) and am != "") - self.assertTrue(isinstance(pm, base) and pm != "") + self.assertTrue(isinstance(am, str) and am != "") + self.assertTrue(isinstance(pm, str) and pm != "") def test_datetimeProperties(self): diff --git a/unittests/wtc.py b/unittests/wtc.py index 2ecb3d18..7ce9cb75 100644 --- a/unittests/wtc.py +++ b/unittests/wtc.py @@ -1,7 +1,6 @@ import unittest import wx import sys, os -import six #--------------------------------------------------------------------------- @@ -84,12 +83,9 @@ class WidgetTestCase(unittest.TestCase): def myExecfile(self, filename, ns): - if not six.PY3: - execfile(filename, ns) - else: - with open(filename, 'r') as f: - source = f.read() - exec(source, ns) + with open(filename, 'r') as f: + source = f.read() + exec(source, ns) def execSample(self, name): @@ -109,10 +105,7 @@ class Namespace(object): #--------------------------------------------------------------------------- def mybytes(text): - if six.PY3: - return bytes(text, 'utf-8') - else: - return str(text) + return bytes(text, 'utf-8') #--------------------------------------------------------------------------- diff --git a/wx/lib/CDate.py b/wx/lib/CDate.py index d6d2068b..4a91dca2 100644 --- a/wx/lib/CDate.py +++ b/wx/lib/CDate.py @@ -15,7 +15,6 @@ # in a string format, then an error was raised. # """Date and calendar classes and date utitility methods.""" -from __future__ import division import time # I18N diff --git a/wx/lib/agw/artmanager.py b/wx/lib/agw/artmanager.py index fb8f0e93..797442e9 100644 --- a/wx/lib/agw/artmanager.py +++ b/wx/lib/agw/artmanager.py @@ -6,7 +6,7 @@ This module contains drawing routines and customizations for the AGW widgets import wx import random -from six import BytesIO +from io import BytesIO from .fmresources import * diff --git a/wx/lib/agw/aui/auibar.py b/wx/lib/agw/aui/auibar.py index 27eecde4..8a59d8c7 100644 --- a/wx/lib/agw/aui/auibar.py +++ b/wx/lib/agw/aui/auibar.py @@ -31,9 +31,6 @@ import wx from .aui_utilities import BitmapFromBits, StepColour, GetLabelSize from .aui_utilities import GetBaseColour, MakeDisabledBitmap - -import six - from .aui_constants import * @@ -68,7 +65,7 @@ class CommandToolBarEvent(wx.PyCommandEvent): :param integer `win_id`: the window identification number. """ - if type(command_type) in six.integer_types: + if type(command_type) in int: wx.PyCommandEvent.__init__(self, command_type, win_id) else: wx.PyCommandEvent.__init__(self, command_type.GetEventType(), command_type.GetId()) @@ -158,7 +155,7 @@ class AuiToolBarEvent(CommandToolBarEvent): CommandToolBarEvent.__init__(self, command_type, win_id) - if type(command_type) in six.integer_types: + if type(command_type) in int: self.notify = wx.NotifyEvent(command_type, win_id) else: self.notify = wx.NotifyEvent(command_type.GetEventType(), command_type.GetId()) diff --git a/wx/lib/agw/aui/auibook.py b/wx/lib/agw/aui/auibook.py index c63e31ec..573cfd22 100644 --- a/wx/lib/agw/aui/auibook.py +++ b/wx/lib/agw/aui/auibook.py @@ -32,7 +32,6 @@ import wx import datetime from wx.lib.expando import ExpandoTextCtrl -import six from . import tabart as TA @@ -392,7 +391,7 @@ class CommandNotebookEvent(wx.PyCommandEvent): :param integer `win_id`: the window identification number. """ - if type(command_type) in six.integer_types: + if type(command_type) in int: wx.PyCommandEvent.__init__(self, command_type, win_id) else: wx.PyCommandEvent.__init__(self, command_type.GetEventType(), command_type.GetId()) @@ -525,7 +524,7 @@ class AuiNotebookEvent(CommandNotebookEvent): CommandNotebookEvent.__init__(self, command_type, win_id) - if type(command_type) in six.integer_types: + if type(command_type) in int: self.notify = wx.NotifyEvent(command_type, win_id) else: self.notify = wx.NotifyEvent(command_type.GetEventType(), command_type.GetId()) @@ -1174,7 +1173,7 @@ class AuiTabContainer(object): :param `wndOrInt`: an instance of :class:`wx.Window` or an integer specifying a tab index. """ - if type(wndOrInt) in six.integer_types: + if type(wndOrInt) in int: if wndOrInt >= len(self._pages): return False @@ -4081,7 +4080,7 @@ class AuiNotebook(wx.Panel): if page >= self._tabs.GetPageCount(): return False - if not isinstance(image, six.integer_types): + if not isinstance(image, int): raise Exception("The image parameter must be an integer, you passed " \ "%s"%repr(image)) diff --git a/wx/lib/agw/aui/framemanager.py b/wx/lib/agw/aui/framemanager.py index 10cc6bb5..2f7bdae5 100644 --- a/wx/lib/agw/aui/framemanager.py +++ b/wx/lib/agw/aui/framemanager.py @@ -106,8 +106,6 @@ except ImportError: # clock is removed in py3.8 from time import clock as perf_counter import warnings -import six - from . import auibar from . import auibook @@ -993,7 +991,7 @@ class AuiPaneInfo(object): ret = self.MinSize1(arg1) elif isinstance(arg1, tuple): ret = self.MinSize1(wx.Size(*arg1)) - elif isinstance(arg1, six.integer_types) and arg2 is not None: + elif isinstance(arg1, int) and arg2 is not None: ret = self.MinSize2(arg1, arg2) else: raise Exception("Invalid argument passed to `MinSize`: arg1=%s, arg2=%s" % (repr(arg1), repr(arg2))) @@ -1034,7 +1032,7 @@ class AuiPaneInfo(object): ret = self.MaxSize1(arg1) elif isinstance(arg1, tuple): ret = self.MaxSize1(wx.Size(*arg1)) - elif isinstance(arg1, six.integer_types) and arg2 is not None: + elif isinstance(arg1, int) and arg2 is not None: ret = self.MaxSize2(arg1, arg2) else: raise Exception("Invalid argument passed to `MaxSize`: arg1=%s, arg2=%s" % (repr(arg1), repr(arg2))) @@ -1077,7 +1075,7 @@ class AuiPaneInfo(object): ret = self.BestSize1(arg1) elif isinstance(arg1, tuple): ret = self.BestSize1(wx.Size(*arg1)) - elif isinstance(arg1, six.integer_types) and arg2 is not None: + elif isinstance(arg1, int) and arg2 is not None: ret = self.BestSize2(arg1, arg2) else: raise Exception("Invalid argument passed to `BestSize`: arg1=%s, arg2=%s" % (repr(arg1), repr(arg2))) @@ -4128,7 +4126,7 @@ class AuiManager(wx.EvtHandler): :param `item`: either a pane name or a :class:`wx.Window`. """ - if isinstance(item, six.string_types): + if isinstance(item, str): return self.GetPaneByName(item) else: return self.GetPaneByWidget(item) @@ -6471,7 +6469,7 @@ class AuiManager(wx.EvtHandler): elif paneInfo.IsNotebookControl() and not paneInfo.window: paneInfo.window = self._notebooks[paneInfo.notebook_id] - for notebook_id, pnp in six.iteritems(pages_and_panes): + for notebook_id, pnp in pages_and_panes.items(): # sort the panes with dock_pos sorted_pnp = sorted(pnp, key=lambda pane: pane.dock_pos) notebook = self._notebooks[notebook_id] @@ -9928,7 +9926,7 @@ class AuiManager(wx.EvtHandler): if not restoreToolAlreadyInToolbar: tool = minimize_toolbar.AddSimpleTool(ID_RESTORE_FRAME, paneInfo.caption, restore_bitmap, - _(six.u("Restore %s")) % paneInfo.caption, target=target) + _("Restore %s") % paneInfo.caption, target=target) tool.SetUserData((ID_RESTORE_FRAME, paneInfo.window)) minimize_toolbar.SetAuiManager(self) minimize_toolbar.Realize() diff --git a/wx/lib/agw/customtreectrl.py b/wx/lib/agw/customtreectrl.py index 40bd1fb4..c48926b2 100644 --- a/wx/lib/agw/customtreectrl.py +++ b/wx/lib/agw/customtreectrl.py @@ -349,8 +349,6 @@ License And Version Latest Revision: Helio Guilherme @ 09 Aug 2018, 21.35 GMT -Version 2.7 - """ # Version Info @@ -359,9 +357,6 @@ __version__ = "2.7" import wx from wx.lib.expando import ExpandoTextCtrl -# Python 2/3 compatibility helper -import six - # ---------------------------------------------------------------------------- # Constants # ---------------------------------------------------------------------------- diff --git a/wx/lib/agw/flatmenu.py b/wx/lib/agw/flatmenu.py index e8678491..9ff0e3ef 100644 --- a/wx/lib/agw/flatmenu.py +++ b/wx/lib/agw/flatmenu.py @@ -200,8 +200,6 @@ import math import wx.lib.colourutils as colourutils -import six - from .fmcustomizedlg import FMCustomizeDlg from .artmanager import ArtManager, DCSaver from .fmresources import * @@ -590,7 +588,7 @@ class FMRenderer(object): else: - stream = six.BytesIO(xpm) + stream = io.BytesIO(xpm) img = wx.Image(stream) return wx.Bitmap(img) @@ -2226,7 +2224,7 @@ class MenuEntryInfo(object): :param integer `cmd`: the menu accelerator identifier. """ - if isinstance(titleOrMenu, six.string_types): + if isinstance(titleOrMenu, str): self._title = titleOrMenu self._menu = menu @@ -3595,7 +3593,7 @@ class FlatMenuBar(wx.Panel): if self._showCustomize: if invT + invM > 0: self._moreMenu.AppendSeparator() - item = FlatMenuItem(self._moreMenu, self._popupDlgCmdId, _(six.u("Customize..."))) + item = FlatMenuItem(self._moreMenu, self._popupDlgCmdId, _("Customize...")) self._moreMenu.AppendItem(item) diff --git a/wx/lib/agw/flatnotebook.py b/wx/lib/agw/flatnotebook.py index 987a70a9..91043e6a 100644 --- a/wx/lib/agw/flatnotebook.py +++ b/wx/lib/agw/flatnotebook.py @@ -192,8 +192,6 @@ import math import weakref import pickle -import six - # Used on OSX to get access to carbon api constants if wx.Platform == '__WXMAC__': try: @@ -6550,7 +6548,7 @@ class PageContainer(wx.Panel): if page < len(self._pagesInfoVec): return self._pagesInfoVec[page].GetCaption() else: - return six.u('') + return '' def SetPageText(self, page, text): diff --git a/wx/lib/agw/floatspin.py b/wx/lib/agw/floatspin.py index cb6be099..57afe5e5 100644 --- a/wx/lib/agw/floatspin.py +++ b/wx/lib/agw/floatspin.py @@ -177,10 +177,7 @@ import wx import locale from math import ceil, floor -# Python 2/3 compatibility helper -import six -if six.PY3: - long = int +long = int # Set The Styles For The Underline wx.TextCtrl FS_READONLY = 1 @@ -1379,7 +1376,7 @@ class FixedPoint(object): self.n = n return - if isinstance(value, six.integer_types): + if isinstance(value, int): self.n = int(value) * _tento(p) return diff --git a/wx/lib/agw/fmcustomizedlg.py b/wx/lib/agw/fmcustomizedlg.py index e7b06307..4a1c407a 100644 --- a/wx/lib/agw/fmcustomizedlg.py +++ b/wx/lib/agw/fmcustomizedlg.py @@ -14,14 +14,9 @@ This module contains a custom dialog class used to personalize the appearance of a :class:`~wx.lib.agw.flatmenu.FlatMenu` on the fly, allowing also the user of your application to do the same. """ +from collections import UserDict import wx -import six - -if six.PY2: - from UserDict import UserDict -else: - from collections import UserDict from .artmanager import ArtManager from .fmresources import * diff --git a/wx/lib/agw/hypertreelist.py b/wx/lib/agw/hypertreelist.py index 19c9be6f..02ba644d 100644 --- a/wx/lib/agw/hypertreelist.py +++ b/wx/lib/agw/hypertreelist.py @@ -302,9 +302,6 @@ from wx.lib.agw.customtreectrl import DragImage, TreeEvent, GenericTreeItem, Cho from wx.lib.agw.customtreectrl import TreeEditTimer as TreeListEditTimer from wx.lib.agw.customtreectrl import EVT_TREE_ITEM_CHECKING, EVT_TREE_ITEM_CHECKED, EVT_TREE_ITEM_HYPERLINK -# Python 2/3 compatibility helper -import six - if sys.version_info >= (3, 11): from typing import Self else: @@ -458,7 +455,7 @@ class TreeListColumnInfo(object): :param `edit`: ``True`` to set the column as editable, ``False`` otherwise. """ - if isinstance(input, six.string_types): + if isinstance(input, str): self._text = input self._width = width self._flag = flag @@ -3667,7 +3664,7 @@ class TreeListMainWindow(CustomTreeCtrl): if self._curColumn == -1: self._curColumn = 0 - self.SetItemText(self._editItem, six.text_type(value), self._curColumn) + self.SetItemText(self._editItem, str(value), self._curColumn) def OnCancelEdit(self): diff --git a/wx/lib/agw/persist/persist_constants.py b/wx/lib/agw/persist/persist_constants.py index 1f454fa6..a5f26652 100644 --- a/wx/lib/agw/persist/persist_constants.py +++ b/wx/lib/agw/persist/persist_constants.py @@ -12,7 +12,6 @@ This module contains all the constants used by the persistent objects. import wx import wx.dataview as dv -import six # ----------------------------------------------------------------------------------- # # PersistenceManager styles @@ -33,14 +32,14 @@ BAD_DEFAULT_NAMES = ["widget", "wxSpinButton", "auiFloating", "AuiTabCtrl", "mas for name in dir(wx): if "NameStr" in name: val = getattr(wx, name) - if six.PY3 and isinstance(val, bytes): + if isinstance(val, bytes): val = val.decode('utf-8') BAD_DEFAULT_NAMES.append(val) for name in dir(dv): if "NameStr" in name: val = getattr(dv, name) - if six.PY3 and isinstance(val, bytes): + if isinstance(val, bytes): val = val.decode('utf-8') BAD_DEFAULT_NAMES.append(val) diff --git a/wx/lib/agw/persist/persistencemanager.py b/wx/lib/agw/persist/persistencemanager.py index a787d4eb..d448fffb 100644 --- a/wx/lib/agw/persist/persistencemanager.py +++ b/wx/lib/agw/persist/persistencemanager.py @@ -35,7 +35,6 @@ import datetime import wx import wx.adv -import six from .persist_handlers import FindHandler, HasCtrlHandler @@ -44,7 +43,7 @@ from .persist_constants import PM_DEFAULT_STYLE, PM_PERSIST_CONTROL_VALUE # ----------------------------------------------------------------------------------- # -class PersistentObject(object): +class PersistentObject: """ :class:`PersistentObject`: ABC for anything persistent. @@ -785,10 +784,10 @@ class PersistenceManager(object): kind = repr(value.__class__).split("'")[1] if self._customConfigHandler is not None: - result = self._customConfigHandler.SaveValue(self.GetKey(obj, keyName), repr((kind, six.text_type(value)))) + result = self._customConfigHandler.SaveValue(self.GetKey(obj, keyName), repr((kind, str(value)))) else: config = self.GetPersistenceFile() - result = config.Write(self.GetKey(obj, keyName), repr((kind, six.text_type(value)))) + result = config.Write(self.GetKey(obj, keyName), repr((kind, str(value)))) config.Flush() return result diff --git a/wx/lib/agw/ribbon/bar.py b/wx/lib/agw/ribbon/bar.py index c3ea1a35..09004dfd 100644 --- a/wx/lib/agw/ribbon/bar.py +++ b/wx/lib/agw/ribbon/bar.py @@ -98,8 +98,6 @@ See Also import wx from functools import cmp_to_key -import six - from .control import RibbonControl from .art_internal import RibbonPageTabInfo @@ -607,7 +605,7 @@ class RibbonBar(RibbonControl): def SetActivePage(self, page): """ See comments on :meth:`~RibbonBar.SetActivePageByIndex` and :meth:`~RibbonBar.SetActivePageByPage`. """ - if isinstance(page, six.integer_types): + if isinstance(page, int): return self.SetActivePageByIndex(page) return self.SetActivePageByPage(page) diff --git a/wx/lib/agw/ribbon/buttonbar.py b/wx/lib/agw/ribbon/buttonbar.py index 577da693..8df44b01 100644 --- a/wx/lib/agw/ribbon/buttonbar.py +++ b/wx/lib/agw/ribbon/buttonbar.py @@ -46,8 +46,6 @@ Event Name Description import wx -import six - from .control import RibbonControl from .art import * @@ -345,7 +343,7 @@ class RibbonButtonBar(RibbonControl): if not bitmap.IsOk() and not bitmap_small.IsOk(): raise Exception("Invalid main bitmap") - if not isinstance(help_string, six.string_types): + if not isinstance(help_string, str): raise Exception("Invalid help string parameter") if not self._buttons: diff --git a/wx/lib/agw/rulerctrl.py b/wx/lib/agw/rulerctrl.py index b13ae51a..c2aeca8f 100644 --- a/wx/lib/agw/rulerctrl.py +++ b/wx/lib/agw/rulerctrl.py @@ -153,6 +153,7 @@ Version 0.4 """ +import io import wx import math import zlib @@ -166,9 +167,6 @@ try: except: pass -# Python 2/3 compatibility helper -import six - # Built-in formats IntFormat = 1 """ Integer format. """ @@ -225,7 +223,7 @@ def GetIndicatorBitmap(): def GetIndicatorImage(): """ Returns the image indicator as a :class:`wx.Image`. """ - stream = six.BytesIO(GetIndicatorData()) + stream = io.BytesIO(GetIndicatorData()) return wx.Image(stream) diff --git a/wx/lib/agw/scrolledthumbnail.py b/wx/lib/agw/scrolledthumbnail.py index 437e6c55..22155816 100644 --- a/wx/lib/agw/scrolledthumbnail.py +++ b/wx/lib/agw/scrolledthumbnail.py @@ -173,18 +173,15 @@ Version 1.0 # Beginning Of ThumbnailCtrl wxPython Code #---------------------------------------------------------------------- +import io import os import wx -import six import zlib from math import radians from wx.lib.embeddedimage import PyEmbeddedImage -if six.PY3: - import _thread as thread -else: - import thread +import _thread as thread #---------------------------------------------------------------------- # Get Default Icon/Data @@ -308,9 +305,9 @@ b'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\xac \xcc\xc1\ def getShadow(): """ Creates a shadow behind every thumbnail. """ - sh_tr = wx.Image(six.BytesIO(getDataTR())).ConvertToBitmap() - sh_bl = wx.Image(six.BytesIO(getDataBL())).ConvertToBitmap() - sh_sh = wx.Image(six.BytesIO(getDataSH())).Rescale(500, 500, wx.IMAGE_QUALITY_HIGH) + sh_tr = wx.Image(io.BytesIO(getDataTR())).ConvertToBitmap() + sh_bl = wx.Image(io.BytesIO(getDataBL())).ConvertToBitmap() + sh_sh = wx.Image(io.BytesIO(getDataSH())).Rescale(500, 500, wx.IMAGE_QUALITY_HIGH) return (sh_tr, sh_bl, sh_sh.ConvertToBitmap()) diff --git a/wx/lib/agw/ultimatelistctrl.py b/wx/lib/agw/ultimatelistctrl.py index e12da76f..1c12dd8f 100644 --- a/wx/lib/agw/ultimatelistctrl.py +++ b/wx/lib/agw/ultimatelistctrl.py @@ -236,11 +236,10 @@ Version 0.8 import wx import math import bisect +import io import zlib from functools import cmp_to_key -import six - from wx.lib.expando import ExpandoTextCtrl # Version Info @@ -550,7 +549,7 @@ IL_FIXED_SIZE = 0 IL_VARIABLE_SIZE = 1 # Python integers, to make long types to work with CreateListItem -INTEGER_TYPES = six.integer_types +INTEGER_TYPES = int # ---------------------------------------------------------------------------- @@ -652,7 +651,7 @@ def GetdragcursorBitmap(): def GetdragcursorImage(): """ Returns the drag and drop cursor image as a :class:`wx.Image`. """ - stream = six.BytesIO(GetdragcursorData()) + stream = io.BytesIO(GetdragcursorData()) return wx.Image(stream) @@ -13124,9 +13123,9 @@ class UltimateListCtrl(wx.Control): if entry: pos = self.GetItemCount() - self.InsertStringItem(pos, six.u(entry[0])) + self.InsertStringItem(pos, str(entry[0])) for i in range(1, len(entry)): - self.SetStringItem(pos, i, six.u(entry[i])) + self.SetStringItem(pos, i, str(entry[i])) return pos diff --git a/wx/lib/agw/xlsgrid.py b/wx/lib/agw/xlsgrid.py index c8676c66..7583a2a3 100644 --- a/wx/lib/agw/xlsgrid.py +++ b/wx/lib/agw/xlsgrid.py @@ -250,8 +250,6 @@ import string import wx.grid as gridlib -import six - from wx.lib.embeddedimage import PyEmbeddedImage from wx.lib.wordwrap import wordwrap @@ -439,8 +437,8 @@ def SplitThousands(s, tSep=',', dSep='.'): """ - if not isinstance(s, six.string_types): - s = six.u(s) + if not isinstance(s, str): + s = str(s) cnt = 0 numChars = dSep + '0123456789' @@ -837,7 +835,7 @@ class XLSText(object): value = representation%value except ValueError: # Fall back to string - value = six.u(value) + value = str(value) if "#," in number_format: value = SplitThousands(value) diff --git a/wx/lib/colourchooser/__init__.py b/wx/lib/colourchooser/__init__.py index b149067f..31ddf517 100644 --- a/wx/lib/colourchooser/__init__.py +++ b/wx/lib/colourchooser/__init__.py @@ -12,8 +12,6 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. """ -from __future__ import absolute_import - # 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net) # # o 2.5 compatibility update. diff --git a/wx/lib/colourchooser/pycolourchooser.py b/wx/lib/colourchooser/pycolourchooser.py index 12437648..6c3beae8 100644 --- a/wx/lib/colourchooser/pycolourchooser.py +++ b/wx/lib/colourchooser/pycolourchooser.py @@ -12,8 +12,6 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. """ -from __future__ import absolute_import - # 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net) # # o 2.5 compatibility update. diff --git a/wx/lib/colourchooser/pycolourslider.py b/wx/lib/colourchooser/pycolourslider.py index f7f043a0..b88cd527 100644 --- a/wx/lib/colourchooser/pycolourslider.py +++ b/wx/lib/colourchooser/pycolourslider.py @@ -16,8 +16,6 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. """ -from __future__ import absolute_import - # 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net) # # o 2.5 compatibility update. diff --git a/wx/lib/colourchooser/pypalette.py b/wx/lib/colourchooser/pypalette.py index 71b9fc2d..cb81d2b5 100644 --- a/wx/lib/colourchooser/pypalette.py +++ b/wx/lib/colourchooser/pypalette.py @@ -16,8 +16,6 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. """ -from __future__ import absolute_import - # 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net) # # o 2.5 compatibility update. diff --git a/wx/lib/embeddedimage.py b/wx/lib/embeddedimage.py index 116de595..6ba4674e 100644 --- a/wx/lib/embeddedimage.py +++ b/wx/lib/embeddedimage.py @@ -13,9 +13,9 @@ #---------------------------------------------------------------------- import base64 +from io import BytesIO import wx -from six import BytesIO try: b64decode = base64.b64decode @@ -23,7 +23,7 @@ except AttributeError: b64decode = base64.decodestring -class PyEmbeddedImage(object): +class PyEmbeddedImage: """ PyEmbeddedImage is primarily intended to be used by code generated by img2py as a means of embedding image data in a python module so diff --git a/wx/lib/fancytext.py b/wx/lib/fancytext.py index ee78f2a6..862cc133 100644 --- a/wx/lib/fancytext.py +++ b/wx/lib/fancytext.py @@ -58,7 +58,6 @@ import math import sys import wx -import six import xml.parsers.expat @@ -255,8 +254,6 @@ class Renderer: def renderCharacterData(self, data, x, y): raise NotImplementedError() -from six import PY3 - def _addGreek(): alpha = 0xE1 Alpha = 0xC1 @@ -265,10 +262,7 @@ def _addGreek(): for i, name in enumerate(_greek_letters): def start(self, attrs, code=chr(alpha+i)): self.start_font({"encoding" : _greekEncoding}) - if not PY3: - self.characterData(code.decode('iso8859-7')) - else: - self.characterData(code) + self.characterData(code) self.end_font() setattr(Renderer, "start_%s" % name, start) setattr(Renderer, "end_%s" % name, end) @@ -276,10 +270,7 @@ def _addGreek(): continue # There is no capital for altsigma def start(self, attrs, code=chr(Alpha+i)): self.start_font({"encoding" : _greekEncoding}) - if not PY3: - self.characterData(code.decode('iso8859-7')) - else: - self.characterData(code) + self.characterData(code) self.end_font() setattr(Renderer, "start_%s" % name.capitalize(), start) setattr(Renderer, "end_%s" % name.capitalize(), end) @@ -366,8 +357,6 @@ def RenderToRenderer(str, renderer, enclose=True): if enclose: str = '%s' % str p = xml.parsers.expat.ParserCreate() - if six.PY2: - p.returns_unicode = 0 p.StartElementHandler = renderer.startElement p.EndElementHandler = renderer.endElement p.CharacterDataHandler = renderer.characterData diff --git a/wx/lib/floatcanvas/FCObjects.py b/wx/lib/floatcanvas/FCObjects.py index bf307bdc..1ddc62b1 100644 --- a/wx/lib/floatcanvas/FCObjects.py +++ b/wx/lib/floatcanvas/FCObjects.py @@ -17,7 +17,6 @@ This is where FloatCanvas defines its drawings objects. import sys import wx -import six import numpy as N @@ -228,14 +227,8 @@ class DrawObject: if not self._Canvas.HitColorGenerator: # first call to prevent the background color from being used. self._Canvas.HitColorGenerator = _colorGenerator() - if six.PY3: - next(self._Canvas.HitColorGenerator) - else: - self._Canvas.HitColorGenerator.next() - if six.PY3: - self.HitColor = next(self._Canvas.HitColorGenerator) - else: - self.HitColor = self._Canvas.HitColorGenerator.next() + next(self._Canvas.HitColorGenerator) + self.HitColor = next(self._Canvas.HitColorGenerator) self.SetHitPen(self.HitColor,self.HitLineWidth) self.SetHitBrush(self.HitColor) # put the object in the hit dict, indexed by it's color @@ -2890,15 +2883,9 @@ class Group(DrawObject): if not self._Canvas.HitColorGenerator: self._Canvas.HitColorGenerator = _colorGenerator() # first call to prevent the background color from being used. - if six.PY2: - self._Canvas.HitColorGenerator.next() - else: - next(self._Canvas.HitColorGenerator) + next(self._Canvas.HitColorGenerator) # Set all contained objects to the same Hit color: - if six.PY2: - self.HitColor = self._Canvas.HitColorGenerator.next() - else: - self.HitColor = next(self._Canvas.HitColorGenerator) + self.HitColor = next(self._Canvas.HitColorGenerator) self._ChangeChildrenHitColor(self.ObjectList) # put the object in the hit dict, indexed by it's color if not self._Canvas.HitDict: diff --git a/wx/lib/floatcanvas/FloatCanvas.py b/wx/lib/floatcanvas/FloatCanvas.py index ebdd689f..9e77d769 100644 --- a/wx/lib/floatcanvas/FloatCanvas.py +++ b/wx/lib/floatcanvas/FloatCanvas.py @@ -42,8 +42,6 @@ Many samples are available in the `wxPhoenix/samples/floatcanvas` folder. """ -from __future__ import division - import sys mac = sys.platform.startswith("darwin") @@ -53,7 +51,6 @@ try: except ImportError: from time import clock import wx -import six from .FCObjects import * diff --git a/wx/lib/floatcanvas/Resources.py b/wx/lib/floatcanvas/Resources.py index 7235c456..0065e079 100644 --- a/wx/lib/floatcanvas/Resources.py +++ b/wx/lib/floatcanvas/Resources.py @@ -4,7 +4,7 @@ from wx import Image as ImageFromStream from wx import Bitmap as BitmapFromImage -from six import BytesIO +from io import BytesIO import zlib diff --git a/wx/lib/floatcanvas/ScreenShot.py b/wx/lib/floatcanvas/ScreenShot.py index e26d856a..3ac33b90 100644 --- a/wx/lib/floatcanvas/ScreenShot.py +++ b/wx/lib/floatcanvas/ScreenShot.py @@ -4,7 +4,7 @@ from wx import Image as ImageFromStream from wx import BitmapFromImage -from six import BytesIO +from io import BytesIO import zlib diff --git a/wx/lib/graphics.py b/wx/lib/graphics.py index c02783fd..71cbf5a0 100644 --- a/wx/lib/graphics.py +++ b/wx/lib/graphics.py @@ -39,7 +39,6 @@ the ``wx.GraphicsContext`` classes a little better than Cairo's. import sys import math -import six import wx import wx.lib.wxcairo as wxcairo @@ -1890,7 +1889,7 @@ def _makeColour(colour): Helper which makes a wx.Colour from any of the allowed typemaps (string, tuple, etc.) """ - if isinstance(colour, (six.string_types, tuple)): + if isinstance(colour, (str, tuple)): return wx.NamedColour(colour) else: return colour diff --git a/wx/lib/inspection.py b/wx/lib/inspection.py index 4d2d1c7d..53b77dda 100644 --- a/wx/lib/inspection.py +++ b/wx/lib/inspection.py @@ -28,7 +28,6 @@ import wx.py import wx.stc #import wx.aui as aui import wx.lib.agw.aui as aui -import six import wx.lib.utils as utils import sys import inspect @@ -635,7 +634,7 @@ class InspectionInfoPanel(wx.stc.StyledTextCtrl): def Fmt(self, name, value): - if isinstance(value, six.string_types): + if isinstance(value, str): return " %s = '%s'" % (name, value) else: return " %s = %s" % (name, value) diff --git a/wx/lib/intctrl.py b/wx/lib/intctrl.py index c4ca9ea9..f1740cc1 100644 --- a/wx/lib/intctrl.py +++ b/wx/lib/intctrl.py @@ -47,11 +47,7 @@ import six MAXSIZE = six.MAXSIZE # (constants should be in upper case) MINSIZE = -six.MAXSIZE-1 - -if six.PY2: - LONGTYPE = long -else: - LONGTYPE = int +LONGTYPE = int #---------------------------------------------------------------------------- @@ -469,10 +465,7 @@ class IntCtrl(wx.TextCtrl): self.__default_color = wx.BLACK self.__oob_color = wx.RED self.__allow_none = 0 - if six.PY2: - self.__allow_long = 0 - else: - self.__allow_long = 1 + self.__allow_long = 1 self.__oldvalue = None if validator == wx.DefaultValidator: @@ -491,10 +484,7 @@ class IntCtrl(wx.TextCtrl): self.SetLimited(limited) self.SetColors(default_color, oob_color) self.SetNoneAllowed(allow_none) - if six.PY2: - self.SetLongAllowed(allow_long) - else: - self.SetLongAllowed(1) + self.SetLongAllowed(1) self.ChangeValue(value) def OnText( self, event ): @@ -708,7 +698,7 @@ class IntCtrl(wx.TextCtrl): value = self.GetValue() if( not (value is None and self.IsNoneAllowed()) - and type(value) not in six.integer_types ): + and type(value) not in int ): raise ValueError ( 'IntCtrl requires integer values, passed %s'% repr(value) ) @@ -820,7 +810,7 @@ class IntCtrl(wx.TextCtrl): elif type(value) == LONGTYPE and not self.IsLongAllowed(): raise ValueError ( 'IntCtrl requires integer value, passed long' ) - elif type(value) not in six.integer_types: + elif type(value) not in int: raise ValueError ( 'IntCtrl requires integer value, passed %s'% repr(value) ) diff --git a/wx/lib/masked/combobox.py b/wx/lib/masked/combobox.py index f9afb1f7..484368c7 100644 --- a/wx/lib/masked/combobox.py +++ b/wx/lib/masked/combobox.py @@ -478,7 +478,7 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ): penalty. """ if self._mask: - if not isinstance(choice, six.string_types): + if not isinstance(choice, str): raise TypeError('%s: choices must be a sequence of strings' % str(self._index)) elif not self.IsValid(choice): raise ValueError('%s: "%s" is not a valid value for the control as specified.' % (str(self._index), choice)) @@ -731,7 +731,7 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ): # work around bug in wx 2.5 wx.CallAfter(self.SetInsertionPoint, 0) wx.CallAfter(self.SetInsertionPoint, end) - elif isinstance(match_index, six.string_types): + elif isinstance(match_index, str): ## dbg('CallAfter SetValue') # Preserve the textbox contents # See commentary in _OnReturn docstring. diff --git a/wx/lib/masked/ipaddrctrl.py b/wx/lib/masked/ipaddrctrl.py index 0ea398e0..a20f8da9 100644 --- a/wx/lib/masked/ipaddrctrl.py +++ b/wx/lib/masked/ipaddrctrl.py @@ -23,7 +23,6 @@ user hits '.' when typing. """ import wx -import six from wx.lib.masked import BaseMaskedTextCtrl # jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would @@ -188,7 +187,7 @@ class IpAddrCtrl( BaseMaskedTextCtrl, IpAddrCtrlAccessorsMixin ): """ ## dbg('IpAddrCtrl::SetValue(%s)' % str(value), indent=1) - if not isinstance(value, six.string_types): + if not isinstance(value, str): ## dbg(indent=0) raise ValueError('%s must be a string' % str(value)) diff --git a/wx/lib/masked/maskededit.py b/wx/lib/masked/maskededit.py index 23391c28..87335d42 100644 --- a/wx/lib/masked/maskededit.py +++ b/wx/lib/masked/maskededit.py @@ -813,7 +813,6 @@ import string import sys import wx -import six # jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would # be a good place to implement the 2.3 logger class @@ -1490,7 +1489,7 @@ class Field: raise TypeError('%s: choices must be a sequence of strings' % str(self._index)) elif len( self._choices) > 0: for choice in self._choices: - if not isinstance(choice, six.string_types): + if not isinstance(choice, str): ## dbg(indent=0, suspend=0) raise TypeError('%s: choices must be a sequence of strings' % str(self._index)) @@ -1954,7 +1953,7 @@ class MaskedEditMixin: for key in ('emptyBackgroundColour', 'invalidBackgroundColour', 'validBackgroundColour', 'foregroundColour', 'signedForegroundColour'): if key in ctrl_kwargs: - if isinstance(ctrl_kwargs[key], six.string_types): + if isinstance(ctrl_kwargs[key], str): c = wx.Colour(ctrl_kwargs[key]) if c.Get() == (-1, -1, -1): raise TypeError('%s not a legal color specification for %s' % (repr(ctrl_kwargs[key]), key)) @@ -3062,23 +3061,15 @@ class MaskedEditMixin: if key < 256: char = chr(key) # (must work if we got this far) - if not six.PY3: - char = char.decode(self._defaultEncoding) else: char = unichr(event.GetUnicodeKey()) ## dbg('unicode char:', char) - excludes = six.text_type() - if not isinstance(field._excludeChars, six.text_type): - if six.PY3: - excludes += field._excludeChars - else: - excludes += field._excludeChars.decode(self._defaultEncoding) - if not isinstance(self._ctrl_constraints, six.text_type): - if six.PY3: - excludes += field._excludeChars - else: - excludes += self._ctrl_constraints._excludeChars.decode(self._defaultEncoding) + excludes = str() + if not isinstance(field._excludeChars, str): + excludes += field._excludeChars + if not isinstance(self._ctrl_constraints, str): + excludes += field._excludeChars else: excludes += self._ctrl_constraints._excludeChars @@ -4634,11 +4625,6 @@ class MaskedEditMixin: maskChar = self.maskdict[pos] okchars = self.maskchardict[maskChar] ## entry, get mask approved characters - # convert okchars to unicode if required; will force subsequent appendings to - # result in unicode strings - if not six.PY3 and not isinstance(okchars, six.text_type): - okchars = okchars.decode(self._defaultEncoding) - field = self._FindField(pos) if okchars and field._okSpaces: ## Allow spaces? okchars += " " @@ -5225,12 +5211,6 @@ class MaskedEditMixin: left = text[0:pos] right = text[pos+1:] - if not isinstance(char, six.text_type): - # convert the keyboard constant to a unicode value, to - # ensure it can be concatenated into the control value: - if not six.PY3: - char = char.decode(self._defaultEncoding) - newtext = left + char + right #### dbg('left: "%s"' % left) #### dbg('right: "%s"' % right) @@ -5764,8 +5744,6 @@ class MaskedEditMixin: else: item = 'selection' ## dbg('maxlength:', maxlength) - if not six.PY3 and not isinstance(paste_text, six.text_type): - paste_text = paste_text.decode(self._defaultEncoding) length_considered = len(paste_text) if length_considered > maxlength: @@ -5871,9 +5849,6 @@ class MaskedEditMixin: if paste_text is not None: - if not six.PY3 and not isinstance(paste_text, six.text_type): - paste_text = paste_text.decode(self._defaultEncoding) - ## dbg('paste text: "%s"' % paste_text) # (conversion will raise ValueError if paste isn't legal) sel_start, sel_to = self._GetSelection() diff --git a/wx/lib/masked/numctrl.py b/wx/lib/masked/numctrl.py index ac659c26..d0177d19 100644 --- a/wx/lib/masked/numctrl.py +++ b/wx/lib/masked/numctrl.py @@ -401,7 +401,6 @@ GetAutoSize() import copy import wx -import six from sys import maxsize MAXINT = maxsize # (constants should be in upper case) @@ -1641,7 +1640,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): ## dbg(indent=0) return self._template - elif isinstance(value, six.string_types): + elif isinstance(value, str): value = self._GetNumValue(value) ## dbg('cleansed num value: "%s"' % value) if value == "": diff --git a/wx/lib/masked/timectrl.py b/wx/lib/masked/timectrl.py index 6ca738d3..32c1d619 100644 --- a/wx/lib/masked/timectrl.py +++ b/wx/lib/masked/timectrl.py @@ -281,7 +281,6 @@ IsLimited() import copy import wx -import six from wx.tools.dbg import Logger from wx.lib.masked import Field, BaseMaskedTextCtrl @@ -762,8 +761,8 @@ class TimeCtrl(BaseMaskedTextCtrl): ## dbg('value = "%s"' % value) valid = True # assume true - if isinstance(value, six.string_types): - value = six.text_type(value) # convert to regular string + if isinstance(value, str): + value = str(value) # convert to regular string # Construct constant wxDateTime, then try to parse the string: wxdt = wx.DateTime.FromDMY(1, 0, 1970) @@ -1385,7 +1384,7 @@ class TimeCtrl(BaseMaskedTextCtrl): if self.IsLimited() and not self.IsInBounds(value): ## dbg(indent=0) raise ValueError ( - 'value %s is not within the bounds of the control' % six.text_type(value) ) + 'value %s is not within the bounds of the control' % str(value) ) ## dbg(indent=0) return value diff --git a/wx/lib/mixins/listctrl.py b/wx/lib/mixins/listctrl.py index fe91d713..2d55ee85 100644 --- a/wx/lib/mixins/listctrl.py +++ b/wx/lib/mixins/listctrl.py @@ -33,12 +33,9 @@ import locale import wx -import six -if six.PY3: - # python 3 lacks cmp: - def cmp(a, b): - return (a > b) - (a < b) +def cmp(a, b): + return (a > b) - (a < b) #---------------------------------------------------------------------------- @@ -161,10 +158,10 @@ class ColumnSorterMixin: item2 = self.itemDataMap[key2][col] #--- Internationalization of string sorting with locale module - if isinstance(item1, six.text_type) and isinstance(item2, six.text_type): + if isinstance(item1, str) and isinstance(item2, str): # both are unicode (py2) or str (py3) cmpVal = locale.strcoll(item1, item2) - elif isinstance(item1, six.binary_type) or isinstance(item2, six.binary_type): + elif isinstance(item1, bytes) or isinstance(item2, bytes): # at least one is a str (py2) or byte (py3) cmpVal = locale.strcoll(str(item1), str(item2)) else: diff --git a/wx/lib/multisash.py b/wx/lib/multisash.py index 487c8aab..a55c7684 100644 --- a/wx/lib/multisash.py +++ b/wx/lib/multisash.py @@ -21,7 +21,6 @@ import wx -import six MV_HOR = 0 MV_VER = not MV_HOR @@ -63,7 +62,7 @@ class MultiSash(wx.Window): def SetSaveData(self,data): mod = data['_defChild_mod'] dChild = mod + '.' + data['_defChild_class'] - six.exec_('import %s' % mod) + exec('import %s' % mod) self._defChild = eval(dChild) old = self.child self.child = MultiSplit(self,self,wx.Point(0,0),self.GetSize()) @@ -327,7 +326,7 @@ class MultiViewLeaf(wx.Window): def SetSaveData(self,data): mod = data['detailClass_mod'] dChild = mod + '.' + data['detailClass_class'] - six.exec_('import %s' % mod) + exec('import %s' % mod) detClass = eval(dChild) self.SetSize(data['x'],data['y'],data['w'],data['h']) old = self.detail diff --git a/wx/lib/pdfviewer/viewer.py b/wx/lib/pdfviewer/viewer.py index 84745ec7..86ba7506 100644 --- a/wx/lib/pdfviewer/viewer.py +++ b/wx/lib/pdfviewer/viewer.py @@ -27,7 +27,7 @@ import bisect import itertools import copy import shutil -from six import BytesIO, string_types +from io import BytesIO import wx @@ -199,7 +199,7 @@ class pdfViewer(wx.ScrolledWindow): return BytesIO(stream) self.pdfpathname = '' - if isinstance(pdf_file, string_types): + if isinstance(pdf_file, str): # a filename/path string, save its name self.pdfpathname = pdf_file # remove comment from next line to test using a file-like object @@ -507,7 +507,7 @@ class mupdfProcessor(object): Could also be a string representing a path to a PDF file. """ self.parent = parent - if isinstance(pdf_file, string_types): + if isinstance(pdf_file, str): # a filename/path string, pass the name to pymupdf.open pathname = pdf_file self.pdfdoc = pymupdf.open(pathname) diff --git a/wx/lib/printout.py b/wx/lib/printout.py index abc42c60..4c68be68 100644 --- a/wx/lib/printout.py +++ b/wx/lib/printout.py @@ -27,9 +27,7 @@ import copy import types import wx -import six - -class PrintBase(object): +class PrintBase: def SetPrintFont(self, font): # set the DC font parameters fattr = font["Attr"] if fattr[0] == 1: @@ -273,7 +271,7 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase): self.column.append(pos_x) #module logic expects two dimensional data -- fix input if needed - if isinstance(self.data, six.string_types): + if isinstance(self.data, str): self.data = [[copy.copy(self.data)]] # a string becomes a single cell try: rows = len(self.data) @@ -282,7 +280,7 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase): rows = 1 first_value = self.data[0] - if isinstance(first_value, six.string_types): # a sequence of strings + if isinstance(first_value, str): # a sequence of strings if self.label == [] and self.set_column == []: data = [] for x in self.data: #becomes one column @@ -562,7 +560,7 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase): self.col = 0 max_y = 0 for vtxt in row_val: - if not isinstance(vtxt, six.string_types): + if not isinstance(vtxt, str): vtxt = str(vtxt) self.region = self.column[self.col+1] - self.column[self.col] self.indent = self.column[self.col] diff --git a/wx/lib/pubsub/core/callables.py b/wx/lib/pubsub/core/callables.py index 7e798c54..c6bb3fdd 100644 --- a/wx/lib/pubsub/core/callables.py +++ b/wx/lib/pubsub/core/callables.py @@ -11,13 +11,14 @@ CallArgsInfo regarding its autoTopicArgName data member. :license: BSD, see LICENSE_BSD_Simple.txt for details. """ +import sys from inspect import ismethod, isfunction, signature, Parameter -from .. import py2and3 - AUTO_TOPIC = '## your listener wants topic name ## (string unlikely to be used by caller)' +def getexcobj(): + return sys.exc_info()[1] def getModule(obj): """Get the module in which an object was defined. Returns '__main__' @@ -189,8 +190,7 @@ def getArgs(callable_): try: func, firstArgIdx = getRawFunction(callable_) except ValueError: - from .. import py2and3 - exc = py2and3.getexcobj() + exc = getexcobj() raise ListenerMismatchError(str(exc), callable_) return CallArgsInfo(func, firstArgIdx) diff --git a/wx/lib/pubsub/core/imp2.py b/wx/lib/pubsub/core/imp2.py index c4641e33..933c7b34 100644 --- a/wx/lib/pubsub/core/imp2.py +++ b/wx/lib/pubsub/core/imp2.py @@ -7,14 +7,13 @@ closely. """ import sys -from .. import py2and3 def _resolve_name(name, package, level): """Return the absolute name of the module to be imported.""" if not hasattr(package, 'rindex'): raise ValueError("'package' not set to a string") dot = len(package) - for x in py2and3.xrange(level, 1, -1): + for x in range(level, 1, -1): try: dot = package.rindex('.', 0, dot) except ValueError: diff --git a/wx/lib/pubsub/core/kwargs/publisher.py b/wx/lib/pubsub/core/kwargs/publisher.py index 37c28d8c..bda42fc5 100644 --- a/wx/lib/pubsub/core/kwargs/publisher.py +++ b/wx/lib/pubsub/core/kwargs/publisher.py @@ -6,7 +6,7 @@ from .publisherbase import PublisherBase from .datamsg import Message -from .. import (policies, py2and3) +from .. import (policies) @@ -42,7 +42,7 @@ class PublisherArg1Stage2(Publisher): def __init__(self, kwargs, commonArgName): extra = kwargs.copy() del extra[commonArgName] - msg = 'Sender has too many kwargs (%s)' % ( py2and3.keys(extra),) + msg = 'Sender has too many kwargs (%s)' % ( extra.keys(),) RuntimeError.__init__(self, msg) class SenderWrongKwargName(RuntimeError): @@ -60,7 +60,7 @@ class PublisherArg1Stage2(Publisher): if len(kwarg) > 1: raise self.SenderTooManyKwargs(kwarg, commonArgName) elif len(kwarg) == 1 and commonArgName not in kwarg: - raise self.SenderWrongKwargName( py2and3.keys(kwarg)[0], commonArgName) + raise self.SenderWrongKwargName( kwarg.keys()[0], commonArgName) data = kwarg.get(commonArgName, None) kwargs = { commonArgName: self.Msg( _topicName, data) } diff --git a/wx/lib/pubsub/core/kwargs/topicargspecimpl.py b/wx/lib/pubsub/core/kwargs/topicargspecimpl.py index 73120d5c..ea9817f1 100644 --- a/wx/lib/pubsub/core/kwargs/topicargspecimpl.py +++ b/wx/lib/pubsub/core/kwargs/topicargspecimpl.py @@ -9,7 +9,6 @@ import weakref from .topicutils import (stringize, WeakNone) from .validatedefnargs import verifySubset -from .. import py2and3 ### Exceptions raised during check() from sendMessage() @@ -101,7 +100,7 @@ class ArgsInfo: """docs is a mapping from arg names to their documentation""" if not self.isComplete(): raise - for arg, doc in py2and3.iteritems(docs): + for arg, doc in docs.items(): self.allDocs[arg] = doc def check(self, msgKwargs): @@ -115,14 +114,14 @@ class ArgsInfo: hasReqd = (needReqd <= all) if not hasReqd: raise SenderMissingReqdMsgDataError( - self.topicNameTuple, py2and3.keys(msgKwargs), needReqd - all) + self.topicNameTuple, msgKwargs.keys(), needReqd - all) # check that all other args are among the optional spec optional = all - needReqd ok = (optional <= set(self.allOptional)) if not ok: raise SenderUnknownMsgDataError( self.topicNameTuple, - py2and3.keys(msgKwargs), optional - set(self.allOptional) ) + msgKwargs.keys(), optional - set(self.allOptional) ) def filterArgs(self, msgKwargs): """Returns a dict which contains only those items of msgKwargs diff --git a/wx/lib/pubsub/core/publisherbase.py b/wx/lib/pubsub/core/publisherbase.py index b48e3989..129f9388 100644 --- a/wx/lib/pubsub/core/publisherbase.py +++ b/wx/lib/pubsub/core/publisherbase.py @@ -8,8 +8,6 @@ from .topicmgr import ( TreeConfig ) -from .. import py2and3 - class PublisherBase: """ @@ -177,7 +175,7 @@ class PublisherBase: if topicName is None: # unsubscribe all listeners from all topics topicsMap = self.__topicMgr._topicsMap - for topicName, topicObj in py2and3.iteritems(topicsMap): + for topicName, topicObj in topicsMap.items(): if topicFilter is None or topicFilter(topicName): tmp = topicObj.unsubscribeAllListeners(listenerFilter) unsubdListeners.extend(tmp) diff --git a/wx/lib/pubsub/core/topicdefnprovider.py b/wx/lib/pubsub/core/topicdefnprovider.py index a60015a8..6aca10fc 100644 --- a/wx/lib/pubsub/core/topicdefnprovider.py +++ b/wx/lib/pubsub/core/topicdefnprovider.py @@ -4,12 +4,11 @@ """ -import os, re, inspect +import os, re, inspect, io from textwrap import TextWrapper, dedent from .. import ( policies, - py2and3 ) from .topicargspec import ( topicArgsFromCallable, @@ -129,7 +128,7 @@ class TopicDefnDeserialClass(ITopicDefnDeserializer): def getNextTopic(self): self.__iterStarted = True try: - topicNameTuple, topicClassObj = py2and3.nextiter(self.__nextTopic) + topicNameTuple, topicClassObj = next(self.__nextTopic) except StopIteration: return None @@ -357,7 +356,7 @@ class TopicDefnProvider(ITopicDefnProvider): return desc, spec def topicNames(self): - return py2and3.iterkeys(self.__topicDefns) + return self.__topicDefns.keys() def getTreeDoc(self): return self.__treeDocs @@ -428,13 +427,13 @@ def exportTopicTreeSpec(moduleName = None, rootTopic=None, bak='bak', moduleDoc= if rootTopic is None: from .. import pub rootTopic = pub.getDefaultTopicMgr().getRootAllTopics() - elif py2and3.isstring(rootTopic): + elif isintance(rootTopic, str): from .. import pub rootTopic = pub.getDefaultTopicMgr().getTopic(rootTopic) # create exporter if moduleName is None: - capture = py2and3.StringIO() + capture = io.StringIO() TopicTreeSpecPrinter(rootTopic, fileObj=capture, treeDoc=moduleDoc) return capture.getvalue() @@ -485,7 +484,7 @@ class TopicTreeSpecPrinter: args = dict(width=width, indentStep=indentStep, treeDoc=treeDoc, footer=footer, fileObj=fileObj) def fmItem(argName, argVal): - if py2and3.isstring(argVal): + if isinstance(argVal, str): MIN_OFFSET = 5 lenAV = width - MIN_OFFSET - len(argName) if lenAV > 0: @@ -493,7 +492,7 @@ class TopicTreeSpecPrinter: elif argName == 'fileObj': argVal = fileObj.__class__.__name__ return '# - %s: %s' % (argName, argVal) - fmtArgs = [fmItem(key, args[key]) for key in sorted(py2and3.iterkeys(args))] + fmtArgs = [fmItem(key, args[key]) for key in sorted(args.keys())] self.__comment = [ '# Automatically generated by %s(**kwargs).' % self.__class__.__name__, '# The kwargs were:', diff --git a/wx/lib/pubsub/core/topicmgr.py b/wx/lib/pubsub/core/topicmgr.py index 10342a48..4247dc2a 100644 --- a/wx/lib/pubsub/core/topicmgr.py +++ b/wx/lib/pubsub/core/topicmgr.py @@ -40,8 +40,6 @@ from .treeconfig import TreeConfig from .topicdefnprovider import ITopicDefnProvider from .topicmgrimpl import getRootTopicSpec -from .. import py2and3 - # --------------------------------------------------------- @@ -255,7 +253,7 @@ class TopicManager: def checkAllTopicsHaveMDS(self): """Check that all topics that have been created for their MDS. Raise a TopicDefnError if one is found that does not have one.""" - for topic in py2and3.itervalues(self._topicsMap): + for topic in self._topicsMap.values(): if not topic.hasMDS(): raise TopicDefnError(topic.getNameTuple()) @@ -287,7 +285,7 @@ class TopicManager: subscribed. Note: the listener can also get messages from any sub-topic of returned list.""" assocTopics = [] - for topicObj in py2and3.itervalues(self._topicsMap): + for topicObj in self._topicsMap.values(): if topicObj.hasListener(listener): assocTopics.append(topicObj) return assocTopics diff --git a/wx/lib/pubsub/core/topicobj.py b/wx/lib/pubsub/core/topicobj.py index edff9584..5cfef56f 100644 --- a/wx/lib/pubsub/core/topicobj.py +++ b/wx/lib/pubsub/core/topicobj.py @@ -4,7 +4,7 @@ Provide the Topic class. :copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved. :license: BSD, see LICENSE_BSD_Simple.txt for details. """ - +import sys from weakref import ref as weakref @@ -38,8 +38,8 @@ from .topicargspec import ( MessageDataSpecError, ) -from .. import py2and3 - +def getexcobj(): + return sys.exc_info()[1] class Topic(PublisherMixin): """ @@ -140,7 +140,7 @@ class Topic(PublisherMixin): self.__parentTopic()._getListenerSpec()) except MessageDataSpecError: # discard the lower part of the stack trace - exc = py2and3.getexcobj() + exc = getexcobj() raise exc self.__finalize() @@ -242,7 +242,7 @@ class Topic(PublisherMixin): def getSubtopics(self): """Get a list of Topic instances that are subtopics of self.""" - return py2and3.values(self.__subTopics) + return self.__subTopics.values() def getNumListeners(self): """Return number of listeners currently subscribed to topic. This is @@ -262,12 +262,12 @@ class Topic(PublisherMixin): def getListeners(self): """Get a copy of list of listeners subscribed to this topic. Safe to iterate over while listeners get un/subscribed from this topics (such as while sending a message).""" - return py2and3.keys(self.__listeners) + return self.__listeners.keys() def getListenersIter(self): """Get an iterator over listeners subscribed to this topic. Do not use if listeners can be un/subscribed while iterating. """ - return py2and3.iterkeys(self.__listeners) + return self.__listeners.keys() def validate(self, listener): """Checks whether listener could be subscribed to this topic: @@ -337,11 +337,11 @@ class Topic(PublisherMixin): if filter is None: for listener in self.__listeners: listener._unlinkFromTopic_() - unsubd = py2and3.keys(self.__listeners) + unsubd = self.__listeners.keys() self.__listeners = {} else: unsubd = [] - for listener in py2and3.keys(self.__listeners): + for listener in self.__listeners.keys(): if filter(listener): unsubd.append(listener) listener._unlinkFromTopic_() @@ -408,7 +408,7 @@ class Topic(PublisherMixin): handler( listener.name(), topicObj ) self.__handlingUncaughtListenerExc = False except Exception: - exc = py2and3.getexcobj() + exc = getexcobj() #print 'exception raised', exc self.__handlingUncaughtListenerExc = False raise ExcHandlerError(listener.name(), topicObj, exc) @@ -441,7 +441,7 @@ class Topic(PublisherMixin): self.unsubscribeAllListeners() self.__parentTopic = None - for subName, subObj in py2and3.iteritems(self.__subTopics): + for subName, subObj in self.__subTopics.items(): assert isinstance(subObj, Topic) #print 'Unlinking %s from parent' % subObj.getName() subObj.__undefineBranch(topicsMap) diff --git a/wx/lib/pubsub/core/topicutils.py b/wx/lib/pubsub/core/topicutils.py index 4b3d5cec..460b1459 100644 --- a/wx/lib/pubsub/core/topicutils.py +++ b/wx/lib/pubsub/core/topicutils.py @@ -5,15 +5,16 @@ Various utilities used by topic-related modules. :license: BSD, see LICENSE_BSD_Simple.txt for details. """ +import sys from textwrap import TextWrapper, dedent from .topicexc import TopicNameError -from .. import py2and3 - __all__ = [] +def getexcobj(): + return sys.exc_info()[1] UNDERSCORE = '_' # topic name can't start with this # just want something unlikely to clash with user's topic names @@ -81,7 +82,7 @@ def stringize(topicName): topic. Otherwise, assume topicName is a tuple and convert it to to a dotted name i.e. ('a','b','c') => 'a.b.c'. Empty name is not allowed (ValueError). The reverse operation is tupleize(topicName).""" - if py2and3.isstring(topicName): + if isinstance(topicName, str): return topicName if hasattr(topicName, "msgDataSpec"): @@ -90,7 +91,7 @@ def stringize(topicName): try: name = '.'.join(topicName) except Exception: - exc = py2and3.getexcobj() + exc = getexcobj() raise TopicNameError(topicName, str(exc)) return name @@ -105,7 +106,7 @@ def tupleize(topicName): # then better use isinstance(name, tuple) if hasattr(topicName, "msgDataSpec"): topicName = topicName._topicNameStr - if py2and3.isstring(topicName): + if isinstance(topicName, str): topicTuple = tuple(topicName.split('.')) else: topicTuple = tuple(topicName) # assume already tuple of strings diff --git a/wx/lib/pubsub/py2and3.py b/wx/lib/pubsub/py2and3.py deleted file mode 100644 index e00bc680..00000000 --- a/wx/lib/pubsub/py2and3.py +++ /dev/null @@ -1,608 +0,0 @@ -"""Utilities for writing code that runs on Python 2 and 3""" - -# Copyright (c) 2010-2013 Benjamin Peterson -# -# 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. - -import operator -import sys -import types - -__author__ = "Benjamin Peterson " -__version__ = "1.4.1" - - -# Useful for very coarse version differentiation. -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - -if PY3: - string_types = str, - integer_types = int, - class_types = type, - text_type = str - binary_type = bytes - - MAXSIZE = sys.maxsize -else: - string_types = basestring, - integer_types = (int, long) - class_types = (type, types.ClassType) - text_type = unicode - binary_type = str - - if sys.platform.startswith("java"): - # Jython always uses 32 bits. - MAXSIZE = int((1 << 31) - 1) - else: - # It's possible to have sizeof(long) != sizeof(Py_ssize_t). - class X(object): - def __len__(self): - return 1 << 31 - try: - len(X()) - except OverflowError: - # 32-bit - MAXSIZE = int((1 << 31) - 1) - else: - # 64-bit - MAXSIZE = int((1 << 63) - 1) - del X - - -def _add_doc(func, doc): - """Add documentation to a function.""" - func.__doc__ = doc - - -def _import_module(name): - """Import module, returning the module after the last dot.""" - __import__(name) - return sys.modules[name] - - -class _LazyDescr(object): - - def __init__(self, name): - self.name = name - - def __get__(self, obj, tp): - result = self._resolve() - setattr(obj, self.name, result) - # This is a bit ugly, but it avoids running this again. - delattr(tp, self.name) - return result - - -class MovedModule(_LazyDescr): - - def __init__(self, name, old, new=None): - super(MovedModule, self).__init__(name) - if PY3: - if new is None: - new = name - self.mod = new - else: - self.mod = old - - def _resolve(self): - return _import_module(self.mod) - - -class MovedAttribute(_LazyDescr): - - def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): - super(MovedAttribute, self).__init__(name) - if PY3: - if new_mod is None: - new_mod = name - self.mod = new_mod - if new_attr is None: - if old_attr is None: - new_attr = name - else: - new_attr = old_attr - self.attr = new_attr - else: - self.mod = old_mod - if old_attr is None: - old_attr = name - self.attr = old_attr - - def _resolve(self): - module = _import_module(self.mod) - return getattr(module, self.attr) - - - -class _MovedItems(types.ModuleType): - """Lazy loading of moved objects""" - - -_moved_attributes = [ - MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), - MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), - MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), - MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), - MovedAttribute("map", "itertools", "builtins", "imap", "map"), - MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("reload_module", "__builtin__", "imp", "reload"), - MovedAttribute("reduce", "__builtin__", "functools"), - MovedAttribute("StringIO", "StringIO", "io"), - MovedAttribute("UserString", "UserString", "collections"), - MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), - MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), - - MovedModule("builtins", "__builtin__"), - MovedModule("configparser", "ConfigParser"), - MovedModule("copyreg", "copy_reg"), - MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), - MovedModule("http_cookies", "Cookie", "http.cookies"), - MovedModule("html_entities", "htmlentitydefs", "html.entities"), - MovedModule("html_parser", "HTMLParser", "html.parser"), - MovedModule("http_client", "httplib", "http.client"), - MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), - MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), - MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), - MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), - MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), - MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), - MovedModule("cPickle", "cPickle", "pickle"), - MovedModule("queue", "Queue"), - MovedModule("reprlib", "repr"), - MovedModule("socketserver", "SocketServer"), - MovedModule("tkinter", "Tkinter"), - MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), - MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), - MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), - MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), - MovedModule("tkinter_tix", "Tix", "tkinter.tix"), - MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), - MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), - MovedModule("tkinter_colorchooser", "tkColorChooser", - "tkinter.colorchooser"), - MovedModule("tkinter_commondialog", "tkCommonDialog", - "tkinter.commondialog"), - MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), - MovedModule("tkinter_font", "tkFont", "tkinter.font"), - MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), - MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", - "tkinter.simpledialog"), - MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), - MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), - MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), - MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), - MovedModule("winreg", "_winreg"), -] -for attr in _moved_attributes: - setattr(_MovedItems, attr.name, attr) -del attr - -moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves") - - - -class Module_six_moves_urllib_parse(types.ModuleType): - """Lazy loading of moved objects in six.moves.urllib_parse""" - - -_urllib_parse_moved_attributes = [ - MovedAttribute("ParseResult", "urlparse", "urllib.parse"), - MovedAttribute("parse_qs", "urlparse", "urllib.parse"), - MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), - MovedAttribute("urldefrag", "urlparse", "urllib.parse"), - MovedAttribute("urljoin", "urlparse", "urllib.parse"), - MovedAttribute("urlparse", "urlparse", "urllib.parse"), - MovedAttribute("urlsplit", "urlparse", "urllib.parse"), - MovedAttribute("urlunparse", "urlparse", "urllib.parse"), - MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), - MovedAttribute("quote", "urllib", "urllib.parse"), - MovedAttribute("quote_plus", "urllib", "urllib.parse"), - MovedAttribute("unquote", "urllib", "urllib.parse"), - MovedAttribute("unquote_plus", "urllib", "urllib.parse"), - MovedAttribute("urlencode", "urllib", "urllib.parse"), -] -for attr in _urllib_parse_moved_attributes: - setattr(Module_six_moves_urllib_parse, attr.name, attr) -del attr - -sys.modules[__name__ + ".moves.urllib_parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse") -sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib.parse") - - -class Module_six_moves_urllib_error(types.ModuleType): - """Lazy loading of moved objects in six.moves.urllib_error""" - - -_urllib_error_moved_attributes = [ - MovedAttribute("URLError", "urllib2", "urllib.error"), - MovedAttribute("HTTPError", "urllib2", "urllib.error"), - MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), -] -for attr in _urllib_error_moved_attributes: - setattr(Module_six_moves_urllib_error, attr.name, attr) -del attr - -sys.modules[__name__ + ".moves.urllib_error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib_error") -sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib.error") - - -class Module_six_moves_urllib_request(types.ModuleType): - """Lazy loading of moved objects in six.moves.urllib_request""" - - -_urllib_request_moved_attributes = [ - MovedAttribute("urlopen", "urllib2", "urllib.request"), - MovedAttribute("install_opener", "urllib2", "urllib.request"), - MovedAttribute("build_opener", "urllib2", "urllib.request"), - MovedAttribute("pathname2url", "urllib", "urllib.request"), - MovedAttribute("url2pathname", "urllib", "urllib.request"), - MovedAttribute("getproxies", "urllib", "urllib.request"), - MovedAttribute("Request", "urllib2", "urllib.request"), - MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), - MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), - MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), - MovedAttribute("BaseHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), - MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), - MovedAttribute("FileHandler", "urllib2", "urllib.request"), - MovedAttribute("FTPHandler", "urllib2", "urllib.request"), - MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), - MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), - MovedAttribute("urlretrieve", "urllib", "urllib.request"), - MovedAttribute("urlcleanup", "urllib", "urllib.request"), - MovedAttribute("URLopener", "urllib", "urllib.request"), - MovedAttribute("FancyURLopener", "urllib", "urllib.request"), -] -for attr in _urllib_request_moved_attributes: - setattr(Module_six_moves_urllib_request, attr.name, attr) -del attr - -sys.modules[__name__ + ".moves.urllib_request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib_request") -sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib.request") - - -class Module_six_moves_urllib_response(types.ModuleType): - """Lazy loading of moved objects in six.moves.urllib_response""" - - -_urllib_response_moved_attributes = [ - MovedAttribute("addbase", "urllib", "urllib.response"), - MovedAttribute("addclosehook", "urllib", "urllib.response"), - MovedAttribute("addinfo", "urllib", "urllib.response"), - MovedAttribute("addinfourl", "urllib", "urllib.response"), -] -for attr in _urllib_response_moved_attributes: - setattr(Module_six_moves_urllib_response, attr.name, attr) -del attr - -sys.modules[__name__ + ".moves.urllib_response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib_response") -sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib.response") - - -class Module_six_moves_urllib_robotparser(types.ModuleType): - """Lazy loading of moved objects in six.moves.urllib_robotparser""" - - -_urllib_robotparser_moved_attributes = [ - MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), -] -for attr in _urllib_robotparser_moved_attributes: - setattr(Module_six_moves_urllib_robotparser, attr.name, attr) -del attr - -sys.modules[__name__ + ".moves.urllib_robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib_robotparser") -sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser") - - -class Module_six_moves_urllib(types.ModuleType): - """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" - parse = sys.modules[__name__ + ".moves.urllib_parse"] - error = sys.modules[__name__ + ".moves.urllib_error"] - request = sys.modules[__name__ + ".moves.urllib_request"] - response = sys.modules[__name__ + ".moves.urllib_response"] - robotparser = sys.modules[__name__ + ".moves.urllib_robotparser"] - - -sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib") - - -def add_move(move): - """Add an item to six.moves.""" - setattr(_MovedItems, move.name, move) - - -def remove_move(name): - """Remove item from six.moves.""" - try: - delattr(_MovedItems, name) - except AttributeError: - try: - del moves.__dict__[name] - except KeyError: - raise AttributeError("no such move, %r" % (name,)) - - -if PY3: - _meth_func = "__func__" - _meth_self = "__self__" - - _func_closure = "__closure__" - _func_code = "__code__" - _func_defaults = "__defaults__" - _func_globals = "__globals__" - - _iterkeys = "keys" - _itervalues = "values" - _iteritems = "items" - _iterlists = "lists" -else: - _meth_func = "im_func" - _meth_self = "im_self" - - _func_closure = "func_closure" - _func_code = "func_code" - _func_defaults = "func_defaults" - _func_globals = "func_globals" - - _iterkeys = "iterkeys" - _itervalues = "itervalues" - _iteritems = "iteritems" - _iterlists = "iterlists" - - -try: - advance_iterator = next -except NameError: - def advance_iterator(it): - return it.next() -next = advance_iterator - - -try: - callable = callable -except NameError: - def callable(obj): - return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) - - -if PY3: - def get_unbound_function(unbound): - return unbound - - create_bound_method = types.MethodType - - Iterator = object -else: - def get_unbound_function(unbound): - return unbound.im_func - - def create_bound_method(func, obj): - return types.MethodType(func, obj, obj.__class__) - - class Iterator(object): - - def next(self): - return type(self).__next__(self) - - callable = callable -_add_doc(get_unbound_function, - """Get the function out of a possibly unbound function""") - - -get_method_function = operator.attrgetter(_meth_func) -get_method_self = operator.attrgetter(_meth_self) -get_function_closure = operator.attrgetter(_func_closure) -get_function_code = operator.attrgetter(_func_code) -get_function_defaults = operator.attrgetter(_func_defaults) -get_function_globals = operator.attrgetter(_func_globals) - - -def iterkeys(d, **kw): - """Return an iterator over the keys of a dictionary.""" - return iter(getattr(d, _iterkeys)(**kw)) - -def itervalues(d, **kw): - """Return an iterator over the values of a dictionary.""" - return iter(getattr(d, _itervalues)(**kw)) - -def iteritems(d, **kw): - """Return an iterator over the (key, value) pairs of a dictionary.""" - return iter(getattr(d, _iteritems)(**kw)) - -def iterlists(d, **kw): - """Return an iterator over the (key, [values]) pairs of a dictionary.""" - return iter(getattr(d, _iterlists)(**kw)) - - -if PY3: - def b(s): - return s.encode("latin-1") - def u(s): - return s - unichr = chr - if sys.version_info[1] <= 1: - def int2byte(i): - return bytes((i,)) - else: - # This is about 2x faster than the implementation above on 3.2+ - int2byte = operator.methodcaller("to_bytes", 1, "big") - byte2int = operator.itemgetter(0) - indexbytes = operator.getitem - iterbytes = iter - import io - StringIO = io.StringIO - BytesIO = io.BytesIO -else: - def b(s): - return s - def u(s): - return unicode(s, "unicode_escape") - unichr = unichr - int2byte = chr - def byte2int(bs): - return ord(bs[0]) - def indexbytes(buf, i): - return ord(buf[i]) - def iterbytes(buf): - return (ord(byte) for byte in buf) - import StringIO - StringIO = BytesIO = StringIO.StringIO -_add_doc(b, """Byte literal""") -_add_doc(u, """Text literal""") - - -if PY3: - import builtins - exec_ = getattr(builtins, "exec") - - - def reraise(tp, value, tb=None): - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - - - print_ = getattr(builtins, "print") - del builtins - -else: - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - - - exec_("""def reraise(tp, value, tb=None): - raise tp, value, tb -""") - - - def print_(*args, **kwargs): - """The new-style print function.""" - fp = kwargs.pop("file", sys.stdout) - if fp is None: - return - def write(data): - if not isinstance(data, basestring): - data = str(data) - fp.write(data) - want_unicode = False - sep = kwargs.pop("sep", None) - if sep is not None: - if isinstance(sep, unicode): - want_unicode = True - elif not isinstance(sep, str): - raise TypeError("sep must be None or a string") - end = kwargs.pop("end", None) - if end is not None: - if isinstance(end, unicode): - want_unicode = True - elif not isinstance(end, str): - raise TypeError("end must be None or a string") - if kwargs: - raise TypeError("invalid keyword arguments to print()") - if not want_unicode: - for arg in args: - if isinstance(arg, unicode): - want_unicode = True - break - if want_unicode: - newline = unicode("\n") - space = unicode(" ") - else: - newline = "\n" - space = " " - if sep is None: - sep = space - if end is None: - end = newline - for i, arg in enumerate(args): - if i: - write(sep) - write(arg) - write(end) - -_add_doc(reraise, """Reraise an exception.""") - - -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - return meta("NewBase", bases, {}) - -def add_metaclass(metaclass): - """Class decorator for creating a class with a metaclass.""" - def wrapper(cls): - orig_vars = cls.__dict__.copy() - orig_vars.pop('__dict__', None) - orig_vars.pop('__weakref__', None) - for slots_var in orig_vars.get('__slots__', ()): - orig_vars.pop(slots_var) - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper - -def getexcobj(): - return sys.exc_info()[1] - -if PY3: - xrange = range -else: - xrange = xrange - -if PY3: - def keys(dictObj): - return list(dictObj.keys()) - def values(dictObj): - return list(dictObj.values()) - def nextiter(container): - return next(container) -else: - def keys(dictObj): - return dictObj.keys() - def values(dictObj): - return dictObj.values() - def nextiter(container): - return container.next() - -if PY3: - def isstring(obj): - return isinstance(obj, str) -else: - def isstring(obj): - return isinstance(obj, (str, unicode)) - diff --git a/wx/lib/pubsub/utils/misc.py b/wx/lib/pubsub/utils/misc.py index 29a4b931..96394308 100644 --- a/wx/lib/pubsub/utils/misc.py +++ b/wx/lib/pubsub/utils/misc.py @@ -6,8 +6,6 @@ printTreeDocs and printTreeSpec. :license: BSD, see LICENSE_BSD_Simple.txt for details. """ -from __future__ import print_function - import sys __all__ = ('printImported', 'StructMsg', 'Callback', 'Enum' ) diff --git a/wx/lib/pubsub/utils/xmltopicdefnprovider.py b/wx/lib/pubsub/utils/xmltopicdefnprovider.py index e9b4ea34..bca65d16 100644 --- a/wx/lib/pubsub/utils/xmltopicdefnprovider.py +++ b/wx/lib/pubsub/utils/xmltopicdefnprovider.py @@ -45,8 +45,6 @@ of the XML tree. :license: BSD, see LICENSE_BSD_Simple.txt for details. """ -from __future__ import print_function - __author__ = 'Joshua R English' __revision__ = 6 __date__ = '2013-07-27' @@ -58,7 +56,6 @@ from ..core.topicdefnprovider import ( ArgSpecGiven, TOPIC_TREE_FROM_STRING, ) -from .. import py2and3 try: from elementtree import ElementTree as ET @@ -162,7 +159,7 @@ class XmlTopicDefnProvider(ITopicDefnProvider): return self._topics.get(topicNameTuple, (None, None)) def topicNames(self): - return py2and3.iterkeys(self._topics) # dict_keys iter in 3, list in 2 + return self._topics.keys() def getTreeDoc(self): return self._treeDoc @@ -259,7 +256,7 @@ def exportTopicTreeSpecXml(moduleName=None, rootTopic=None, bak='bak', moduleDoc if rootTopic is None: from .. import pub rootTopic = pub.getDefaultTopicTreeRoot() - elif py2and3.isstring(rootTopic): + elif isintance(rootTopic, str): from .. import pub rootTopic = pub.getTopic(rootTopic) diff --git a/wx/lib/rcsizer.py b/wx/lib/rcsizer.py index 6c5ff6e5..ce7d7251 100644 --- a/wx/lib/rcsizer.py +++ b/wx/lib/rcsizer.py @@ -33,9 +33,7 @@ encouraged to switch. import operator import wx -import six -if six.PY3: - from functools import reduce as reduce +from functools import reduce as reduce # After the lib and demo no longer uses this sizer enable this warning... diff --git a/wx/lib/softwareupdate.py b/wx/lib/softwareupdate.py index 55906334..e2831319 100644 --- a/wx/lib/softwareupdate.py +++ b/wx/lib/softwareupdate.py @@ -30,14 +30,8 @@ import wx import sys import os import atexit -import six - -if six.PY3: - from urllib.request import urlopen - from urllib.error import URLError -else: - from urllib2 import urlopen - from urllib2 import URLError +from urllib.request import urlopen +from urllib.error import URLError from wx.lib.dialogs import MultiMessageBox diff --git a/wx/lib/wxcairo/wx_pycairo.py b/wx/lib/wxcairo/wx_pycairo.py index a8dd044d..19a28dd1 100644 --- a/wx/lib/wxcairo/wx_pycairo.py +++ b/wx/lib/wxcairo/wx_pycairo.py @@ -16,7 +16,6 @@ wx.lib.wxcairo implementation functions using PyCairo. """ import wx -from six import PY3 import cairo import ctypes @@ -413,16 +412,10 @@ def _loadPycairoAPI(): if not hasattr(cairo, 'CAPI'): return - if PY3: - PyCapsule_GetPointer = ctypes.pythonapi.PyCapsule_GetPointer - PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p] - PyCapsule_GetPointer.restype = ctypes.c_void_p - ptr = PyCapsule_GetPointer(cairo.CAPI, b'cairo.CAPI') - else: - PyCObject_AsVoidPtr = ctypes.pythonapi.PyCObject_AsVoidPtr - PyCObject_AsVoidPtr.argtypes = [ctypes.py_object] - PyCObject_AsVoidPtr.restype = ctypes.c_void_p - ptr = PyCObject_AsVoidPtr(cairo.CAPI) + PyCapsule_GetPointer = ctypes.pythonapi.PyCapsule_GetPointer + PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p] + PyCapsule_GetPointer.restype = ctypes.c_void_p + ptr = PyCapsule_GetPointer(cairo.CAPI, b'cairo.CAPI') pycairoAPI = ctypes.cast(ptr, ctypes.POINTER(Pycairo_CAPI)).contents #---------------------------------------------------------------------------- diff --git a/wx/py/filling.py b/wx/py/filling.py index 05bf175f..ccca8434 100644 --- a/wx/py/filling.py +++ b/wx/py/filling.py @@ -2,10 +2,8 @@ the local namespace or any object.""" __author__ = "Patrick K. O'Brien " -# Tags: py3-port import wx -import six from . import dispatcher from . import editwindow @@ -115,13 +113,13 @@ class FillingTree(wx.TreeCtrl): busy = wx.BusyCursor() otype = type(obj) if (isinstance(obj, dict) - or 'BTrees' in six.text_type(otype) + or 'BTrees' in str(otype) and hasattr(obj, 'keys')): return obj d = {} if isinstance(obj, (list, tuple)): for n in range(len(obj)): - key = '[' + six.text_type(n) + ']' + key = '[' + str(n) + ']' d[key] = obj[n] if otype not in COMMONTYPES: for key in introspect.getAttributeNames(obj): @@ -143,14 +141,14 @@ class FillingTree(wx.TreeCtrl): children = self.objGetChildren(obj) if not children: return - keys = sorted(children, key=lambda x: six.text_type(x).lower()) + keys = sorted(children, key=lambda x: str(x).lower()) for key in keys: - itemtext = six.text_type(key) + itemtext = str(key) # Show string dictionary items with single quotes, except # for the first level of items, if they represent a # namespace. if isinstance(obj, dict) \ - and isinstance(key, six.string_types) \ + and isinstance(key, str) \ and (item != self.root or (item == self.root and not self.rootIsNamespace)): itemtext = repr(key) @@ -173,12 +171,12 @@ class FillingTree(wx.TreeCtrl): otype = type(obj) text = '' text += self.getFullName(item) - text += '\n\nType: ' + six.text_type(otype) + text += '\n\nType: ' + str(otype) try: - value = six.text_type(obj) + value = str(obj) except Exception: value = '' - if isinstance(obj, six.string_types): + if isinstance(obj, str): value = repr(obj) text += u'\n\nValue: ' + value if otype not in SIMPLETYPES: @@ -187,7 +185,7 @@ class FillingTree(wx.TreeCtrl): inspect.getdoc(obj).strip() + '"""' except Exception: pass - if isinstance(obj, six.class_types): + if isinstance(obj, type): try: text += '\n\nClass Definition:\n\n' + \ inspect.getsource(obj.__class__) @@ -212,7 +210,7 @@ class FillingTree(wx.TreeCtrl): # Apply dictionary syntax to dictionary items, except the root # and first level children of a namespace. if ((isinstance(obj, dict) - or 'BTrees' in six.text_type(type(obj)) + or 'BTrees' in str(type(obj)) and hasattr(obj, 'keys')) and ((item != self.root and parent != self.root) or (parent == self.root and not self.rootIsNamespace))): diff --git a/wx/py/images.py b/wx/py/images.py index fd46033a..71bee777 100644 --- a/wx/py/images.py +++ b/wx/py/images.py @@ -3,7 +3,7 @@ __author__ = "Patrick K. O'Brien / David Mashburn " import wx -from six import BytesIO +from io import BytesIO def getPyIcon(shellName='PyCrust'): icon = wx.Icon() diff --git a/wx/py/interpreter.py b/wx/py/interpreter.py index 94eea2ec..b73c8a86 100644 --- a/wx/py/interpreter.py +++ b/wx/py/interpreter.py @@ -10,7 +10,6 @@ from code import InteractiveInterpreter, compile_command from . import dispatcher from . import introspect import wx -import six class Interpreter(InteractiveInterpreter): """Interpreter based on code.InteractiveInterpreter.""" @@ -25,7 +24,7 @@ class Interpreter(InteractiveInterpreter): self.stdout = stdout self.stderr = stderr if rawin: - from six.moves import builtins + import builtins builtins.raw_input = rawin del builtins if showInterpIntro: @@ -56,14 +55,6 @@ class Interpreter(InteractiveInterpreter): commandBuffer until we have a complete command. If not, we delete that last list.""" - # In case the command is unicode try encoding it - if not six.PY3: - if type(command) == unicode: - try: - command = command.encode('utf-8') - except UnicodeEncodeError: - pass # otherwise leave it alone - if not self.more: try: del self.commandBuffer[-1] except IndexError: pass diff --git a/wx/py/introspect.py b/wx/py/introspect.py index f2d86dbc..66efba42 100644 --- a/wx/py/introspect.py +++ b/wx/py/introspect.py @@ -9,7 +9,7 @@ import inspect import tokenize import types import wx -from six import BytesIO, PY3, string_types +from io import BytesIO def getAutoCompleteList(command='', locals=None, includeMagic=1, includeSingle=1, includeDouble=1): @@ -180,7 +180,7 @@ def getCallTip(command='', locals=None): try: argspec = str(inspect.signature(obj)) # PY35 or later except AttributeError: - argspec = inspect.getargspec(obj) if not PY3 else inspect.getfullargspec(obj) + argspec = inspect.getfullargspec(obj) argspec = inspect.formatargspec(*argspec) if dropSelf: # The first parameter to a method is a reference to an @@ -270,7 +270,7 @@ def getRoot(command, terminator=None): line = token[4] if tokentype in (tokenize.ENDMARKER, tokenize.NEWLINE): continue - if PY3 and tokentype is tokenize.ENCODING: + if tokentype is tokenize.ENCODING: line = lastline break if tokentype in (tokenize.NAME, tokenize.STRING, tokenize.NUMBER) \ @@ -316,7 +316,7 @@ def getTokens(command): """Return list of token tuples for command.""" # In case the command is unicode try encoding it - if isinstance(command, string_types): + if isinstance(command, str): try: command = command.encode('utf-8') except UnicodeEncodeError: @@ -330,13 +330,8 @@ def getTokens(command): # tokens = [token for token in tokenize.generate_tokens(f.readline)] # because of need to append as much as possible before TokenError. try: - if not PY3: - def eater(*args): - tokens.append(args) - tokenize.tokenize_loop(f.readline, eater) - else: - for t in tokenize.tokenize(f.readline): - tokens.append(t) + for t in tokenize.tokenize(f.readline): + tokens.append(t) except tokenize.TokenError: # This is due to a premature EOF, which we expect since we are # feeding in fragments of Python code. diff --git a/wx/py/shell.py b/wx/py/shell.py index 47ced4df..d5b83f3a 100755 --- a/wx/py/shell.py +++ b/wx/py/shell.py @@ -8,7 +8,6 @@ __author__ = "Patrick K. O'Brien " import wx from wx import stc -from six import PY3 import keyword import os @@ -410,7 +409,7 @@ class Shell(editwindow.EditWindow): This sets "close", "exit" and "quit" to a helpful string. """ - from six.moves import builtins + import builtins builtins.close = builtins.exit = builtins.quit = \ 'Click on the close button to leave the application.' builtins.cd = cd @@ -438,12 +437,9 @@ class Shell(editwindow.EditWindow): """Execute the user's PYTHONSTARTUP script if they have one.""" if startupScript and os.path.isfile(startupScript): text = 'Startup script executed: ' + startupScript - if PY3: - self.push('print(%r)' % text) - self.push('with open(%r, "r") as f:\n' - ' exec(f.read())\n' % (startupScript)) - else: - self.push('print(%r); execfile(%r)' % (text, startupScript)) + self.push('print(%r)' % text) + self.push('with open(%r, "r") as f:\n' + ' exec(f.read())\n' % (startupScript)) self.interp.startupScript = startupScript else: self.push('') diff --git a/wx/py/sliceshell.py b/wx/py/sliceshell.py index 1bbc643d..f2d57936 100755 --- a/wx/py/sliceshell.py +++ b/wx/py/sliceshell.py @@ -15,7 +15,6 @@ __author__ += "Patrick K. O'Brien " import wx from wx import stc -from six import PY3 import keyword import os @@ -980,12 +979,7 @@ class SlicesShell(editwindow.EditWindow): This sets "close", "exit" and "quit" to a helpful string. """ - from six import PY3 - if PY3: - import builtins - else: - import __builtin__ - builtins = __builtin__ + import builtins builtins.close = builtins.exit = builtins.quit = \ 'Click on the close button to leave the application.' builtins.cd = cd diff --git a/wx/tools/pywxrc.py b/wx/tools/pywxrc.py index 552fcba1..2dd16a40 100644 --- a/wx/tools/pywxrc.py +++ b/wx/tools/pywxrc.py @@ -31,8 +31,6 @@ Usage: python pywxrc.py -h -o, --output output filename, or - for stdout """ -from __future__ import print_function - import sys, os, getopt, glob, re import xml.dom.minidom as minidom from six import byte2int diff --git a/wx/tools/wxget.py b/wx/tools/wxget.py index 4c74c42f..86a8c2b5 100644 --- a/wx/tools/wxget.py +++ b/wx/tools/wxget.py @@ -26,22 +26,15 @@ Where URL is a file URL and the optional DEST_DIR is a destination directory to download to, (default is to prompt the user). The --trusted option can be used to suppress certificate checks. """ -from __future__ import (division, absolute_import, print_function, unicode_literals) - import sys import os import wx import subprocess import ssl -if sys.version_info >= (3,): - from urllib.error import (HTTPError, URLError) - import urllib.request as urllib2 - import urllib.parse as urlparse -else: - import urllib2 - from urllib2 import (HTTPError, URLError) - import urlparse +from urllib.error import (HTTPError, URLError) +import urllib.request as urllib2 +import urllib.parse as urlparse try: import pip diff --git a/wx/tools/wxget_docs_demo.py b/wx/tools/wxget_docs_demo.py index 0e20618e..d06ecd85 100644 --- a/wx/tools/wxget_docs_demo.py +++ b/wx/tools/wxget_docs_demo.py @@ -26,24 +26,16 @@ launch it. Use: doc|demo --force to force a fresh download. """ -from __future__ import (division, absolute_import, print_function, unicode_literals) - import sys import os import subprocess import webbrowser import tarfile import warnings -if sys.version_info >= (3,): - from urllib.error import HTTPError - import urllib.request as urllib2 - import urllib.parse as urlparse - from urllib.request import pathname2url -else: - import urllib2 - from urllib2 import HTTPError - import urlparse - from urllib import pathname2url +from urllib.error import HTTPError +import urllib.request as urllib2 +import urllib.parse as urlparse +from urllib.request import pathname2url import wx from wx.tools import wxget From 323e78c0852a4ee58e32bd3bac8aa258a25b00f0 Mon Sep 17 00:00:00 2001 From: Alexandre Detiste Date: Fri, 22 Mar 2024 00:25:15 +0100 Subject: [PATCH 3/8] remove more Python2 hybridation --- build.py | 9 +----- buildtools/build_wxwidgets.py | 8 ++--- buildtools/config.py | 31 ++++--------------- buildtools/distutils_hacks.py | 2 +- etg/rawbmp.py | 7 ++--- etgtools/extractors.py | 8 ++--- etgtools/generators.py | 15 ++-------- etgtools/sphinx_generator.py | 23 ++++++-------- etgtools/tweaker_tools.py | 9 ++---- packaging/setup.py | 11 +++---- sphinxtools/inheritance.py | 8 ++--- sphinxtools/librarydescription.py | 19 ++---------- sphinxtools/modulehunter.py | 22 ++++---------- sphinxtools/postprocess.py | 7 ++--- sphinxtools/utilities.py | 25 +++------------- wx/lib/activexwrapper.py | 2 +- wx/lib/agw/aui/aui_constants.py | 16 ++-------- wx/py/sliceshell.py | 9 ++---- wx/py/tests/test_introspect.py | 50 ------------------------------- wx/svg/_nanosvg.pyx | 2 -- wx/tools/img2py.py | 5 +--- 21 files changed, 54 insertions(+), 234 deletions(-) diff --git a/build.py b/build.py index 420df995..d6a926f4 100755 --- a/build.py +++ b/build.py @@ -53,10 +53,6 @@ from buildtools.config import Config, msg, opj, posixjoin, loadETG, etg2sip, fi import buildtools.version as version -# which version of Python is running this script -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - # defaults PYVER = '2.7' @@ -1086,7 +1082,7 @@ def _removeSidebar(path): tag = soup.find('div', 'document') if tag: tag.attrs['class'] = ['document-no-sidebar'] - text = unicode(soup) if PY2 else str(soup) + text = str(soup) with textfile_open(filename, 'wt') as f: f.write(text) @@ -1507,9 +1503,6 @@ def cmd_build_wx(options, args): if options.jom: build_options.append('--jom') - if PY2: - build_options.append('--no_dpi_aware') - else: # Platform is something other than MSW if options.osx_carbon: diff --git a/buildtools/build_wxwidgets.py b/buildtools/build_wxwidgets.py index f1d41d37..d21ea1b3 100644 --- a/buildtools/build_wxwidgets.py +++ b/buildtools/build_wxwidgets.py @@ -18,8 +18,6 @@ import subprocess from buildtools import builder from buildtools.config import getVisCVersion -PY3 = sys.version_info[0] == 3 - # builder object wxBuilder = None @@ -427,8 +425,7 @@ def main(wxDir, args): setupFile = os.path.join(mswIncludeDir, "setup.h") with open(setupFile, "rb") as f: setupText = f.read() - if PY3: - setupText = setupText.decode('utf-8') + setupText = setupText.decode('utf-8') for flag in flags: setupText, subsMade = re.subn(flag + r"\s+?\d", "%s %s" % (flag, flags[flag]), setupText) @@ -437,8 +434,7 @@ def main(wxDir, args): sys.exit(1) with open(setupFile, "wb") as f: - if PY3: - setupText = setupText.encode('utf-8') + setupText = setupText.encode('utf-8') f.write(setupText) args = [] diff --git a/buildtools/config.py b/buildtools/config.py index dda3c675..c3662ef4 100644 --- a/buildtools/config.py +++ b/buildtools/config.py @@ -485,18 +485,8 @@ class Configuration(object): def build_locale_list(self, srcdir): # get a list of all files under the srcdir, to be used for install_data - if sys.version_info[0] == 2: - def walk_helper(lst, dirname, files): - for f in files: - filename = opj(dirname, f) - if not os.path.isdir(filename): - lst.append( (dirname, [filename]) ) - file_list = [] - os.path.walk(srcdir, walk_helper, file_list) - return file_list - else: - # TODO: Python3 version using os.walk generator - return [] + # TODO: Python3 version using os.walk generator + return [] def find_data_files(self, srcdir, *wildcards, **kw): @@ -916,8 +906,7 @@ def runcmd(cmd, getOutput=False, echoCmd=True, fatal=True, onError=None): if getOutput: outputEncoding = 'cp1252' if sys.platform == 'win32' else 'utf-8' output = sp.stdout.read() - if sys.version_info > (3,): - output = output.decode(outputEncoding) + output = output.decode(outputEncoding) output = output.rstrip() rval = sp.wait() @@ -936,11 +925,8 @@ def runcmd(cmd, getOutput=False, echoCmd=True, fatal=True, onError=None): def myExecfile(filename, ns): - if sys.version_info < (3,): - execfile(filename, ns) - else: - with open(filename, 'r') as f: - exec(f.read(), ns) + with open(filename, 'r') as f: + exec(f.read(), ns) def textfile_open(filename, mode='rt'): @@ -950,12 +936,7 @@ def textfile_open(filename, mode='rt'): mode parameter must include the 't' to put the stream into text mode. """ assert 't' in mode - if sys.version_info < (3,): - import codecs - mode = mode.replace('t', '') - return codecs.open(filename, mode, encoding='utf-8') - else: - return open(filename, mode, encoding='utf-8') + return open(filename, mode, encoding='utf-8') def getSipFiles(names): diff --git a/buildtools/distutils_hacks.py b/buildtools/distutils_hacks.py index eafd5983..cbd4f958 100644 --- a/buildtools/distutils_hacks.py +++ b/buildtools/distutils_hacks.py @@ -315,7 +315,7 @@ distutils.cygwinccompiler.CygwinCCompiler._compile = _compile # into the .pyd files as expected. So we'll strip out that option via # a monkey-patch of the msvc9compiler.MSVCCompiler.initialize method. -if os.name == 'nt' and sys.version_info >= (2,6): +if os.name == 'nt': import distutils.msvc9compiler _orig_initialize = distutils.msvc9compiler.MSVCCompiler.initialize diff --git a/etg/rawbmp.py b/etg/rawbmp.py index 699c8d88..bc464456 100644 --- a/etg/rawbmp.py +++ b/etg/rawbmp.py @@ -122,13 +122,10 @@ def addPixelDataBaseClass(module): X = property(lambda self: x) Y = property(lambda self: y) - import sys - rangeFunc = range if sys.version_info >= (3,) else xrange - pf = PixelFacade() - for y in rangeFunc(height): + for y in range(height): pixels.MoveTo(self, 0, y) - for x in rangeFunc(width): + for x in range(width): # We always generate the same pf instance, but it # accesses the pixels object which we use to iterate # over the pixel buffer. diff --git a/etgtools/extractors.py b/etgtools/extractors.py index 047d159d..fcd762c4 100644 --- a/etgtools/extractors.py +++ b/etgtools/extractors.py @@ -33,7 +33,7 @@ else: # methods, functions and other items in the C/C++ API being wrapped. #--------------------------------------------------------------------------- -class BaseDef(object): +class BaseDef: """ The base class for all element types and provides the common attributes and functions that they all share. @@ -1698,11 +1698,7 @@ def flattenNode(node, rstrip=True): # TODO: can we just use ElementTree.tostring for this function? if node is None: return "" - if sys.version_info < (3,): - strclass = basestring - else: - strclass = str - if isinstance(node, strclass): + if isinstance(node, str): return node text = node.text or "" for n in node: diff --git a/etgtools/generators.py b/etgtools/generators.py index ba94a662..6723a460 100644 --- a/etgtools/generators.py +++ b/etgtools/generators.py @@ -100,13 +100,7 @@ def wrapText(text, dontWrap: str = ''): # in the StringIO import io class Utf8EncodingStream(io.StringIO): - if sys.version_info < (3,): - def write(self, text): - if isinstance(text, str): - text = text.decode('utf-8') - return io.StringIO.write(self, text) - - + pass def textfile_open(filename, mode='rt'): @@ -116,12 +110,7 @@ def textfile_open(filename, mode='rt'): mode parameter must include the 't' to put the stream into text mode. """ assert 't' in mode - if sys.version_info < (3,): - import codecs - mode = mode.replace('t', '') - return codecs.open(filename, mode, encoding='utf-8') - else: - return open(filename, mode, encoding='utf-8') + return open(filename, mode, encoding='utf-8') #--------------------------------------------------------------------------- diff --git a/etgtools/sphinx_generator.py b/etgtools/sphinx_generator.py index 88591dba..b64ae2f3 100644 --- a/etgtools/sphinx_generator.py +++ b/etgtools/sphinx_generator.py @@ -20,12 +20,7 @@ import sys import shutil import textwrap -if sys.version_info < (3, ): - from StringIO import StringIO - string_base = basestring -else: - from io import StringIO - string_base = str +from io import StringIO import xml.etree.ElementTree as et @@ -146,7 +141,7 @@ class Node(object): :returns: The element text for the input `tag_name` or ``None``. """ - if isinstance(self.element, string_base): + if isinstance(self.element, str): return None return self.element.get(tag_name) @@ -268,7 +263,7 @@ class Node(object): if self.element is None: return text - if isinstance(self.element, string_base): + if isinstance(self.element, str): text = self.element else: text, tail = self.element.text, self.element.tail @@ -1381,7 +1376,7 @@ class Snippet(Node): if tag == 'sp': self.snippet += ' ' - if isinstance(element, string_base): + if isinstance(element, str): self.snippet += element else: if element.text: @@ -2006,7 +2001,7 @@ class XMLDocString(object): # Some of the Extractors (xml item) will set deprecated themselves, in which case it is set as a # non-empty string. In such cases, this branch will insert a deprecated section into the xml tree # so that the Node Tree (see classes above) will generate the deprecated tag on their own in self.RecurseXML - if hasattr(xml_item, 'deprecated') and xml_item.deprecated and isinstance(xml_item.deprecated, string_base): + if hasattr(xml_item, 'deprecated') and xml_item.deprecated and isinstance(xml_item.deprecated, str): element = et.Element('deprecated', kind='deprecated') element.text = xml_item.deprecated @@ -2128,7 +2123,7 @@ class XMLDocString(object): if element is None: return Node('', parent) - if isinstance(element, string_base): + if isinstance(element, str): rest_class = Paragraph(element, parent, self.kind) return rest_class @@ -2754,7 +2749,7 @@ class XMLDocString(object): name = convertToPython(name) stream.write('%-80s' % name) - if not isinstance(docstrings, string_base): + if not isinstance(docstrings, str): rest_class = self.RecurseXML(docstrings, self.root) docstrings = rest_class.Join() @@ -3394,7 +3389,7 @@ class SphinxGenerator(generators.DocsGeneratorBase): brief = memberVar.briefDoc briefDoc = None - if not isinstance(brief, string_base): + if not isinstance(brief, str): docstring = XMLDocString(memberVar) #docstring.current_module = self.current_module briefDoc = docstring.GetBrief() @@ -3541,7 +3536,7 @@ class SphinxGenerator(generators.DocsGeneratorBase): simple_docs = convertToPython(method.pyDocstring) else: brief = method.briefDoc - if not isinstance(brief, string_base): + if not isinstance(brief, str): docstring = XMLDocString(method) docstring.kind = 'method' docstring.current_module = self.current_module diff --git a/etgtools/tweaker_tools.py b/etgtools/tweaker_tools.py index 663bc0d9..dc4fca43 100644 --- a/etgtools/tweaker_tools.py +++ b/etgtools/tweaker_tools.py @@ -22,7 +22,6 @@ import textwrap from typing import Optional, Tuple -PY3 = sys.version_info[0] == 3 isWindows = sys.platform.startswith('win') magicMethods = { @@ -131,12 +130,8 @@ class FixWxPrefix(object): names = list() filename = 'wx/core.pyi' - if PY3: - with open(filename, 'rt', encoding='utf-8') as f: - text = f.read() - else: - with open(filename, 'r') as f: - text = f.read() + with open(filename, 'rt', encoding='utf-8') as f: + text = f.read() parseTree = ast.parse(text, filename) for item in parseTree.body: _processItem(item, names) diff --git a/packaging/setup.py b/packaging/setup.py index ef1b6c7b..5e82beea 100644 --- a/packaging/setup.py +++ b/packaging/setup.py @@ -15,7 +15,7 @@ # folder, so let's accommodate them... #--------------------------------------------------------------------------- -import sys, os, glob +import os, glob # Restructure the content of the tarball so things like pip or easy_install # know how to build stuff. To be compatible with those tools the main source @@ -39,10 +39,7 @@ for wc in ['wxWidgets/configure', # Now execute the real setup.py that was copied here in order to do whatever # command was trying to be done before. -if sys.version_info < (3,): - execfile('setup.py') -else: - with open('setup.py', 'r') as f: - source = f.read() - exec(source) +with open('setup.py', 'r') as f: + source = f.read() +exec(source) diff --git a/sphinxtools/inheritance.py b/sphinxtools/inheritance.py index acd7a803..18704ed3 100644 --- a/sphinxtools/inheritance.py +++ b/sphinxtools/inheritance.py @@ -24,13 +24,9 @@ from .constants import INHERITANCEROOT ENOENT = getattr(errno, 'ENOENT', 0) EPIPE = getattr(errno, 'EPIPE', 0) -if sys.version_info < (3, ): - string_base = basestring -else: - string_base = str -class InheritanceDiagram(object): +class InheritanceDiagram: """ Given a list of classes, determines the set of classes that they inherit from all the way to the root "object", and then is able to generate a @@ -239,7 +235,7 @@ class InheritanceDiagram(object): code = self.generate_dot(class_summary) # graphviz expects UTF-8 by default - if isinstance(code, string_base): + if isinstance(code, str): code = code.encode('utf-8') dot_args = ['dot'] diff --git a/sphinxtools/librarydescription.py b/sphinxtools/librarydescription.py index 56d48134..6fa28706 100644 --- a/sphinxtools/librarydescription.py +++ b/sphinxtools/librarydescription.py @@ -1,25 +1,17 @@ import sys import os import re - -if sys.version_info < (3,): - from StringIO import StringIO -else: - from io import StringIO +from io import StringIO from inspect import getmro, getclasstree, getdoc, getcomments from .utilities import makeSummary, chopDescription, writeSphinxOutput, PickleFile -from .utilities import findControlImages, formatExternalLink, isPython3 +from .utilities import findControlImages, formatExternalLink from .constants import object_types, MODULE_TO_ICON, DOXY_2_REST, SPHINXROOT from . import templates EPYDOC_PATTERN = re.compile(r'\S+{\S+}', re.DOTALL) -if sys.version_info < (3,): - reload(sys) - sys.setdefaultencoding('utf-8') - def make_class_tree(tree): @@ -1016,12 +1008,7 @@ class Property(ChildrenBase): class Attribute(ChildrenBase): def __init__(self, name, specs, value): - - if isPython3(): - specs = str(specs) - else: - specs = unicode(specs) - + specs = str(specs) start, end = specs.find("'"), specs.rfind("'") specs = specs[start+1:end] diff --git a/sphinxtools/modulehunter.py b/sphinxtools/modulehunter.py index f53ad678..7626614a 100644 --- a/sphinxtools/modulehunter.py +++ b/sphinxtools/modulehunter.py @@ -148,10 +148,7 @@ def analyze_params(obj, signature): pvalue = pvalue.strip() if pname in pevals: try: - if isPython3(): - peval = str(pevals[pname]) - else: - peval = unicode(pevals[pname]) + peval = str(pevals[pname]) except UnicodeDecodeError: peval = repr(pevals[pname]) except TypeError: @@ -216,7 +213,7 @@ def inspect_source(method_class, obj, source): def is_classmethod(instancemethod): """ Determine if an instancemethod is a classmethod. """ - # attribute = (isPython3() and ['__self__'] or ['im_self'])[0] + # attribute = (['__self__'] or ['im_self'])[0] # if hasattr(instancemethod, attribute): # return getattr(instancemethod, attribute) is not None # return False @@ -284,20 +281,11 @@ def describe_func(obj, parent_class, module_name): try: code = None if method in [object_types.METHOD, object_types.METHOD_DESCRIPTOR, object_types.INSTANCE_METHOD]: - if isPython3(): - code = obj.__func__.__code__ - else: - code = obj.im_func.func_code + code = obj.__func__.__code__ elif method == object_types.STATIC_METHOD: - if isPython3(): - code = obj.__func__.__code__ - else: - code = obj.im_func.func_code + code = obj.__func__.__code__ else: - if isPython3(): - code = obj.__code__ - else: - code = obj.func_code + code = obj.__code__ except AttributeError: code = None diff --git a/sphinxtools/postprocess.py b/sphinxtools/postprocess.py index 65d82512..0c66051d 100644 --- a/sphinxtools/postprocess.py +++ b/sphinxtools/postprocess.py @@ -25,9 +25,6 @@ from .constants import HTML_REPLACE, TODAY, SPHINXROOT, SECTIONS_EXCLUDE from .constants import CONSTANT_INSTANCES, WIDGETS_IMAGES_ROOT, SPHINX_IMAGES_ROOT from .constants import DOCSTRING_KEY -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - # ----------------------------------------------------------------------- # @@ -750,7 +747,7 @@ def removeHeaderImage(text, options): tag = soup.find('div', 'headerimage') if tag: tag.extract() - text = unicode(soup) if PY2 else str(soup) + text = str(soup) return text @@ -762,7 +759,7 @@ def tweakModuleIndex(text): href = tag['href'].split('.html#') if len(href) == 2 and href[0] == href[1]: tag['href'] = href[0] + '.html' - return unicode(soup) if PY2 else str(soup) + return str(soup) def tooltipsOnInheritance(text, class_summary): diff --git a/sphinxtools/utilities.py b/sphinxtools/utilities.py index d330bd49..1662aa34 100644 --- a/sphinxtools/utilities.py +++ b/sphinxtools/utilities.py @@ -16,14 +16,8 @@ import codecs import shutil import re -if sys.version_info < (3,): - import cPickle as pickle - from UserDict import UserDict - string_base = basestring -else: - import pickle - from collections import UserDict - string_base = str +import pickle +from collections import UserDict # Phoenix-specific imports from .templates import TEMPLATE_CONTRIB @@ -448,7 +442,7 @@ def findControlImages(elementOrString): """ from etgtools.tweaker_tools import removeWxPrefix - if isinstance(elementOrString, string_base): + if isinstance(elementOrString, str): class_name = py_class_name = elementOrString.lower() else: element = elementOrString @@ -860,12 +854,6 @@ def formatExternalLink(fullname, inheritance=False): return full_page -def isPython3(): - """ Returns ``True`` if we are using Python 3.x. """ - - return sys.version_info >= (3, ) - - def textfile_open(filename, mode='rt'): """ Simple wrapper around open() that will use codecs.open on Python2 and @@ -873,9 +861,4 @@ def textfile_open(filename, mode='rt'): mode parameter must include the 't' to put the stream into text mode. """ assert 't' in mode - if sys.version_info < (3,): - import codecs - mode = mode.replace('t', '') - return codecs.open(filename, mode, encoding='utf-8') - else: - return open(filename, mode, encoding='utf-8') + return open(filename, mode, encoding='utf-8') diff --git a/wx/lib/activexwrapper.py b/wx/lib/activexwrapper.py index bd1e4c21..d795d80d 100644 --- a/wx/lib/activexwrapper.py +++ b/wx/lib/activexwrapper.py @@ -24,7 +24,7 @@ except ImportError: if hasattr(sys, "frozen"): import os, win32api dllpath = os.path.join(win32api.GetSystemDirectory(), 'MFC71.DLL') - if sys.version[:3] >= '2.4' and not os.path.exists(dllpath): + if not os.path.exists(dllpath): message = "%s not found" % dllpath else: raise # original error message diff --git a/wx/lib/agw/aui/aui_constants.py b/wx/lib/agw/aui/aui_constants.py index b7add75d..fc499010 100644 --- a/wx/lib/agw/aui/aui_constants.py +++ b/wx/lib/agw/aui/aui_constants.py @@ -2594,16 +2594,7 @@ SWITCHER_TEXT_MARGIN_Y = 1 if __name__ == '__main__': # Easy image extraction. import sys - if sys.version_info[0] == 2: - PY2 = True - PY3 = False - elif sys.version_info[0] == 3: - PY2 = False - PY3 = True - if PY2: - answer = int(raw_input('Enter 1 to extract all bitmaps: ')) - elif PY3: - answer = int(input('Enter 1 to extract all bitmaps: ')) + answer = int(input('Enter 1 to extract all bitmaps: ')) if answer == 1: app = wx.App(0) import os @@ -2622,7 +2613,4 @@ if __name__ == '__main__': except Exception: pass app.MainLoop() - if PY2: - raw_input('Press Enter To Exit.') - elif PY3: - input('Press Enter To Exit.') \ No newline at end of file + input('Press Enter To Exit.') diff --git a/wx/py/sliceshell.py b/wx/py/sliceshell.py index f2d57936..dcfb918a 100755 --- a/wx/py/sliceshell.py +++ b/wx/py/sliceshell.py @@ -1008,12 +1008,9 @@ class SlicesShell(editwindow.EditWindow): """Execute the user's PYTHONSTARTUP script if they have one.""" if startupScript and os.path.isfile(startupScript): text = 'Startup script executed: ' + startupScript - if PY3: - self.push('print(%r)' % text) - self.push('with open(%r, "r") as f:\n' - ' exec(f.read())\n' % (startupScript)) - else: - self.push('print(%r); execfile(%r)' % (text, startupScript)) + self.push('print(%r)' % text) + self.push('with open(%r, "r") as f:\n' + ' exec(f.read())\n' % (startupScript)) self.interp.startupScript = startupScript else: self.push('') diff --git a/wx/py/tests/test_introspect.py b/wx/py/tests/test_introspect.py index 9c2f9775..87804e4b 100644 --- a/wx/py/tests/test_introspect.py +++ b/wx/py/tests/test_introspect.py @@ -8,8 +8,6 @@ import os import unittest from wx.py import introspect -PY3 = sys.version_info[0] == 3 - """ These unittest methods are preferred: ------------------------------------- @@ -394,21 +392,6 @@ class GetBaseObjectTestCase(unittest.TestCase): # Class with no init. (Bar, Bar, 0), ] - if not PY3: - values.extend([ - # Byte-compiled code. - (ham.func_code, ham.func_code, 0), - # Class with init. - (Foo, Foo.__init__.im_func, 1), - # Bound method. - (spam.foo, spam.foo.im_func, 1), - # Bound method with self named something else (spam). - (spam.bar, spam.bar.im_func, 1), - # Unbound method. (Do not drop the self argument.) - (eggs, eggs.im_func, 0), - # Callable instance. - (spam, spam.__call__.im_func, 1), - ]) for object, baseObject, dropSelf in values: result = introspect.getBaseObject(object) self.assertEqual(result, (baseObject, dropSelf)) @@ -674,16 +657,6 @@ class GetAttributeNamesTestCase(GetAttributeTestCase): # BrokenStr instance. brokenStr, ] - if not PY3: - self.items.extend([ - long(123), - unicode(""), - xrange(0), - # Byte-compiled code. - ham.func_code, - # Buffer. - buffer(''), - ]) def tearDown(self): self.items = None @@ -829,34 +802,11 @@ class Q(P): class GetConstructorTestCase(unittest.TestCase): - @unittest.skipIf(PY3, "Python2 specific test") - def test_getConstructor(self): - args = ('self', 'a', 'b', 'args', 'kwargs') - varnames = introspect.getConstructor(O).func_code.co_varnames - self.assertEqual(varnames, args) - varnames = introspect.getConstructor(P).func_code.co_varnames - self.assertEqual(varnames, args) - args = ('self', 'c', 'd') - varnames = introspect.getConstructor(Q).func_code.co_varnames - self.assertEqual(varnames, args) - def test_getConstructor_None(self): values = (N, 1, 'spam', {}, [], (), dir) for value in values: self.assertEqual(introspect.getConstructor(N), None) - @unittest.skipIf(PY3, "Python2 specific test") - def test_getConstructor_MultipleInheritance(self): - # Test old style inheritance rules. - args = ('self', 'a') - varnames = introspect.getConstructor(D1).func_code.co_varnames - self.assertEqual(varnames, args) - if 'object' in __builtins__: - # Test new style inheritance rules as well. - args = ('self', 'b') - varnames = introspect.getConstructor(D2).func_code.co_varnames - self.assertEqual(varnames, args) - if __name__ == '__main__': unittest.main() diff --git a/wx/svg/_nanosvg.pyx b/wx/svg/_nanosvg.pyx index d1cae1aa..3dbb1adb 100644 --- a/wx/svg/_nanosvg.pyx +++ b/wx/svg/_nanosvg.pyx @@ -46,8 +46,6 @@ from cpython.buffer cimport ( Py_buffer, PyObject_CheckBuffer, PyObject_GetBuffer, PyBUF_SIMPLE, PyBuffer_Release) -PY2 = sys.version_info[0] == 2 - #---------------------------------------------------------------------------- # Replicate the C enums and values for Python, dropping the leading 'N' diff --git a/wx/tools/img2py.py b/wx/tools/img2py.py index 258e72c7..f848b446 100644 --- a/wx/tools/img2py.py +++ b/wx/tools/img2py.py @@ -198,10 +198,7 @@ def img2py(image_file, python_file, while data: part = data[:72] data = data[72:] - if sys.version > '3': - output = ' %s' % part - else: - output = ' "%s"' % part + output = ' %s' % part if not data: output += ")" lines.append(output) From 66a93209174f1173ff774e9ecf50331ae63f7fd3 Mon Sep 17 00:00:00 2001 From: Alexandre Detiste Date: Fri, 22 Mar 2024 08:15:00 +0100 Subject: [PATCH 4/8] finish removing six --- demo/KeyEvents.py | 7 +++---- demo/Main.py | 11 ++++++----- demo/Threads.py | 2 +- requirements/install.txt | 4 +--- wx/lib/agw/zoombar.py | 4 +--- wx/lib/intctrl.py | 5 ++--- wx/svg/__init__.py | 2 +- wx/tools/pywxrc.py | 4 +++- 8 files changed, 18 insertions(+), 21 deletions(-) diff --git a/demo/KeyEvents.py b/demo/KeyEvents.py index b6239675..f0f48851 100644 --- a/demo/KeyEvents.py +++ b/demo/KeyEvents.py @@ -2,7 +2,6 @@ import wx import wx.lib.mixins.listctrl as listmix -from six import unichr #---------------------------------------------------------------------- @@ -265,15 +264,15 @@ class KeyLog(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin): if keycode == 0: keyname = "NUL" elif keycode < 27: - keyname = u"Ctrl-%s" % unichr(ord('A') + keycode-1) + keyname = u"Ctrl-%s" % chr(ord('A') + keycode-1) else: - keyname = u"\"%s\"" % unichr(keycode) + keyname = u"\"%s\"" % chr(keycode) else: keyname = u"(%s)" % keycode UniChr = '' if "unicode" in wx.PlatformInfo: - UniChr = "\"" + unichr(evt.GetUnicodeKey()) + "\"" + UniChr = "\"" + chr(evt.GetUnicodeKey()) + "\"" modifiers = "" for mod, ch in [(evt.ControlDown(), 'C'), diff --git a/demo/Main.py b/demo/Main.py index 0c5ea6ee..0264de0a 100644 --- a/demo/Main.py +++ b/demo/Main.py @@ -52,8 +52,11 @@ # Last updated: Andrea Gavana, 20 Oct 2008, 18.00 GMT import sys, os, time, traceback +import pickle import re import shutil +import urllib.error +import urllib.request from io import BytesIO from threading import Thread @@ -67,8 +70,6 @@ from wx.adv import TaskBarIcon as TaskBarIcon from wx.adv import SplashScreen as SplashScreen import wx.lib.mixins.inspection -from six.moves import cPickle -from six.moves import urllib import version @@ -1636,7 +1637,7 @@ class wxPythonDemo(wx.Frame): with open(pickledFile, "rb") as fid: try: - self.pickledData = cPickle.load(fid) + self.pickledData = pickle.load(fid) except: self.pickledData = {} @@ -1677,7 +1678,7 @@ class wxPythonDemo(wx.Frame): item.Check(self.allowDocs) self.Bind(wx.EVT_MENU, self.OnAllowDownload, item) - item = wx.MenuItem(menu, -1, 'Delete saved docs', 'Deletes the cPickle file where docs are stored') + item = wx.MenuItem(menu, -1, 'Delete saved docs', 'Deletes the pickle file where docs are stored') item.SetBitmap(images.catalog['deletedocs'].GetBitmap()) menu.Append(item) self.Bind(wx.EVT_MENU, self.OnDeleteDocs, item) @@ -2486,7 +2487,7 @@ class wxPythonDemo(wx.Frame): MakeDocDirs() pickledFile = GetDocFile() with open(pickledFile, "wb") as fid: - cPickle.dump(self.pickledData, fid, cPickle.HIGHEST_PROTOCOL) + pickle.dump(self.pickledData, fid, pickle.HIGHEST_PROTOCOL) self.Destroy() diff --git a/demo/Threads.py b/demo/Threads.py index 9dff2970..fca037d9 100644 --- a/demo/Threads.py +++ b/demo/Threads.py @@ -1,6 +1,6 @@ import random import time -from six.moves import _thread +import _thread import wx import wx.lib.newevent diff --git a/requirements/install.txt b/requirements/install.txt index 90ce0832..ef65365f 100644 --- a/requirements/install.txt +++ b/requirements/install.txt @@ -1,6 +1,4 @@ # Runtime dependencies needed when using wxPython Phoenix -numpy < 1.17 ; python_version <= '2.7' numpy ; python_version >= '3.0' and python_version < '3.12' # pillow < 3.0 -six -typing-extensions; python_version < '3.11' \ No newline at end of file +typing-extensions; python_version < '3.11' diff --git a/wx/lib/agw/zoombar.py b/wx/lib/agw/zoombar.py index 8c2afd05..144d0429 100644 --- a/wx/lib/agw/zoombar.py +++ b/wx/lib/agw/zoombar.py @@ -133,8 +133,6 @@ Version 0.1 import wx import sys -import six - from wx.lib.embeddedimage import PyEmbeddedImage zoombackgrey = PyEmbeddedImage( @@ -375,7 +373,7 @@ class ZoomBarImage(object): self._oldHeight = 0 self._vCenter = 0 self._hCenter = 0 - self._oldInc = -six.MAXSIZE + self._oldInc = -sys.MAXSIZE self._isSeparator = False self._enabled = True diff --git a/wx/lib/intctrl.py b/wx/lib/intctrl.py index f1740cc1..5cb9123f 100644 --- a/wx/lib/intctrl.py +++ b/wx/lib/intctrl.py @@ -41,12 +41,11 @@ import string import types import wx -import six #---------------------------------------------------------------------------- -MAXSIZE = six.MAXSIZE # (constants should be in upper case) -MINSIZE = -six.MAXSIZE-1 +MAXSIZE = sys.maxsize # (constants should be in upper case) +MINSIZE = -sys.MAXSIZE-1 LONGTYPE = int #---------------------------------------------------------------------------- diff --git a/wx/svg/__init__.py b/wx/svg/__init__.py index 9f611110..ff196cb1 100644 --- a/wx/svg/__init__.py +++ b/wx/svg/__init__.py @@ -80,9 +80,9 @@ will be adjusted accordingly.:: bmp = img.ConvertToScaledBitmap(wx.Size(24,24), self) """ +from itertools import zip_longest import wx -from six.moves import zip_longest from ._nanosvg import * diff --git a/wx/tools/pywxrc.py b/wx/tools/pywxrc.py index 2dd16a40..3aafd962 100644 --- a/wx/tools/pywxrc.py +++ b/wx/tools/pywxrc.py @@ -33,7 +33,9 @@ Usage: python pywxrc.py -h import sys, os, getopt, glob, re import xml.dom.minidom as minidom -from six import byte2int + +import operator +byte2int = operator.itemgetter(0) #---------------------------------------------------------------------- From bb35bcd9d9eed6277c39d895c98f23b166da75d7 Mon Sep 17 00:00:00 2001 From: Scott Talbert Date: Mon, 3 Feb 2025 20:13:56 -0500 Subject: [PATCH 5/8] Fix bugs in Python2 / six removal --- etgtools/tweaker_tools.py | 4 +-- unittests/test_string.py | 34 +++++++++---------- wx/lib/agw/aui/auibar.py | 4 +-- wx/lib/agw/aui/auibook.py | 6 ++-- wx/lib/agw/customtreectrl.py | 2 ++ wx/lib/agw/flatmenu.py | 1 + wx/lib/agw/ultimatelistctrl.py | 11 +++--- wx/lib/agw/zoombar.py | 2 +- wx/lib/intctrl.py | 6 ++-- wx/lib/pubsub/core/kwargs/publisher.py | 4 +-- wx/lib/pubsub/core/kwargs/topicargspecimpl.py | 4 +-- wx/lib/pubsub/core/topicdefnprovider.py | 6 ++-- wx/lib/pubsub/core/topicobj.py | 10 +++--- wx/lib/pubsub/utils/xmltopicdefnprovider.py | 4 +-- 14 files changed, 49 insertions(+), 49 deletions(-) diff --git a/etgtools/tweaker_tools.py b/etgtools/tweaker_tools.py index dc4fca43..dc74b646 100644 --- a/etgtools/tweaker_tools.py +++ b/etgtools/tweaker_tools.py @@ -168,8 +168,8 @@ class FixWxPrefix(object): Handles translation of common C++ types to Python types, as well as a few specific wx types to Python types. """ - double_type = 'float' if PY3 else 'double' - long_type = 'int' if PY3 else 'long' + double_type = 'float' + long_type = 'int' type_map = { # Some types are guesses, marked with TODO to verify automatic # conversion actually happens. Also, these are the type-names diff --git a/unittests/test_string.py b/unittests/test_string.py index a2406ed6..12ee4b12 100644 --- a/unittests/test_string.py +++ b/unittests/test_string.py @@ -9,27 +9,27 @@ from unittests import wtc class String(unittest.TestCase): if hasattr(wx, 'testStringTypemap'): - def test_StringTypemapsPy3(self): - utf = b'\xc3\xa9l\xc3\xa9phant' # utf-8 bytes - uni = utf.decode('utf-8') # convert to unicode - iso = uni.encode('iso-8859-1') # make a string with a different encoding + def test_StringTypemapsPy3(self): + utf = b'\xc3\xa9l\xc3\xa9phant' # utf-8 bytes + uni = utf.decode('utf-8') # convert to unicode + iso = uni.encode('iso-8859-1') # make a string with a different encoding - # ascii - result = wx.testStringTypemap(b'hello') - self.assertTrue(type(result) == str) - self.assertTrue(result == 'hello') + # ascii + result = wx.testStringTypemap(b'hello') + self.assertTrue(type(result) == str) + self.assertTrue(result == 'hello') - # unicode should pass through unmodified - result = wx.testStringTypemap(uni) - self.assertTrue(result == uni) + # unicode should pass through unmodified + result = wx.testStringTypemap(uni) + self.assertTrue(result == uni) - # utf-8 is converted - result = wx.testStringTypemap(utf) - self.assertTrue(result == uni) + # utf-8 is converted + result = wx.testStringTypemap(utf) + self.assertTrue(result == uni) - # can't auto-convert this - with self.assertRaises(UnicodeDecodeError): - result = wx.testStringTypemap(iso) + # can't auto-convert this + with self.assertRaises(UnicodeDecodeError): + result = wx.testStringTypemap(iso) #--------------------------------------------------------------------------- diff --git a/wx/lib/agw/aui/auibar.py b/wx/lib/agw/aui/auibar.py index 8a59d8c7..84c80d17 100644 --- a/wx/lib/agw/aui/auibar.py +++ b/wx/lib/agw/aui/auibar.py @@ -65,7 +65,7 @@ class CommandToolBarEvent(wx.PyCommandEvent): :param integer `win_id`: the window identification number. """ - if type(command_type) in int: + if isinstance(command_type, int): wx.PyCommandEvent.__init__(self, command_type, win_id) else: wx.PyCommandEvent.__init__(self, command_type.GetEventType(), command_type.GetId()) @@ -155,7 +155,7 @@ class AuiToolBarEvent(CommandToolBarEvent): CommandToolBarEvent.__init__(self, command_type, win_id) - if type(command_type) in int: + if isinstance(command_type, int): self.notify = wx.NotifyEvent(command_type, win_id) else: self.notify = wx.NotifyEvent(command_type.GetEventType(), command_type.GetId()) diff --git a/wx/lib/agw/aui/auibook.py b/wx/lib/agw/aui/auibook.py index 573cfd22..28f1e19b 100644 --- a/wx/lib/agw/aui/auibook.py +++ b/wx/lib/agw/aui/auibook.py @@ -391,7 +391,7 @@ class CommandNotebookEvent(wx.PyCommandEvent): :param integer `win_id`: the window identification number. """ - if type(command_type) in int: + if isinstance(command_type, int): wx.PyCommandEvent.__init__(self, command_type, win_id) else: wx.PyCommandEvent.__init__(self, command_type.GetEventType(), command_type.GetId()) @@ -524,7 +524,7 @@ class AuiNotebookEvent(CommandNotebookEvent): CommandNotebookEvent.__init__(self, command_type, win_id) - if type(command_type) in int: + if isinstance(command_type, int): self.notify = wx.NotifyEvent(command_type, win_id) else: self.notify = wx.NotifyEvent(command_type.GetEventType(), command_type.GetId()) @@ -1173,7 +1173,7 @@ class AuiTabContainer(object): :param `wndOrInt`: an instance of :class:`wx.Window` or an integer specifying a tab index. """ - if type(wndOrInt) in int: + if isinstance(wndOrInt, int): if wndOrInt >= len(self._pages): return False diff --git a/wx/lib/agw/customtreectrl.py b/wx/lib/agw/customtreectrl.py index c48926b2..1ac41a3a 100644 --- a/wx/lib/agw/customtreectrl.py +++ b/wx/lib/agw/customtreectrl.py @@ -349,6 +349,8 @@ License And Version Latest Revision: Helio Guilherme @ 09 Aug 2018, 21.35 GMT +Version 2.7 + """ # Version Info diff --git a/wx/lib/agw/flatmenu.py b/wx/lib/agw/flatmenu.py index 9ff0e3ef..92752b44 100644 --- a/wx/lib/agw/flatmenu.py +++ b/wx/lib/agw/flatmenu.py @@ -197,6 +197,7 @@ __version__ = "1.0" import wx import os import math +import io import wx.lib.colourutils as colourutils diff --git a/wx/lib/agw/ultimatelistctrl.py b/wx/lib/agw/ultimatelistctrl.py index 1c12dd8f..91ba9b2d 100644 --- a/wx/lib/agw/ultimatelistctrl.py +++ b/wx/lib/agw/ultimatelistctrl.py @@ -548,9 +548,6 @@ if wx.Platform == "__WXMSW__": IL_FIXED_SIZE = 0 IL_VARIABLE_SIZE = 1 -# Python integers, to make long types to work with CreateListItem -INTEGER_TYPES = int - # ---------------------------------------------------------------------------- # Functions @@ -567,7 +564,7 @@ def to_list(input): if isinstance(input, list): return input - elif isinstance(input, INTEGER_TYPES): + elif isinstance(input, int): return [input] else: raise Exception("Invalid parameter passed to `to_list`: only integers and list are accepted.") @@ -595,7 +592,7 @@ def CreateListItem(itemOrId, col): :param `col`: the item column. """ - if type(itemOrId) in INTEGER_TYPES: + if isinstance(itemOrId, int): item = UltimateListItem() item._itemId = itemOrId item._col = col @@ -2285,7 +2282,7 @@ class CommandListEvent(wx.PyCommandEvent): :param `winid`: the event identifier. """ - if type(commandTypeOrEvent) in INTEGER_TYPES: + if isinstance(commandTypeOrEvent, int): wx.PyCommandEvent.__init__(self, commandTypeOrEvent, winid) @@ -2452,7 +2449,7 @@ class UltimateListEvent(CommandListEvent): CommandListEvent.__init__(self, commandTypeOrEvent, winid) - if type(commandTypeOrEvent) in INTEGER_TYPES: + if isinstance(commandTypeOrEvent, int): self.notify = wx.NotifyEvent(commandTypeOrEvent, winid) else: self.notify = wx.NotifyEvent(commandTypeOrEvent.GetEventType(), commandTypeOrEvent.GetId()) diff --git a/wx/lib/agw/zoombar.py b/wx/lib/agw/zoombar.py index 144d0429..1a93969e 100644 --- a/wx/lib/agw/zoombar.py +++ b/wx/lib/agw/zoombar.py @@ -373,7 +373,7 @@ class ZoomBarImage(object): self._oldHeight = 0 self._vCenter = 0 self._hCenter = 0 - self._oldInc = -sys.MAXSIZE + self._oldInc = -sys.maxsize self._isSeparator = False self._enabled = True diff --git a/wx/lib/intctrl.py b/wx/lib/intctrl.py index 5cb9123f..3d5002bc 100644 --- a/wx/lib/intctrl.py +++ b/wx/lib/intctrl.py @@ -45,7 +45,7 @@ import wx #---------------------------------------------------------------------------- MAXSIZE = sys.maxsize # (constants should be in upper case) -MINSIZE = -sys.MAXSIZE-1 +MINSIZE = -sys.maxsize-1 LONGTYPE = int #---------------------------------------------------------------------------- @@ -697,7 +697,7 @@ class IntCtrl(wx.TextCtrl): value = self.GetValue() if( not (value is None and self.IsNoneAllowed()) - and type(value) not in int ): + and not isinstance(value, int) ): raise ValueError ( 'IntCtrl requires integer values, passed %s'% repr(value) ) @@ -809,7 +809,7 @@ class IntCtrl(wx.TextCtrl): elif type(value) == LONGTYPE and not self.IsLongAllowed(): raise ValueError ( 'IntCtrl requires integer value, passed long' ) - elif type(value) not in int: + elif not isinstance(value, int): raise ValueError ( 'IntCtrl requires integer value, passed %s'% repr(value) ) diff --git a/wx/lib/pubsub/core/kwargs/publisher.py b/wx/lib/pubsub/core/kwargs/publisher.py index bda42fc5..fbe2076f 100644 --- a/wx/lib/pubsub/core/kwargs/publisher.py +++ b/wx/lib/pubsub/core/kwargs/publisher.py @@ -42,7 +42,7 @@ class PublisherArg1Stage2(Publisher): def __init__(self, kwargs, commonArgName): extra = kwargs.copy() del extra[commonArgName] - msg = 'Sender has too many kwargs (%s)' % ( extra.keys(),) + msg = 'Sender has too many kwargs (%s)' % ( list(extra.keys()),) RuntimeError.__init__(self, msg) class SenderWrongKwargName(RuntimeError): @@ -60,7 +60,7 @@ class PublisherArg1Stage2(Publisher): if len(kwarg) > 1: raise self.SenderTooManyKwargs(kwarg, commonArgName) elif len(kwarg) == 1 and commonArgName not in kwarg: - raise self.SenderWrongKwargName( kwarg.keys()[0], commonArgName) + raise self.SenderWrongKwargName( list(kwarg.keys())[0], commonArgName) data = kwarg.get(commonArgName, None) kwargs = { commonArgName: self.Msg( _topicName, data) } diff --git a/wx/lib/pubsub/core/kwargs/topicargspecimpl.py b/wx/lib/pubsub/core/kwargs/topicargspecimpl.py index ea9817f1..863baf8a 100644 --- a/wx/lib/pubsub/core/kwargs/topicargspecimpl.py +++ b/wx/lib/pubsub/core/kwargs/topicargspecimpl.py @@ -114,14 +114,14 @@ class ArgsInfo: hasReqd = (needReqd <= all) if not hasReqd: raise SenderMissingReqdMsgDataError( - self.topicNameTuple, msgKwargs.keys(), needReqd - all) + self.topicNameTuple, list(msgKwargs.keys()), needReqd - all) # check that all other args are among the optional spec optional = all - needReqd ok = (optional <= set(self.allOptional)) if not ok: raise SenderUnknownMsgDataError( self.topicNameTuple, - msgKwargs.keys(), optional - set(self.allOptional) ) + list(msgKwargs.keys()), optional - set(self.allOptional) ) def filterArgs(self, msgKwargs): """Returns a dict which contains only those items of msgKwargs diff --git a/wx/lib/pubsub/core/topicdefnprovider.py b/wx/lib/pubsub/core/topicdefnprovider.py index 6aca10fc..b8327106 100644 --- a/wx/lib/pubsub/core/topicdefnprovider.py +++ b/wx/lib/pubsub/core/topicdefnprovider.py @@ -295,7 +295,7 @@ class TopicDefnDeserialString(ITopicDefnDeserializer): # remove the temporary module and its compiled version (*.pyc) os.remove(self.__filename) try: # py3.2+ uses special folder/filename for .pyc files - from imp import cache_from_source + from importlib.util import cache_from_source os.remove(cache_from_source(self.__filename)) except ImportError: os.remove(self.__filename + 'c') @@ -356,7 +356,7 @@ class TopicDefnProvider(ITopicDefnProvider): return desc, spec def topicNames(self): - return self.__topicDefns.keys() + return iter(self.__topicDefns.keys()) def getTreeDoc(self): return self.__treeDocs @@ -427,7 +427,7 @@ def exportTopicTreeSpec(moduleName = None, rootTopic=None, bak='bak', moduleDoc= if rootTopic is None: from .. import pub rootTopic = pub.getDefaultTopicMgr().getRootAllTopics() - elif isintance(rootTopic, str): + elif isinstance(rootTopic, str): from .. import pub rootTopic = pub.getDefaultTopicMgr().getTopic(rootTopic) diff --git a/wx/lib/pubsub/core/topicobj.py b/wx/lib/pubsub/core/topicobj.py index 5cfef56f..32c3f0e5 100644 --- a/wx/lib/pubsub/core/topicobj.py +++ b/wx/lib/pubsub/core/topicobj.py @@ -242,7 +242,7 @@ class Topic(PublisherMixin): def getSubtopics(self): """Get a list of Topic instances that are subtopics of self.""" - return self.__subTopics.values() + return list(self.__subTopics.values()) def getNumListeners(self): """Return number of listeners currently subscribed to topic. This is @@ -262,12 +262,12 @@ class Topic(PublisherMixin): def getListeners(self): """Get a copy of list of listeners subscribed to this topic. Safe to iterate over while listeners get un/subscribed from this topics (such as while sending a message).""" - return self.__listeners.keys() + return list(self.__listeners.keys()) def getListenersIter(self): """Get an iterator over listeners subscribed to this topic. Do not use if listeners can be un/subscribed while iterating. """ - return self.__listeners.keys() + return iter(self.__listeners.keys()) def validate(self, listener): """Checks whether listener could be subscribed to this topic: @@ -337,11 +337,11 @@ class Topic(PublisherMixin): if filter is None: for listener in self.__listeners: listener._unlinkFromTopic_() - unsubd = self.__listeners.keys() + unsubd = list(self.__listeners.keys()) self.__listeners = {} else: unsubd = [] - for listener in self.__listeners.keys(): + for listener in list(self.__listeners.keys()): if filter(listener): unsubd.append(listener) listener._unlinkFromTopic_() diff --git a/wx/lib/pubsub/utils/xmltopicdefnprovider.py b/wx/lib/pubsub/utils/xmltopicdefnprovider.py index bca65d16..48f49e24 100644 --- a/wx/lib/pubsub/utils/xmltopicdefnprovider.py +++ b/wx/lib/pubsub/utils/xmltopicdefnprovider.py @@ -159,7 +159,7 @@ class XmlTopicDefnProvider(ITopicDefnProvider): return self._topics.get(topicNameTuple, (None, None)) def topicNames(self): - return self._topics.keys() + return iter(self._topics.keys()) def getTreeDoc(self): return self._treeDoc @@ -256,7 +256,7 @@ def exportTopicTreeSpecXml(moduleName=None, rootTopic=None, bak='bak', moduleDoc if rootTopic is None: from .. import pub rootTopic = pub.getDefaultTopicTreeRoot() - elif isintance(rootTopic, str): + elif isinstance(rootTopic, str): from .. import pub rootTopic = pub.getTopic(rootTopic) From b0bde88a2c9ecf866c459a793d7d9beb17f92098 Mon Sep 17 00:00:00 2001 From: Scott Talbert Date: Mon, 3 Feb 2025 20:22:26 -0500 Subject: [PATCH 6/8] Remove pathlib2 backport - pathlib was added in Python 3.4 --- build.py | 6 +- buildtools/backports/pathlib2/__init__.py | 1675 --------------------- buildtools/backports/pathlib2/scandir.py | 693 --------- 3 files changed, 1 insertion(+), 2373 deletions(-) delete mode 100644 buildtools/backports/pathlib2/__init__.py delete mode 100644 buildtools/backports/pathlib2/scandir.py diff --git a/build.py b/build.py index d6a926f4..8e30d8e6 100755 --- a/build.py +++ b/build.py @@ -18,6 +18,7 @@ import glob import hashlib import optparse import os +import pathlib import re import shutil import subprocess @@ -28,11 +29,6 @@ import shlex import textwrap import warnings -try: - import pathlib -except ImportError: - import buildtools.backports.pathlib2 as pathlib - try: from shutil import which except ImportError: diff --git a/buildtools/backports/pathlib2/__init__.py b/buildtools/backports/pathlib2/__init__.py deleted file mode 100644 index 698ba558..00000000 --- a/buildtools/backports/pathlib2/__init__.py +++ /dev/null @@ -1,1675 +0,0 @@ -# Copyright (c) 2014-2017 Matthias C. M. Troffaes -# Copyright (c) 2012-2014 Antoine Pitrou and contributors -# Distributed under the terms of the MIT License. - -import ctypes -import fnmatch -import functools -import io -import ntpath -import os -import posixpath -import re - -try: - import six -except ImportError: - import buildtools.backports.six as six - -import sys -from collections import Sequence -from errno import EINVAL, ENOENT, ENOTDIR, EEXIST, EPERM, EACCES -from operator import attrgetter - -from stat import ( - S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO) -try: - from urllib import quote as urlquote_from_bytes -except ImportError: - from urllib.parse import quote_from_bytes as urlquote_from_bytes - - -try: - intern = intern -except NameError: - intern = sys.intern - -supports_symlinks = True -if os.name == 'nt': - import nt - if sys.getwindowsversion()[:2] >= (6, 0) and sys.version_info >= (3, 2): - from nt import _getfinalpathname - else: - supports_symlinks = False - _getfinalpathname = None -else: - nt = None - -try: - from os import scandir as os_scandir -except ImportError: - from .scandir import scandir as os_scandir - -__all__ = [ - "PurePath", "PurePosixPath", "PureWindowsPath", - "Path", "PosixPath", "WindowsPath", - ] - -# -# Internals -# - - -def _py2_fsencode(parts): - # py2 => minimal unicode support - assert six.PY2 - return [part.encode('ascii') if isinstance(part, six.text_type) - else part for part in parts] - - -def _try_except_fileexistserror(try_func, except_func, else_func=None): - if sys.version_info >= (3, 3): - try: - try_func() - except FileExistsError as exc: - except_func(exc) - else: - if else_func is not None: - else_func() - else: - try: - try_func() - except EnvironmentError as exc: - if exc.errno != EEXIST: - raise - else: - except_func(exc) - else: - if else_func is not None: - else_func() - - -def _try_except_filenotfounderror(try_func, except_func): - if sys.version_info >= (3, 3): - try: - try_func() - except FileNotFoundError as exc: - except_func(exc) - else: - try: - try_func() - except EnvironmentError as exc: - if exc.errno != ENOENT: - raise - else: - except_func(exc) - - -def _try_except_permissionerror_iter(try_iter, except_iter): - if sys.version_info >= (3, 3): - try: - for x in try_iter(): - yield x - except PermissionError as exc: - for x in except_iter(exc): - yield x - else: - try: - for x in try_iter(): - yield x - except EnvironmentError as exc: - if exc.errno not in (EPERM, EACCES): - raise - else: - for x in except_iter(exc): - yield x - - -def _win32_get_unique_path_id(path): - # get file information, needed for samefile on older Python versions - # see http://timgolden.me.uk/python/win32_how_do_i/ - # see_if_two_files_are_the_same_file.html - from ctypes import POINTER, Structure, WinError - from ctypes.wintypes import DWORD, HANDLE, BOOL - - class FILETIME(Structure): - _fields_ = [("datetime_lo", DWORD), - ("datetime_hi", DWORD), - ] - - class BY_HANDLE_FILE_INFORMATION(Structure): - _fields_ = [("attributes", DWORD), - ("created_at", FILETIME), - ("accessed_at", FILETIME), - ("written_at", FILETIME), - ("volume", DWORD), - ("file_hi", DWORD), - ("file_lo", DWORD), - ("n_links", DWORD), - ("index_hi", DWORD), - ("index_lo", DWORD), - ] - - CreateFile = ctypes.windll.kernel32.CreateFileW - CreateFile.argtypes = [ctypes.c_wchar_p, DWORD, DWORD, ctypes.c_void_p, - DWORD, DWORD, HANDLE] - CreateFile.restype = HANDLE - GetFileInformationByHandle = ( - ctypes.windll.kernel32.GetFileInformationByHandle) - GetFileInformationByHandle.argtypes = [ - HANDLE, POINTER(BY_HANDLE_FILE_INFORMATION)] - GetFileInformationByHandle.restype = BOOL - CloseHandle = ctypes.windll.kernel32.CloseHandle - CloseHandle.argtypes = [HANDLE] - CloseHandle.restype = BOOL - GENERIC_READ = 0x80000000 - FILE_SHARE_READ = 0x00000001 - FILE_FLAG_BACKUP_SEMANTICS = 0x02000000 - OPEN_EXISTING = 3 - if os.path.isdir(path): - flags = FILE_FLAG_BACKUP_SEMANTICS - else: - flags = 0 - hfile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, - None, OPEN_EXISTING, flags, None) - if hfile == 0xffffffff: - if sys.version_info >= (3, 3): - raise FileNotFoundError(path) - else: - exc = OSError("file not found: path") - exc.errno = ENOENT - raise exc - info = BY_HANDLE_FILE_INFORMATION() - success = GetFileInformationByHandle(hfile, info) - CloseHandle(hfile) - if success == 0: - raise WinError() - return info.volume, info.index_hi, info.index_lo - - -def _is_wildcard_pattern(pat): - # Whether this pattern needs actual matching using fnmatch, or can - # be looked up directly as a file. - return "*" in pat or "?" in pat or "[" in pat - - -class _Flavour(object): - - """A flavour implements a particular (platform-specific) set of path - semantics.""" - - def __init__(self): - self.join = self.sep.join - - def parse_parts(self, parts): - if six.PY2: - parts = _py2_fsencode(parts) - parsed = [] - sep = self.sep - altsep = self.altsep - drv = root = '' - it = reversed(parts) - for part in it: - if not part: - continue - if altsep: - part = part.replace(altsep, sep) - drv, root, rel = self.splitroot(part) - if sep in rel: - for x in reversed(rel.split(sep)): - if x and x != '.': - parsed.append(intern(x)) - else: - if rel and rel != '.': - parsed.append(intern(rel)) - if drv or root: - if not drv: - # If no drive is present, try to find one in the previous - # parts. This makes the result of parsing e.g. - # ("C:", "/", "a") reasonably intuitive. - for part in it: - if not part: - continue - if altsep: - part = part.replace(altsep, sep) - drv = self.splitroot(part)[0] - if drv: - break - break - if drv or root: - parsed.append(drv + root) - parsed.reverse() - return drv, root, parsed - - def join_parsed_parts(self, drv, root, parts, drv2, root2, parts2): - """ - Join the two paths represented by the respective - (drive, root, parts) tuples. Return a new (drive, root, parts) tuple. - """ - if root2: - if not drv2 and drv: - return drv, root2, [drv + root2] + parts2[1:] - elif drv2: - if drv2 == drv or self.casefold(drv2) == self.casefold(drv): - # Same drive => second path is relative to the first - return drv, root, parts + parts2[1:] - else: - # Second path is non-anchored (common case) - return drv, root, parts + parts2 - return drv2, root2, parts2 - - -class _WindowsFlavour(_Flavour): - # Reference for Windows paths can be found at - # http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx - - sep = '\\' - altsep = '/' - has_drv = True - pathmod = ntpath - - is_supported = (os.name == 'nt') - - drive_letters = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') - ext_namespace_prefix = '\\\\?\\' - - reserved_names = ( - set(['CON', 'PRN', 'AUX', 'NUL']) | - set(['COM%d' % i for i in range(1, 10)]) | - set(['LPT%d' % i for i in range(1, 10)]) - ) - - # Interesting findings about extended paths: - # - '\\?\c:\a', '//?/c:\a' and '//?/c:/a' are all supported - # but '\\?\c:/a' is not - # - extended paths are always absolute; "relative" extended paths will - # fail. - - def splitroot(self, part, sep=sep): - first = part[0:1] - second = part[1:2] - if (second == sep and first == sep): - # XXX extended paths should also disable the collapsing of "." - # components (according to MSDN docs). - prefix, part = self._split_extended_path(part) - first = part[0:1] - second = part[1:2] - else: - prefix = '' - third = part[2:3] - if (second == sep and first == sep and third != sep): - # is a UNC path: - # vvvvvvvvvvvvvvvvvvvvv root - # \\machine\mountpoint\directory\etc\... - # directory ^^^^^^^^^^^^^^ - index = part.find(sep, 2) - if index != -1: - index2 = part.find(sep, index + 1) - # a UNC path can't have two slashes in a row - # (after the initial two) - if index2 != index + 1: - if index2 == -1: - index2 = len(part) - if prefix: - return prefix + part[1:index2], sep, part[index2 + 1:] - else: - return part[:index2], sep, part[index2 + 1:] - drv = root = '' - if second == ':' and first in self.drive_letters: - drv = part[:2] - part = part[2:] - first = third - if first == sep: - root = first - part = part.lstrip(sep) - return prefix + drv, root, part - - def casefold(self, s): - return s.lower() - - def casefold_parts(self, parts): - return [p.lower() for p in parts] - - def resolve(self, path, strict=False): - s = str(path) - if not s: - return os.getcwd() - previous_s = None - if _getfinalpathname is not None: - if strict: - return self._ext_to_normal(_getfinalpathname(s)) - else: - # End of the path after the first one not found - tail_parts = [] - while True: - try: - s = self._ext_to_normal(_getfinalpathname(s)) - except FileNotFoundError: - previous_s = s - s, tail = os.path.split(s) - tail_parts.append(tail) - if previous_s == s: - return path - else: - return os.path.join(s, *reversed(tail_parts)) - # Means fallback on absolute - return None - - def _split_extended_path(self, s, ext_prefix=ext_namespace_prefix): - prefix = '' - if s.startswith(ext_prefix): - prefix = s[:4] - s = s[4:] - if s.startswith('UNC\\'): - prefix += s[:3] - s = '\\' + s[3:] - return prefix, s - - def _ext_to_normal(self, s): - # Turn back an extended path into a normal DOS-like path - return self._split_extended_path(s)[1] - - def is_reserved(self, parts): - # NOTE: the rules for reserved names seem somewhat complicated - # (e.g. r"..\NUL" is reserved but not r"foo\NUL"). - # We err on the side of caution and return True for paths which are - # not considered reserved by Windows. - if not parts: - return False - if parts[0].startswith('\\\\'): - # UNC paths are never reserved - return False - return parts[-1].partition('.')[0].upper() in self.reserved_names - - def make_uri(self, path): - # Under Windows, file URIs use the UTF-8 encoding. - drive = path.drive - if len(drive) == 2 and drive[1] == ':': - # It's a path on a local drive => 'file:///c:/a/b' - rest = path.as_posix()[2:].lstrip('/') - return 'file:///%s/%s' % ( - drive, urlquote_from_bytes(rest.encode('utf-8'))) - else: - # It's a path on a network drive => 'file://host/share/a/b' - return 'file:' + urlquote_from_bytes( - path.as_posix().encode('utf-8')) - - def gethomedir(self, username): - if 'HOME' in os.environ: - userhome = os.environ['HOME'] - elif 'USERPROFILE' in os.environ: - userhome = os.environ['USERPROFILE'] - elif 'HOMEPATH' in os.environ: - try: - drv = os.environ['HOMEDRIVE'] - except KeyError: - drv = '' - userhome = drv + os.environ['HOMEPATH'] - else: - raise RuntimeError("Can't determine home directory") - - if username: - # Try to guess user home directory. By default all users - # directories are located in the same place and are named by - # corresponding usernames. If current user home directory points - # to nonstandard place, this guess is likely wrong. - if os.environ['USERNAME'] != username: - drv, root, parts = self.parse_parts((userhome,)) - if parts[-1] != os.environ['USERNAME']: - raise RuntimeError("Can't determine home directory " - "for %r" % username) - parts[-1] = username - if drv or root: - userhome = drv + root + self.join(parts[1:]) - else: - userhome = self.join(parts) - return userhome - - -class _PosixFlavour(_Flavour): - sep = '/' - altsep = '' - has_drv = False - pathmod = posixpath - - is_supported = (os.name != 'nt') - - def splitroot(self, part, sep=sep): - if part and part[0] == sep: - stripped_part = part.lstrip(sep) - # According to POSIX path resolution: - # http://pubs.opengroup.org/onlinepubs/009695399/basedefs/ - # xbd_chap04.html#tag_04_11 - # "A pathname that begins with two successive slashes may be - # interpreted in an implementation-defined manner, although more - # than two leading slashes shall be treated as a single slash". - if len(part) - len(stripped_part) == 2: - return '', sep * 2, stripped_part - else: - return '', sep, stripped_part - else: - return '', '', part - - def casefold(self, s): - return s - - def casefold_parts(self, parts): - return parts - - def resolve(self, path, strict=False): - sep = self.sep - accessor = path._accessor - seen = {} - - def _resolve(path, rest): - if rest.startswith(sep): - path = '' - - for name in rest.split(sep): - if not name or name == '.': - # current dir - continue - if name == '..': - # parent dir - path, _, _ = path.rpartition(sep) - continue - newpath = path + sep + name - if newpath in seen: - # Already seen this path - path = seen[newpath] - if path is not None: - # use cached value - continue - # The symlink is not resolved, so we must have a symlink - # loop. - raise RuntimeError("Symlink loop from %r" % newpath) - # Resolve the symbolic link - try: - target = accessor.readlink(newpath) - except OSError as e: - if e.errno != EINVAL and strict: - raise - # Not a symlink, or non-strict mode. We just leave the path - # untouched. - path = newpath - else: - seen[newpath] = None # not resolved symlink - path = _resolve(path, target) - seen[newpath] = path # resolved symlink - - return path - # NOTE: according to POSIX, getcwd() cannot contain path components - # which are symlinks. - base = '' if path.is_absolute() else os.getcwd() - return _resolve(base, str(path)) or sep - - def is_reserved(self, parts): - return False - - def make_uri(self, path): - # We represent the path using the local filesystem encoding, - # for portability to other applications. - bpath = bytes(path) - return 'file://' + urlquote_from_bytes(bpath) - - def gethomedir(self, username): - if not username: - try: - return os.environ['HOME'] - except KeyError: - import pwd - return pwd.getpwuid(os.getuid()).pw_dir - else: - import pwd - try: - return pwd.getpwnam(username).pw_dir - except KeyError: - raise RuntimeError("Can't determine home directory " - "for %r" % username) - - -_windows_flavour = _WindowsFlavour() -_posix_flavour = _PosixFlavour() - - -class _Accessor: - - """An accessor implements a particular (system-specific or not) way of - accessing paths on the filesystem.""" - - -class _NormalAccessor(_Accessor): - - def _wrap_strfunc(strfunc): - @functools.wraps(strfunc) - def wrapped(pathobj, *args): - return strfunc(str(pathobj), *args) - return staticmethod(wrapped) - - def _wrap_binary_strfunc(strfunc): - @functools.wraps(strfunc) - def wrapped(pathobjA, pathobjB, *args): - return strfunc(str(pathobjA), str(pathobjB), *args) - return staticmethod(wrapped) - - stat = _wrap_strfunc(os.stat) - - lstat = _wrap_strfunc(os.lstat) - - open = _wrap_strfunc(os.open) - - listdir = _wrap_strfunc(os.listdir) - - scandir = _wrap_strfunc(os_scandir) - - chmod = _wrap_strfunc(os.chmod) - - if hasattr(os, "lchmod"): - lchmod = _wrap_strfunc(os.lchmod) - else: - def lchmod(self, pathobj, mode): - raise NotImplementedError("lchmod() not available on this system") - - mkdir = _wrap_strfunc(os.mkdir) - - unlink = _wrap_strfunc(os.unlink) - - rmdir = _wrap_strfunc(os.rmdir) - - rename = _wrap_binary_strfunc(os.rename) - - if sys.version_info >= (3, 3): - replace = _wrap_binary_strfunc(os.replace) - - if nt: - if supports_symlinks: - symlink = _wrap_binary_strfunc(os.symlink) - else: - def symlink(a, b, target_is_directory): - raise NotImplementedError( - "symlink() not available on this system") - else: - # Under POSIX, os.symlink() takes two args - @staticmethod - def symlink(a, b, target_is_directory): - return os.symlink(str(a), str(b)) - - utime = _wrap_strfunc(os.utime) - - # Helper for resolve() - def readlink(self, path): - return os.readlink(path) - - -_normal_accessor = _NormalAccessor() - - -# -# Globbing helpers -# - -def _make_selector(pattern_parts): - pat = pattern_parts[0] - child_parts = pattern_parts[1:] - if pat == '**': - cls = _RecursiveWildcardSelector - elif '**' in pat: - raise ValueError( - "Invalid pattern: '**' can only be an entire path component") - elif _is_wildcard_pattern(pat): - cls = _WildcardSelector - else: - cls = _PreciseSelector - return cls(pat, child_parts) - - -if hasattr(functools, "lru_cache"): - _make_selector = functools.lru_cache()(_make_selector) - - -class _Selector: - - """A selector matches a specific glob pattern part against the children - of a given path.""" - - def __init__(self, child_parts): - self.child_parts = child_parts - if child_parts: - self.successor = _make_selector(child_parts) - self.dironly = True - else: - self.successor = _TerminatingSelector() - self.dironly = False - - def select_from(self, parent_path): - """Iterate over all child paths of `parent_path` matched by this - selector. This can contain parent_path itself.""" - path_cls = type(parent_path) - is_dir = path_cls.is_dir - exists = path_cls.exists - scandir = parent_path._accessor.scandir - if not is_dir(parent_path): - return iter([]) - return self._select_from(parent_path, is_dir, exists, scandir) - - -class _TerminatingSelector: - - def _select_from(self, parent_path, is_dir, exists, scandir): - yield parent_path - - -class _PreciseSelector(_Selector): - - def __init__(self, name, child_parts): - self.name = name - _Selector.__init__(self, child_parts) - - def _select_from(self, parent_path, is_dir, exists, scandir): - def try_iter(): - path = parent_path._make_child_relpath(self.name) - if (is_dir if self.dironly else exists)(path): - for p in self.successor._select_from( - path, is_dir, exists, scandir): - yield p - - def except_iter(exc): - return - yield - - for x in _try_except_permissionerror_iter(try_iter, except_iter): - yield x - - -class _WildcardSelector(_Selector): - - def __init__(self, pat, child_parts): - self.pat = re.compile(fnmatch.translate(pat)) - _Selector.__init__(self, child_parts) - - def _select_from(self, parent_path, is_dir, exists, scandir): - def try_iter(): - cf = parent_path._flavour.casefold - entries = list(scandir(parent_path)) - for entry in entries: - if not self.dironly or entry.is_dir(): - name = entry.name - casefolded = cf(name) - if self.pat.match(casefolded): - path = parent_path._make_child_relpath(name) - for p in self.successor._select_from( - path, is_dir, exists, scandir): - yield p - - def except_iter(exc): - return - yield - - for x in _try_except_permissionerror_iter(try_iter, except_iter): - yield x - - -class _RecursiveWildcardSelector(_Selector): - - def __init__(self, pat, child_parts): - _Selector.__init__(self, child_parts) - - def _iterate_directories(self, parent_path, is_dir, scandir): - yield parent_path - - def try_iter(): - entries = list(scandir(parent_path)) - for entry in entries: - if entry.is_dir() and not entry.is_symlink(): - path = parent_path._make_child_relpath(entry.name) - for p in self._iterate_directories(path, is_dir, scandir): - yield p - - def except_iter(exc): - return - yield - - for x in _try_except_permissionerror_iter(try_iter, except_iter): - yield x - - def _select_from(self, parent_path, is_dir, exists, scandir): - def try_iter(): - yielded = set() - try: - successor_select = self.successor._select_from - for starting_point in self._iterate_directories( - parent_path, is_dir, scandir): - for p in successor_select( - starting_point, is_dir, exists, scandir): - if p not in yielded: - yield p - yielded.add(p) - finally: - yielded.clear() - - def except_iter(exc): - return - yield - - for x in _try_except_permissionerror_iter(try_iter, except_iter): - yield x - - -# -# Public API -# - -class _PathParents(Sequence): - - """This object provides sequence-like access to the logical ancestors - of a path. Don't try to construct it yourself.""" - __slots__ = ('_pathcls', '_drv', '_root', '_parts') - - def __init__(self, path): - # We don't store the instance to avoid reference cycles - self._pathcls = type(path) - self._drv = path._drv - self._root = path._root - self._parts = path._parts - - def __len__(self): - if self._drv or self._root: - return len(self._parts) - 1 - else: - return len(self._parts) - - def __getitem__(self, idx): - if idx < 0 or idx >= len(self): - raise IndexError(idx) - return self._pathcls._from_parsed_parts(self._drv, self._root, - self._parts[:-idx - 1]) - - def __repr__(self): - return "<{0}.parents>".format(self._pathcls.__name__) - - -class PurePath(object): - - """PurePath represents a filesystem path and offers operations which - don't imply any actual filesystem I/O. Depending on your system, - instantiating a PurePath will return either a PurePosixPath or a - PureWindowsPath object. You can also instantiate either of these classes - directly, regardless of your system. - """ - __slots__ = ( - '_drv', '_root', '_parts', - '_str', '_hash', '_pparts', '_cached_cparts', - ) - - def __new__(cls, *args): - """Construct a PurePath from one or several strings and or existing - PurePath objects. The strings and path objects are combined so as - to yield a canonicalized path, which is incorporated into the - new PurePath object. - """ - if cls is PurePath: - cls = PureWindowsPath if os.name == 'nt' else PurePosixPath - return cls._from_parts(args) - - def __reduce__(self): - # Using the parts tuple helps share interned path parts - # when pickling related paths. - return (self.__class__, tuple(self._parts)) - - @classmethod - def _parse_args(cls, args): - # This is useful when you don't want to create an instance, just - # canonicalize some constructor arguments. - parts = [] - for a in args: - if isinstance(a, PurePath): - parts += a._parts - else: - if sys.version_info >= (3, 6): - a = os.fspath(a) - else: - # duck typing for older Python versions - if hasattr(a, "__fspath__"): - a = a.__fspath__() - if isinstance(a, str): - # Force-cast str subclasses to str (issue #21127) - parts.append(str(a)) - # also handle unicode for PY2 (six.text_type = unicode) - elif six.PY2 and isinstance(a, six.text_type): - # cast to str using filesystem encoding - parts.append(a.encode(sys.getfilesystemencoding())) - else: - raise TypeError( - "argument should be a str object or an os.PathLike " - "object returning str, not %r" - % type(a)) - return cls._flavour.parse_parts(parts) - - @classmethod - def _from_parts(cls, args, init=True): - # We need to call _parse_args on the instance, so as to get the - # right flavour. - self = object.__new__(cls) - drv, root, parts = self._parse_args(args) - self._drv = drv - self._root = root - self._parts = parts - if init: - self._init() - return self - - @classmethod - def _from_parsed_parts(cls, drv, root, parts, init=True): - self = object.__new__(cls) - self._drv = drv - self._root = root - self._parts = parts - if init: - self._init() - return self - - @classmethod - def _format_parsed_parts(cls, drv, root, parts): - if drv or root: - return drv + root + cls._flavour.join(parts[1:]) - else: - return cls._flavour.join(parts) - - def _init(self): - # Overridden in concrete Path - pass - - def _make_child(self, args): - drv, root, parts = self._parse_args(args) - drv, root, parts = self._flavour.join_parsed_parts( - self._drv, self._root, self._parts, drv, root, parts) - return self._from_parsed_parts(drv, root, parts) - - def __str__(self): - """Return the string representation of the path, suitable for - passing to system calls.""" - try: - return self._str - except AttributeError: - self._str = self._format_parsed_parts(self._drv, self._root, - self._parts) or '.' - return self._str - - def __fspath__(self): - return str(self) - - def as_posix(self): - """Return the string representation of the path with forward (/) - slashes.""" - f = self._flavour - return str(self).replace(f.sep, '/') - - def __bytes__(self): - """Return the bytes representation of the path. This is only - recommended to use under Unix.""" - if sys.version_info < (3, 2): - raise NotImplementedError("needs Python 3.2 or later") - return os.fsencode(str(self)) - - def __repr__(self): - return "{0}({1!r})".format(self.__class__.__name__, self.as_posix()) - - def as_uri(self): - """Return the path as a 'file' URI.""" - if not self.is_absolute(): - raise ValueError("relative path can't be expressed as a file URI") - return self._flavour.make_uri(self) - - @property - def _cparts(self): - # Cached casefolded parts, for hashing and comparison - try: - return self._cached_cparts - except AttributeError: - self._cached_cparts = self._flavour.casefold_parts(self._parts) - return self._cached_cparts - - def __eq__(self, other): - if not isinstance(other, PurePath): - return NotImplemented - return ( - self._cparts == other._cparts - and self._flavour is other._flavour) - - def __ne__(self, other): - return not self == other - - def __hash__(self): - try: - return self._hash - except AttributeError: - self._hash = hash(tuple(self._cparts)) - return self._hash - - def __lt__(self, other): - if (not isinstance(other, PurePath) - or self._flavour is not other._flavour): - return NotImplemented - return self._cparts < other._cparts - - def __le__(self, other): - if (not isinstance(other, PurePath) - or self._flavour is not other._flavour): - return NotImplemented - return self._cparts <= other._cparts - - def __gt__(self, other): - if (not isinstance(other, PurePath) - or self._flavour is not other._flavour): - return NotImplemented - return self._cparts > other._cparts - - def __ge__(self, other): - if (not isinstance(other, PurePath) - or self._flavour is not other._flavour): - return NotImplemented - return self._cparts >= other._cparts - - drive = property(attrgetter('_drv'), - doc="""The drive prefix (letter or UNC path), if any.""") - - root = property(attrgetter('_root'), - doc="""The root of the path, if any.""") - - @property - def anchor(self): - """The concatenation of the drive and root, or ''.""" - anchor = self._drv + self._root - return anchor - - @property - def name(self): - """The final path component, if any.""" - parts = self._parts - if len(parts) == (1 if (self._drv or self._root) else 0): - return '' - return parts[-1] - - @property - def suffix(self): - """The final component's last suffix, if any.""" - name = self.name - i = name.rfind('.') - if 0 < i < len(name) - 1: - return name[i:] - else: - return '' - - @property - def suffixes(self): - """A list of the final component's suffixes, if any.""" - name = self.name - if name.endswith('.'): - return [] - name = name.lstrip('.') - return ['.' + suffix for suffix in name.split('.')[1:]] - - @property - def stem(self): - """The final path component, minus its last suffix.""" - name = self.name - i = name.rfind('.') - if 0 < i < len(name) - 1: - return name[:i] - else: - return name - - def with_name(self, name): - """Return a new path with the file name changed.""" - if not self.name: - raise ValueError("%r has an empty name" % (self,)) - drv, root, parts = self._flavour.parse_parts((name,)) - if (not name or name[-1] in [self._flavour.sep, self._flavour.altsep] - or drv or root or len(parts) != 1): - raise ValueError("Invalid name %r" % (name)) - return self._from_parsed_parts(self._drv, self._root, - self._parts[:-1] + [name]) - - def with_suffix(self, suffix): - """Return a new path with the file suffix changed (or added, if - none). - """ - # XXX if suffix is None, should the current suffix be removed? - f = self._flavour - if f.sep in suffix or f.altsep and f.altsep in suffix: - raise ValueError("Invalid suffix %r" % (suffix)) - if suffix and not suffix.startswith('.') or suffix == '.': - raise ValueError("Invalid suffix %r" % (suffix)) - name = self.name - if not name: - raise ValueError("%r has an empty name" % (self,)) - old_suffix = self.suffix - if not old_suffix: - name = name + suffix - else: - name = name[:-len(old_suffix)] + suffix - return self._from_parsed_parts(self._drv, self._root, - self._parts[:-1] + [name]) - - def relative_to(self, *other): - """Return the relative path to another path identified by the passed - arguments. If the operation is not possible (because this is not - a subpath of the other path), raise ValueError. - """ - # For the purpose of this method, drive and root are considered - # separate parts, i.e.: - # Path('c:/').relative_to('c:') gives Path('/') - # Path('c:/').relative_to('/') raise ValueError - if not other: - raise TypeError("need at least one argument") - parts = self._parts - drv = self._drv - root = self._root - if root: - abs_parts = [drv, root] + parts[1:] - else: - abs_parts = parts - to_drv, to_root, to_parts = self._parse_args(other) - if to_root: - to_abs_parts = [to_drv, to_root] + to_parts[1:] - else: - to_abs_parts = to_parts - n = len(to_abs_parts) - cf = self._flavour.casefold_parts - if (root or drv) if n == 0 else cf(abs_parts[:n]) != cf(to_abs_parts): - formatted = self._format_parsed_parts(to_drv, to_root, to_parts) - raise ValueError("{0!r} does not start with {1!r}" - .format(str(self), str(formatted))) - return self._from_parsed_parts('', root if n == 1 else '', - abs_parts[n:]) - - @property - def parts(self): - """An object providing sequence-like access to the - components in the filesystem path.""" - # We cache the tuple to avoid building a new one each time .parts - # is accessed. XXX is this necessary? - try: - return self._pparts - except AttributeError: - self._pparts = tuple(self._parts) - return self._pparts - - def joinpath(self, *args): - """Combine this path with one or several arguments, and return a - new path representing either a subpath (if all arguments are relative - paths) or a totally different path (if one of the arguments is - anchored). - """ - return self._make_child(args) - - def __truediv__(self, key): - return self._make_child((key,)) - - def __rtruediv__(self, key): - return self._from_parts([key] + self._parts) - - if six.PY2: - __div__ = __truediv__ - __rdiv__ = __rtruediv__ - - @property - def parent(self): - """The logical parent of the path.""" - drv = self._drv - root = self._root - parts = self._parts - if len(parts) == 1 and (drv or root): - return self - return self._from_parsed_parts(drv, root, parts[:-1]) - - @property - def parents(self): - """A sequence of this path's logical parents.""" - return _PathParents(self) - - def is_absolute(self): - """True if the path is absolute (has both a root and, if applicable, - a drive).""" - if not self._root: - return False - return not self._flavour.has_drv or bool(self._drv) - - def is_reserved(self): - """Return True if the path contains one of the special names reserved - by the system, if any.""" - return self._flavour.is_reserved(self._parts) - - def match(self, path_pattern): - """ - Return True if this path matches the given pattern. - """ - cf = self._flavour.casefold - path_pattern = cf(path_pattern) - drv, root, pat_parts = self._flavour.parse_parts((path_pattern,)) - if not pat_parts: - raise ValueError("empty pattern") - if drv and drv != cf(self._drv): - return False - if root and root != cf(self._root): - return False - parts = self._cparts - if drv or root: - if len(pat_parts) != len(parts): - return False - pat_parts = pat_parts[1:] - elif len(pat_parts) > len(parts): - return False - for part, pat in zip(reversed(parts), reversed(pat_parts)): - if not fnmatch.fnmatchcase(part, pat): - return False - return True - - -# Can't subclass os.PathLike from PurePath and keep the constructor -# optimizations in PurePath._parse_args(). -if sys.version_info >= (3, 6): - os.PathLike.register(PurePath) - - -class PurePosixPath(PurePath): - _flavour = _posix_flavour - __slots__ = () - - -class PureWindowsPath(PurePath): - _flavour = _windows_flavour - __slots__ = () - - -# Filesystem-accessing classes - - -class Path(PurePath): - __slots__ = ( - '_accessor', - '_closed', - ) - - def __new__(cls, *args, **kwargs): - if cls is Path: - cls = WindowsPath if os.name == 'nt' else PosixPath - self = cls._from_parts(args, init=False) - if not self._flavour.is_supported: - raise NotImplementedError("cannot instantiate %r on your system" - % (cls.__name__,)) - self._init() - return self - - def _init(self, - # Private non-constructor arguments - template=None, - ): - self._closed = False - if template is not None: - self._accessor = template._accessor - else: - self._accessor = _normal_accessor - - def _make_child_relpath(self, part): - # This is an optimization used for dir walking. `part` must be - # a single part relative to this path. - parts = self._parts + [part] - return self._from_parsed_parts(self._drv, self._root, parts) - - def __enter__(self): - if self._closed: - self._raise_closed() - return self - - def __exit__(self, t, v, tb): - self._closed = True - - def _raise_closed(self): - raise ValueError("I/O operation on closed path") - - def _opener(self, name, flags, mode=0o666): - # A stub for the opener argument to built-in open() - return self._accessor.open(self, flags, mode) - - def _raw_open(self, flags, mode=0o777): - """ - Open the file pointed by this path and return a file descriptor, - as os.open() does. - """ - if self._closed: - self._raise_closed() - return self._accessor.open(self, flags, mode) - - # Public API - - @classmethod - def cwd(cls): - """Return a new path pointing to the current working directory - (as returned by os.getcwd()). - """ - return cls(os.getcwd()) - - @classmethod - def home(cls): - """Return a new path pointing to the user's home directory (as - returned by os.path.expanduser('~')). - """ - return cls(cls()._flavour.gethomedir(None)) - - def samefile(self, other_path): - """Return whether other_path is the same or not as this file - (as returned by os.path.samefile()). - """ - if hasattr(os.path, "samestat"): - st = self.stat() - try: - other_st = other_path.stat() - except AttributeError: - other_st = os.stat(other_path) - return os.path.samestat(st, other_st) - else: - filename1 = six.text_type(self) - filename2 = six.text_type(other_path) - st1 = _win32_get_unique_path_id(filename1) - st2 = _win32_get_unique_path_id(filename2) - return st1 == st2 - - def iterdir(self): - """Iterate over the files in this directory. Does not yield any - result for the special paths '.' and '..'. - """ - if self._closed: - self._raise_closed() - for name in self._accessor.listdir(self): - if name in ('.', '..'): - # Yielding a path object for these makes little sense - continue - yield self._make_child_relpath(name) - if self._closed: - self._raise_closed() - - def glob(self, pattern): - """Iterate over this subtree and yield all existing files (of any - kind, including directories) matching the given pattern. - """ - if not pattern: - raise ValueError("Unacceptable pattern: {0!r}".format(pattern)) - pattern = self._flavour.casefold(pattern) - drv, root, pattern_parts = self._flavour.parse_parts((pattern,)) - if drv or root: - raise NotImplementedError("Non-relative patterns are unsupported") - selector = _make_selector(tuple(pattern_parts)) - for p in selector.select_from(self): - yield p - - def rglob(self, pattern): - """Recursively yield all existing files (of any kind, including - directories) matching the given pattern, anywhere in this subtree. - """ - pattern = self._flavour.casefold(pattern) - drv, root, pattern_parts = self._flavour.parse_parts((pattern,)) - if drv or root: - raise NotImplementedError("Non-relative patterns are unsupported") - selector = _make_selector(("**",) + tuple(pattern_parts)) - for p in selector.select_from(self): - yield p - - def absolute(self): - """Return an absolute version of this path. This function works - even if the path doesn't point to anything. - - No normalization is done, i.e. all '.' and '..' will be kept along. - Use resolve() to get the canonical path to a file. - """ - # XXX untested yet! - if self._closed: - self._raise_closed() - if self.is_absolute(): - return self - # FIXME this must defer to the specific flavour (and, under Windows, - # use nt._getfullpathname()) - obj = self._from_parts([os.getcwd()] + self._parts, init=False) - obj._init(template=self) - return obj - - def resolve(self, strict=False): - """ - Make the path absolute, resolving all symlinks on the way and also - normalizing it (for example turning slashes into backslashes under - Windows). - """ - if self._closed: - self._raise_closed() - s = self._flavour.resolve(self, strict=strict) - if s is None: - # No symlink resolution => for consistency, raise an error if - # the path doesn't exist or is forbidden - self.stat() - s = str(self.absolute()) - # Now we have no symlinks in the path, it's safe to normalize it. - normed = self._flavour.pathmod.normpath(s) - obj = self._from_parts((normed,), init=False) - obj._init(template=self) - return obj - - def stat(self): - """ - Return the result of the stat() system call on this path, like - os.stat() does. - """ - return self._accessor.stat(self) - - def owner(self): - """ - Return the login name of the file owner. - """ - import pwd - return pwd.getpwuid(self.stat().st_uid).pw_name - - def group(self): - """ - Return the group name of the file gid. - """ - import grp - return grp.getgrgid(self.stat().st_gid).gr_name - - def open(self, mode='r', buffering=-1, encoding=None, - errors=None, newline=None): - """ - Open the file pointed by this path and return a file object, as - the built-in open() function does. - """ - if self._closed: - self._raise_closed() - if sys.version_info >= (3, 3): - return io.open( - str(self), mode, buffering, encoding, errors, newline, - opener=self._opener) - else: - return io.open(str(self), mode, buffering, - encoding, errors, newline) - - def read_bytes(self): - """ - Open the file in bytes mode, read it, and close the file. - """ - with self.open(mode='rb') as f: - return f.read() - - def read_text(self, encoding=None, errors=None): - """ - Open the file in text mode, read it, and close the file. - """ - with self.open(mode='r', encoding=encoding, errors=errors) as f: - return f.read() - - def write_bytes(self, data): - """ - Open the file in bytes mode, write to it, and close the file. - """ - if not isinstance(data, six.binary_type): - raise TypeError( - 'data must be %s, not %s' % - (six.binary_type.__name__, data.__class__.__name__)) - with self.open(mode='wb') as f: - return f.write(data) - - def write_text(self, data, encoding=None, errors=None): - """ - Open the file in text mode, write to it, and close the file. - """ - if not isinstance(data, six.text_type): - raise TypeError( - 'data must be %s, not %s' % - (six.text_type.__name__, data.__class__.__name__)) - with self.open(mode='w', encoding=encoding, errors=errors) as f: - return f.write(data) - - def touch(self, mode=0o666, exist_ok=True): - """ - Create this file with the given access mode, if it doesn't exist. - """ - if self._closed: - self._raise_closed() - if exist_ok: - # First try to bump modification time - # Implementation note: GNU touch uses the UTIME_NOW option of - # the utimensat() / futimens() functions. - try: - self._accessor.utime(self, None) - except OSError: - # Avoid exception chaining - pass - else: - return - flags = os.O_CREAT | os.O_WRONLY - if not exist_ok: - flags |= os.O_EXCL - fd = self._raw_open(flags, mode) - os.close(fd) - - def mkdir(self, mode=0o777, parents=False, exist_ok=False): - """ - Create a new directory at this given path. - """ - if self._closed: - self._raise_closed() - - def _try_func(): - self._accessor.mkdir(self, mode) - - def _exc_func(exc): - if not parents or self.parent == self: - raise exc - self.parent.mkdir(parents=True, exist_ok=True) - self.mkdir(mode, parents=False, exist_ok=exist_ok) - - try: - _try_except_filenotfounderror(_try_func, _exc_func) - except OSError: - if not exist_ok or not self.is_dir(): - raise - - def chmod(self, mode): - """ - Change the permissions of the path, like os.chmod(). - """ - if self._closed: - self._raise_closed() - self._accessor.chmod(self, mode) - - def lchmod(self, mode): - """ - Like chmod(), except if the path points to a symlink, the symlink's - permissions are changed, rather than its target's. - """ - if self._closed: - self._raise_closed() - self._accessor.lchmod(self, mode) - - def unlink(self): - """ - Remove this file or link. - If the path is a directory, use rmdir() instead. - """ - if self._closed: - self._raise_closed() - self._accessor.unlink(self) - - def rmdir(self): - """ - Remove this directory. The directory must be empty. - """ - if self._closed: - self._raise_closed() - self._accessor.rmdir(self) - - def lstat(self): - """ - Like stat(), except if the path points to a symlink, the symlink's - status information is returned, rather than its target's. - """ - if self._closed: - self._raise_closed() - return self._accessor.lstat(self) - - def rename(self, target): - """ - Rename this path to the given path. - """ - if self._closed: - self._raise_closed() - self._accessor.rename(self, target) - - def replace(self, target): - """ - Rename this path to the given path, clobbering the existing - destination if it exists. - """ - if sys.version_info < (3, 3): - raise NotImplementedError("replace() is only available " - "with Python 3.3 and later") - if self._closed: - self._raise_closed() - self._accessor.replace(self, target) - - def symlink_to(self, target, target_is_directory=False): - """ - Make this path a symlink pointing to the given path. - Note the order of arguments (self, target) is the reverse of - os.symlink's. - """ - if self._closed: - self._raise_closed() - self._accessor.symlink(target, self, target_is_directory) - - # Convenience functions for querying the stat results - - def exists(self): - """ - Whether this path exists. - """ - try: - self.stat() - except OSError as e: - if e.errno not in (ENOENT, ENOTDIR): - raise - return False - return True - - def is_dir(self): - """ - Whether this path is a directory. - """ - try: - return S_ISDIR(self.stat().st_mode) - except OSError as e: - if e.errno not in (ENOENT, ENOTDIR): - raise - # Path doesn't exist or is a broken symlink - # (see https://bitbucket.org/pitrou/pathlib/issue/12/) - return False - - def is_file(self): - """ - Whether this path is a regular file (also True for symlinks pointing - to regular files). - """ - try: - return S_ISREG(self.stat().st_mode) - except OSError as e: - if e.errno not in (ENOENT, ENOTDIR): - raise - # Path doesn't exist or is a broken symlink - # (see https://bitbucket.org/pitrou/pathlib/issue/12/) - return False - - def is_symlink(self): - """ - Whether this path is a symbolic link. - """ - try: - return S_ISLNK(self.lstat().st_mode) - except OSError as e: - if e.errno not in (ENOENT, ENOTDIR): - raise - # Path doesn't exist - return False - - def is_block_device(self): - """ - Whether this path is a block device. - """ - try: - return S_ISBLK(self.stat().st_mode) - except OSError as e: - if e.errno not in (ENOENT, ENOTDIR): - raise - # Path doesn't exist or is a broken symlink - # (see https://bitbucket.org/pitrou/pathlib/issue/12/) - return False - - def is_char_device(self): - """ - Whether this path is a character device. - """ - try: - return S_ISCHR(self.stat().st_mode) - except OSError as e: - if e.errno not in (ENOENT, ENOTDIR): - raise - # Path doesn't exist or is a broken symlink - # (see https://bitbucket.org/pitrou/pathlib/issue/12/) - return False - - def is_fifo(self): - """ - Whether this path is a FIFO. - """ - try: - return S_ISFIFO(self.stat().st_mode) - except OSError as e: - if e.errno not in (ENOENT, ENOTDIR): - raise - # Path doesn't exist or is a broken symlink - # (see https://bitbucket.org/pitrou/pathlib/issue/12/) - return False - - def is_socket(self): - """ - Whether this path is a socket. - """ - try: - return S_ISSOCK(self.stat().st_mode) - except OSError as e: - if e.errno not in (ENOENT, ENOTDIR): - raise - # Path doesn't exist or is a broken symlink - # (see https://bitbucket.org/pitrou/pathlib/issue/12/) - return False - - def expanduser(self): - """ Return a new path with expanded ~ and ~user constructs - (as returned by os.path.expanduser) - """ - if (not (self._drv or self._root) - and self._parts and self._parts[0][:1] == '~'): - homedir = self._flavour.gethomedir(self._parts[0][1:]) - return self._from_parts([homedir] + self._parts[1:]) - - return self - - -class PosixPath(Path, PurePosixPath): - __slots__ = () - - -class WindowsPath(Path, PureWindowsPath): - __slots__ = () - - def owner(self): - raise NotImplementedError("Path.owner() is unsupported on this system") - - def group(self): - raise NotImplementedError("Path.group() is unsupported on this system") diff --git a/buildtools/backports/pathlib2/scandir.py b/buildtools/backports/pathlib2/scandir.py deleted file mode 100644 index 2d0029ad..00000000 --- a/buildtools/backports/pathlib2/scandir.py +++ /dev/null @@ -1,693 +0,0 @@ -"""scandir, a better directory iterator and faster os.walk(), now in the Python 3.5 stdlib - -scandir() is a generator version of os.listdir() that returns an -iterator over files in a directory, and also exposes the extra -information most OSes provide while iterating files in a directory -(such as type and stat information). - -This module also includes a version of os.walk() that uses scandir() -to speed it up significantly. - -See README.md or https://github.com/benhoyt/scandir for rationale and -docs, or read PEP 471 (https://www.python.org/dev/peps/pep-0471/) for -more details on its inclusion into Python 3.5 - -scandir is released under the new BSD 3-clause license. See -LICENSE.txt for the full license text. -""" - -from __future__ import division - -from errno import ENOENT -from os import listdir, lstat, stat, strerror -from os.path import join, islink -from stat import S_IFDIR, S_IFLNK, S_IFREG -import collections -import sys - -try: - import _scandir -except ImportError: - _scandir = None - -try: - import ctypes -except ImportError: - ctypes = None - -if _scandir is None and ctypes is None: - import warnings - warnings.warn("scandir can't find the compiled _scandir C module " - "or ctypes, using slow generic fallback") - -__version__ = '1.10.0' -__all__ = ['scandir', 'walk'] - -# Windows FILE_ATTRIBUTE constants for interpreting the -# FIND_DATA.dwFileAttributes member -FILE_ATTRIBUTE_ARCHIVE = 32 -FILE_ATTRIBUTE_COMPRESSED = 2048 -FILE_ATTRIBUTE_DEVICE = 64 -FILE_ATTRIBUTE_DIRECTORY = 16 -FILE_ATTRIBUTE_ENCRYPTED = 16384 -FILE_ATTRIBUTE_HIDDEN = 2 -FILE_ATTRIBUTE_INTEGRITY_STREAM = 32768 -FILE_ATTRIBUTE_NORMAL = 128 -FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192 -FILE_ATTRIBUTE_NO_SCRUB_DATA = 131072 -FILE_ATTRIBUTE_OFFLINE = 4096 -FILE_ATTRIBUTE_READONLY = 1 -FILE_ATTRIBUTE_REPARSE_POINT = 1024 -FILE_ATTRIBUTE_SPARSE_FILE = 512 -FILE_ATTRIBUTE_SYSTEM = 4 -FILE_ATTRIBUTE_TEMPORARY = 256 -FILE_ATTRIBUTE_VIRTUAL = 65536 - -IS_PY3 = sys.version_info >= (3, 0) - -if IS_PY3: - unicode = str # Because Python <= 3.2 doesn't have u'unicode' syntax - - -class GenericDirEntry(object): - __slots__ = ('name', '_stat', '_lstat', '_scandir_path', '_path') - - def __init__(self, scandir_path, name): - self._scandir_path = scandir_path - self.name = name - self._stat = None - self._lstat = None - self._path = None - - @property - def path(self): - if self._path is None: - self._path = join(self._scandir_path, self.name) - return self._path - - def stat(self, follow_symlinks=True): - if follow_symlinks: - if self._stat is None: - self._stat = stat(self.path) - return self._stat - else: - if self._lstat is None: - self._lstat = lstat(self.path) - return self._lstat - - # The code duplication below is intentional: this is for slightly - # better performance on systems that fall back to GenericDirEntry. - # It avoids an additional attribute lookup and method call, which - # are relatively slow on CPython. - def is_dir(self, follow_symlinks=True): - try: - st = self.stat(follow_symlinks=follow_symlinks) - except OSError as e: - if e.errno != ENOENT: - raise - return False # Path doesn't exist or is a broken symlink - return st.st_mode & 0o170000 == S_IFDIR - - def is_file(self, follow_symlinks=True): - try: - st = self.stat(follow_symlinks=follow_symlinks) - except OSError as e: - if e.errno != ENOENT: - raise - return False # Path doesn't exist or is a broken symlink - return st.st_mode & 0o170000 == S_IFREG - - def is_symlink(self): - try: - st = self.stat(follow_symlinks=False) - except OSError as e: - if e.errno != ENOENT: - raise - return False # Path doesn't exist or is a broken symlink - return st.st_mode & 0o170000 == S_IFLNK - - def inode(self): - st = self.stat(follow_symlinks=False) - return st.st_ino - - def __str__(self): - return '<{0}: {1!r}>'.format(self.__class__.__name__, self.name) - - __repr__ = __str__ - - -def _scandir_generic(path=unicode('.')): - """Like os.listdir(), but yield DirEntry objects instead of returning - a list of names. - """ - for name in listdir(path): - yield GenericDirEntry(path, name) - - -if IS_PY3 and sys.platform == 'win32': - def scandir_generic(path=unicode('.')): - if isinstance(path, bytes): - raise TypeError("os.scandir() doesn't support bytes path on Windows, use Unicode instead") - return _scandir_generic(path) - scandir_generic.__doc__ = _scandir_generic.__doc__ -else: - scandir_generic = _scandir_generic - - -scandir_c = None -scandir_python = None - - -if sys.platform == 'win32': - if ctypes is not None: - from ctypes import wintypes - - # Various constants from windows.h - INVALID_HANDLE_VALUE = ctypes.c_void_p(-1).value - ERROR_FILE_NOT_FOUND = 2 - ERROR_NO_MORE_FILES = 18 - IO_REPARSE_TAG_SYMLINK = 0xA000000C - - # Number of seconds between 1601-01-01 and 1970-01-01 - SECONDS_BETWEEN_EPOCHS = 11644473600 - - kernel32 = ctypes.windll.kernel32 - - # ctypes wrappers for (wide string versions of) FindFirstFile, - # FindNextFile, and FindClose - FindFirstFile = kernel32.FindFirstFileW - FindFirstFile.argtypes = [ - wintypes.LPCWSTR, - ctypes.POINTER(wintypes.WIN32_FIND_DATAW), - ] - FindFirstFile.restype = wintypes.HANDLE - - FindNextFile = kernel32.FindNextFileW - FindNextFile.argtypes = [ - wintypes.HANDLE, - ctypes.POINTER(wintypes.WIN32_FIND_DATAW), - ] - FindNextFile.restype = wintypes.BOOL - - FindClose = kernel32.FindClose - FindClose.argtypes = [wintypes.HANDLE] - FindClose.restype = wintypes.BOOL - - Win32StatResult = collections.namedtuple('Win32StatResult', [ - 'st_mode', - 'st_ino', - 'st_dev', - 'st_nlink', - 'st_uid', - 'st_gid', - 'st_size', - 'st_atime', - 'st_mtime', - 'st_ctime', - 'st_atime_ns', - 'st_mtime_ns', - 'st_ctime_ns', - 'st_file_attributes', - ]) - - def filetime_to_time(filetime): - """Convert Win32 FILETIME to time since Unix epoch in seconds.""" - total = filetime.dwHighDateTime << 32 | filetime.dwLowDateTime - return total / 10000000 - SECONDS_BETWEEN_EPOCHS - - def find_data_to_stat(data): - """Convert Win32 FIND_DATA struct to stat_result.""" - # First convert Win32 dwFileAttributes to st_mode - attributes = data.dwFileAttributes - st_mode = 0 - if attributes & FILE_ATTRIBUTE_DIRECTORY: - st_mode |= S_IFDIR | 0o111 - else: - st_mode |= S_IFREG - if attributes & FILE_ATTRIBUTE_READONLY: - st_mode |= 0o444 - else: - st_mode |= 0o666 - if (attributes & FILE_ATTRIBUTE_REPARSE_POINT and - data.dwReserved0 == IO_REPARSE_TAG_SYMLINK): - st_mode ^= st_mode & 0o170000 - st_mode |= S_IFLNK - - st_size = data.nFileSizeHigh << 32 | data.nFileSizeLow - st_atime = filetime_to_time(data.ftLastAccessTime) - st_mtime = filetime_to_time(data.ftLastWriteTime) - st_ctime = filetime_to_time(data.ftCreationTime) - - # Some fields set to zero per CPython's posixmodule.c: st_ino, st_dev, - # st_nlink, st_uid, st_gid - return Win32StatResult(st_mode, 0, 0, 0, 0, 0, st_size, - st_atime, st_mtime, st_ctime, - int(st_atime * 1000000000), - int(st_mtime * 1000000000), - int(st_ctime * 1000000000), - attributes) - - class Win32DirEntryPython(object): - __slots__ = ('name', '_stat', '_lstat', '_find_data', '_scandir_path', '_path', '_inode') - - def __init__(self, scandir_path, name, find_data): - self._scandir_path = scandir_path - self.name = name - self._stat = None - self._lstat = None - self._find_data = find_data - self._path = None - self._inode = None - - @property - def path(self): - if self._path is None: - self._path = join(self._scandir_path, self.name) - return self._path - - def stat(self, follow_symlinks=True): - if follow_symlinks: - if self._stat is None: - if self.is_symlink(): - # It's a symlink, call link-following stat() - self._stat = stat(self.path) - else: - # Not a symlink, stat is same as lstat value - if self._lstat is None: - self._lstat = find_data_to_stat(self._find_data) - self._stat = self._lstat - return self._stat - else: - if self._lstat is None: - # Lazily convert to stat object, because it's slow - # in Python, and often we only need is_dir() etc - self._lstat = find_data_to_stat(self._find_data) - return self._lstat - - def is_dir(self, follow_symlinks=True): - is_symlink = self.is_symlink() - if follow_symlinks and is_symlink: - try: - return self.stat().st_mode & 0o170000 == S_IFDIR - except OSError as e: - if e.errno != ENOENT: - raise - return False - elif is_symlink: - return False - else: - return (self._find_data.dwFileAttributes & - FILE_ATTRIBUTE_DIRECTORY != 0) - - def is_file(self, follow_symlinks=True): - is_symlink = self.is_symlink() - if follow_symlinks and is_symlink: - try: - return self.stat().st_mode & 0o170000 == S_IFREG - except OSError as e: - if e.errno != ENOENT: - raise - return False - elif is_symlink: - return False - else: - return (self._find_data.dwFileAttributes & - FILE_ATTRIBUTE_DIRECTORY == 0) - - def is_symlink(self): - return (self._find_data.dwFileAttributes & - FILE_ATTRIBUTE_REPARSE_POINT != 0 and - self._find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) - - def inode(self): - if self._inode is None: - self._inode = lstat(self.path).st_ino - return self._inode - - def __str__(self): - return '<{0}: {1!r}>'.format(self.__class__.__name__, self.name) - - __repr__ = __str__ - - def win_error(error, filename): - exc = WindowsError(error, ctypes.FormatError(error)) - exc.filename = filename - return exc - - def _scandir_python(path=unicode('.')): - """Like os.listdir(), but yield DirEntry objects instead of returning - a list of names. - """ - # Call FindFirstFile and handle errors - if isinstance(path, bytes): - is_bytes = True - filename = join(path.decode('mbcs', 'strict'), '*.*') - else: - is_bytes = False - filename = join(path, '*.*') - data = wintypes.WIN32_FIND_DATAW() - data_p = ctypes.byref(data) - handle = FindFirstFile(filename, data_p) - if handle == INVALID_HANDLE_VALUE: - error = ctypes.GetLastError() - if error == ERROR_FILE_NOT_FOUND: - # No files, don't yield anything - return - raise win_error(error, path) - - # Call FindNextFile in a loop, stopping when no more files - try: - while True: - # Skip '.' and '..' (current and parent directory), but - # otherwise yield (filename, stat_result) tuple - name = data.cFileName - if name not in ('.', '..'): - if is_bytes: - name = name.encode('mbcs', 'replace') - yield Win32DirEntryPython(path, name, data) - - data = wintypes.WIN32_FIND_DATAW() - data_p = ctypes.byref(data) - success = FindNextFile(handle, data_p) - if not success: - error = ctypes.GetLastError() - if error == ERROR_NO_MORE_FILES: - break - raise win_error(error, path) - finally: - if not FindClose(handle): - raise win_error(ctypes.GetLastError(), path) - - if IS_PY3: - def scandir_python(path=unicode('.')): - if isinstance(path, bytes): - raise TypeError("os.scandir() doesn't support bytes path on Windows, use Unicode instead") - return _scandir_python(path) - scandir_python.__doc__ = _scandir_python.__doc__ - else: - scandir_python = _scandir_python - - if _scandir is not None: - scandir_c = _scandir.scandir - DirEntry_c = _scandir.DirEntry - - if _scandir is not None: - scandir = scandir_c - DirEntry = DirEntry_c - elif ctypes is not None: - scandir = scandir_python - DirEntry = Win32DirEntryPython - else: - scandir = scandir_generic - DirEntry = GenericDirEntry - - -# Linux, OS X, and BSD implementation -elif sys.platform.startswith(('linux', 'darwin', 'sunos5')) or 'bsd' in sys.platform: - have_dirent_d_type = (sys.platform != 'sunos5') - - if ctypes is not None and have_dirent_d_type: - import ctypes.util - - DIR_p = ctypes.c_void_p - - # Rather annoying how the dirent struct is slightly different on each - # platform. The only fields we care about are d_name and d_type. - class Dirent(ctypes.Structure): - if sys.platform.startswith('linux'): - _fields_ = ( - ('d_ino', ctypes.c_ulong), - ('d_off', ctypes.c_long), - ('d_reclen', ctypes.c_ushort), - ('d_type', ctypes.c_byte), - ('d_name', ctypes.c_char * 256), - ) - elif 'openbsd' in sys.platform: - _fields_ = ( - ('d_ino', ctypes.c_uint64), - ('d_off', ctypes.c_uint64), - ('d_reclen', ctypes.c_uint16), - ('d_type', ctypes.c_uint8), - ('d_namlen', ctypes.c_uint8), - ('__d_padding', ctypes.c_uint8 * 4), - ('d_name', ctypes.c_char * 256), - ) - else: - _fields_ = ( - ('d_ino', ctypes.c_uint32), # must be uint32, not ulong - ('d_reclen', ctypes.c_ushort), - ('d_type', ctypes.c_byte), - ('d_namlen', ctypes.c_byte), - ('d_name', ctypes.c_char * 256), - ) - - DT_UNKNOWN = 0 - DT_DIR = 4 - DT_REG = 8 - DT_LNK = 10 - - Dirent_p = ctypes.POINTER(Dirent) - Dirent_pp = ctypes.POINTER(Dirent_p) - - libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True) - opendir = libc.opendir - opendir.argtypes = [ctypes.c_char_p] - opendir.restype = DIR_p - - readdir_r = libc.readdir_r - readdir_r.argtypes = [DIR_p, Dirent_p, Dirent_pp] - readdir_r.restype = ctypes.c_int - - closedir = libc.closedir - closedir.argtypes = [DIR_p] - closedir.restype = ctypes.c_int - - file_system_encoding = sys.getfilesystemencoding() - - class PosixDirEntry(object): - __slots__ = ('name', '_d_type', '_stat', '_lstat', '_scandir_path', '_path', '_inode') - - def __init__(self, scandir_path, name, d_type, inode): - self._scandir_path = scandir_path - self.name = name - self._d_type = d_type - self._inode = inode - self._stat = None - self._lstat = None - self._path = None - - @property - def path(self): - if self._path is None: - self._path = join(self._scandir_path, self.name) - return self._path - - def stat(self, follow_symlinks=True): - if follow_symlinks: - if self._stat is None: - if self.is_symlink(): - self._stat = stat(self.path) - else: - if self._lstat is None: - self._lstat = lstat(self.path) - self._stat = self._lstat - return self._stat - else: - if self._lstat is None: - self._lstat = lstat(self.path) - return self._lstat - - def is_dir(self, follow_symlinks=True): - if (self._d_type == DT_UNKNOWN or - (follow_symlinks and self.is_symlink())): - try: - st = self.stat(follow_symlinks=follow_symlinks) - except OSError as e: - if e.errno != ENOENT: - raise - return False - return st.st_mode & 0o170000 == S_IFDIR - else: - return self._d_type == DT_DIR - - def is_file(self, follow_symlinks=True): - if (self._d_type == DT_UNKNOWN or - (follow_symlinks and self.is_symlink())): - try: - st = self.stat(follow_symlinks=follow_symlinks) - except OSError as e: - if e.errno != ENOENT: - raise - return False - return st.st_mode & 0o170000 == S_IFREG - else: - return self._d_type == DT_REG - - def is_symlink(self): - if self._d_type == DT_UNKNOWN: - try: - st = self.stat(follow_symlinks=False) - except OSError as e: - if e.errno != ENOENT: - raise - return False - return st.st_mode & 0o170000 == S_IFLNK - else: - return self._d_type == DT_LNK - - def inode(self): - return self._inode - - def __str__(self): - return '<{0}: {1!r}>'.format(self.__class__.__name__, self.name) - - __repr__ = __str__ - - def posix_error(filename): - errno = ctypes.get_errno() - exc = OSError(errno, strerror(errno)) - exc.filename = filename - return exc - - def scandir_python(path=unicode('.')): - """Like os.listdir(), but yield DirEntry objects instead of returning - a list of names. - """ - if isinstance(path, bytes): - opendir_path = path - is_bytes = True - else: - opendir_path = path.encode(file_system_encoding) - is_bytes = False - dir_p = opendir(opendir_path) - if not dir_p: - raise posix_error(path) - try: - result = Dirent_p() - while True: - entry = Dirent() - if readdir_r(dir_p, entry, result): - raise posix_error(path) - if not result: - break - name = entry.d_name - if name not in (b'.', b'..'): - if not is_bytes: - name = name.decode(file_system_encoding) - yield PosixDirEntry(path, name, entry.d_type, entry.d_ino) - finally: - if closedir(dir_p): - raise posix_error(path) - - if _scandir is not None: - scandir_c = _scandir.scandir - DirEntry_c = _scandir.DirEntry - - if _scandir is not None: - scandir = scandir_c - DirEntry = DirEntry_c - elif ctypes is not None and have_dirent_d_type: - scandir = scandir_python - DirEntry = PosixDirEntry - else: - scandir = scandir_generic - DirEntry = GenericDirEntry - - -# Some other system -- no d_type or stat information -else: - scandir = scandir_generic - DirEntry = GenericDirEntry - - -def _walk(top, topdown=True, onerror=None, followlinks=False): - """Like Python 3.5's implementation of os.walk() -- faster than - the pre-Python 3.5 version as it uses scandir() internally. - """ - dirs = [] - nondirs = [] - - # We may not have read permission for top, in which case we can't - # get a list of the files the directory contains. os.walk - # always suppressed the exception then, rather than blow up for a - # minor reason when (say) a thousand readable directories are still - # left to visit. That logic is copied here. - try: - scandir_it = scandir(top) - except OSError as error: - if onerror is not None: - onerror(error) - return - - while True: - try: - try: - entry = next(scandir_it) - except StopIteration: - break - except OSError as error: - if onerror is not None: - onerror(error) - return - - try: - is_dir = entry.is_dir() - except OSError: - # If is_dir() raises an OSError, consider that the entry is not - # a directory, same behaviour than os.path.isdir(). - is_dir = False - - if is_dir: - dirs.append(entry.name) - else: - nondirs.append(entry.name) - - if not topdown and is_dir: - # Bottom-up: recurse into sub-directory, but exclude symlinks to - # directories if followlinks is False - if followlinks: - walk_into = True - else: - try: - is_symlink = entry.is_symlink() - except OSError: - # If is_symlink() raises an OSError, consider that the - # entry is not a symbolic link, same behaviour than - # os.path.islink(). - is_symlink = False - walk_into = not is_symlink - - if walk_into: - for entry in walk(entry.path, topdown, onerror, followlinks): - yield entry - - # Yield before recursion if going top down - if topdown: - yield top, dirs, nondirs - - # Recurse into sub-directories - for name in dirs: - new_path = join(top, name) - # Issue #23605: os.path.islink() is used instead of caching - # entry.is_symlink() result during the loop on os.scandir() because - # the caller can replace the directory entry during the "yield" - # above. - if followlinks or not islink(new_path): - for entry in walk(new_path, topdown, onerror, followlinks): - yield entry - else: - # Yield after recursion if going bottom up - yield top, dirs, nondirs - - -if IS_PY3 or sys.platform != 'win32': - walk = _walk -else: - # Fix for broken unicode handling on Windows on Python 2.x, see: - # https://github.com/benhoyt/scandir/issues/54 - file_system_encoding = sys.getfilesystemencoding() - - def walk(top, topdown=True, onerror=None, followlinks=False): - if isinstance(top, bytes): - top = top.decode(file_system_encoding) - return _walk(top, topdown, onerror, followlinks) From bf2a6554e2188883e560583fa97c1258bde52a6b Mon Sep 17 00:00:00 2001 From: Scott Talbert Date: Mon, 3 Feb 2025 20:27:43 -0500 Subject: [PATCH 7/8] Remove textwrap backport - textwrap added in Python 3.4 --- buildtools/backports/textwrap3.py | 535 ------------------------------ etg/image.py | 2 +- wscript | 5 +- 3 files changed, 2 insertions(+), 540 deletions(-) delete mode 100644 buildtools/backports/textwrap3.py diff --git a/buildtools/backports/textwrap3.py b/buildtools/backports/textwrap3.py deleted file mode 100644 index be47d73a..00000000 --- a/buildtools/backports/textwrap3.py +++ /dev/null @@ -1,535 +0,0 @@ -"""Text wrapping and filling. -""" - -# Copied from Python 3.6's textrap -# https://raw.githubusercontent.com/python/cpython/master/Lib/textwrap.py -# As of commit: https://github.com/python/cpython/commit/f3ebc9fe3fae3d44da4d0da9764ed7c033115f12 -# Then lightly modified to make less Python 3 specific -# - print_function -# - no kw-only arguments -# - different handling of str.translate -# - more tests -# - bespoke handling of genuine Unicode emdash - -# Copyright (C) 1999-2001 Gregory P. Ward. -# Copyright (C) 2002, 2003 Python Software Foundation. -# Written by Greg Ward - -from __future__ import print_function -import re -import sys - -_PY2 = sys.version_info[0] == 2 - -__all__ = ['TextWrapper', 'wrap', 'fill', 'dedent', 'indent', 'shorten'] - -def _translate(s, mapping): - """ - Shim for Python 2 str translate, which uses an archic form of str.translate - that expects a string or buffer based table. But in Python 2, - unicode.translate is compatible with Python 3 model of a dict-based mapping - table, so wash through the unicode type, then back-map to str type. - Could alternatively just shift up to unicode, which is what most strings should - be anyway, but that path is fraught with danger of causing downstream errors. - """ - if _PY2 and isinstance(s, str): - return str(unicode(s).translate(mapping)) - else: - return s.translate(mapping) # default path - -# Hardcode the recognized whitespace characters to the US-ASCII -# whitespace characters. The main reason for doing this is that -# some Unicode spaces (like \u00a0) are non-breaking whitespaces. -_whitespace = '\t\n\x0b\x0c\r ' - -class TextWrapper: - """ - Object for wrapping/filling text. The public interface consists of - the wrap() and fill() methods; the other methods are just there for - subclasses to override in order to tweak the default behaviour. - If you want to completely replace the main wrapping algorithm, - you'll probably have to override _wrap_chunks(). - - Several instance attributes control various aspects of wrapping: - width (default: 70) - the maximum width of wrapped lines (unless break_long_words - is false) - initial_indent (default: "") - string that will be prepended to the first line of wrapped - output. Counts towards the line's width. - subsequent_indent (default: "") - string that will be prepended to all lines save the first - of wrapped output; also counts towards each line's width. - expand_tabs (default: true) - Expand tabs in input text to spaces before further processing. - Each tab will become 0 .. 'tabsize' spaces, depending on its position - in its line. If false, each tab is treated as a single character. - tabsize (default: 8) - Expand tabs in input text to 0 .. 'tabsize' spaces, unless - 'expand_tabs' is false. - replace_whitespace (default: true) - Replace all whitespace characters in the input text by spaces - after tab expansion. Note that if expand_tabs is false and - replace_whitespace is true, every tab will be converted to a - single space! - fix_sentence_endings (default: false) - Ensure that sentence-ending punctuation is always followed - by two spaces. Off by default because the algorithm is - (unavoidably) imperfect. - break_long_words (default: true) - Break words longer than 'width'. If false, those words will not - be broken, and some lines might be longer than 'width'. - break_on_hyphens (default: true) - Allow breaking hyphenated words. If true, wrapping will occur - preferably on whitespaces and right after hyphens part of - compound words. - drop_whitespace (default: true) - Drop leading and trailing whitespace from lines. - max_lines (default: None) - Truncate wrapped lines. - placeholder (default: ' [...]') - Append to the last line of truncated text. - """ - - unicode_whitespace_trans = {} - uspace = ord(' ') - for x in _whitespace: - unicode_whitespace_trans[ord(x)] = uspace - - # This funky little regex is just the trick for splitting - # text up into word-wrappable chunks. E.g. - # "Hello there -- you goof-ball, use the -b option!" - # splits into - # Hello/ /there/ /--/ /you/ /goof-/ball,/ /use/ /the/ /-b/ /option! - # (after stripping out empty strings). - word_punct = r'[\w!"\'&.,?]' - letter = r'[^\d\W]' - whitespace = r'[%s]' % re.escape(_whitespace) - nowhitespace = '[^' + whitespace[1:] - emdash = u'\u2014' - wordsep_re = re.compile(r''' - ( # any whitespace - %(ws)s+ - | # em-dash between words - (?<=%(wp)s) -{2,} (?=\w) - | # Unicode em-dash between words - (?<=%(wp)s) %(emdash)s (?=\w) - | # word, possibly hyphenated - %(nws)s+? (?: - # hyphenated word - -(?: (?<=%(lt)s{2}-) | (?<=%(lt)s-%(lt)s-)) - (?= %(lt)s -? %(lt)s) - | # end of word - (?=%(ws)s|\Z) - | # em-dash - (?<=%(wp)s) (?=-{2,}\w) - | # Unicode em-dash - (?<=%(wp)s) (?=%(emdash)s\w) - ) - )''' % {'wp': word_punct, 'lt': letter, - 'ws': whitespace, 'nws': nowhitespace, - 'emdash': emdash}, - re.VERBOSE | re.UNICODE) - del word_punct, letter, nowhitespace, emdash - - # NB re.UNICODE flag added for consistent behavior across Python 2 and 3 - # Not really needed in Python 3, but without it, Python 2 foolishly does - # not consider letters with diacritical marks (e.g. the very common - # '\N{LATIN SMALL LETTER E WITH ACUTE}') to be "word" characters (`\w`) - - # NB Unicode em dash cannot be easily combined with -- case, because the - # -{2,} admits the (slightly degenerate) --- etc. cases, which are - # unique to simulate em dashes - - # If \N{EM DASH} finds favor, then direct handling of \N{HYPHEN} - # and \N{NON-BREAKING HYPHEN} make sense as follow-ons - - # This less funky little regex just split on recognized spaces. E.g. - # "Hello there -- you goof-ball, use the -b option!" - # splits into - # Hello/ /there/ /--/ /you/ /goof-ball,/ /use/ /the/ /-b/ /option!/ - wordsep_simple_re = re.compile(r'(%s+)' % whitespace) - del whitespace - - # XXX this is not locale- or charset-aware -- string.lowercase - # is US-ASCII only (and therefore English-only) - sentence_end_re = re.compile(r'[a-z]' # lowercase letter - r'[\.\!\?]' # sentence-ending punct. - r'[\"\']?' # optional end-of-quote - r'\Z') # end of chunk - - def __init__(self, - width=70, - initial_indent="", - subsequent_indent="", - expand_tabs=True, - replace_whitespace=True, - fix_sentence_endings=False, - break_long_words=True, - drop_whitespace=True, - break_on_hyphens=True, - tabsize=8, - max_lines=None, - placeholder=' [...]'): - self.width = width - self.initial_indent = initial_indent - self.subsequent_indent = subsequent_indent - self.expand_tabs = expand_tabs - self.replace_whitespace = replace_whitespace - self.fix_sentence_endings = fix_sentence_endings - self.break_long_words = break_long_words - self.drop_whitespace = drop_whitespace - self.break_on_hyphens = break_on_hyphens - self.tabsize = tabsize - self.max_lines = max_lines - self.placeholder = placeholder - - - # -- Private methods ----------------------------------------------- - # (possibly useful for subclasses to override) - - def _munge_whitespace(self, text): - """_munge_whitespace(text : string) -> string - - Munge whitespace in text: expand tabs and convert all other - whitespace characters to spaces. Eg. " foo\\tbar\\n\\nbaz" - becomes " foo bar baz". - """ - if self.expand_tabs: - text = text.expandtabs(self.tabsize) - if self.replace_whitespace: - # text = text.translate(self.unicode_whitespace_trans) - # shim for Python 2 str - text = _translate(text, self.unicode_whitespace_trans) - - return text - - - def _split(self, text): - """_split(text : string) -> [string] - - Split the text to wrap into indivisible chunks. Chunks are - not quite the same as words; see _wrap_chunks() for full - details. As an example, the text - Look, goof-ball -- use the -b option! - breaks into the following chunks: - 'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ', - 'use', ' ', 'the', ' ', '-b', ' ', 'option!' - if break_on_hyphens is True, or in: - 'Look,', ' ', 'goof-ball', ' ', '--', ' ', - 'use', ' ', 'the', ' ', '-b', ' ', option!' - otherwise. - """ - if self.break_on_hyphens is True: - chunks = self.wordsep_re.split(text) - else: - chunks = self.wordsep_simple_re.split(text) - chunks = [c for c in chunks if c] - return chunks - - def _fix_sentence_endings(self, chunks): - """_fix_sentence_endings(chunks : [string]) - - Correct for sentence endings buried in 'chunks'. Eg. when the - original text contains "... foo.\\nBar ...", munge_whitespace() - and split() will convert that to [..., "foo.", " ", "Bar", ...] - which has one too few spaces; this method simply changes the one - space to two. - """ - i = 0 - patsearch = self.sentence_end_re.search - while i < len(chunks)-1: - if chunks[i+1] == " " and patsearch(chunks[i]): - chunks[i+1] = " " - i += 2 - else: - i += 1 - - def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width): - """_handle_long_word(chunks : [string], - cur_line : [string], - cur_len : int, width : int) - - Handle a chunk of text (most likely a word, not whitespace) that - is too long to fit in any line. - """ - # Figure out when indent is larger than the specified width, and make - # sure at least one character is stripped off on every pass - if width < 1: - space_left = 1 - else: - space_left = width - cur_len - - # If we're allowed to break long words, then do so: put as much - # of the next chunk onto the current line as will fit. - if self.break_long_words: - cur_line.append(reversed_chunks[-1][:space_left]) - reversed_chunks[-1] = reversed_chunks[-1][space_left:] - - # Otherwise, we have to preserve the long word intact. Only add - # it to the current line if there's nothing already there -- - # that minimizes how much we violate the width constraint. - elif not cur_line: - cur_line.append(reversed_chunks.pop()) - - # If we're not allowed to break long words, and there's already - # text on the current line, do nothing. Next time through the - # main loop of _wrap_chunks(), we'll wind up here again, but - # cur_len will be zero, so the next line will be entirely - # devoted to the long word that we can't handle right now. - - def _wrap_chunks(self, chunks): - """_wrap_chunks(chunks : [string]) -> [string] - - Wrap a sequence of text chunks and return a list of lines of - length 'self.width' or less. (If 'break_long_words' is false, - some lines may be longer than this.) Chunks correspond roughly - to words and the whitespace between them: each chunk is - indivisible (modulo 'break_long_words'), but a line break can - come between any two chunks. Chunks should not have internal - whitespace; ie. a chunk is either all whitespace or a "word". - Whitespace chunks will be removed from the beginning and end of - lines, but apart from that whitespace is preserved. - """ - lines = [] - if self.width <= 0: - raise ValueError("invalid width %r (must be > 0)" % self.width) - if self.max_lines is not None: - if self.max_lines > 1: - indent = self.subsequent_indent - else: - indent = self.initial_indent - if len(indent) + len(self.placeholder.lstrip()) > self.width: - raise ValueError("placeholder too large for max width") - - # Arrange in reverse order so items can be efficiently popped - # from a stack of chucks. - chunks.reverse() - - while chunks: - - # Start the list of chunks that will make up the current line. - # cur_len is just the length of all the chunks in cur_line. - cur_line = [] - cur_len = 0 - - # Figure out which static string will prefix this line. - if lines: - indent = self.subsequent_indent - else: - indent = self.initial_indent - - # Maximum width for this line. - width = self.width - len(indent) - - # First chunk on line is whitespace -- drop it, unless this - # is the very beginning of the text (ie. no lines started yet). - if self.drop_whitespace and chunks[-1].strip() == '' and lines: - del chunks[-1] - - while chunks: - l = len(chunks[-1]) - - # Can at least squeeze this chunk onto the current line. - if cur_len + l <= width: - cur_line.append(chunks.pop()) - cur_len += l - - # Nope, this line is full. - else: - break - - # The current line is full, and the next chunk is too big to - # fit on *any* line (not just this one). - if chunks and len(chunks[-1]) > width: - self._handle_long_word(chunks, cur_line, cur_len, width) - cur_len = sum(map(len, cur_line)) - - # If the last chunk on this line is all whitespace, drop it. - if self.drop_whitespace and cur_line and cur_line[-1].strip() == '': - cur_len -= len(cur_line[-1]) - del cur_line[-1] - - if cur_line: - if (self.max_lines is None or - len(lines) + 1 < self.max_lines or - (not chunks or - self.drop_whitespace and - len(chunks) == 1 and - not chunks[0].strip()) and cur_len <= width): - # Convert current line back to a string and store it in - # list of all lines (return value). - lines.append(indent + ''.join(cur_line)) - else: - while cur_line: - if (cur_line[-1].strip() and - cur_len + len(self.placeholder) <= width): - cur_line.append(self.placeholder) - lines.append(indent + ''.join(cur_line)) - break - cur_len -= len(cur_line[-1]) - del cur_line[-1] - else: - if lines: - prev_line = lines[-1].rstrip() - if (len(prev_line) + len(self.placeholder) <= - self.width): - lines[-1] = prev_line + self.placeholder - break - lines.append(indent + self.placeholder.lstrip()) - break - - return lines - - def _split_chunks(self, text): - text = self._munge_whitespace(text) - return self._split(text) - - # -- Public interface ---------------------------------------------- - - def wrap(self, text): - """wrap(text : string) -> [string] - - Reformat the single paragraph in 'text' so it fits in lines of - no more than 'self.width' columns, and return a list of wrapped - lines. Tabs in 'text' are expanded with string.expandtabs(), - and all other whitespace characters (including newline) are - converted to space. - """ - chunks = self._split_chunks(text) - if self.fix_sentence_endings: - self._fix_sentence_endings(chunks) - return self._wrap_chunks(chunks) - - def fill(self, text): - """fill(text : string) -> string - - Reformat the single paragraph in 'text' to fit in lines of no - more than 'self.width' columns, and return a new string - containing the entire wrapped paragraph. - """ - return "\n".join(self.wrap(text)) - - -# -- Convenience interface --------------------------------------------- - -def wrap(text, width=70, **kwargs): - """Wrap a single paragraph of text, returning a list of wrapped lines. - - Reformat the single paragraph in 'text' so it fits in lines of no - more than 'width' columns, and return a list of wrapped lines. By - default, tabs in 'text' are expanded with string.expandtabs(), and - all other whitespace characters (including newline) are converted to - space. See TextWrapper class for available keyword args to customize - wrapping behaviour. - """ - w = TextWrapper(width=width, **kwargs) - return w.wrap(text) - -def fill(text, width=70, **kwargs): - """Fill a single paragraph of text, returning a new string. - - Reformat the single paragraph in 'text' to fit in lines of no more - than 'width' columns, and return a new string containing the entire - wrapped paragraph. As with wrap(), tabs are expanded and other - whitespace characters converted to space. See TextWrapper class for - available keyword args to customize wrapping behaviour. - """ - w = TextWrapper(width=width, **kwargs) - return w.fill(text) - -def shorten(text, width, **kwargs): - """Collapse and truncate the given text to fit in the given width. - - The text first has its whitespace collapsed. If it then fits in - the *width*, it is returned as is. Otherwise, as many words - as possible are joined and then the placeholder is appended:: - - >>> textwrap.shorten("Hello world!", width=12) - 'Hello world!' - >>> textwrap.shorten("Hello world!", width=11) - 'Hello [...]' - """ - w = TextWrapper(width=width, max_lines=1, **kwargs) - return w.fill(' '.join(text.strip().split())) - - -# -- Loosely related functionality ------------------------------------- - -_whitespace_only_re = re.compile('^[ \t]+$', re.MULTILINE) -_leading_whitespace_re = re.compile('(^[ \t]*)(?:[^ \t\n])', re.MULTILINE) - -def dedent(text): - """Remove any common leading whitespace from every line in `text`. - - This can be used to make triple-quoted strings line up with the left - edge of the display, while still presenting them in the source code - in indented form. - - Note that tabs and spaces are both treated as whitespace, but they - are not equal: the lines " hello" and "\\thello" are - considered to have no common leading whitespace. (This behaviour is - new in Python 2.5; older versions of this module incorrectly - expanded tabs before searching for common leading whitespace.) - """ - # Look for the longest leading string of spaces and tabs common to - # all lines. - debug = False - margin = None - text = _whitespace_only_re.sub('', text) - indents = _leading_whitespace_re.findall(text) - for indent in indents: - if margin is None: - margin = indent - - # Current line more deeply indented than previous winner: - # no change (previous winner is still on top). - elif indent.startswith(margin): - pass - - # Current line consistent with and no deeper than previous winner: - # it's the new winner. - elif margin.startswith(indent): - margin = indent - - # Find the largest common whitespace between current line and previous - # winner. - else: - for i, (x, y) in enumerate(zip(margin, indent)): - if x != y: - margin = margin[:i] - break - - # sanity check (testing/debugging only) - if 0 and margin: # pragma: no cover - for line in text.split("\n"): - assert not line or line.startswith(margin), \ - "line = %r, margin = %r" % (line, margin) - - if margin: - text = re.sub(r'(?m)^' + margin, '', text) - return text - - -def indent(text, prefix, predicate=None): - """Adds 'prefix' to the beginning of selected lines in 'text'. - - If 'predicate' is provided, 'prefix' will only be added to the lines - where 'predicate(line)' is True. If 'predicate' is not provided, - it will default to adding 'prefix' to all non-empty lines that do not - consist solely of whitespace characters. - """ - if predicate is None: - def predicate(line): - return line.strip() - - def prefixed_lines(): - for line in text.splitlines(True): - yield (prefix + line if predicate(line) else line) - return ''.join(prefixed_lines()) - - -if __name__ == "__main__": - #print dedent("\tfoo\n\tbar") - #print dedent(" \thello there\n \t how are you?") - print(dedent("Hello there.\n This is indented.")) # pragma: no cover diff --git a/etg/image.py b/etg/image.py index 11c44e7b..468b81ed 100644 --- a/etg/image.py +++ b/etg/image.py @@ -11,7 +11,7 @@ import etgtools import etgtools.tweaker_tools as tools -from buildtools.backports.textwrap3 import dedent +from textwrap import dedent PACKAGE = "wx" MODULE = "_core" diff --git a/wscript b/wscript index 1114a985..aab8a29d 100644 --- a/wscript +++ b/wscript @@ -11,10 +11,7 @@ import sys import os import setuptools -try: - from textwrap import indent -except ImportError: - from buildtools.backports.textwrap3 import indent +from textwrap import indent from buildtools.config import Config, runcmd, msg, getMSVCInfo, generateVersionFiles cfg = Config(True) From a29322f6781ad053f312553d8d8eef8df667136e Mon Sep 17 00:00:00 2001 From: Scott Talbert Date: Mon, 3 Feb 2025 20:31:24 -0500 Subject: [PATCH 8/8] Remove shutil.which backport - it was added in Python 3.3 --- build.py | 5 +- buildtools/backports/__init__.py | 0 buildtools/backports/shutil_which.py | 78 ---------------------------- 3 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 buildtools/backports/__init__.py delete mode 100644 buildtools/backports/shutil_which.py diff --git a/build.py b/build.py index 8e30d8e6..d82b94b1 100755 --- a/build.py +++ b/build.py @@ -29,10 +29,7 @@ import shlex import textwrap import warnings -try: - from shutil import which -except ImportError: - from buildtools.backports.shutil_which import which +from shutil import which try: from setuptools.modified import newer, newer_group diff --git a/buildtools/backports/__init__.py b/buildtools/backports/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/buildtools/backports/shutil_which.py b/buildtools/backports/shutil_which.py deleted file mode 100644 index 1182bc91..00000000 --- a/buildtools/backports/shutil_which.py +++ /dev/null @@ -1,78 +0,0 @@ -"""Backport of shutil.which from Python 3.5 - -The function is included unmodified from Python stdlib 3.5.1, -and is (C) Python -""" -from __future__ import absolute_import # Import system's os, not backports.os. - -import os -import sys - -__version__ = '3.5.1' - -def backport_which(cmd, mode=os.F_OK | os.X_OK, path=None): - """Given a command, mode, and a PATH string, return the path which - conforms to the given mode on the PATH, or None if there is no such - file. - - `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result - of os.environ.get("PATH"), or can be overridden with a custom search - path. - - """ - # Check that a given file can be accessed with the correct mode. - # Additionally check that `file` is not a directory, as on Windows - # directories pass the os.access check. - def _access_check(fn, mode): - return (os.path.exists(fn) and os.access(fn, mode) - and not os.path.isdir(fn)) - - # If we're given a path with a directory part, look it up directly rather - # than referring to PATH directories. This includes checking relative to the - # current directory, e.g. ./script - if os.path.dirname(cmd): - if _access_check(cmd, mode): - return cmd - return None - - if path is None: - path = os.environ.get("PATH", os.defpath) - if not path: - return None - path = path.split(os.pathsep) - - if sys.platform == "win32": - # The current directory takes precedence on Windows. - if not os.curdir in path: - path.insert(0, os.curdir) - - # PATHEXT is necessary to check on Windows. - pathext = os.environ.get("PATHEXT", "").split(os.pathsep) - # See if the given file matches any of the expected path extensions. - # This will allow us to short circuit when given "python.exe". - # If it does match, only test that one, otherwise we have to try - # others. - if any(cmd.lower().endswith(ext.lower()) for ext in pathext): - files = [cmd] - else: - files = [cmd + ext for ext in pathext] - else: - # On other platforms you don't have things like PATHEXT to tell you - # what file suffixes are executable, so just pass on cmd as-is. - files = [cmd] - - seen = set() - for dir in path: - normdir = os.path.normcase(dir) - if not normdir in seen: - seen.add(normdir) - for thefile in files: - name = os.path.join(dir, thefile) - if _access_check(name, mode): - return name - return None - -try: - from shutil import which -except ImportError: - which = backport_which