From c9c5fb238a695dcf22e463c0b95a651bd8e6d28e Mon Sep 17 00:00:00 2001 From: Avasam Date: Fri, 26 Jul 2024 19:03:32 -0400 Subject: [PATCH 1/7] simplify dict iterations from Python 2 to 3 migration --- AutoDuck/Dump2HHC.py | 8 +-- AutoDuck/InsertExternalOverviews.py | 8 +-- AutoDuck/py2d.py | 4 +- Pythonwin/pywin/Demos/app/customprint.py | 4 +- Pythonwin/pywin/debugger/configui.py | 2 +- Pythonwin/pywin/debugger/debugger.py | 2 +- Pythonwin/pywin/framework/dbgcommands.py | 2 +- Pythonwin/pywin/framework/mdi_pychecker.py | 4 +- Pythonwin/pywin/framework/scriptutils.py | 2 +- Pythonwin/pywin/framework/sgrepmdi.py | 4 +- Pythonwin/pywin/mfc/dialog.py | 6 +- Pythonwin/pywin/scintilla/bindings.py | 2 +- Pythonwin/pywin/scintilla/config.py | 6 +- Pythonwin/pywin/scintilla/configui.py | 3 +- Pythonwin/pywin/scintilla/formatter.py | 6 +- Pythonwin/pywin/scintilla/view.py | 16 ++--- Pythonwin/pywin/tools/browser.py | 9 +-- adodbapi/adodbapi.py | 4 +- adodbapi/apibase.py | 2 +- adodbapi/process_connect_string.py | 2 +- com/win32com/client/__init__.py | 16 ++--- com/win32com/client/build.py | 23 ++++---- com/win32com/client/dynamic.py | 11 ++-- com/win32com/client/gencache.py | 16 +++-- com/win32com/client/genpy.py | 58 ++++++------------- com/win32com/demos/dump_clipboard.py | 2 +- com/win32com/makegw/makegwparse.py | 7 +-- com/win32com/server/policy.py | 4 +- com/win32com/servers/dictionary.py | 2 +- com/win32com/test/testDictionary.py | 2 +- com/win32com/test/testIterators.py | 2 +- com/win32com/test/testmakepy.py | 2 +- com/win32com/universal.py | 4 +- com/win32comext/axdebug/debugger.py | 4 +- com/win32comext/axdebug/expressions.py | 4 +- com/win32comext/axscript/client/framework.py | 2 +- com/win32comext/axscript/client/pyscript.py | 2 +- com/win32comext/axscript/server/axsite.py | 2 +- .../shell/demos/IFileOperationProgressSink.py | 2 +- .../shell/demos/ITransferAdviseSink.py | 8 ++- .../shell/demos/servers/shell_view.py | 4 +- isapi/install.py | 16 +++-- win32/Demos/GetSaveFileName.py | 4 +- win32/Demos/rastest.py | 10 ++-- win32/Demos/security/sspi/fetch_url.py | 6 +- win32/Demos/security/sspi/simple_auth.py | 2 +- win32/Demos/win32clipboardDemo.py | 9 +-- win32/Demos/win32console_demo.py | 5 +- win32/Demos/win32netdemo.py | 7 +-- win32/Lib/win32timezone.py | 12 ++-- win32/Lib/win32verstamp.py | 2 +- win32/test/test_win32api.py | 2 +- win32/test/test_win32guistruct.py | 6 +- 53 files changed, 151 insertions(+), 203 deletions(-) diff --git a/AutoDuck/Dump2HHC.py b/AutoDuck/Dump2HHC.py index ef16a38168..343bdbca11 100644 --- a/AutoDuck/Dump2HHC.py +++ b/AutoDuck/Dump2HHC.py @@ -231,9 +231,7 @@ def _urlescape(name): def _genCategoryHTMLFromDict(dict, output): - keys = list(dict.keys()) - keys.sort() - for key in keys: + for key in sorted(dict): topic = dict[key] output.write(f'
  • {topic.name}\n') @@ -285,9 +283,7 @@ def genCategoryHTML(output_dir, cats): def _genItemsFromDict(dict, cat, output, target, do_children=1): CHM = "mk:@MSITStore:%s.chm::/" % target - keys = list(dict.keys()) - keys.sort() - for k in keys: + for k in sorted(dict): context = dict[k].context name = dict[k].name output.write( diff --git a/AutoDuck/InsertExternalOverviews.py b/AutoDuck/InsertExternalOverviews.py index c0465e40bc..e4bbd8d516 100644 --- a/AutoDuck/InsertExternalOverviews.py +++ b/AutoDuck/InsertExternalOverviews.py @@ -26,12 +26,8 @@ def genHTML(doc): s = "" for cat in doc: s += f"

    {cat.label}

    \n" - dict = {} - for item in cat.overviewItems.items: - dict[item.name] = item.href - keys = list(dict.keys()) - keys.sort() - for k in keys: + dict = {item.name: item.href for item in cat.overviewItems.items} + for k in sorted(dict): s += f'
  • {k}\n' return s diff --git a/AutoDuck/py2d.py b/AutoDuck/py2d.py index 6a0452bf72..647fb7121e 100644 --- a/AutoDuck/py2d.py +++ b/AutoDuck/py2d.py @@ -100,7 +100,7 @@ def build_module(fp, mod_name): functions = [] classes = [] constants = [] - for name, ob in list(mod.__dict__.items()): + for name, ob in mod.__dict__.items(): if name.startswith("_"): continue if hasattr(ob, "__module__") and ob.__module__ != mod_name: @@ -139,7 +139,7 @@ def build_module(fp, mod_name): func_infos = [] # We need to iter the keys then to a getattr() so the funky descriptor # things work. - for n in list(ob.ob.__dict__.keys()): + for n in ob.ob.__dict__: o = getattr(ob.ob, n) if isinstance(o, (types.FunctionType, types.MethodType)): info = BuildInfo(n, o) diff --git a/Pythonwin/pywin/Demos/app/customprint.py b/Pythonwin/pywin/Demos/app/customprint.py index 4a666ca41a..4d9371d68d 100644 --- a/Pythonwin/pywin/Demos/app/customprint.py +++ b/Pythonwin/pywin/Demos/app/customprint.py @@ -45,9 +45,7 @@ def OnDraw(self, dc): oldPen = None x, y = self.size delta = 2 - colors = list(self.colors.keys()) - colors.sort() - colors *= 2 + colors = sorted(self.colors) * 2 for color in colors: if oldPen is None: oldPen = dc.SelectObject(self.pens[color]) diff --git a/Pythonwin/pywin/debugger/configui.py b/Pythonwin/pywin/debugger/configui.py index 32de4ee5ff..c24d5cda11 100644 --- a/Pythonwin/pywin/debugger/configui.py +++ b/Pythonwin/pywin/debugger/configui.py @@ -19,7 +19,7 @@ def OnInitDialog(self): def OnOK(self): self.UpdateData() dirty = 0 - for key, val in list(self.items()): + for key, val in self.items(): if key in self.options: if self.options[key] != val: self.options[key] = val diff --git a/Pythonwin/pywin/debugger/debugger.py b/Pythonwin/pywin/debugger/debugger.py index 2cddf0ea3b..dca59b8c7d 100644 --- a/Pythonwin/pywin/debugger/debugger.py +++ b/Pythonwin/pywin/debugger/debugger.py @@ -389,7 +389,7 @@ def DeleteSelected(self): item_id = self.GetItem(num)[6] from bdb import Breakpoint - for bplist in list(Breakpoint.bplist.values()): + for bplist in Breakpoint.bplist.values(): for bp in bplist: if id(bp) == item_id: self.debugger.clear_break(bp.file, bp.line) diff --git a/Pythonwin/pywin/framework/dbgcommands.py b/Pythonwin/pywin/framework/dbgcommands.py index e295926c79..f6aa38358c 100644 --- a/Pythonwin/pywin/framework/dbgcommands.py +++ b/Pythonwin/pywin/framework/dbgcommands.py @@ -37,7 +37,7 @@ def HookCommands(self): if not methUpdate is None: frame.HookCommandUpdate(methUpdate, id) - for id in list(IdToBarNames.keys()): + for id in IdToBarNames: frame.HookCommand(self.OnDebuggerBar, id) frame.HookCommandUpdate(self.OnUpdateDebuggerBar, id) diff --git a/Pythonwin/pywin/framework/mdi_pychecker.py b/Pythonwin/pywin/framework/mdi_pychecker.py index 03e5e220f1..cd31a9a18a 100644 --- a/Pythonwin/pywin/framework/mdi_pychecker.py +++ b/Pythonwin/pywin/framework/mdi_pychecker.py @@ -112,9 +112,7 @@ def __init__(self, str, recurse=0): sd = sd.lower() if sd not in dirs: dirs[sd] = None - self.dirs = [] - for d in dirs.keys(): - self.dirs.append(d) + self.dirs = list(dirs) def __getitem__(self, key): return self.dirs[key] diff --git a/Pythonwin/pywin/framework/scriptutils.py b/Pythonwin/pywin/framework/scriptutils.py index 98c34b4778..fe57113ddd 100644 --- a/Pythonwin/pywin/framework/scriptutils.py +++ b/Pythonwin/pywin/framework/scriptutils.py @@ -440,7 +440,7 @@ def ImportFile(): # note that some packages (*cough* email *cough*) use "lazy importers" # meaning sys.modules can change as a side-effect of looking at # module.__file__ - so we must take a copy (ie, list(items())) - for key, mod in list(sys.modules.items()): + for key, mod in sys.modules.items(): if getattr(mod, "__file__", None): fname = mod.__file__ base, ext = os.path.splitext(fname) diff --git a/Pythonwin/pywin/framework/sgrepmdi.py b/Pythonwin/pywin/framework/sgrepmdi.py index 539fe6d124..f318f731f8 100644 --- a/Pythonwin/pywin/framework/sgrepmdi.py +++ b/Pythonwin/pywin/framework/sgrepmdi.py @@ -94,9 +94,7 @@ def __init__(self, str, recurse=0): sd = sd.lower() if sd not in dirs: dirs[sd] = None - self.dirs = [] - for d in list(dirs.keys()): - self.dirs.append(d) + self.dirs = list(dirs) def __getitem__(self, key): return self.dirs[key] diff --git a/Pythonwin/pywin/mfc/dialog.py b/Pythonwin/pywin/mfc/dialog.py index 93a5ba6504..4edb141236 100644 --- a/Pythonwin/pywin/mfc/dialog.py +++ b/Pythonwin/pywin/mfc/dialog.py @@ -83,13 +83,13 @@ def __setitem__(self, key, item): self._obj_.data[key] = item # self.UpdateData(0) def keys(self): - return list(self.data.keys()) + return self.data.keys() def items(self): - return list(self.data.items()) + return self.data.items() def values(self): - return list(self.data.values()) + return self.data.values() def __contains__(self, key): return key in self.data diff --git a/Pythonwin/pywin/scintilla/bindings.py b/Pythonwin/pywin/scintilla/bindings.py index 60001c7494..e35be8a574 100644 --- a/Pythonwin/pywin/scintilla/bindings.py +++ b/Pythonwin/pywin/scintilla/bindings.py @@ -56,7 +56,7 @@ def prepare_configure(self): self.keymap = {} def complete_configure(self): - for id in command_to_events.keys(): + for id in command_to_events: self.parent_view.HookCommand(self._OnCommand, id) def close(self): diff --git a/Pythonwin/pywin/scintilla/config.py b/Pythonwin/pywin/scintilla/config.py index 6f5a6396fd..e67368dfed 100644 --- a/Pythonwin/pywin/scintilla/config.py +++ b/Pythonwin/pywin/scintilla/config.py @@ -198,7 +198,7 @@ def configure(self, editor, subsections=None): ns = None if ns: num = 0 - for name, func in list(ns.items()): + for name, func in ns.items(): if isinstance(func, types.FunctionType) and name[:1] != "_": bindings.bind(name, func) num += 1 @@ -230,10 +230,8 @@ def get_key_binding(self, event, subsections=None): for subsection in subsections: map = self.key_to_events.get(subsection) if map is None: # Build it - map = {} keymap = subsection_keymap.get(subsection, {}) - for key_info, map_event in list(keymap.items()): - map[map_event] = key_info + map = {map_event: key_info for key_info, map_event in keymap.items()} self.key_to_events[subsection] = map info = map.get(event) diff --git a/Pythonwin/pywin/scintilla/configui.py b/Pythonwin/pywin/scintilla/configui.py index 9da2fbf75e..c8e81257ab 100644 --- a/Pythonwin/pywin/scintilla/configui.py +++ b/Pythonwin/pywin/scintilla/configui.py @@ -88,8 +88,7 @@ def OnInitDialog(self): self.butIsDefaultBackground = self.GetDlgItem(win32ui.IDC_CHECK2) self.listbox = self.GetDlgItem(win32ui.IDC_LIST1) self.HookCommand(self.OnListCommand, win32ui.IDC_LIST1) - names = list(self.styles.keys()) - names.sort() + names = sorted(self.styles) for name in names: if self.styles[name].aliased is None: self.listbox.AddString(name) diff --git a/Pythonwin/pywin/scintilla/formatter.py b/Pythonwin/pywin/scintilla/formatter.py index 6e3459dcc9..cff9ee60e3 100644 --- a/Pythonwin/pywin/scintilla/formatter.py +++ b/Pythonwin/pywin/scintilla/formatter.py @@ -185,7 +185,7 @@ def ApplyFormattingStyles(self, bReload=1): defaultStyle = Style("default", baseFormat) defaultStyle.stylenum = scintillacon.STYLE_DEFAULT self._ReformatStyle(defaultStyle) - for style in list(self.styles.values()): + for style in self.styles.values(): if style.aliased is None: style.NormalizeAgainstDefault(baseFormat) self._ReformatStyle(style) @@ -202,7 +202,7 @@ def LoadPreferences(self): ) self.bUseFixed = int(self.LoadPreference("Use Fixed", 1)) - for style in list(self.styles.values()): + for style in self.styles.values(): new = self.LoadPreference(style.name, str(style.format)) try: style.format = eval(new) @@ -222,7 +222,7 @@ def SavePreferences(self): self.SavePreference("Base Format Fixed", str(self.baseFormatFixed)) self.SavePreference("Base Format Proportional", str(self.baseFormatProp)) self.SavePreference("Use Fixed", self.bUseFixed) - for style in list(self.styles.values()): + for style in self.styles.values(): if style.aliased is None: self.SavePreference(style.name, str(style.format)) bg_name = style.name + " background" diff --git a/Pythonwin/pywin/scintilla/view.py b/Pythonwin/pywin/scintilla/view.py index e941487509..1cbc26e0d2 100644 --- a/Pythonwin/pywin/scintilla/view.py +++ b/Pythonwin/pywin/scintilla/view.py @@ -517,10 +517,14 @@ def list2dict(l): ) ) - # ensure all keys are strings. - items = [str(k) for k in items_dict.keys()] - # All names that start with "_" go! - items = [k for k in items if not k.startswith("_")] + items = [ + k + for k in + # ensure all keys are strings. + map(str, items_dict) + # All names that start with "_" go! + if not k.startswith("_") + ] if not items: # Heuristics a-la AutoExpand @@ -550,9 +554,7 @@ def list2dict(l): if curclass and left == "self": self._UpdateWithClassMethods(unique, curclass) - items = [ - word for word in unique.keys() if word[:2] != "__" or word[-2:] != "__" - ] + items = [word for word in unique if word[:2] != "__" or word[-2:] != "__"] # Ignore the word currently to the right of the dot - probably a red-herring. try: items.remove(right[1:]) diff --git a/Pythonwin/pywin/tools/browser.py b/Pythonwin/pywin/tools/browser.py index b0fd7cab17..6a301c3de0 100644 --- a/Pythonwin/pywin/tools/browser.py +++ b/Pythonwin/pywin/tools/browser.py @@ -110,7 +110,7 @@ def CalculateIsExpandable(self): if hasattr(self.myobject, "__doc__"): return 1 try: - for key in self.myobject.__dict__.keys(): + for key in self.myobject.__dict__: if key not in special_names: return 1 except (AttributeError, TypeError): @@ -288,12 +288,7 @@ def IsExpandable(self): return len(self.myobject) > 0 def GetSubList(self): - ret = [] - keys = list(self.myobject.keys()) - keys.sort() - for key in keys: - ob = self.myobject[key] - ret.append(MakeHLI(ob, str(key))) + ret = [MakeHLI(self.myobject[key], str(key)) for key in sorted(self.myobject)] self.InsertDocString(ret) return ret diff --git a/adodbapi/adodbapi.py b/adodbapi/adodbapi.py index 4e85bc525b..949fcfe542 100644 --- a/adodbapi/adodbapi.py +++ b/adodbapi/adodbapi.py @@ -326,9 +326,7 @@ def close(self): an Error (or subclass) exception will be raised if any operation is attempted with the connection. The same applies to all cursor objects trying to use the connection. """ - for crsr in list(self.cursors.values())[ - : - ]: # copy the list, then close each one + for crsr in self.cursors.values(): crsr.close(dont_tell_me=True) # close without back-link clearing self.messages = [] try: diff --git a/adodbapi/apibase.py b/adodbapi/apibase.py index 749c378d38..b7d1f3ae36 100644 --- a/adodbapi/apibase.py +++ b/adodbapi/apibase.py @@ -564,7 +564,7 @@ def __next__(self): yield self._getValue(n) def __repr__(self): # create a human readable representation - taglist = sorted(list(self.rows.columnNames.items()), key=lambda x: x[1]) + taglist = sorted(self.rows.columnNames.items(), key=lambda x: x[1]) s = " 0)) @@ -325,7 +325,7 @@ def EnumObjects(self, hwndOwner, flags): mod_objects = get_clbr_for_file(self.path) my_objects = mod_objects[self.class_name] pidls = [] - for func_name, lineno in my_objects.methods.items(): + for func_name in my_objects.methods: pidl = ["object\0" + self.path + "\0" + self.class_name + "." + func_name] pidls.append(pidl) return NewEnum(pidls, iid=shell.IID_IEnumIDList, useDispatcher=(debug > 0)) diff --git a/isapi/install.py b/isapi/install.py index 61462f4f6f..8429f41ef9 100644 --- a/isapi/install.py +++ b/isapi/install.py @@ -10,6 +10,7 @@ import stat import sys import traceback +from collections.abc import Mapping import pythoncom import win32api @@ -687,15 +688,12 @@ def UninstallModule(conf_module_name, params, options, log=lambda *args: None): } -def build_usage(handler_map): - docstrings = [handler.__doc__ for handler in handler_map.values()] - all_args = dict(zip(iter(handler_map.keys()), docstrings)) - arg_names = "|".join(iter(all_args.keys())) - usage_string = "%prog [options] [" + arg_names + "]\n" - usage_string += "commands:\n" - for arg, desc in all_args.items(): - usage_string += " %-10s: %s" % (arg, desc) + "\n" - return usage_string[:-1] +def build_usage(handler_map: Mapping[str, object]) -> str: + arg_names = "|".join(handler_map) + lines = [ + " %-10s: %s" % (arg, handler.__doc__) for arg, handler in handler_map.items() + ] + return f"%prog [options] [{arg_names}]\ncommands:\n" + "\n".join(lines) def MergeStandardOptions(options, params): diff --git a/win32/Demos/GetSaveFileName.py b/win32/Demos/GetSaveFileName.py index 2858750529..bff34dcdd3 100644 --- a/win32/Demos/GetSaveFileName.py +++ b/win32/Demos/GetSaveFileName.py @@ -20,7 +20,7 @@ print("save file names:", repr(fname)) print("filter used:", repr(customfilter)) print("Flags:", flags) -for k, v in list(win32con.__dict__.items()): +for k, v in win32con.__dict__.items(): if k.startswith("OFN_") and flags & v: print("\t" + k) @@ -38,6 +38,6 @@ print("open file names:", repr(fname)) print("filter used:", repr(customfilter)) print("Flags:", flags) -for k, v in list(win32con.__dict__.items()): +for k, v in win32con.__dict__.items(): if k.startswith("OFN_") and flags & v: print("\t" + k) diff --git a/win32/Demos/rastest.py b/win32/Demos/rastest.py index 9b23747872..4b6d1b289a 100644 --- a/win32/Demos/rastest.py +++ b/win32/Demos/rastest.py @@ -4,18 +4,16 @@ import os import sys +import win32event import win32ras # Build a little dictionary of RAS states to decent strings. # eg win32ras.RASCS_OpenPort -> "OpenPort" -stateMap = {} -for name, val in list(win32ras.__dict__.items()): - if name[:6] == "RASCS_": - stateMap[val] = name[6:] +stateMap = { + val: name[6:] for name, val in win32ras.__dict__.items() if name[:6] == "RASCS_" +} # Use a lock so the callback can tell the main thread when it is finished. -import win32event - callbackEvent = win32event.CreateEvent(None, 0, 0, None) diff --git a/win32/Demos/security/sspi/fetch_url.py b/win32/Demos/security/sspi/fetch_url.py index d6addf9eef..cd9995487c 100644 --- a/win32/Demos/security/sspi/fetch_url.py +++ b/win32/Demos/security/sspi/fetch_url.py @@ -36,7 +36,7 @@ def open_url(host, url): print("After redirect response is", resp.status, resp.reason) if options.show_headers: print("Initial response headers:") - for name, val in list(resp.msg.items()): + for name, val in resp.msg.items(): print(f" {name}: {val}") if options.show_body: print(body) @@ -60,7 +60,7 @@ def open_url(host, url): resp = h.getresponse() if options.show_headers: print("Token dance headers:") - for name, val in list(resp.msg.items()): + for name, val in resp.msg.items(): print(f" {name}: {val}") if err == 0: @@ -107,7 +107,7 @@ def open_url(host, url): print("Second fetch response is", resp.status, resp.reason) if options.show_headers: print("Second response headers:") - for name, val in list(resp.msg.items()): + for name, val in resp.msg.items(): print(f" {name}: {val}") resp.read(int(resp.msg.get("content-length", 0))) diff --git a/win32/Demos/security/sspi/simple_auth.py b/win32/Demos/security/sspi/simple_auth.py index 2721ca780d..552e9dc59c 100644 --- a/win32/Demos/security/sspi/simple_auth.py +++ b/win32/Demos/security/sspi/simple_auth.py @@ -9,7 +9,7 @@ def lookup_ret_code(err): - for k, v in list(sspicon.__dict__.items()): + for k, v in sspicon.__dict__.items(): if k[0:6] in ("SEC_I_", "SEC_E_") and v == err: return k diff --git a/win32/Demos/win32clipboardDemo.py b/win32/Demos/win32clipboardDemo.py index 094c0c8520..564233f68b 100644 --- a/win32/Demos/win32clipboardDemo.py +++ b/win32/Demos/win32clipboardDemo.py @@ -8,11 +8,12 @@ print("WARNING: The test code in this module uses assert") print("This instance of Python has asserts disabled, so many tests will be skipped") -cf_names = {} # Build map of CF_* constants to names. -for name, val in list(win32con.__dict__.items()): - if name[:3] == "CF_" and name != "CF_SCREENFONTS": # CF_SCREEN_FONTS==CF_TEXT!?!? - cf_names[val] = name +cf_names = { + val: name + for name, val in win32con.__dict__.items() + if name[:3] == "CF_" and name != "CF_SCREENFONTS" # CF_SCREEN_FONTS==CF_TEXT!?!? +} def TestEmptyClipboard(): diff --git a/win32/Demos/win32console_demo.py b/win32/Demos/win32console_demo.py index bb9162bff5..7153e54c0f 100644 --- a/win32/Demos/win32console_demo.py +++ b/win32/Demos/win32console_demo.py @@ -3,10 +3,7 @@ import win32con import win32console -virtual_keys = {} -for k, v in list(win32con.__dict__.items()): - if k.startswith("VK_"): - virtual_keys[v] = k +virtual_keys = {k: v for k, v in win32con.__dict__.items() if k.startswith("VK_")} free_console = True try: diff --git a/win32/Demos/win32netdemo.py b/win32/Demos/win32netdemo.py index ac5f305db5..6c0a557762 100644 --- a/win32/Demos/win32netdemo.py +++ b/win32/Demos/win32netdemo.py @@ -184,7 +184,7 @@ def GetInfo(userName=None): userName = win32api.GetUserName() print("Dumping level 3 information about user") info = win32net.NetUserGetInfo(server, userName, 3) - for key, val in list(info.items()): + for key, val in info.items(): verbose(f"{key}={val}") @@ -228,10 +228,7 @@ def usage(tests): def main(): - tests = [] - for ob in list(globals().values()): - if isinstance(ob, Callable) and ob.__doc__: - tests.append(ob) + tests = [ob for ob in globals().values() if isinstance(ob, Callable) and ob.__doc__] opts, args = getopt.getopt(sys.argv[1:], "s:hvc") create_user = False for opt, val in opts: diff --git a/win32/Lib/win32timezone.py b/win32/Lib/win32timezone.py index d5605a511b..07b30284fe 100644 --- a/win32/Lib/win32timezone.py +++ b/win32/Lib/win32timezone.py @@ -575,12 +575,14 @@ def _LoadDynamicInfoFromKey(self, key): return del info["FirstEntry"] del info["LastEntry"] - years = map(int, list(info.keys())) - values = map(TimeZoneDefinition, list(info.values())) + + infos = [ + (int(year), TimeZoneDefinition(values)) for year, values in info.items() + ] # create a range mapping that searches by descending year and matches # if the target year is greater or equal. self.dynamicInfo = RangeMap( - zip(years, values), + infos, sort_params={"reverse": True}, key_match_comparator=operator.ge, ) @@ -971,7 +973,7 @@ def __init__(self, source, sort_params={}, key_match_comparator=operator.le): self.match = key_match_comparator def __getitem__(self, item): - sorted_keys = sorted(self.keys(), **self.sort_params) + sorted_keys = sorted(self, **self.sort_params) if isinstance(item, RangeMap.Item): result = self.__getitem__(sorted_keys[item]) else: @@ -1002,7 +1004,7 @@ def is_match(k): raise KeyError(item) def bounds(self): - sorted_keys = sorted(self.keys(), **self.sort_params) + sorted_keys = sorted(self, **self.sort_params) return ( sorted_keys[RangeMap.first_item], sorted_keys[RangeMap.last_item], diff --git a/win32/Lib/win32verstamp.py b/win32/Lib/win32verstamp.py index e9f8c5e45d..a27bcf97ab 100644 --- a/win32/Lib/win32verstamp.py +++ b/win32/Lib/win32verstamp.py @@ -165,7 +165,7 @@ def stamp(pathname, options): if is_debug is None: is_debug = os.path.splitext(pathname)[0].lower().endswith("_d") # convert None to blank strings - for k, v in list(sdata.items()): + for k, v in sdata.items(): if v is None: sdata[k] = "" vs = VS_VERSION_INFO(vmaj, vmin, vsub, vbuild, sdata, vdata, is_debug, is_dll) diff --git a/win32/test/test_win32api.py b/win32/test/test_win32api.py index 5218d519ec..446315f54f 100644 --- a/win32/test/test_win32api.py +++ b/win32/test/test_win32api.py @@ -262,7 +262,7 @@ def testGetSystemPowerStatus(self): "BatteryLifeTime", "BatteryFullLifeTime", ) - self.assertEqual(set(test_keys), set(sps.keys())) + self.assertEqual(set(test_keys), set(sps)) if __name__ == "__main__": diff --git a/win32/test/test_win32guistruct.py b/win32/test/test_win32guistruct.py index 2cea9d5fbc..d09772c8c4 100644 --- a/win32/test/test_win32guistruct.py +++ b/win32/test/test_win32guistruct.py @@ -13,10 +13,8 @@ def assertDictEquals(self, d, **kw): for n, v in kw.items(): self.assertEqual(v, d[n], f"'{n}' doesn't match: {v!r} != {d[n]!r}") checked[n] = True - checked_keys = list(checked.keys()) - passed_keys = list(kw.keys()) - checked_keys.sort() - passed_keys.sort() + checked_keys = sorted(checked) + passed_keys = sorted(kw) self.assertEqual(checked_keys, passed_keys) From d6c7aef241acbcfef9b8c56d415bbcea056e7478 Mon Sep 17 00:00:00 2001 From: Avasam Date: Fri, 26 Jul 2024 19:55:28 -0400 Subject: [PATCH 2/7] Split adodbapi changes --- adodbapi/adodbapi.py | 4 +++- adodbapi/apibase.py | 2 +- adodbapi/process_connect_string.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/adodbapi/adodbapi.py b/adodbapi/adodbapi.py index 949fcfe542..4e85bc525b 100644 --- a/adodbapi/adodbapi.py +++ b/adodbapi/adodbapi.py @@ -326,7 +326,9 @@ def close(self): an Error (or subclass) exception will be raised if any operation is attempted with the connection. The same applies to all cursor objects trying to use the connection. """ - for crsr in self.cursors.values(): + for crsr in list(self.cursors.values())[ + : + ]: # copy the list, then close each one crsr.close(dont_tell_me=True) # close without back-link clearing self.messages = [] try: diff --git a/adodbapi/apibase.py b/adodbapi/apibase.py index b7d1f3ae36..749c378d38 100644 --- a/adodbapi/apibase.py +++ b/adodbapi/apibase.py @@ -564,7 +564,7 @@ def __next__(self): yield self._getValue(n) def __repr__(self): # create a human readable representation - taglist = sorted(self.rows.columnNames.items(), key=lambda x: x[1]) + taglist = sorted(list(self.rows.columnNames.items()), key=lambda x: x[1]) s = " Date: Fri, 26 Jul 2024 20:03:09 -0400 Subject: [PATCH 3/7] Add changes --- CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 0e11d06435..24e66a5ecf 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -155,7 +155,7 @@ Coming in build 307, as yet unreleased * Cleaned up unused imports (#1986, #2051, #1990, #2124, #2126, @Avasam) * Removed duplicated declarations, constants and definitions (#2050 , #1950, #1990, @Avasam) * Small generalized optimization by using augmented assignements (in-place operators) where possible (#2274, @Avasam) -* General speed and size improvements due to all the removed code. (#2046, #1986, #2050, #1950, #2085, #2087, #2051, #1990, #2106, #2127, #2124, #2126, #2177, #2218, #2202, #2205, #2217) +* General speed and size improvements due to all the removed code. (#2046, #1986, #2050, #1950, #2085, #2087, #2051, #1990, #2106, #2127, #2124, #2126, #2177, #2218, #2202, #2205, #2217, #2332) ### adodbapi * Remove references to outdated IronPython (#2049, @Avasam) From 3c117ae8e17755bdf21bab460b37bec16fc5af8e Mon Sep 17 00:00:00 2001 From: Avasam Date: Fri, 26 Jul 2024 20:18:49 -0400 Subject: [PATCH 4/7] Run black --- com/win32com/makegw/makegwparse.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/com/win32com/makegw/makegwparse.py b/com/win32com/makegw/makegwparse.py index cfe03d2352..89a574608e 100644 --- a/com/win32com/makegw/makegwparse.py +++ b/com/win32com/makegw/makegwparse.py @@ -772,9 +772,10 @@ def _GetPythonTypeDesc(self): "PCUITEMID_CHILD_ARRAY": (ArgFormatterIDLIST, 2), "const PCUITEMID_CHILD_ARRAY": (ArgFormatterIDLIST, 2), # Auto-add all the simple types - **{key:(ArgFormatterSimple, 0) for key in ConvertSimpleTypes} + **{key: (ArgFormatterSimple, 0) for key in ConvertSimpleTypes}, } + def make_arg_converter(arg): try: clz = AllConverters[arg.type][0] From 1b96a7995cc3ccf8818f2f85d4704b64c0e936fb Mon Sep 17 00:00:00 2001 From: Avasam Date: Sat, 27 Jul 2024 04:16:14 -0400 Subject: [PATCH 5/7] dict changed size during iteration --- com/win32com/client/build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com/win32com/client/build.py b/com/win32com/client/build.py index bd3725d6c2..4f0730e285 100644 --- a/com/win32com/client/build.py +++ b/com/win32com/client/build.py @@ -315,10 +315,10 @@ def Build(self, typeinfo, attr, bForUser=1): # Now post-process the maps. For any "Get" or "Set" properties # that have arguments, we must turn them into methods. If a method # of the same name already exists, change the name. - for key, item in self.propMapGet.items(): + for key, item in list(self.propMapGet.items()): self._propMapGetCheck_(key, item) - for key, item in self.propMapPut.items(): + for key, item in list(self.propMapPut.items()): self._propMapPutCheck_(key, item) def CountInOutOptArgs(self, argTuple): From 4cd4b301e310036f2e27de51d9874d958fa84ec4 Mon Sep 17 00:00:00 2001 From: Avasam Date: Sun, 13 Oct 2024 13:01:18 -0400 Subject: [PATCH 6/7] Update CHANGES.txt --- CHANGES.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 5c1acc536c..20151184ac 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -14,6 +14,7 @@ https://mhammond.github.io/pywin32_installers.html. Coming in build 309, as yet unreleased -------------------------------------- +* Improved handling of dict iterations (small general speed improvement) (#2332, @Avasam) * Fixed "Open GL Demo" (`Pythonwin/pywin/Demos/openGLDemo.py`) and restore "Font" demo in `Pythonwin/pywin/Demos/guidemo.py` (#2345, @Avasam) Build 308, released 2024-10-12 @@ -178,7 +179,7 @@ as the .chm file, certain MAPI libraries etc, and .exe installers. * Cleaned up unused imports (#1986, #2051, #1990, #2124, #2126, @Avasam) * Removed duplicated declarations, constants and definitions (#2050 , #1950, #1990, @Avasam) * Small generalized optimization by using augmented assignements (in-place operators) where possible (#2274, @Avasam) -* General speed and size improvements due to all the removed code. (#2046, #1986, #2050, #1950, #2085, #2087, #2051, #1990, #2106, #2127, #2124, #2126, #2177, #2218, #2202, #2205, #2217, #2332) +* General speed and size improvements due to all the removed code. (#2046, #1986, #2050, #1950, #2085, #2087, #2051, #1990, #2106, #2127, #2124, #2126, #2177, #2218, #2202, #2205, #2217) ### adodbapi * Remove references to outdated IronPython (#2049, @Avasam) From c29b6dcdbed26bbd71ee167ca6587ea06cee6ce8 Mon Sep 17 00:00:00 2001 From: Avasam Date: Sun, 13 Oct 2024 13:03:12 -0400 Subject: [PATCH 7/7] mention Python 2 --- CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 20151184ac..08f9634512 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -14,7 +14,7 @@ https://mhammond.github.io/pywin32_installers.html. Coming in build 309, as yet unreleased -------------------------------------- -* Improved handling of dict iterations (small general speed improvement) (#2332, @Avasam) +* Improved handling of dict iterations (removes Python 2 support code, small general speed improvement) (#2332, @Avasam) * Fixed "Open GL Demo" (`Pythonwin/pywin/Demos/openGLDemo.py`) and restore "Font" demo in `Pythonwin/pywin/Demos/guidemo.py` (#2345, @Avasam) Build 308, released 2024-10-12