diff --git a/AutoDuck/Dump2HHC.py b/AutoDuck/Dump2HHC.py index 32c728c9db..7213a5f36b 100644 --- a/AutoDuck/Dump2HHC.py +++ b/AutoDuck/Dump2HHC.py @@ -48,7 +48,7 @@ def __str__(self): {"context": self.context, "name": self.name, "contains": self.contains} ) - def __repr__(self): + def __repr__(self) -> str: if len(self.contains) > 0: return repr( {"context": self.context, "name": self.name, "contains": self.contains} diff --git a/CHANGES.txt b/CHANGES.txt index 8955b85a63..5cc48ffd49 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -14,6 +14,21 @@ https://mhammond.github.io/pywin32_installers.html . Coming in build 311, as yet unreleased -------------------------------------- * Fixed a regression that broke special __dunder__ methods with CoClass. (#1870, #2493, @Avasam, @geppi) +* Added missing quotes and closing parenthesis to `win32com.client.build.MapEntry`'s `repr` (#2555, @Avasam) +* The following classes will now use the correct subclass name in `repr`: (#2555, @Avasam) + * `win32rcparser.StringDef` + * `win32pdhquery.QueryError` + * `pywin.tools.browser.HLIPythonObject` + * `win32comext.axscript.client.pyscript.NamedScriptAttribute` + * `win32comext.axscript.client.error.AXScriptException` + * `win32comext.axdebug.debugger.ModuleTreeNode` + * `win32com.server.exception.COMException` + * `win32com.client.VARIANT` +* The following classes now produce a valid `eval` string representation when calling `repr`: (#2555, @Avasam) + * `pywin.tools.browser.HLIPythonObject` + * `win32comext.axscript.client.pyscript.NamedScriptAttribute` + * `win32comext.axscript.client.error.AXScriptException` + * `win32com.server.exception.COMException` Build 310, released 2025/03/16 ------------------------------ diff --git a/Pythonwin/pywin/tools/browser.py b/Pythonwin/pywin/tools/browser.py index 8346d7d019..4d78a3913e 100644 --- a/Pythonwin/pywin/tools/browser.py +++ b/Pythonwin/pywin/tools/browser.py @@ -44,12 +44,10 @@ def __lt__(self, other): def __eq__(self, other): return self.name == other.name - def __repr__(self): - try: - type = self.GetHLIType() - except: - type = "Generic" - return f"HLIPythonObject({type}) - name: {self.name} object: {self.myobject!r}" + def __repr__(self) -> str: + return ( + f"{self.__class__.__name__}(name={self.name!r}, object={self.myobject!r})" + ) def GetText(self): try: diff --git a/Pythonwin/pywin/tools/regedit.py b/Pythonwin/pywin/tools/regedit.py index d8f854ff45..d3b91916fb 100644 --- a/Pythonwin/pywin/tools/regedit.py +++ b/Pythonwin/pywin/tools/regedit.py @@ -331,11 +331,9 @@ def __eq__(self, other): and self.userName == other.userName ) - def __repr__(self): - return "<{} with root={}, key={}>".format( - self.__class__.__name__, - self.keyRoot, - self.keyName, + def __repr__(self) -> str: + return ( + f"<{self.__class__.__name__} with root={self.keyRoot}, key={self.keyName}>" ) def GetText(self): diff --git a/com/win32com/client/__init__.py b/com/win32com/client/__init__.py index d060fae00d..33140e9108 100644 --- a/com/win32com/client/__init__.py +++ b/com/win32com/client/__init__.py @@ -555,7 +555,7 @@ def __dir__(self): return list(set(attributes)) # Provide a prettier name than the CLSID - def __repr__(self): + def __repr__(self) -> str: # Need to get the docstring for the module for this class. try: mod_doc = sys.modules[self.__class__.__module__].__doc__ @@ -630,7 +630,7 @@ def __init__(self, oobj=None): oobj = pythoncom.new(self.CLSID) self.__dict__["_dispobj_"] = self.default_interface(oobj) - def __repr__(self): + def __repr__(self) -> str: return f"" def __getattr__(self, attr): @@ -700,5 +700,5 @@ def _del_value(self): value = property(_get_value, _set_value, _del_value) - def __repr__(self): - return f"win32com.client.VARIANT({self.varianttype!r}, {self._value!r})" + def __repr__(self) -> str: + return f"{self.__class__.__qualname__}({self.varianttype!r}, {self._value!r})" diff --git a/com/win32com/client/build.py b/com/win32com/client/build.py index 4b7628438e..ac3e843803 100644 --- a/com/win32com/client/build.py +++ b/com/win32com/client/build.py @@ -70,7 +70,7 @@ class NotSupportedException(Exception): class MapEntry: - "Simple holder for named attibutes - items in a map." + """Simple holder for named attributes - items in a map.""" def __init__( self, @@ -92,17 +92,16 @@ def __init__( self.doc = doc self.resultCLSID = resultCLSID self.resultDocumentation = resultDoc - self.wasProperty = ( - 0 # Have I been transformed into a function so I can pass args? - ) + self.wasProperty = 0 + """Has this MapEntry been transformed into a function so it can pass args?""" self.hidden = hidden - def __repr__(self): + def __repr__(self) -> str: return ( - "MapEntry(dispid={s.dispid}, desc={s.desc}, names={s.names}, doc={s.doc!r}, " - "resultCLSID={s.resultCLSID}, resultDocumentation={s.resultDocumentation}, " - "wasProperty={s.wasProperty}, hidden={s.hidden}" - ).format(s=self) + "MapEntry(" + + ", ".join([f"{key}{value!r}" for key, value in self.__dict__.items()]) + + ")" + ) def GetResultCLSID(self): rc = self.resultCLSID diff --git a/com/win32com/client/dynamic.py b/com/win32com/client/dynamic.py index 3738da9031..ebe61d9755 100644 --- a/com/win32com/client/dynamic.py +++ b/com/win32com/client/dynamic.py @@ -220,8 +220,8 @@ def __bool__(self): # _Possibly_ want to defer to __len__ if available, but I'm not sure this is # desirable??? - def __repr__(self): - return "" % (self._username_) + def __repr__(self) -> str: + return f"" def __str__(self): # __str__ is used when the user does "print(object)", so we gracefully diff --git a/com/win32com/client/genpy.py b/com/win32com/client/genpy.py index 9d960451c0..9e1e9782be 100644 --- a/com/win32com/client/genpy.py +++ b/com/win32com/client/genpy.py @@ -111,7 +111,7 @@ def __lt__(self, other): return self.doc < other.doc return self.order < other.order - def __repr__(self): + def __repr__(self) -> str: return f"OleItem: doc={self.doc!r}, order={self.order}" diff --git a/com/win32com/server/exception.py b/com/win32com/server/exception.py index 43c08fcac1..5a57a8690b 100644 --- a/com/win32com/server/exception.py +++ b/com/win32com/server/exception.py @@ -77,8 +77,8 @@ def __init__( # todo - fill in the exception value pythoncom.com_error.__init__(self, scode, self.description, None, -1) - def __repr__(self): - return f"" + def __repr__(self) -> str: + return f"{self.__class__.__name__}(scode={self.scode!r}, desc={self.description!r})" def IsCOMException(t=None): diff --git a/com/win32comext/axdebug/debugger.py b/com/win32comext/axdebug/debugger.py index d0585b9b6f..d63074f251 100644 --- a/com/win32comext/axdebug/debugger.py +++ b/com/win32comext/axdebug/debugger.py @@ -18,8 +18,8 @@ def __init__(self, module): self.realNode = None self.cont = codecontainer.SourceModuleContainer(module) - def __repr__(self): - return f"" + def __repr__(self) -> str: + return f"<{self.__class__.__name__} wrapping {self.module}>" def Attach(self, parentRealNode): self.realNode.Attach(parentRealNode) diff --git a/com/win32comext/axscript/client/error.py b/com/win32comext/axscript/client/error.py index 41711abdd8..31f28c9e7a 100644 --- a/com/win32comext/axscript/client/error.py +++ b/com/win32comext/axscript/client/error.py @@ -218,9 +218,6 @@ def ExtractTracebackInfo(self, tb: TracebackType, site: COMScript): line = None return filename, lineno, name, line - def __repr__(self): - return "AXScriptException Object with description:" + self.description - def ProcessAXScriptException( scriptingSite: AXSite, diff --git a/com/win32comext/axscript/client/framework.py b/com/win32comext/axscript/client/framework.py index c4a04329f8..850efa6162 100644 --- a/com/win32comext/axscript/client/framework.py +++ b/com/win32comext/axscript/client/framework.py @@ -165,8 +165,8 @@ class Event: def __init__(self): self.name = "" - def __repr__(self): - return "<%s at %d: %s>" % (self.__class__.__name__, id(self), self.name) + def __repr__(self) -> str: + return f"<{self.__class__.__name__} at {id(self)}: {self.name}>" def Reset(self): pass @@ -314,16 +314,11 @@ def __init__(self, parentItem, name, dispatch, flags): # trace("Creating ScriptItem", name, "of parent", parentItem,"with dispatch", dispatch) - def __repr__(self): + def __repr__(self) -> str: flagsDesc = "" if self.flags is not None and self.flags & axscript.SCRIPTITEM_GLOBALMEMBERS: flagsDesc = "/Global" - return "<%s at %d: %s%s>" % ( - self.__class__.__name__, - id(self), - self.name, - flagsDesc, - ) + return f"<{self.__class__.__name__} at {id(self)}: {self.name}{flagsDesc}>" def _dump_(self, level): flagDescs = [] diff --git a/com/win32comext/axscript/client/pyscript.py b/com/win32comext/axscript/client/pyscript.py index 91d3ed2c1e..3c0df9844b 100644 --- a/com/win32comext/axscript/client/pyscript.py +++ b/com/win32comext/axscript/client/pyscript.py @@ -108,8 +108,8 @@ class NamedScriptAttribute: def __init__(self, scriptItem): self.__dict__["_scriptItem_"] = scriptItem - def __repr__(self): - return f"" + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self._scriptItem_!r})" def __getattr__(self, attr): # If a known subitem, return it. diff --git a/win32/Lib/win32pdhquery.py b/win32/Lib/win32pdhquery.py index e356f89142..3ff66b9950 100644 --- a/win32/Lib/win32pdhquery.py +++ b/win32/Lib/win32pdhquery.py @@ -564,7 +564,7 @@ class QueryError(Exception): def __init__(self, query: BaseQuery): self.query = query - def __repr__(self): - return f"" + def __repr__(self) -> str: + return f"<{self.__class__.__name__} in {self.query!r}>" __str__ = __repr__ diff --git a/win32/Lib/win32rcparser.py b/win32/Lib/win32rcparser.py index 183f075b1c..3d3acd98b0 100644 --- a/win32/Lib/win32rcparser.py +++ b/win32/Lib/win32rcparser.py @@ -168,8 +168,8 @@ def __init__(self, id, idNum, value): self.idNum = idNum self.value = value - def __repr__(self): - return f"StringDef({self.id!r}, {self.idNum!r}, {self.value!r})" + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.id!r}, {self.idNum!r}, {self.value!r})" class RCParser: diff --git a/win32/Lib/win32timezone.py b/win32/Lib/win32timezone.py index d9f69700ab..216c49fc40 100644 --- a/win32/Lib/win32timezone.py +++ b/win32/Lib/win32timezone.py @@ -663,11 +663,11 @@ def _LoadDynamicInfoFromKey(self, key) -> None: ) def __repr__(self) -> str: - result = f"{self.__class__.__name__}({self.timeZoneName!r}" - if self.fixedStandardTime: - result += ", True" - result += ")" - return result + return ( + f"{self.__class__.__name__}({self.timeZoneName!r}" + + (", True" if self.fixedStandardTime else "") + + ")" + ) def __str__(self) -> str: return self.displayName