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)