-Things can appear to get wierd when editing a file with mixed tabs and spaces.
+Things can appear to get weird when editing a file with mixed tabs and spaces.
Although mixed tabs and spaces in the same indent is evil, there are a number
of source files that have certain classes/functions indented with spaces, and others
that use tabs. The editor will not correctly adjust to the current block - whatever
diff --git a/Pythonwin/pythondoc.h b/Pythonwin/pythondoc.h
index d0c2811d2..fb5f4b13c 100644
--- a/Pythonwin/pythondoc.h
+++ b/Pythonwin/pythondoc.h
@@ -112,7 +112,7 @@ BOOL CPythonDocTemp::OnSaveDocument(const TCHAR *fileName)
// @pyparm string|fileName||The name of the file being saved.
// @xref
// @comm If a handler is defined for this function, the base (MFC) function will not
- // be called. If necessary, the handler must call this function explicitely.
+ // be called. If necessary, the handler must call this function explicitly.
CVirtualHelper helper("OnSaveDocument", this);
if (helper.call(fileName)) {
int ret;
@@ -131,7 +131,7 @@ BOOL CPythonDocTemp::OnOpenDocument(const TCHAR *fileName)
// @pyvirtual int|PyCDocument|OnOpenDocument|Called by the MFC architecture.
// @xref
// @comm If a handler is defined for this function, the base (MFC) function will not
- // be called. If necessary, the handler must call this function explicitely.
+ // be called. If necessary, the handler must call this function explicitly.
CVirtualHelper helper("OnOpenDocument", this);
if (!helper.HaveHandler()) {
PyErr_SetString(ui_module_error, "PyCDocument::OnOpenDocument handler does not exist.");
@@ -155,7 +155,7 @@ BOOL CPythonDocTemp::OnNewDocument()
// @pyvirtual int|PyCDocument|OnNewDocument|Called by the MFC architecture.
// @xref
// @comm If a handler is defined for this function, the base (MFC) function will not
- // be called. If necessary, the handler must call this function explicitely.
+ // be called. If necessary, the handler must call this function explicitly.
CVirtualHelper helper("OnNewDocument", this);
if (!helper.HaveHandler()) {
helper.release_full();
@@ -182,7 +182,7 @@ void CPythonDocTemp::OnCloseDocument()
// @pyvirtual |PyCDocument|OnCloseDocument|Called by the MFC architecture.
// @xref
// @comm If a handler is defined for this function, the base (MFC) function will not
- // be called. If necessary, the handler must call this function explicitely.
+ // be called. If necessary, the handler must call this function explicitly.
CVirtualHelper helper("OnCloseDocument", this);
if (helper.HaveHandler()) {
helper.call();
@@ -215,7 +215,7 @@ void CPythonDocTemp::DeleteContents()
P::DeleteContents();
}
// @comm If a handler is defined for this function, the base (MFC) function will not
- // be called. If necessary, the handler must call this function explicitely.
+ // be called. If necessary, the handler must call this function explicitly.
}
template
BOOL CPythonDocTemp::SaveModified()
@@ -223,7 +223,7 @@ BOOL CPythonDocTemp
::SaveModified()
// @pyvirtual int|PyCDocument|SaveModified|Called by the MFC architecture when a document is closed.
// @xref
// @comm If a handler is defined for this function, the base (MFC) function will not
- // be called. If necessary, the handler must call this function explicitely.
+ // be called. If necessary, the handler must call this function explicitly.
CVirtualHelper helper("SaveModified", this);
if (!helper.HaveHandler()) {
helper.release_full();
@@ -244,7 +244,7 @@ void CPythonDocTemp::OnChangedViewList()
// @pyvirtual int|PyCDocument|OnChangedViewList|Called by the MFC architecture when after a view is attached.
// @xref
// @comm If a handler is defined for this function, the base (MFC) function will not
- // be called. If necessary, the handler must call this function explicitely.
+ // be called. If necessary, the handler must call this function explicitly.
CVirtualHelper helper("OnChangedViewList", this);
if (helper.HaveHandler() && helper.call()) {
return;
diff --git a/Pythonwin/pywin/debugger/fail.py b/Pythonwin/pywin/debugger/fail.py
index dbb5320ae..0afc70eb3 100644
--- a/Pythonwin/pywin/debugger/fail.py
+++ b/Pythonwin/pywin/debugger/fail.py
@@ -28,7 +28,7 @@ def b():
b = 1
pywin.debugger.set_trace()
# After importing or running this module, you are likely to be
- # sitting at the next line. This is because we explicitely
+ # sitting at the next line. This is because we explicitly
# broke into the debugger using the "set_trace() function
# "pywin.debugger.brk()" is a shorter alias for this.
c()
diff --git a/Pythonwin/pywin/dialogs/list.py b/Pythonwin/pywin/dialogs/list.py
index 4e1877955..377a7cade 100644
--- a/Pythonwin/pywin/dialogs/list.py
+++ b/Pythonwin/pywin/dialogs/list.py
@@ -44,14 +44,17 @@ def OnListClick(self, id, code):
return 1
def OnListItemChange(self, std, extra):
- (hwndFrom, idFrom, code), (
- itemNotify,
- sub,
- newState,
- oldState,
- change,
- point,
- lparam,
+ (
+ (hwndFrom, idFrom, code),
+ (
+ itemNotify,
+ sub,
+ newState,
+ oldState,
+ change,
+ point,
+ lparam,
+ ),
) = (std, extra)
oldSel = (oldState & commctrl.LVIS_SELECTED) != 0
newSel = (newState & commctrl.LVIS_SELECTED) != 0
diff --git a/Pythonwin/pywin/framework/app.py b/Pythonwin/pywin/framework/app.py
index 4e0f09b94..ddd64b197 100644
--- a/Pythonwin/pywin/framework/app.py
+++ b/Pythonwin/pywin/framework/app.py
@@ -2,9 +2,11 @@
# The application is responsible for managing the main frame window.
#
# We also grab the FileOpen command, to invoke our Python editor
-" The PythonWin application code. Manages most aspects of MDI, etc "
+"The PythonWin application code. Manages most aspects of MDI, etc"
+
from __future__ import annotations
+import builtins
import os
import sys
import traceback
@@ -392,9 +394,7 @@ def Win32Input(prompt=None):
def HookInput():
- import code
-
- sys.modules["builtins"].input = Win32Input
+ builtins.input = Win32Input
def HaveGoodGUI():
diff --git a/Pythonwin/pywin/framework/editor/editor.py b/Pythonwin/pywin/framework/editor/editor.py
index facb5b23f..a83f20312 100644
--- a/Pythonwin/pywin/framework/editor/editor.py
+++ b/Pythonwin/pywin/framework/editor/editor.py
@@ -9,7 +9,7 @@
# We now support reloading of externally modified documented
# (eg, presumably by some other process, such as source control or
# another editor.
-# We also suport auto-loading of externally modified files.
+# We also support auto-loading of externally modified files.
# - if the current document has not been modified in this
# editor, but has been modified on disk, then the file
# can be automatically reloaded.
@@ -19,7 +19,6 @@
import re
-import regex
import win32api
import win32con
import win32ui
@@ -36,8 +35,8 @@
# from pywin.mfc.docview import EditView as ParentEditorView
# from pywin.mfc.docview import Document as ParentEditorDocument
-patImport = regex.symcomp(r"import \(.*\)")
-patIndent = regex.compile(r"^\([ \t]*[~ \t]\)")
+patImport = re.compile(r"import (?P.*)")
+patIndent = re.compile(r"^([ \t]*[~ \t])")
ID_LOCATE_FILE = 0xE200
ID_GOTO_LINE = 0xE2001
@@ -364,9 +363,10 @@ def OnRClick(self, params):
# look for a module name
line = self._obj_.GetLine().strip()
flags = win32con.MF_STRING | win32con.MF_ENABLED
- if patImport.match(line) == len(line):
+ matchResult = patImport.match(line)
+ if matchResult and matchResult[0] == line:
menu.AppendMenu(
- flags, ID_LOCATE_FILE, "&Locate %s.py" % patImport.group("name")
+ flags, ID_LOCATE_FILE, "&Locate %s.py" % matchResult.group("name")
)
menu.AppendMenu(win32con.MF_SEPARATOR)
menu.AppendMenu(flags, win32ui.ID_EDIT_UNDO, "&Undo")
diff --git a/Pythonwin/pywin/framework/editor/vss.py b/Pythonwin/pywin/framework/editor/vss.py
index 4a772acef..fa3b51ed3 100644
--- a/Pythonwin/pywin/framework/editor/vss.py
+++ b/Pythonwin/pywin/framework/editor/vss.py
@@ -86,7 +86,7 @@ def CheckoutFile(fileName):
project, vssFname, database = rc
if g_sourceSafe is None:
g_sourceSafe = win32com.client.Dispatch("SourceSafe")
- # SS seems a bit wierd. It defaults the arguments as empty strings, but
+ # SS seems a bit weird. It defaults the arguments as empty strings, but
# then complains when they are used - so we pass "Missing"
if not database:
database = pythoncom.Missing
diff --git a/Pythonwin/pywin/framework/intpyapp.py b/Pythonwin/pywin/framework/intpyapp.py
index acbd34cc1..de02fdace 100644
--- a/Pythonwin/pywin/framework/intpyapp.py
+++ b/Pythonwin/pywin/framework/intpyapp.py
@@ -467,7 +467,7 @@ def OnFileLocate(self, id, code):
else:
win32ui.GetApp().OpenDocumentFile(newName)
- # Display all the "options" proprety pages we can find
+ # Display all the "options" property pages we can find
def OnViewOptions(self, id, code):
win32ui.InitRichEdit()
sheet = dialog.PropertySheet("Pythonwin Options")
diff --git a/Pythonwin/pywin/framework/mdi_pychecker.py b/Pythonwin/pywin/framework/mdi_pychecker.py
index cd31a9a18..3108c2e81 100644
--- a/Pythonwin/pywin/framework/mdi_pychecker.py
+++ b/Pythonwin/pywin/framework/mdi_pychecker.py
@@ -145,8 +145,7 @@ def __radd__(self, other):
# Group(1) is the filename, group(2) is the lineno.
-# regexGrepResult=regex.compile(r"^\([a-zA-Z]:.*\)(\([0-9]+\))")
-# regexGrep=re.compile(r"^([a-zA-Z]:[^(]*)\((\d+)\)")
+# regexGrep = re.compile(r"^([a-zA-Z]:[^(]*)\((\d+)\)")
regexGrep = re.compile(r"^(..[^\(:]+)?[\(:](\d+)[\):]:?\s*(.*)")
# these are the atom numbers defined by Windows for basic dialog controls
diff --git a/Pythonwin/pywin/framework/scriptutils.py b/Pythonwin/pywin/framework/scriptutils.py
index fe57113dd..32811190b 100644
--- a/Pythonwin/pywin/framework/scriptutils.py
+++ b/Pythonwin/pywin/framework/scriptutils.py
@@ -27,9 +27,7 @@
debugging_options = """No debugging
Step-through in the debugger
Run in the debugger
-Post-Mortem of unhandled exceptions""".split(
- "\n"
-)
+Post-Mortem of unhandled exceptions""".split("\n")
byte_cr = b"\r"
byte_lf = b"\n"
diff --git a/Pythonwin/pywin/framework/sgrepmdi.py b/Pythonwin/pywin/framework/sgrepmdi.py
index f318f731f..0016cc854 100644
--- a/Pythonwin/pywin/framework/sgrepmdi.py
+++ b/Pythonwin/pywin/framework/sgrepmdi.py
@@ -127,8 +127,6 @@ def __radd__(self, other):
# Group(1) is the filename, group(2) is the lineno.
-# regexGrepResult=regex.compile(r"^\([a-zA-Z]:.*\)(\([0-9]+\))")
-
regexGrep = re.compile(r"^([a-zA-Z]:[^(]*)\(([0-9]+)\)")
# these are the atom numbers defined by Windows for basic dialog controls
diff --git a/Pythonwin/pywin/framework/startup.py b/Pythonwin/pywin/framework/startup.py
index 3cc6c0169..ca7a44d87 100644
--- a/Pythonwin/pywin/framework/startup.py
+++ b/Pythonwin/pywin/framework/startup.py
@@ -50,7 +50,7 @@
pywin.__path__[0] = win32ui.FullPath(pywin.__path__[0])
pywin.framework.__path__[0] = win32ui.FullPath(pywin.framework.__path__[0])
-# make a few wierd sys values. This is so later we can clobber sys.argv to trick
+# make a few weird sys values. This is so later we can clobber sys.argv to trick
# scripts when running under a GUI environment.
moduleName = "pywin.framework.intpyapp"
diff --git a/Pythonwin/pywin/framework/stdin.py b/Pythonwin/pywin/framework/stdin.py
index 1614fbe91..b7d71dc19 100644
--- a/Pythonwin/pywin/framework/stdin.py
+++ b/Pythonwin/pywin/framework/stdin.py
@@ -16,6 +16,7 @@
import sys
sys.stdin = sys.stdin.real_file
"""
+
import sys
get_input_line = input
diff --git a/Pythonwin/pywin/mfc/activex.py b/Pythonwin/pywin/mfc/activex.py
index f3d9939a4..3d0207aca 100644
--- a/Pythonwin/pywin/mfc/activex.py
+++ b/Pythonwin/pywin/mfc/activex.py
@@ -1,5 +1,4 @@
-"""Support for ActiveX control hosting in Pythonwin.
-"""
+"""Support for ActiveX control hosting in Pythonwin."""
import win32ui
import win32uiole
diff --git a/Pythonwin/pywin/scintilla/keycodes.py b/Pythonwin/pywin/scintilla/keycodes.py
index d94ccda47..12867080a 100644
--- a/Pythonwin/pywin/scintilla/keycodes.py
+++ b/Pythonwin/pywin/scintilla/keycodes.py
@@ -70,7 +70,7 @@ def get_vk(chardesc):
def parse_key_name(name):
- name += "-" # Add a sentinal
+ name += "-" # Add a sentinel
start = pos = 0
max = len(name)
toks = []
diff --git a/Pythonwin/pywin/scintilla/view.py b/Pythonwin/pywin/scintilla/view.py
index 99680f18e..0134f3151 100644
--- a/Pythonwin/pywin/scintilla/view.py
+++ b/Pythonwin/pywin/scintilla/view.py
@@ -749,7 +749,7 @@ def CalculatePageRanges(self, dc, pInfo):
pageStart = self.FormatRange(dc, pageStart, textLen, rc, 0)
maxPage += 1
self.starts[maxPage] = pageStart
- # And a sentinal for one page past the end
+ # And a sentinel for one page past the end
self.starts[maxPage + 1] = textLen
# When actually printing, maxPage doesn't have any effect at this late state.
# but is needed to make the Print Preview work correctly.
diff --git a/Pythonwin/pywin/test/test_pywin.py b/Pythonwin/pywin/test/test_pywin.py
index 6cf973a92..49acc9d5e 100644
--- a/Pythonwin/pywin/test/test_pywin.py
+++ b/Pythonwin/pywin/test/test_pywin.py
@@ -47,8 +47,7 @@ def setUpClass(cls):
def _restore_oe():
sys.stdout, sys.stderr = cls.std_oe_orig
- if sys.version_info >= (3, 8):
- cls.addClassCleanup(_restore_oe)
+ cls.addClassCleanup(_restore_oe)
sys.argv[1:] = ["/new", src_dir + "\\_dbgscript.py"]
if not _indebugger:
thisApp.InitInstance()
@@ -65,7 +64,7 @@ def tearDownClass(cls):
win32api.PostQuitMessage()
win32gui.PumpWaitingMessages()
cls.app.ExitInstance()
- sys.stdout, sys.stderr = cls.std_oe_orig # py3.7
+ sys.stdout, sys.stderr = cls.std_oe_orig
def test_1_pydocs_and_finddlg(self):
mf = win32ui.GetMainFrame()
diff --git a/Pythonwin/win32bitmap.cpp b/Pythonwin/win32bitmap.cpp
index 157457063..0422fbf75 100644
--- a/Pythonwin/win32bitmap.cpp
+++ b/Pythonwin/win32bitmap.cpp
@@ -210,7 +210,7 @@ PyObject *ui_bitmap_load_bitmap_file(PyObject *self, PyObject *args)
return NULL;
}
*/
- /* Attempt to load wierd bitmap format.
+ /* Attempt to load weird bitmap format.
if (bmFileHeader.bfOffBits) {
PyObject *args = Py_BuildValue("(i)", bmFileHeader.bfOffBits);
result = gui_call_object(seeker, args);
diff --git a/Pythonwin/win32dlg.cpp b/Pythonwin/win32dlg.cpp
index 598aae410..6a0e2fecb 100644
--- a/Pythonwin/win32dlg.cpp
+++ b/Pythonwin/win32dlg.cpp
@@ -162,7 +162,7 @@ PyCDialog::~PyCDialog()
GlobalFree(hSaved);
}
- ui_assoc_object::SetAssocInvalid(); // must call this explicitely, as I ignore SetAssocInvalid
+ ui_assoc_object::SetAssocInvalid(); // must call this explicitly, as I ignore SetAssocInvalid
Py_XDECREF(ddlist); // we can not have the pointer deleted at window destruction time
// for a dialog (as MFC still needs it after the dialog has completed
BOOL bManDeleteSave = bManualDelete;
diff --git a/Pythonwin/win32virt.cpp b/Pythonwin/win32virt.cpp
index 5d049fbf3..a53aa58a8 100644
--- a/Pythonwin/win32virt.cpp
+++ b/Pythonwin/win32virt.cpp
@@ -42,7 +42,7 @@ CVirtualHelper::CVirtualHelper(const char *iname, void *iassoc, EnumVirtualError
PyErr_Fetch(&t, &v, &tb);
handler = PyObject_GetAttrString(py_bob->virtualInst, (char *)iname);
if (handler) {
- // explicitely check a method returned, else the classes
+ // explicitly check a method returned, else the classes
// delegation may cause a circular call chain.
if (!PyMethod_Check(handler)) {
if (!PyCFunction_Check(handler)) {
diff --git a/adodbapi/adodbapi.py b/adodbapi/adodbapi.py
index 4e85bc525..19adbfb30 100644
--- a/adodbapi/adodbapi.py
+++ b/adodbapi/adodbapi.py
@@ -66,7 +66,7 @@ def getIndexedValue(obj, index):
def make_COM_connecter():
try:
pythoncom.CoInitialize() # v2.1 Paj
- c = Dispatch("ADODB.Connection") # connect _after_ CoIninialize v2.1.1 adamvan
+ c = Dispatch("ADODB.Connection") # connect _after_ CoInitialize v2.1.1 adamvan
except:
raise api.InterfaceError(
"Windows COM Error: Dispatch('ADODB.Connection') failed."
@@ -395,9 +395,7 @@ def _rollback(self):
# If attributes has adXactAbortRetaining it performs retaining aborts that is,
# calling RollbackTrans automatically starts a new transaction. Not all providers support this.
# If not, we will have to start a new transaction by this command:
- if (
- not self.transaction_level
- ): # if self.transaction_level == 0 or self.transaction_level is None:
+ if not self.transaction_level:
self.transaction_level = self.connector.BeginTrans()
except Exception as e:
self._raiseConnectionError(api.ProgrammingError, e)
@@ -595,7 +593,7 @@ def _raiseCursorError(self, errorclass, errorvalue):
eh(self.connection, self, errorclass, errorvalue)
def build_column_info(self, recordset):
- self.converters = [] # convertion function for each column
+ self.converters = [] # conversion function for each column
self.columnNames = {} # names of columns {lowercase name : number,...}
self._description = None
@@ -634,9 +632,8 @@ def _makeDescriptionFromRS(self):
if self.rs.EOF or self.rs.BOF:
display_size = None
else:
- display_size = (
- f.ActualSize
- ) # TODO: Is this the correct defintion according to the DB API 2 Spec ?
+ # TODO: Is this the correct defintion according to the DB API 2 Spec ?
+ display_size = f.ActualSize
null_ok = bool(f.Attributes & adc.adFldMayBeNull) # v2.1 Cole
desc.append(
(
@@ -774,9 +771,8 @@ def get_returned_parameters(self):
after the last recordset has been read. In that case, you must coll nextset() until it
returns None, then call this method to get your returned information."""
- retLst = (
- []
- ) # store procedures may return altered parameters, including an added "return value" item
+ # store procedures may return altered parameters, including an added "return value" item
+ retLst = []
for p in tuple(self.cmd.Parameters):
if verbose > 2:
print(
@@ -907,9 +903,8 @@ def _buildADOparameterList(self, parameters, sproc=False):
)
i += 1
else: # -- build own parameter list
- if (
- self._parameter_names
- ): # we expect a dictionary of parameters, this is the list of expected names
+ # we expect a dictionary of parameters, this is the list of expected names
+ if self._parameter_names:
for parm_name in self._parameter_names:
elem = parameters[parm_name]
adotype = api.pyTypeToADOType(elem)
diff --git a/adodbapi/examples/db_print.py b/adodbapi/examples/db_print.py
index c0eb83ee4..fc86a8b3c 100644
--- a/adodbapi/examples/db_print.py
+++ b/adodbapi/examples/db_print.py
@@ -1,4 +1,4 @@
-""" db_print.py -- a simple demo for ADO database reads."""
+"""db_print.py -- a simple demo for ADO database reads."""
import sys
diff --git a/adodbapi/examples/db_table_names.py b/adodbapi/examples/db_table_names.py
index 907bdb85e..17ff58349 100644
--- a/adodbapi/examples/db_table_names.py
+++ b/adodbapi/examples/db_table_names.py
@@ -1,4 +1,4 @@
-""" db_table_names.py -- a simple demo for ADO database table listing."""
+"""db_table_names.py -- a simple demo for ADO database table listing."""
import sys
diff --git a/adodbapi/process_connect_string.py b/adodbapi/process_connect_string.py
index d8b29f280..b1d4e4e93 100644
--- a/adodbapi/process_connect_string.py
+++ b/adodbapi/process_connect_string.py
@@ -1,137 +1,135 @@
-""" a clumsy attempt at a macro language to let the programmer execute code on the server (ex: determine 64bit)"""
-
-from . import is64bit
-
-
-def macro_call(macro_name, args, kwargs):
- """allow the programmer to perform limited processing on the server by passing macro names and args
-
- :new_key - the key name the macro will create
- :args[0] - macro name
- :args[1:] - any arguments
- :code - the value of the keyword item
- :kwargs - the connection keyword dictionary. ??key has been removed
- --> the value to put in for kwargs['name'] = value
- """
- if isinstance(args, (str, str)):
- args = [
- args
- ] # the user forgot to pass a sequence, so make a string into args[0]
- new_key = args[0]
- try:
- if macro_name == "is64bit":
- if is64bit.Python(): # if on 64 bit Python
- return new_key, args[1] # return first argument
- else:
- try:
- return new_key, args[2] # else return second argument (if defined)
- except IndexError:
- return new_key, "" # else return blank
-
- elif (
- macro_name == "getuser"
- ): # get the name of the user the server is logged in under
- if not new_key in kwargs:
- import getpass
-
- return new_key, getpass.getuser()
-
- elif macro_name == "getnode": # get the name of the computer running the server
- import platform
-
- try:
- return new_key, args[1] % platform.node()
- except IndexError:
- return new_key, platform.node()
-
- elif macro_name == "getenv": # expand the server's environment variable args[1]
- try:
- dflt = args[2] # if not found, default from args[2]
- except IndexError: # or blank
- dflt = ""
- return new_key, os.environ.get(args[1], dflt)
-
- elif macro_name == "auto_security":
- if (
- not "user" in kwargs or not kwargs["user"]
- ): # missing, blank, or Null username
- return new_key, "Integrated Security=SSPI"
- return new_key, "User ID=%(user)s; Password=%(password)s" % kwargs
-
- elif (
- macro_name == "find_temp_test_path"
- ): # helper function for testing ado operation -- undocumented
- import os
- import tempfile
-
- return new_key, os.path.join(
- tempfile.gettempdir(), "adodbapi_test", args[1]
- )
-
- raise ValueError(f"Unknown connect string macro={macro_name}")
- except:
- raise ValueError(f"Error in macro processing {macro_name} {args!r}")
-
-
-def process(
- args, kwargs, expand_macros=False
-): # --> connection string with keyword arguments processed.
- """attempts to inject arguments into a connection string using Python "%" operator for strings
-
- co: adodbapi connection object
- args: positional parameters from the .connect() call
- kvargs: keyword arguments from the .connect() call
- """
- try:
- dsn = args[0]
- except IndexError:
- dsn = None
- if isinstance(
- dsn, dict
- ): # as a convenience the first argument may be django settings
- kwargs.update(dsn)
- elif (
- dsn
- ): # the connection string is passed to the connection as part of the keyword dictionary
- kwargs["connection_string"] = dsn
- try:
- a1 = args[1]
- except IndexError:
- a1 = None
- # historically, the second positional argument might be a timeout value
- if isinstance(a1, int):
- kwargs["timeout"] = a1
- # if the second positional argument is a string, then it is user
- elif isinstance(a1, str):
- kwargs["user"] = a1
- # if the second positional argument is a dictionary, use it as keyword arguments, too
- elif isinstance(a1, dict):
- kwargs.update(a1)
- try:
- kwargs["password"] = args[2] # the third positional argument is password
- kwargs["host"] = args[3] # the fourth positional argument is host name
- kwargs["database"] = args[4] # the fifth positional argument is database name
- except IndexError:
- pass
-
- # make sure connection string is defined somehow
- if not "connection_string" in kwargs:
- try: # perhaps 'dsn' was defined
- kwargs["connection_string"] = kwargs["dsn"]
- except KeyError:
- try: # as a last effort, use the "host" keyword
- kwargs["connection_string"] = kwargs["host"]
- except KeyError:
- raise TypeError("Must define 'connection_string' for ado connections")
- if expand_macros:
- for kwarg in list(kwargs.keys()):
- if kwarg.startswith("macro_"): # If a key defines a macro
- macro_name = kwarg[6:] # name without the "macro_"
- macro_code = kwargs.pop(
- kwarg
- ) # we remove the macro_key and get the code to execute
- new_key, rslt = macro_call(
- macro_name, macro_code, kwargs
- ) # run the code in the local context
- kwargs[new_key] = rslt # put the result back in the keywords dict
- return kwargs
+"""a clumsy attempt at a macro language to let the programmer execute code on the server (ex: determine 64bit)"""
+
+from . import is64bit
+
+
+def macro_call(macro_name, args, kwargs):
+ """allow the programmer to perform limited processing on the server by passing macro names and args
+
+ :new_key - the key name the macro will create
+ :args[0] - macro name
+ :args[1:] - any arguments
+ :code - the value of the keyword item
+ :kwargs - the connection keyword dictionary. ??key has been removed
+ --> the value to put in for kwargs['name'] = value
+ """
+ if isinstance(args, (str, str)):
+ args = [
+ args
+ ] # the user forgot to pass a sequence, so make a string into args[0]
+ new_key = args[0]
+ try:
+ if macro_name == "is64bit":
+ if is64bit.Python(): # if on 64 bit Python
+ return new_key, args[1] # return first argument
+ else:
+ try:
+ return new_key, args[2] # else return second argument (if defined)
+ except IndexError:
+ return new_key, "" # else return blank
+
+ elif (
+ macro_name == "getuser"
+ ): # get the name of the user the server is logged in under
+ if not new_key in kwargs:
+ import getpass
+
+ return new_key, getpass.getuser()
+
+ elif macro_name == "getnode": # get the name of the computer running the server
+ import platform
+
+ try:
+ return new_key, args[1] % platform.node()
+ except IndexError:
+ return new_key, platform.node()
+
+ elif macro_name == "getenv": # expand the server's environment variable args[1]
+ try:
+ dflt = args[2] # if not found, default from args[2]
+ except IndexError: # or blank
+ dflt = ""
+ return new_key, os.environ.get(args[1], dflt)
+
+ elif macro_name == "auto_security":
+ if (
+ not "user" in kwargs or not kwargs["user"]
+ ): # missing, blank, or Null username
+ return new_key, "Integrated Security=SSPI"
+ return new_key, "User ID=%(user)s; Password=%(password)s" % kwargs
+
+ elif (
+ macro_name == "find_temp_test_path"
+ ): # helper function for testing ado operation -- undocumented
+ import os
+ import tempfile
+
+ return new_key, os.path.join(
+ tempfile.gettempdir(), "adodbapi_test", args[1]
+ )
+
+ raise ValueError(f"Unknown connect string macro={macro_name}")
+ except:
+ raise ValueError(f"Error in macro processing {macro_name} {args!r}")
+
+
+def process(
+ args, kwargs, expand_macros=False
+): # --> connection string with keyword arguments processed.
+ """attempts to inject arguments into a connection string using Python "%" operator for strings
+
+ co: adodbapi connection object
+ args: positional parameters from the .connect() call
+ kvargs: keyword arguments from the .connect() call
+ """
+ try:
+ dsn = args[0]
+ except IndexError:
+ dsn = None
+ # as a convenience the first argument may be django settings
+ if isinstance(dsn, dict):
+ kwargs.update(dsn)
+ # the connection string is passed to the connection as part of the keyword dictionary
+ elif dsn:
+ kwargs["connection_string"] = dsn
+ try:
+ a1 = args[1]
+ except IndexError:
+ a1 = None
+ # historically, the second positional argument might be a timeout value
+ if isinstance(a1, int):
+ kwargs["timeout"] = a1
+ # if the second positional argument is a string, then it is user
+ elif isinstance(a1, str):
+ kwargs["user"] = a1
+ # if the second positional argument is a dictionary, use it as keyword arguments, too
+ elif isinstance(a1, dict):
+ kwargs.update(a1)
+ try:
+ kwargs["password"] = args[2] # the third positional argument is password
+ kwargs["host"] = args[3] # the fourth positional argument is host name
+ kwargs["database"] = args[4] # the fifth positional argument is database name
+ except IndexError:
+ pass
+
+ # make sure connection string is defined somehow
+ if not "connection_string" in kwargs:
+ try: # perhaps 'dsn' was defined
+ kwargs["connection_string"] = kwargs["dsn"]
+ except KeyError:
+ try: # as a last effort, use the "host" keyword
+ kwargs["connection_string"] = kwargs["host"]
+ except KeyError:
+ raise TypeError("Must define 'connection_string' for ado connections")
+ if expand_macros:
+ for kwarg in list(kwargs.keys()):
+ if kwarg.startswith("macro_"): # If a key defines a macro
+ macro_name = kwarg[6:] # name without the "macro_"
+ macro_code = kwargs.pop(
+ kwarg
+ ) # we remove the macro_key and get the code to execute
+ new_key, rslt = macro_call(
+ macro_name, macro_code, kwargs
+ ) # run the code in the local context
+ kwargs[new_key] = rslt # put the result back in the keywords dict
+ return kwargs
diff --git a/adodbapi/readme.txt b/adodbapi/readme.txt
index 00f76f7c2..877c400cb 100644
--- a/adodbapi/readme.txt
+++ b/adodbapi/readme.txt
@@ -34,7 +34,7 @@ Try:
or:
adodbapi.apibase.variantConversions[adodbapi.ado_consts.adNumeric] = adodbapi.apibase.cvtFloat
or:
- adodbapi.apibase.variantConversions[adodbapi.ado_consts.adNumeric] = write_your_own_convertion_function
+ adodbapi.apibase.variantConversions[adodbapi.ado_consts.adNumeric] = write_your_own_conversion_function
............
notes for 2.6.2:
The definitive source has been moved to https://github.com/mhammond/pywin32/tree/master/adodbapi.
diff --git a/adodbapi/test/adodbapitest.py b/adodbapi/test/adodbapitest.py
index 1b50e595f..88dab1267 100644
--- a/adodbapi/test/adodbapitest.py
+++ b/adodbapi/test/adodbapitest.py
@@ -1,4 +1,4 @@
-""" Unit tests version 2.6.1.0 for adodbapi"""
+"""Unit tests version 2.6.1.0 for adodbapi"""
"""
adodbapi - A python DB API 2.0 interface to Microsoft ADO
@@ -213,7 +213,7 @@ def testUserDefinedConversionForExactNumericTypes(self):
# now return strings
adodbapi.variantConversions[ado_consts.adNumeric] = adodbapi.cvtString
self.helpTestDataType("numeric(18,2)", "NUMBER", "3.45")
- # now a completly weird user defined convertion
+ # now a completely weird user defined conversion
adodbapi.variantConversions[ado_consts.adNumeric] = (
lambda x: "!!This function returns a funny unicode string %s!!" % x
)
@@ -228,7 +228,7 @@ def testUserDefinedConversionForExactNumericTypes(self):
finally:
# now reset the converter to its original function
adodbapi.variantConversions[ado_consts.adNumeric] = (
- oldconverter # Restore the original convertion function
+ oldconverter # Restore the original conversion function
)
def helpTestDataType(
@@ -325,15 +325,16 @@ def helpTestDataType(
rs = crsr.fetchone()
if allowedReturnValues:
allowedTypes = tuple([type(aRV) for aRV in allowedReturnValues])
- assert isinstance(
- rs[0], allowedTypes
- ), 'result type "%s" must be one of %s' % (type(rs[0]), allowedTypes)
+ assert isinstance(rs[0], allowedTypes), (
+ 'result type "%s" must be one of %s' % (type(rs[0]), allowedTypes)
+ )
else:
- assert isinstance(
- rs[0], type(pyData)
- ), 'result type "%s" must be instance of %s' % (
- type(rs[0]),
- type(pyData),
+ assert isinstance(rs[0], type(pyData)), (
+ 'result type "%s" must be instance of %s'
+ % (
+ type(rs[0]),
+ type(pyData),
+ )
)
if compareAlmostEqual and DBAPIDataTypeString == "DATETIME":
@@ -343,9 +344,9 @@ def helpTestDataType(
elif compareAlmostEqual:
s = float(pyData)
v = float(rs[0])
- assert (
- abs(v - s) / s < 0.00001
- ), "Values not almost equal recvd=%s, expected=%f" % (rs[0], s)
+ assert abs(v - s) / s < 0.00001, (
+ "Values not almost equal recvd=%s, expected=%f" % (rs[0], s)
+ )
else:
if allowedReturnValues:
ok = False
@@ -487,7 +488,7 @@ def testDataTypeDate(self):
)
def testDataTypeBinary(self):
- binfld = b"\x07\x00\xE2\x40*"
+ binfld = b"\x07\x00\xe2\x40*"
arv = [binfld, adodbapi.Binary(binfld), bytes(binfld)]
if self.getEngine() == "PostgreSQL":
self.helpTestDataType(
@@ -692,9 +693,9 @@ def testRowIterator(self):
rec = crsr.fetchone()
# check that stepping through an emulated row works
for j in range(len(inParam)):
- assert (
- rec[j] == inParam[j]
- ), 'returned value:"%s" != test value:"%s"' % (rec[j], inParam[j])
+ assert rec[j] == inParam[j], (
+ 'returned value:"%s" != test value:"%s"' % (rec[j], inParam[j])
+ )
# check that we can get a complete tuple from a row
assert (
tuple(rec) == inParam
diff --git a/adodbapi/test/dbapi20.py b/adodbapi/test/dbapi20.py
index 5639e4c3c..ea920d42b 100644
--- a/adodbapi/test/dbapi20.py
+++ b/adodbapi/test/dbapi20.py
@@ -1,14 +1,14 @@
#!/usr/bin/env python
-""" Python DB API 2.0 driver compliance unit test suite.
+"""Python DB API 2.0 driver compliance unit test suite.
- This software is Public Domain and may be used without restrictions.
+ This software is Public Domain and may be used without restrictions.
- "Now we have booze and barflies entering the discussion, plus rumours of
- DBAs on drugs... and I won't tell you what flashes through my mind each
- time I read the subject line with 'Anal Compliance' in it. All around
- this is turning out to be a thoroughly unwholesome unit test."
+"Now we have booze and barflies entering the discussion, plus rumours of
+ DBAs on drugs... and I won't tell you what flashes through my mind each
+ time I read the subject line with 'Anal Compliance' in it. All around
+ this is turning out to be a thoroughly unwholesome unit test."
- -- Ian Bicking
+ -- Ian Bicking
"""
__version__ = "$Revision: 1.15.0 $"[11:-2]
@@ -71,7 +71,7 @@
# - Now a subclass of TestCase, to avoid requiring the driver stub
# to use multiple inheritance
# - Reversed the polarity of buggy test in test_description
-# - Test exception heirarchy correctly
+# - Test exception hierarchy correctly
# - self.populate is now self._populate(), so if a driver stub
# overrides self.ddl1 this change propogates
# - VARCHAR columns now have a width, which will hopefully make the
@@ -198,7 +198,7 @@ def test_paramstyle(self):
def test_Exceptions(self):
# Make sure required exceptions exist, and are in the
- # defined heirarchy.
+ # defined hierarchy.
if sys.version[0] == "3": # under Python 3 StardardError no longer exists
self.assertTrue(issubclass(self.driver.Warning, Exception))
self.assertTrue(issubclass(self.driver.Error, Exception))
diff --git a/adodbapi/test/setuptestframework.py b/adodbapi/test/setuptestframework.py
index 65b99e990..4b9de6a7d 100644
--- a/adodbapi/test/setuptestframework.py
+++ b/adodbapi/test/setuptestframework.py
@@ -1,6 +1,7 @@
#!/usr/bin/python2
# Configure this in order to run the testcases.
"setuptestframework.py v 2.6.0.8"
+
import os
import shutil
import tempfile
@@ -55,7 +56,7 @@ def makeadopackage(testfolder):
shutil.copy(os.path.join(adoPath, f), newpackage)
return testfolder
else:
- raise OSError("Connot find source of adodbapi to test.")
+ raise OSError("Cannot find source of adodbapi to test.")
def makemdb(testfolder, mdb_name):
diff --git a/build_all.bat b/build_all.bat
index 536aee00d..ec8cbbaa2 100644
--- a/build_all.bat
+++ b/build_all.bat
@@ -1,7 +1,3 @@
-py -3.7-32 setup.py -q build
-@if errorlevel 1 goto failed
-py -3.7 setup.py -q build
-@if errorlevel 1 goto failed
py -3.8-32 setup.py -q build
@if errorlevel 1 goto failed
py -3.8 setup.py -q build
diff --git a/build_env.md b/build_env.md
index d9c55ac10..7e166c4d9 100644
--- a/build_env.md
+++ b/build_env.md
@@ -117,7 +117,7 @@ where mc
```
(Note that the above process for 'mc' doesn't appear necessary for VS2017, but
-markh hasn't tried with VS2019 - please share your experiences!)
+@mhammond hasn't tried with VS2019 - please share your experiences!)
# Build
@@ -149,7 +149,6 @@ from the pywin32 directory.
- Update `setuptools` and set the following environment variables to ensure it is used:
```shell
- set SETUPTOOLS_USE_DISTUTILS=1
set DISTUTILS_USE_SDK=1
```
diff --git a/com/TestSources/PyCOMTest/PyCOMImpl.cpp b/com/TestSources/PyCOMTest/PyCOMImpl.cpp
index a4616fef0..6ba0af0c4 100644
--- a/com/TestSources/PyCOMTest/PyCOMImpl.cpp
+++ b/com/TestSources/PyCOMTest/PyCOMImpl.cpp
@@ -618,6 +618,35 @@ HRESULT CPyCOMTest::GetStruct(TestStruct1 *ret)
*ret = r;
return S_OK;
}
+
+HRESULT CPyCOMTest::ModifyStruct(TestStruct1 *prec)
+{
+ prec->int_value = 100;
+ prec->str_value = SysAllocString(L"Nothing is as constant as change");
+ return S_OK;
+}
+
+HRESULT CPyCOMTest::VerifyArrayOfStructs(TestStruct2 *prec, VARIANT_BOOL *is_ok)
+{
+ long i;
+ TestStruct1 *pdata = NULL;
+ HRESULT hr;
+
+ hr = SafeArrayAccessData(prec->array_of_records, reinterpret_cast(&pdata));
+ if (FAILED(hr)) {
+ return E_FAIL;
+ }
+ *is_ok = VARIANT_TRUE;
+ for (i = 0; i < prec->rec_count; i++)
+ {
+ if (_wcsicmp(pdata[i].str_value, L"This is record number") != 0 || pdata[i].int_value != i + 1) {
+ *is_ok = VARIANT_FALSE;
+ break;
+ }
+ }
+ return S_OK;
+}
+
HRESULT CPyCOMTest::DoubleString(BSTR in, BSTR *out)
{
*out = SysAllocStringLen(NULL, SysStringLen(in) * 2);
diff --git a/com/TestSources/PyCOMTest/PyCOMImpl.h b/com/TestSources/PyCOMTest/PyCOMImpl.h
index e285268f1..7b1f83c2b 100644
--- a/com/TestSources/PyCOMTest/PyCOMImpl.h
+++ b/com/TestSources/PyCOMTest/PyCOMImpl.h
@@ -119,6 +119,9 @@ class CPyCOMTest : public IDispatchImplowner);
else if (V_VT(&vret) == (VT_BYREF | VT_ARRAY | VT_RECORD)) {
SAFEARRAY *psa = *V_ARRAYREF(&vret);
- int d = SafeArrayGetDim(psa);
- if (sub_data == NULL)
- return PyErr_Format(PyExc_RuntimeError, "Did not get a buffer for the array!");
if (SafeArrayGetDim(psa) != 1)
return PyErr_Format(PyExc_TypeError, "Only support single dimensional arrays of records");
IRecordInfo *sub = NULL;
@@ -526,7 +523,13 @@ PyObject *PyRecord::getattro(PyObject *self, PyObject *obname)
ret_tuple = PyTuple_New(nelems);
if (ret_tuple == NULL)
goto array_end;
- this_data = (BYTE *)sub_data;
+ // We're dealing here with a Record field that is a SAFEARRAY of Records.
+ // Therefore the VARIANT that was returned by the call to 'pyrec->pri->GetFieldNoCopy'
+ // does contain a reference to the SAFEARRAY of Records, i.e. the actual data of the
+ // Record elements of this SAFEARRAY is referenced by the 'pvData' field of the SAFEARRAY.
+ // In this particular case the implementation of 'GetFieldNoCopy' returns a NULL pointer
+ // in the last parameter, i.e. 'sub_data == NULL'.
+ this_data = (BYTE *)psa->pvData;
for (i = 0; i < nelems; i++) {
PyTuple_SET_ITEM(ret_tuple, i, new PyRecord(sub, this_data, pyrec->owner));
this_data += element_size;
diff --git a/com/win32com/src/dllmain.cpp b/com/win32com/src/dllmain.cpp
index f1f80e8d9..c9203aeaa 100644
--- a/com/win32com/src/dllmain.cpp
+++ b/com/win32com/src/dllmain.cpp
@@ -156,7 +156,7 @@ typedef HRESULT(WINAPI *PFNCoInitializeEx)(LPVOID pvReserved, DWORD dwCoInit);
// particular about the order of shutdown - in MAPI's case, you MUST
// do the CoUninit _before_ the MAPIUninit.
// These functions have logic so the Python programmer can call either
-// the Init for Term function explicitely, and the framework will detect
+// the Init for Term function explicitly, and the framework will detect
// it no longer needs doing.
// XXX - Needs more thought about threading implications.
HRESULT PyCom_CoInitializeEx(LPVOID reserved, DWORD dwInit)
diff --git a/com/win32com/src/oleargs.cpp b/com/win32com/src/oleargs.cpp
index 33c925987..91fded5b1 100644
--- a/com/win32com/src/oleargs.cpp
+++ b/com/win32com/src/oleargs.cpp
@@ -4,6 +4,7 @@
#include "stdafx.h"
#include "PythonCOM.h"
+#include "PyRecord.h"
extern PyObject *PyObject_FromRecordInfo(IRecordInfo *, void *, ULONG);
extern PyObject *PyObject_FromSAFEARRAYRecordInfo(SAFEARRAY *psa);
@@ -278,9 +279,23 @@ BOOL PyCom_VariantFromPyObject(PyObject *obj, VARIANT *var)
// So make sure this check is after anything else which qualifies.
else if (PySequence_Check(obj)) {
V_ARRAY(var) = NULL; // not a valid, existing array.
- if (!PyCom_SAFEARRAYFromPyObject(obj, &V_ARRAY(var)))
- return FALSE;
- V_VT(var) = VT_ARRAY | VT_VARIANT;
+ BOOL is_record_item = false;
+ if (PyObject_Length(obj) > 0) {
+ PyObject *obItemCheck = PySequence_GetItem(obj, 0);
+ is_record_item = PyRecord_Check(obItemCheck);
+ }
+ // If the sequence elements are PyRecord objects we do NOT package
+ // them as VARIANT elements but put them directly into the SAFEARRAY.
+ if (is_record_item) {
+ if (!PyCom_SAFEARRAYFromPyObject(obj, &V_ARRAY(var), VT_RECORD))
+ return FALSE;
+ V_VT(var) = VT_ARRAY | VT_RECORD;
+ }
+ else {
+ if (!PyCom_SAFEARRAYFromPyObject(obj, &V_ARRAY(var)))
+ return FALSE;
+ V_VT(var) = VT_ARRAY | VT_VARIANT;
+ }
}
else if (PyRecord_Check(obj)) {
if (!PyObject_AsVARIANTRecordInfo(obj, var))
@@ -554,6 +569,9 @@ static BOOL PyCom_SAFEARRAYFromPyObjectBuildDimension(PyObject *obj, SAFEARRAY *
helper.m_reqdType = vt;
ok = helper.MakeObjToVariant(item, &element);
switch (vt) {
+ case VT_RECORD:
+ pvData = V_RECORD(&element);
+ break;
case VT_DISPATCH:
pvData = V_DISPATCH(&element);
break;
@@ -759,7 +777,14 @@ static BOOL PyCom_SAFEARRAYFromPyObjectEx(PyObject *obj, SAFEARRAY **ppSA, bool
if (bAllocNewArray) {
// OK - Finally can create the array...
- *ppSA = SafeArrayCreate(vt, cDims, pBounds);
+ if (vt == VT_RECORD) {
+ // SAFEARRAYS of UDTs need a special treatment.
+ obItemCheck = PySequence_GetItem(obj, 0);
+ PyRecord *pyrec = (PyRecord *)obItemCheck;
+ *ppSA = SafeArrayCreateEx(vt, cDims, pBounds, pyrec->pri);
+ }
+ else
+ *ppSA = SafeArrayCreate(vt, cDims, pBounds);
if (*ppSA == NULL) {
delete[] pBounds;
PyErr_SetString(PyExc_MemoryError, "CreatingSafeArray");
@@ -860,7 +885,7 @@ static PyObject *PyCom_PyObjectFromSAFEARRAYDimensionItem(SAFEARRAY *psa, VARENU
hres = SafeArrayGetElement(psa, arrayIndices, &str);
if (FAILED(hres))
break;
- subitem = PyWinObject_FromBstr(str);
+ subitem = PyWinObject_FromBstr(str, TRUE);
break;
}
case VT_DISPATCH: {
@@ -868,7 +893,7 @@ static PyObject *PyCom_PyObjectFromSAFEARRAYDimensionItem(SAFEARRAY *psa, VARENU
hres = SafeArrayGetElement(psa, arrayIndices, &pDisp);
if (FAILED(hres))
break;
- subitem = PyCom_PyObjectFromIUnknown(pDisp, IID_IDispatch, TRUE);
+ subitem = PyCom_PyObjectFromIUnknown(pDisp, IID_IDispatch, FALSE);
break;
}
// case VT_ERROR - handled above with I4
@@ -895,7 +920,7 @@ static PyObject *PyCom_PyObjectFromSAFEARRAYDimensionItem(SAFEARRAY *psa, VARENU
hres = SafeArrayGetElement(psa, arrayIndices, &pUnk);
if (FAILED(hres))
break;
- subitem = PyCom_PyObjectFromIUnknown(pUnk, IID_IUnknown, TRUE);
+ subitem = PyCom_PyObjectFromIUnknown(pUnk, IID_IUnknown, FALSE);
break;
}
// case VT_DECIMAL
@@ -1572,6 +1597,7 @@ BOOL PythonOleArgHelper::MakeObjToVariant(PyObject *obj, VARIANT *var, PyObject
// Nothing else to do - the code below sets the VT up correctly.
break;
case VT_RECORD:
+ case VT_RECORD | VT_BYREF:
rc = PyObject_AsVARIANTRecordInfo(obj, var);
break;
case VT_CY:
diff --git a/com/win32com/src/univgw_dataconv.cpp b/com/win32com/src/univgw_dataconv.cpp
index 23107d01d..520adb66b 100644
--- a/com/win32com/src/univgw_dataconv.cpp
+++ b/com/win32com/src/univgw_dataconv.cpp
@@ -702,7 +702,7 @@ PyObject *dataconv_ReadFromInTuple(PyObject *self, PyObject *args)
default:
obArg = NULL;
PyErr_SetString(PyExc_TypeError, "Unknown/bad type description type!");
- // barf here, we don't wtf they were thinking...
+ // barf here, we don't know wtf they were thinking...
break;
} // switch
} // if ARRAY
diff --git a/com/win32com/test/GenTestScripts.py b/com/win32com/test/GenTestScripts.py
index 079f6a984..8b09df077 100644
--- a/com/win32com/test/GenTestScripts.py
+++ b/com/win32com/test/GenTestScripts.py
@@ -3,6 +3,7 @@
#
import os
import sys
+import traceback
import pythoncom
import win32com
@@ -60,10 +61,7 @@ def GenerateAll():
def CleanAll():
print("Cleaning generated test scripts...")
- try: # Clear exceptions!
- 1 / 0
- except:
- pass
+ traceback.clear_frames(sys.exc_info()[2]) # Clear exceptions!
genPath = GetGenPath()
for args in genList:
try:
diff --git a/com/win32com/test/errorSemantics.py b/com/win32com/test/errorSemantics.py
index 843395c41..fe5045cc8 100644
--- a/com/win32com/test/errorSemantics.py
+++ b/com/win32com/test/errorSemantics.py
@@ -158,7 +158,7 @@ def test():
"The source in the exception tuple did not yield the correct string",
str(com_exc),
)
- assert exc[2] == "\U0001F600", (
+ assert exc[2] == "\U0001f600", (
"The description in the exception tuple did not yield the correct string",
str(com_exc),
)
@@ -213,7 +213,7 @@ def testLogger():
except pythoncom.error as exc:
# `excepinfo` is a tuple with elt 2 being the traceback we captured.
message = exc.excepinfo[2]
- assert message.endswith("Exception: \U0001F600\n")
+ assert message.endswith("Exception: \U0001f600\n")
assert handler.num_emits == 1, handler.num_emits
assert handler.last_record.startswith(
"pythoncom error: Unexpected exception in gateway method 'Commit'"
@@ -228,7 +228,7 @@ def testLogger():
except pythoncom.error as exc:
# `excepinfo` is a tuple with elt 2 being the traceback we captured.
message = exc.excepinfo[2]
- assert message.endswith("Exception: \U0001F600\n")
+ assert message.endswith("Exception: \U0001f600\n")
assert handler.num_emits == 1, handler.num_emits
handler.reset()
diff --git a/com/win32com/test/pippo_server.py b/com/win32com/test/pippo_server.py
index c5ae2df40..d8e964623 100644
--- a/com/win32com/test/pippo_server.py
+++ b/com/win32com/test/pippo_server.py
@@ -41,10 +41,7 @@ def Method3(self, in1):
def BuildTypelib():
- if sys.version_info >= (3, 8):
- from setuptools.modified import newer
- else:
- from distutils.dep_util import newer
+ from setuptools.modified import newer
this_dir = os.path.dirname(__file__)
idl = os.path.abspath(os.path.join(this_dir, "pippo.idl"))
diff --git a/com/win32com/test/testExchange.py b/com/win32com/test/testExchange.py
index 119c16a17..f54422bb6 100644
--- a/com/win32com/test/testExchange.py
+++ b/com/win32com/test/testExchange.py
@@ -91,7 +91,6 @@ def TestUser(session):
def test():
-
oldcwd = os.getcwd()
try:
session = gencache.EnsureDispatch("MAPI.Session")
diff --git a/com/win32com/test/testPippo.py b/com/win32com/test/testPippo.py
index 414483b53..765acf97f 100644
--- a/com/win32com/test/testPippo.py
+++ b/com/win32com/test/testPippo.py
@@ -51,9 +51,8 @@ def testNumpyArrays(self):
self._testArray(numpy.array([-3.14, -2, -0.1, 0.0, 1.1, 2.5, 3]))
def testByteArrays(self):
- if "bytes" in dir(__builtins__):
- self._testArray(b"abcdef")
- self._testArray(bytearray(b"abcdef"))
+ self._testArray(b"abcdef")
+ self._testArray(bytearray(b"abcdef"))
def _testArray(self, inArray):
outArray = self.object.Method3(inArray)
diff --git a/com/win32com/test/testPyComTest.py b/com/win32com/test/testPyComTest.py
index 6b9b7f792..50330e356 100644
--- a/com/win32com/test/testPyComTest.py
+++ b/com/win32com/test/testPyComTest.py
@@ -198,6 +198,18 @@ def TestCommon(o, is_generated):
progress("Checking structs")
r = o.GetStruct()
assert r.int_value == 99 and str(r.str_value) == "Hello from C++"
+ # Dynamic does not support struct byref as [ in, out ] parameters
+ if hasattr(o, "CLSID"):
+ progress("Checking struct byref as [ in, out ] parameter")
+ mod_r = o.ModifyStruct(r)
+ # We expect the input value to stay unchanged
+ assert r.int_value == 99 and str(r.str_value) == "Hello from C++"
+ # and the return value to reflect the modifications performed on the COM server side
+ assert (
+ mod_r.int_value == 100
+ and str(mod_r.str_value) == "Nothing is as constant as change"
+ )
+
assert o.DoubleString("foo") == "foofoo"
progress("Checking var args")
@@ -399,6 +411,7 @@ def TestDynamic():
def TestGenerated():
# Create an instance of the server.
+ from win32com.client import Record
from win32com.client.gencache import EnsureDispatch
o = EnsureDispatch("PyCOMTest.PyCOMTest")
@@ -421,6 +434,19 @@ def TestGenerated():
coclass = GetClass("{B88DD310-BAE8-11D0-AE86-76F2C1000000}")()
TestCounter(coclass, True)
+ # Test records with SAFEARRAY(VT_RECORD) fields.
+ progress("Testing records with SAFEARRAY(VT_RECORD) fields.")
+ l = []
+ for i in range(3):
+ rec = Record("TestStruct1", o)
+ rec.str_value = "This is record number"
+ rec.int_value = i + 1
+ l.append(rec)
+ test_rec = Record("TestStruct2", o)
+ test_rec.array_of_records = l
+ test_rec.rec_count = i + 1
+ assert o.VerifyArrayOfStructs(test_rec)
+
# XXX - this is failing in dynamic tests, but should work fine.
i1, i2 = o.GetMultipleInterfaces()
# Yay - is now an instance returned!
diff --git a/com/win32com/test/testvb.py b/com/win32com/test/testvb.py
index ca5ab7689..65426559d 100644
--- a/com/win32com/test/testvb.py
+++ b/com/win32com/test/testvb.py
@@ -95,10 +95,13 @@ def TestVB(vbtest, bUseGenerated):
vbtest.VariantProperty == "Hello from Python"
), "Could not set the variant string property correctly."
vbtest.VariantProperty = (1.0, 2.0, 3.0)
- assert vbtest.VariantProperty == (
- 1.0,
- 2.0,
- 3.0,
+ assert (
+ vbtest.VariantProperty
+ == (
+ 1.0,
+ 2.0,
+ 3.0,
+ )
), f"Could not set the variant property to an array of floats correctly - '{vbtest.VariantProperty}'."
TestArrays(vbtest, bUseGenerated)
@@ -195,8 +198,8 @@ def _getcount(ob):
check = []
for item in i:
check.append(item)
- assert check == list(
- expected
+ assert (
+ check == list(expected)
), f"Collection iterator {col_name} didn't have {expected!r} 2nd time around (had {check!r})"
# but an iterator is not restartable
check = []
diff --git a/com/win32com/util.py b/com/win32com/util.py
index 0a5748f1e..2fa8931af 100644
--- a/com/win32com/util.py
+++ b/com/win32com/util.py
@@ -1,6 +1,6 @@
"""General utility functions common to client and server.
- This module contains a collection of general purpose utility functions.
+This module contains a collection of general purpose utility functions.
"""
import pythoncom
diff --git a/com/win32comext/adsi/demos/scp.py b/com/win32comext/adsi/demos/scp.py
index b2ff016ec..dc5f831e8 100644
--- a/com/win32comext/adsi/demos/scp.py
+++ b/com/win32comext/adsi/demos/scp.py
@@ -419,7 +419,7 @@ def main():
"--test",
action="store_true",
help="Execute a mini-test suite, providing defaults for most options and args",
- ),
+ )
parser.add_option(
"",
diff --git a/com/win32comext/axdebug/adb.py b/com/win32comext/axdebug/adb.py
index 191041809..ee6b620c5 100644
--- a/com/win32comext/axdebug/adb.py
+++ b/com/win32comext/axdebug/adb.py
@@ -1,5 +1,4 @@
-"""The glue between the Python debugger interface and the Active Debugger interface
-"""
+"""The glue between the Python debugger interface and the Active Debugger interface"""
import _thread
import bdb
diff --git a/com/win32comext/axdebug/contexts.py b/com/win32comext/axdebug/contexts.py
index df6e97760..d732fbae1 100644
--- a/com/win32comext/axdebug/contexts.py
+++ b/com/win32comext/axdebug/contexts.py
@@ -1,6 +1,4 @@
-""" A module for managing the AXDebug I*Contexts
-
-"""
+"""A module for managing the AXDebug I*Contexts"""
from . import adb, axdebug, gateways
diff --git a/com/win32comext/axdebug/documents.py b/com/win32comext/axdebug/documents.py
index 560901fb4..723d2bf13 100644
--- a/com/win32comext/axdebug/documents.py
+++ b/com/win32comext/axdebug/documents.py
@@ -1,5 +1,4 @@
-""" Management of documents for AXDebugging.
-"""
+"""Management of documents for AXDebugging."""
import pythoncom
import win32api
@@ -106,7 +105,7 @@ class CodeContainerProvider:
Given a Python file name (as the debugger knows it by) this will
return a CodeContainer interface suitable for use.
- This provides a simple base imlpementation that simply supports
+ This provides a simple base implementation that simply supports
a dictionary of nodes and providers.
"""
diff --git a/com/win32comext/axdebug/dump.py b/com/win32comext/axdebug/dump.py
index 61a1cfc7a..6500167c0 100644
--- a/com/win32comext/axdebug/dump.py
+++ b/com/win32comext/axdebug/dump.py
@@ -46,9 +46,7 @@ def dumpall():
e = Enumerator(dm.EnumApplications())
for app in e:
print(f"Application: {app.GetName()}")
- node = (
- app.GetRootNode()
- ) # of type PyIDebugApplicationNode->PyIDebugDocumentProvider->PyIDebugDocumentInfo
+ node = app.GetRootNode() # of type PyIDebugApplicationNode->PyIDebugDocumentProvider->PyIDebugDocumentInfo
DumpDebugApplicationNode(node)
diff --git a/com/win32comext/axdebug/util.py b/com/win32comext/axdebug/util.py
index 424c529df..a9796a485 100644
--- a/com/win32comext/axdebug/util.py
+++ b/com/win32comext/axdebug/util.py
@@ -3,6 +3,7 @@
import os
import sys
+import traceback
import win32api
import win32com.server.dispatcher
@@ -43,13 +44,8 @@ def RaiseNotImpl(who=None):
print(f"********* Function {who} Raising E_NOTIMPL ************")
# Print a sort-of "traceback", dumping all the frames leading to here.
- try:
- 1 / 0
- except:
- frame = sys.exc_info()[2].tb_frame
- while frame:
+ for frame, i in traceback.walk_stack(sys._getframe()):
print(f"File: {frame.f_code.co_filename}, Line: {frame.f_lineno}")
- frame = frame.f_back
# and raise the exception for COM
raise COMException(scode=winerror.E_NOTIMPL)
diff --git a/com/win32comext/axscript/client/debug.py b/com/win32comext/axscript/client/debug.py
index 352b86453..bf7ef960a 100644
--- a/com/win32comext/axscript/client/debug.py
+++ b/com/win32comext/axscript/client/debug.py
@@ -125,12 +125,7 @@ def _query_interface_for_debugger_(self, iid):
def OnEnterScript(self):
trace("OnEnterScript")
- try:
- 1 / 0
- except:
- # Bit of a hack - reach into engine.
- baseFrame = sys.exc_info()[2].tb_frame.f_back
- self.adb.SetupAXDebugging(baseFrame)
+ self.adb.SetupAXDebugging(sys._getframe().f_back)
def OnLeaveScript(self):
trace("OnLeaveScript")
diff --git a/com/win32comext/axscript/client/error.py b/com/win32comext/axscript/client/error.py
index 5aadbf9bc..f02e66603 100644
--- a/com/win32comext/axscript/client/error.py
+++ b/com/win32comext/axscript/client/error.py
@@ -1,7 +1,7 @@
"""Exception and error handling.
- This contains the core exceptions that the implementations should raise
- as well as the IActiveScriptError interface code.
+This contains the core exceptions that the implementations should raise
+as well as the IActiveScriptError interface code.
"""
from __future__ import annotations
diff --git a/com/win32comext/axscript/client/framework.py b/com/win32comext/axscript/client/framework.py
index b9f0fd605..c4a04329f 100644
--- a/com/win32comext/axscript/client/framework.py
+++ b/com/win32comext/axscript/client/framework.py
@@ -1,10 +1,10 @@
"""AXScript Client Framework
- This module provides a core framework for an ActiveX Scripting client.
- Derived classes actually implement the AX Client itself, including the
- scoping rules, etc.
+This module provides a core framework for an ActiveX Scripting client.
+Derived classes actually implement the AX Client itself, including the
+scoping rules, etc.
- There are classes defined for the engine itself, and for ScriptItems
+There are classes defined for the engine itself, and for ScriptItems
"""
from __future__ import annotations
diff --git a/com/win32comext/axscript/client/pyscript.py b/com/win32comext/axscript/client/pyscript.py
index fd7806073..e281d16a7 100644
--- a/com/win32comext/axscript/client/pyscript.py
+++ b/com/win32comext/axscript/client/pyscript.py
@@ -100,7 +100,7 @@ def _FindAttribute_(self, attr):
class NamedScriptAttribute:
- "An explicitely named object in an objects namespace"
+ "An explicitly named object in an objects namespace"
# Each named object holds a reference to one of these.
# Whenever a sub-item appears in a namespace, it is really one of these
diff --git a/com/win32comext/axscript/client/scriptdispatch.py b/com/win32comext/axscript/client/scriptdispatch.py
index ca696fe84..6bd29adcb 100644
--- a/com/win32comext/axscript/client/scriptdispatch.py
+++ b/com/win32comext/axscript/client/scriptdispatch.py
@@ -1,8 +1,8 @@
"""dynamic dispatch objects for AX Script.
- This is an IDispatch object that a scripting host may use to
- query and invoke methods on the main script. Not may hosts use
- this yet, so it is not well tested!
+This is an IDispatch object that a scripting host may use to
+query and invoke methods on the main script. Not may hosts use
+this yet, so it is not well tested!
"""
from __future__ import annotations
diff --git a/com/win32comext/axscript/demos/client/ie/demo_intro.htm b/com/win32comext/axscript/demos/client/ie/demo_intro.htm
index 9987d8972..c02be1a6e 100644
--- a/com/win32comext/axscript/demos/client/ie/demo_intro.htm
+++ b/com/win32comext/axscript/demos/client/ie/demo_intro.htm
@@ -30,7 +30,7 @@ Known bugs and problems
Builtin objects such as MARQUEE are giving me grief. Objects accessed via forms are generally
no problem.
If you are trying to use Python with the Windows Scripting Host, note that
-.pys files are not correct registered - you will need to explicitely
+.pys files are not correct registered - you will need to explicitly
specify either cscript.exe or wscript.exe on the command line.