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/CHANGES.txt b/CHANGES.txt index e41e71084a..08f9634512 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 (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 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/com/win32com/client/__init__.py b/com/win32com/client/__init__.py index c0b1a87610..055b7c9cf5 100644 --- a/com/win32com/client/__init__.py +++ b/com/win32com/client/__init__.py @@ -7,6 +7,7 @@ # with dynamic.Dispatch behaviour, where dynamic objects are always used. import sys +from itertools import chain import pythoncom import pywintypes @@ -510,17 +511,18 @@ def __init__(self, oobj=None): self.__dict__["_oleobj_"] = oobj # so we don't call __setattr__ def __dir__(self): - lst = ( - list(self.__dict__.keys()) - + dir(self.__class__) - + list(self._prop_map_get_.keys()) - + list(self._prop_map_put_.keys()) + attributes = chain( + self.__dict__, + dir(self.__class__), + self._prop_map_get_, + self._prop_map_put_, ) + try: - lst += [p.Name for p in self.Properties_] + attributes = chain(attributes, [p.Name for p in self.Properties_]) except AttributeError: pass - return list(set(lst)) + return list(set(attributes)) # Provide a prettier name than the CLSID def __repr__(self): diff --git a/com/win32com/client/build.py b/com/win32com/client/build.py index b75f218218..4f0730e285 100644 --- a/com/win32com/client/build.py +++ b/com/win32com/client/build.py @@ -18,6 +18,7 @@ import datetime import string +from itertools import chain from keyword import iskeyword import pythoncom @@ -493,18 +494,20 @@ def Build(self, typeinfo, attr, bForUser=1): DispatchItem.Build(self, typeinfo, attr, bForUser) assert typeinfo is not None, "Can't build vtables without type info!" - meth_list = ( - list(self.mapFuncs.values()) - + list(self.propMapGet.values()) - + list(self.propMapPut.values()) + meth_list = sorted( + chain( + self.mapFuncs.values(), + self.propMapGet.values(), + self.propMapPut.values(), + ), + key=lambda m: m.desc[7], ) - meth_list.sort(key=lambda m: m.desc[7]) # Now turn this list into the run-time representation # (ready for immediate use or writing to gencache) - self.vtableFuncs = [] - for entry in meth_list: - self.vtableFuncs.append((entry.names, entry.dispid, entry.desc)) + self.vtableFuncs = [ + (entry.names, entry.dispid, entry.desc) for entry in meth_list + ] # A Lazy dispatch item - builds an item on request using info from diff --git a/com/win32com/client/dynamic.py b/com/win32com/client/dynamic.py index ffe7e9e26b..7a269d514e 100644 --- a/com/win32com/client/dynamic.py +++ b/com/win32com/client/dynamic.py @@ -17,6 +17,7 @@ """ import traceback +from itertools import chain from types import MethodType import pythoncom # Needed as code we eval() references it. @@ -233,19 +234,19 @@ def __str__(self): return self.__repr__() def __dir__(self): - lst = list(self.__dict__.keys()) + dir(self.__class__) + self._dir_ole_() + attributes = chain(self.__dict__, dir(self.__class__), self._dir_ole_()) try: - lst += [p.Name for p in self.Properties_] + attributes = chain(attributes, [p.Name for p in self.Properties_]) except AttributeError: pass - return list(set(lst)) + return list(set(attributes)) def _dir_ole_(self): items_dict = {} for iTI in range(0, self._oleobj_.GetTypeInfoCount()): typeInfo = self._oleobj_.GetTypeInfo(iTI) self._UpdateWithITypeInfo_(items_dict, typeInfo) - return list(items_dict.keys()) + return list(items_dict) def _UpdateWithITypeInfo_(self, items_dict, typeInfo): typeInfos = [typeInfo] @@ -455,7 +456,7 @@ def _print_details_(self): print("AxDispatch container", self._username_) try: print("Methods:") - for method in self._olerepr_.mapFuncs.keys(): + for method in self._olerepr_.mapFuncs: print("\t", method) print("Props:") for prop, entry in self._olerepr_.propMap.items(): diff --git a/com/win32com/client/gencache.py b/com/win32com/client/gencache.py index 3854785615..e64449b8bc 100644 --- a/com/win32com/client/gencache.py +++ b/com/win32com/client/gencache.py @@ -420,7 +420,7 @@ def ForgetAboutTypelibInterface(typelib_ob): ) ) # and drop any version redirects to it - for key, val in list(versionRedirectMap.items()): + for key, val in versionRedirectMap.items(): if val == info: del versionRedirectMap[key] @@ -660,7 +660,7 @@ def AddModuleToCache( def SetTypelibForAllClsids(dict): nonlocal dict_modified - for clsid, cls in dict.items(): + for clsid in dict: if clsidToTypelib.get(clsid) != info: clsidToTypelib[clsid] = info dict_modified = True @@ -685,7 +685,7 @@ def GetGeneratedInfos(): zip_file = win32com.__gen_path__[: zip_pos + 4] zip_path = win32com.__gen_path__[zip_pos + 5 :].replace("\\", "/") zf = zipfile.ZipFile(zip_file) - infos = {} + infos = set() for n in zf.namelist(): if not n.startswith(zip_path): continue @@ -701,9 +701,9 @@ def GetGeneratedInfos(): except pywintypes.com_error: # invalid IID continue - infos[(iid, lcid, major, minor)] = 1 + infos.add((iid, lcid, major, minor)) zf.close() - return list(infos.keys()) + return list(infos) else: # on the file system files = glob.glob(win32com.__gen_path__ + "\\*") @@ -760,10 +760,8 @@ def Rebuild(verbose=1): def _Dump(): print("Cache is in directory", win32com.__gen_path__) # Build a unique dir - d = {} - for clsid, (typelibCLSID, lcid, major, minor) in clsidToTypelib.items(): - d[typelibCLSID, lcid, major, minor] = None - for typelibCLSID, lcid, major, minor in d.keys(): + d = set(clsidToTypelib.values()) + for typelibCLSID, lcid, major, minor in d: mod = GetModuleForTypelib(typelibCLSID, lcid, major, minor) print(f"{mod.__doc__} - {typelibCLSID}") diff --git a/com/win32com/client/genpy.py b/com/win32com/client/genpy.py index 6c3e7dc7f1..b11d3b85bc 100644 --- a/com/win32com/client/genpy.py +++ b/com/win32com/client/genpy.py @@ -16,6 +16,7 @@ import os import sys import time +from itertools import chain import pythoncom import win32com @@ -90,14 +91,14 @@ def MakeEventMethodName(eventName): def WriteSinkEventMap(obj, stream): print("\t_dispid_to_func_ = {", file=stream) - for name, entry in ( - list(obj.propMapGet.items()) - + list(obj.propMapPut.items()) - + list(obj.mapFuncs.items()) + for entry in chain( + obj.propMapGet.values(), + obj.propMapPut.values(), + obj.mapFuncs.values(), ): - fdesc = entry.desc + memid = entry.desc.memid print( - '\t\t%9d : "%s",' % (fdesc.memid, MakeEventMethodName(entry.names[0])), + '\t\t%9d : "%s",' % (memid, MakeEventMethodName(entry.names[0])), file=stream, ) print("\t\t}", file=stream) @@ -215,9 +216,7 @@ def WriteEnumerationItems(self, stream): num = 0 enumName = self.doc[0] # Write in name alpha order - names = list(self.mapVars.keys()) - names.sort() - for name in names: + for name in sorted(self.mapVars): entry = self.mapVars[name] vdesc = entry.desc if vdesc[4] == pythoncom.VAR_CONST: @@ -419,10 +418,8 @@ def WriteCallbackClassBody(self, generator): "\t# If you create handlers, they should have the following prototypes:", file=stream, ) - for name, entry in ( - list(self.propMapGet.items()) - + list(self.propMapPut.items()) - + list(self.mapFuncs.items()) + for entry in chain( + self.propMapGet.values(), self.propMapPut.values(), self.mapFuncs.values() ): fdesc = entry.desc methName = MakeEventMethodName(entry.names[0]) @@ -449,17 +446,14 @@ def WriteCallbackClassBody(self, generator): def WriteClassBody(self, generator): stream = generator.file - # Write in alpha order. - names = list(self.mapFuncs.keys()) - names.sort() specialItems = { "count": None, "item": None, "value": None, "_newenum": None, } # If found, will end up with (entry, invoke_tupe) - itemCount = None - for name in names: + # Write in alpha order. + for name in sorted(self.mapFuncs): entry = self.mapFuncs[name] assert entry.desc.desckind == pythoncom.DESCKIND_FUNCDESC # skip [restricted] methods, unless it is the @@ -498,9 +492,7 @@ def WriteClassBody(self, generator): for line in ret: print(line, file=stream) print("\t_prop_map_get_ = {", file=stream) - names = list(self.propMap.keys()) - names.sort() - for key in names: + for key in sorted(self.propMap): entry = self.propMap[key] if generator.bBuildHidden or not entry.hidden: resultName = entry.GetResultName() @@ -545,9 +537,7 @@ def WriteClassBody(self, generator): f'\t\t"{build.MakePublicAttributeName(key)}": {mapEntry},', file=stream, ) - names = list(self.propMapGet.keys()) - names.sort() - for key in names: + for key in sorted(self.propMapGet): entry = self.propMapGet[key] if generator.bBuildHidden or not entry.hidden: if entry.GetResultName(): @@ -597,9 +587,7 @@ def WriteClassBody(self, generator): print("\t_prop_map_put_ = {", file=stream) # These are "Invoke" args - names = list(self.propMap.keys()) - names.sort() - for key in names: + for key in sorted(self.propMap): entry = self.propMap[key] if generator.bBuildHidden or not entry.hidden: lkey = key.lower() @@ -621,9 +609,7 @@ def WriteClassBody(self, generator): file=stream, ) - names = list(self.propMapPut.keys()) - names.sort() - for key in names: + for key in sorted(self.propMapPut): entry = self.propMapPut[key] if generator.bBuildHidden or not entry.hidden: details = entry.desc @@ -1160,10 +1146,8 @@ def do_generate(self): # Generate the constants and their support. if enumItems: print("class constants:", file=stream) - items = list(enumItems.values()) - items.sort() num_written = 0 - for oleitem in items: + for oleitem in sorted(enumItems.values()): num_written += oleitem.WriteEnumerationItems(stream) self.progress.Tick() if not num_written: @@ -1171,15 +1155,11 @@ def do_generate(self): print(file=stream) if self.generate_type == GEN_FULL: - items = [l for l in oleItems.values() if l is not None] - items.sort() - for oleitem in items: + for oleitem in sorted(filter(None, oleItems.values())): self.progress.Tick() oleitem.WriteClass(self) - items = list(vtableItems.values()) - items.sort() - for oleitem in items: + for oleitem in sorted(vtableItems.values()): self.progress.Tick() oleitem.WriteClass(self) else: diff --git a/com/win32com/demos/dump_clipboard.py b/com/win32com/demos/dump_clipboard.py index 534d540a02..4b7d51e969 100644 --- a/com/win32com/demos/dump_clipboard.py +++ b/com/win32com/demos/dump_clipboard.py @@ -11,7 +11,7 @@ val = getattr(win32con, f) format_name_map[val] = f -tymeds = [attr for attr in pythoncom.__dict__.keys() if attr.startswith("TYMED_")] +tymeds = [attr for attr in pythoncom.__dict__ if attr.startswith("TYMED_")] def DumpClipboard(): diff --git a/com/win32com/makegw/makegwparse.py b/com/win32com/makegw/makegwparse.py index 1a2a63c707..89a574608e 100644 --- a/com/win32com/makegw/makegwparse.py +++ b/com/win32com/makegw/makegwparse.py @@ -771,12 +771,10 @@ def _GetPythonTypeDesc(self): "const PUITEMID_CHILD": (ArgFormatterIDLIST, 0), "PCUITEMID_CHILD_ARRAY": (ArgFormatterIDLIST, 2), "const PCUITEMID_CHILD_ARRAY": (ArgFormatterIDLIST, 2), + # Auto-add all the simple types + **{key: (ArgFormatterSimple, 0) for key in ConvertSimpleTypes}, } -# Auto-add all the simple types -for key in ConvertSimpleTypes.keys(): - AllConverters[key] = ArgFormatterSimple, 0 - def make_arg_converter(arg): try: diff --git a/com/win32com/server/policy.py b/com/win32com/server/policy.py index fde608d13b..a907bd620a 100644 --- a/com/win32com/server/policy.py +++ b/com/win32com/server/policy.py @@ -385,10 +385,8 @@ def _GetNextDispID_(self, fdex, dispid): return self._getnextdispid_(fdex, dispid) def _getnextdispid_(self, fdex, dispid): - ids = list(self._name_to_dispid_.values()) + ids = [id for id in self._name_to_dispid_.values() if id != DISPID_STARTENUM] ids.sort() - if DISPID_STARTENUM in ids: - ids.remove(DISPID_STARTENUM) if dispid == DISPID_STARTENUM: return ids[0] else: diff --git a/com/win32com/servers/dictionary.py b/com/win32com/servers/dictionary.py index 12cd3be5b1..f8a7eb249e 100644 --- a/com/win32com/servers/dictionary.py +++ b/com/win32com/servers/dictionary.py @@ -110,7 +110,7 @@ def _invokeex_(self, dispid, lcid, wFlags, args, kwargs, serviceProvider): return len(self._obj_) if dispid == pythoncom.DISPID_NEWENUM: - return util.NewEnum(list(self._obj_.keys())) + return util.NewEnum(list(self._obj_)) raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND) diff --git a/com/win32com/test/testDictionary.py b/com/win32com/test/testDictionary.py index 3e66913322..020efb6068 100644 --- a/com/win32com/test/testDictionary.py +++ b/com/win32com/test/testDictionary.py @@ -17,7 +17,7 @@ def MakeTestDictionary(): def TestDictAgainst(dict, check): - for key, value in list(check.items()): + for key, value in check.items(): assert ( dict(key) == value ), f"Indexing for '{key!r}' gave the incorrect value - {dict[key]!r}/{check[key]!r}" diff --git a/com/win32com/test/testIterators.py b/com/win32com/test/testIterators.py index 260cce673c..2b2248edfd 100644 --- a/com/win32com/test/testIterators.py +++ b/com/win32com/test/testIterators.py @@ -126,7 +126,7 @@ def tearDown(self): def suite(): # We don't want our base class run suite = unittest.TestSuite() - for item in list(globals().values()): + for item in globals().values(): if ( isinstance(item, type) and issubclass(item, unittest.TestCase) diff --git a/com/win32com/test/testmakepy.py b/com/win32com/test/testmakepy.py index 633758649e..eafe99555e 100644 --- a/com/win32com/test/testmakepy.py +++ b/com/win32com/test/testmakepy.py @@ -40,7 +40,7 @@ def TestBuildAll(verbose=1): # interface manually tinfo = (info.clsid, info.lcid, info.major, info.minor) mod = gencache.EnsureModule(info.clsid, info.lcid, info.major, info.minor) - for name in mod.NamesToIIDMap.keys(): + for name in mod.NamesToIIDMap: makepy.GenerateChildFromTypeLibSpec(name, tinfo) return num diff --git a/com/win32com/universal.py b/com/win32com/universal.py index 1063680d21..c79d7d80a1 100644 --- a/com/win32com/universal.py +++ b/com/win32com/universal.py @@ -58,9 +58,7 @@ def RegisterInterfaces(typelibGUID, lcid, major, minor, interface_names=None): ret.append((dispid, invkind, names[0])) else: # Cool - can used cached info. - if not interface_names: - interface_names = list(mod.VTablesToClassMap.values()) - for name in interface_names: + for name in interface_names or mod.VTablesToClassMap.values(): try: iid = mod.NamesToIIDMap[name] except KeyError: diff --git a/com/win32comext/axdebug/debugger.py b/com/win32comext/axdebug/debugger.py index c0b1089f10..d0585b9b6f 100644 --- a/com/win32comext/axdebug/debugger.py +++ b/com/win32comext/axdebug/debugger.py @@ -64,7 +64,7 @@ def BuildModule(module, built_nodes, rootNode, create_node_fn, create_node_args) def RefreshAllModules(builtItems, rootNode, create_node, create_node_args): - for module in list(sys.modules.values()): + for module in sys.modules.values(): BuildModule(module, builtItems, rootNode, create_node, create_node_args) @@ -85,7 +85,7 @@ def FromFileName(self, fname): # if self.currentNumModules != len(sys.modules): # self.axdebugger.RefreshAllModules(self.nodes, self) # self.currentNumModules = len(sys.modules) - # for key in self.ccsAndNodes.keys(): + # for key in self.ccsAndNodes: # print("File:", key) return documents.CodeContainerProvider.FromFileName(self, fname) diff --git a/com/win32comext/axdebug/expressions.py b/com/win32comext/axdebug/expressions.py index d741e45a44..401b9a5996 100644 --- a/com/win32comext/axdebug/expressions.py +++ b/com/win32comext/axdebug/expressions.py @@ -90,10 +90,10 @@ def GetResultAsDebugProperty(self): def MakeEnumDebugProperty(object, dwFieldSpec, nRadix, iid, stackFrame=None): name_vals = [] if hasattr(object, "items") and hasattr(object, "keys"): # If it is a dict. - name_vals = iter(object.items()) + name_vals = object.items() dictionary = object elif hasattr(object, "__dict__"): # object with dictionary, module - name_vals = iter(object.__dict__.items()) + name_vals = object.__dict__.items() dictionary = object.__dict__ infos = [] for name, val in name_vals: diff --git a/com/win32comext/axscript/client/framework.py b/com/win32comext/axscript/client/framework.py index eada9097c7..b9f0fd6055 100644 --- a/com/win32comext/axscript/client/framework.py +++ b/com/win32comext/axscript/client/framework.py @@ -987,7 +987,7 @@ def ResetNamedItems(self): # Due to the way we work, we re-create persistent ones. existing = self.subItems self.subItems = {} - for name, item in existing.items(): + for item in existing.values(): item.Close() if item.flags & axscript.SCRIPTITEM_ISPERSISTENT: self.AddNamedItem(item.name, item.flags) diff --git a/com/win32comext/axscript/client/pyscript.py b/com/win32comext/axscript/client/pyscript.py index 5bf46eb801..6b9ee53ab5 100644 --- a/com/win32comext/axscript/client/pyscript.py +++ b/com/win32comext/axscript/client/pyscript.py @@ -359,7 +359,7 @@ def DoProcessScriptItemEvent(self, item, event, lcid, wFlags, args): except KeyError: # Not there _exactly_ - do case ins search. funcNameLook = funcName.lower() - for attr in self.globalNameSpaceModule.__dict__.keys(): + for attr in self.globalNameSpaceModule.__dict__: if funcNameLook == attr.lower(): function = self.globalNameSpaceModule.__dict__[attr] # cache back in scriptlets, to avoid this overhead next time diff --git a/com/win32comext/axscript/server/axsite.py b/com/win32comext/axscript/server/axsite.py index f907789397..359ea5e0f1 100644 --- a/com/win32comext/axscript/server/axsite.py +++ b/com/win32comext/axscript/server/axsite.py @@ -99,7 +99,7 @@ def AddEngine(self, engine): | axscript.SCRIPTITEM_GLOBALMEMBERS | axscript.SCRIPTITEM_ISPERSISTENT ) - for name in self.objModel.keys(): + for name in self.objModel: newEngine.AddNamedItem(name, flags) newEngine.SetScriptState(axscript.SCRIPTSTATE_INITIALIZED) return newEngine diff --git a/com/win32comext/shell/demos/IFileOperationProgressSink.py b/com/win32comext/shell/demos/IFileOperationProgressSink.py index 9c73f544aa..e7665d0419 100644 --- a/com/win32comext/shell/demos/IFileOperationProgressSink.py +++ b/com/win32comext/shell/demos/IFileOperationProgressSink.py @@ -5,7 +5,7 @@ from win32com.server.policy import DesignatedWrapPolicy from win32com.shell import shell, shellcon -tsf_flags = [(k, v) for k, v in list(shellcon.__dict__.items()) if k.startswith("TSF_")] +tsf_flags = [(k, v) for k, v in shellcon.__dict__.items() if k.startswith("TSF_")] def decode_flags(flags): diff --git a/com/win32comext/shell/demos/ITransferAdviseSink.py b/com/win32comext/shell/demos/ITransferAdviseSink.py index a0a696e2f1..8aed09e7c3 100644 --- a/com/win32comext/shell/demos/ITransferAdviseSink.py +++ b/com/win32comext/shell/demos/ITransferAdviseSink.py @@ -4,12 +4,14 @@ from win32com.server.policy import DesignatedWrapPolicy from win32com.shell import shell, shellcon -tsf_flags = [(k, v) for k, v in list(shellcon.__dict__.items()) if k.startswith("TSF_")] - +tsf_flags = [] TRANSFER_ADVISE_STATES = {} -for k, v in list(shellcon.__dict__.items()): + +for k, v in shellcon.__dict__.items(): if k.startswith("TS_"): TRANSFER_ADVISE_STATES[v] = k + elif k.startswith("TSF_"): + tsf_flags.append((k, v)) def decode_flags(flags): diff --git a/com/win32comext/shell/demos/servers/shell_view.py b/com/win32comext/shell/demos/servers/shell_view.py index abd56bd579..cac0e19adc 100644 --- a/com/win32comext/shell/demos/servers/shell_view.py +++ b/com/win32comext/shell/demos/servers/shell_view.py @@ -260,7 +260,7 @@ def __init__(self, path): def EnumObjects(self, hwndOwner, flags): objects = get_clbr_for_file(self.path) pidls = [] - for name, ob in objects.items(): + for name in objects: pidls.append(["object\0" + self.path + "\0" + name]) return NewEnum(pidls, iid=shell.IID_IEnumIDList, useDispatcher=(debug > 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 7b211303db..9bb321c191 100644 --- a/win32/Lib/win32verstamp.py +++ b/win32/Lib/win32verstamp.py @@ -168,7 +168,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)