Skip to content

Commit af6dd45

Browse files
committed
Replace pywin32_testutil.TestSkipped with unittest.SkipTest
1 parent 84a050c commit af6dd45

File tree

9 files changed

+62
-77
lines changed

9 files changed

+62
-77
lines changed

com/win32comext/directsound/test/ds_test.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import win32api
99
import win32com.directsound.directsound as ds
1010
import win32event
11-
from pywin32_testutil import TestSkipped, find_test_fixture
11+
from pywin32_testutil import find_test_fixture
1212

1313
# next two lines are for for debugging:
1414
# import win32com
@@ -37,7 +37,7 @@ def wav_header_unpack(data):
3737

3838
assert riff == b"RIFF", "invalid wav header"
3939

40-
# fmt chuck is not first chunk, directly followed by data chuck
40+
# fmt chunk is not first chunk, directly followed by data chunk
4141
# It is nowhere required that they are, it is just very common
4242
assert (
4343
fmtsize == 16 and fmt == b"fmt " and data == b"data"
@@ -298,7 +298,7 @@ def testCreate(self):
298298
except pythoncom.com_error as exc:
299299
if exc.hresult != ds.DSERR_NODRIVER:
300300
raise
301-
raise TestSkipped(exc)
301+
raise unittest.SkipTest(str(exc))
302302

303303
def testPlay(self):
304304
"""Mesdames et Messieurs, la cour de Devin Dazzle"""
@@ -318,7 +318,7 @@ def testPlay(self):
318318
except pythoncom.com_error as exc:
319319
if exc.hresult != ds.DSERR_NODRIVER:
320320
raise
321-
raise TestSkipped(exc)
321+
raise unittest.SkipTest(str(exc))
322322
d.SetCooperativeLevel(None, ds.DSSCL_PRIORITY)
323323

324324
sdesc = ds.DSBUFFERDESC()
@@ -358,15 +358,15 @@ def testCreate(self):
358358
except pythoncom.com_error as exc:
359359
if exc.hresult != ds.DSERR_NODRIVER:
360360
raise
361-
raise TestSkipped(exc)
361+
raise unittest.SkipTest(str(exc))
362362

363363
def testRecord(self):
364364
try:
365365
d = ds.DirectSoundCaptureCreate(None, None)
366366
except pythoncom.com_error as exc:
367367
if exc.hresult != ds.DSERR_NODRIVER:
368368
raise
369-
raise TestSkipped(exc)
369+
raise unittest.SkipTest(str(exc))
370370

371371
sdesc = ds.DSCBUFFERDESC()
372372
sdesc.dwBufferBytes = 352800 # 2 seconds

win32/Lib/pywin32_testutil.py

Lines changed: 30 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
# Utilities for the pywin32 tests
1+
"""Utilities for the pywin32 tests"""
2+
3+
from __future__ import annotations
4+
25
import gc
36
import os
47
import site
58
import sys
69
import unittest
10+
from typing import TYPE_CHECKING
711

12+
import pythoncom
13+
import pywintypes
814
import winerror
15+
from win32com.shell.shell import IsUserAnAdmin
16+
17+
if TYPE_CHECKING:
18+
from _typeshed import OptExcInfo
919

1020
##
1121
## unittest related stuff
@@ -145,20 +155,17 @@ def loadTestsFromName(self, name, module=None):
145155

146156
# win32 error codes that probably mean we need to be elevated (ie, if we
147157
# aren't elevated, we treat these error codes as 'skipped')
148-
non_admin_error_codes = [
158+
non_admin_error_codes = {
149159
winerror.ERROR_ACCESS_DENIED,
150160
winerror.ERROR_PRIVILEGE_NOT_HELD,
151-
]
161+
}
152162

153163
_is_admin = None
154164

155165

156166
def check_is_admin():
157167
global _is_admin
158168
if _is_admin is None:
159-
import pythoncom
160-
from win32com.shell.shell import IsUserAnAdmin
161-
162169
try:
163170
_is_admin = IsUserAnAdmin()
164171
except pythoncom.com_error as exc:
@@ -197,30 +204,19 @@ def find_test_fixture(basename, extra_dir="."):
197204
d = os.path.normcase(d)
198205
if os.path.commonprefix([this_file, d]) == d:
199206
# looks like we are in an installed Python, so skip the text.
200-
raise TestSkipped(f"Can't find test fixture '{fname}'")
207+
raise unittest.SkipTest(f"Can't find test fixture '{fname}'")
201208
# Looks like we are running from source, so this is fatal.
202209
raise RuntimeError(f"Can't find test fixture '{fname}'")
203210

204211

205-
# If this exception is raised by a test, the test is reported as a 'skip'
206-
class TestSkipped(Exception):
207-
pass
208-
209-
210212
# The 'TestResult' subclass that records the failures and has the special
211-
# handling for the TestSkipped exception.
213+
# handling for the unittest.SkipTest exception.
212214
class TestResult(unittest.TextTestResult):
213-
def __init__(self, *args, **kw):
214-
super().__init__(*args, **kw)
215-
self.skips = {} # count of skips for each reason.
215+
def addError(self, test: unittest.TestCase, err: OptExcInfo) -> None:
216+
"""Called when an error has occurred.
216217
217-
def addError(self, test, err):
218-
"""Called when an error has occurred. 'err' is a tuple of values as
219-
returned by sys.exc_info().
218+
Translate a couple of 'well-known' exceptions into 'skipped'
220219
"""
221-
# translate a couple of 'well-known' exceptions into 'skipped'
222-
import pywintypes
223-
224220
exc_val = err[1]
225221
# translate ERROR_ACCESS_DENIED for non-admin users to be skipped.
226222
# (access denied errors for an admin user aren't expected.)
@@ -229,42 +225,28 @@ def addError(self, test, err):
229225
and exc_val.winerror in non_admin_error_codes
230226
and not check_is_admin()
231227
):
232-
exc_val = TestSkipped(exc_val)
228+
return self.addSkip(test, str(exc_val))
233229
# and COM errors due to objects not being registered (the com test
234230
# suite will attempt to catch this and handle it itself if the user
235231
# is admin)
236-
elif isinstance(exc_val, pywintypes.com_error) and exc_val.hresult in [
232+
elif isinstance(exc_val, pywintypes.com_error) and exc_val.hresult in {
237233
winerror.CO_E_CLASSSTRING,
238234
winerror.REGDB_E_CLASSNOTREG,
239235
winerror.TYPE_E_LIBNOTREGISTERED,
240-
]:
241-
exc_val = TestSkipped(exc_val)
242-
# NotImplemented generally means the platform doesn't support the
243-
# functionality.
236+
}:
237+
return self.addSkip(test, str(exc_val))
238+
# NotImplemented generally means the platform doesn't support the functionality.
244239
elif isinstance(exc_val, NotImplementedError):
245-
exc_val = TestSkipped(NotImplementedError)
246-
247-
if isinstance(exc_val, TestSkipped):
248-
reason = exc_val.args[0]
249-
# if the reason itself is another exception, get its args.
250-
try:
251-
reason = tuple(reason.args)
252-
except (AttributeError, TypeError):
253-
pass
254-
self.skips.setdefault(reason, 0)
255-
self.skips[reason] += 1
256-
if self.showAll:
257-
self.stream.writeln(f"SKIP ({reason})")
258-
elif self.dots:
259-
self.stream.write("S")
260-
self.stream.flush()
261-
return
240+
return self.addSkip(test, str(exc_val))
241+
262242
super().addError(test, err)
263243

264-
def printErrors(self):
244+
def printErrors(self) -> None:
265245
super().printErrors()
266-
for reason, num_skipped in self.skips.items():
267-
self.stream.writeln("SKIPPED: %d tests - %s" % (num_skipped, reason))
246+
reasons = [reason for (test, reason) in self.skipped]
247+
reason_counts = [(reason, reasons.count(reason)) for reason in set(reasons)]
248+
for reason, num_skipped in reason_counts:
249+
self.stream.writeln(f"SKIPPED: {num_skipped} tests - {reason}")
268250

269251

270252
# TestRunner subclass necessary just to get our TestResult hooked up.

win32/test/test_odbc.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import odbc
88
import pythoncom
9-
from pywin32_testutil import TestSkipped
109
from win32com.client import constants
1110

1211
# We use the DAO ODBC driver
@@ -33,7 +32,7 @@ def setUp(self):
3332
except pythoncom.com_error:
3433
pass
3534
else:
36-
raise TestSkipped("Can't find a DB engine")
35+
raise unittest.SkipTest("Can't find a DB engine")
3736

3837
workspace = dbe.Workspaces(0)
3938

win32/test/test_security.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import win32con
88
import win32security
99
import winerror
10-
from pywin32_testutil import TestSkipped, testmain
10+
from pywin32_testutil import testmain
1111

1212

1313
class SecurityTests(unittest.TestCase):
@@ -27,7 +27,7 @@ def tearDown(self):
2727

2828
def testEqual(self):
2929
if self.admin_sid is None:
30-
raise TestSkipped("No 'Administrator' account is available")
30+
raise unittest.SkipTest("No 'Administrator' account is available")
3131
self.assertEqual(
3232
win32security.LookupAccountName("", "Administrator")[0],
3333
win32security.LookupAccountName("", "Administrator")[0],
@@ -51,7 +51,7 @@ def testSIDInDict(self):
5151

5252
def testBuffer(self):
5353
if self.admin_sid is None:
54-
raise TestSkipped("No 'Administrator' account is available")
54+
raise unittest.SkipTest("No 'Administrator' account is available")
5555
self.assertEqual(
5656
memoryview(win32security.LookupAccountName("", "Administrator")[0]),
5757
memoryview(win32security.LookupAccountName("", "Administrator")[0]),
@@ -97,7 +97,7 @@ def setUp(self):
9797
except win32security.error as exc:
9898
if exc.winerror != winerror.ERROR_NO_SUCH_DOMAIN:
9999
raise
100-
raise TestSkipped(exc)
100+
raise unittest.SkipTest(str(exc))
101101

102102
def tearDown(self):
103103
if self.ds_handle is not None:

win32/test/test_sspi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import sspicon
88
import win32api
99
import win32security
10-
from pywin32_testutil import TestSkipped, testmain
10+
from pywin32_testutil import testmain
1111

1212

1313
# It is quite likely that the Kerberos tests will fail due to not being
@@ -21,7 +21,7 @@ def applyHandlingSkips(func, *args):
2121
sspicon.SEC_E_NO_CREDENTIALS,
2222
sspicon.SEC_E_NO_AUTHENTICATING_AUTHORITY,
2323
]:
24-
raise TestSkipped(exc)
24+
raise unittest.SkipTest(str(exc))
2525
raise
2626

2727

win32/test/test_win32api.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import win32con
1212
import win32event
1313
import winerror
14-
from pywin32_testutil import TestSkipped
1514

1615

1716
class TestError(Exception):
@@ -23,7 +22,7 @@ def testGetCurrentUser(self):
2322
domain = win32api.GetDomainName()
2423
if domain == "NT AUTHORITY":
2524
# Running as a service account, so the comparison will fail
26-
raise TestSkipped("running as service account")
25+
raise unittest.SkipTest("running as service account")
2726
name = f"{domain}\\{win32api.GetUserName()}"
2827
self.assertEqual(name, win32api.GetUserNameEx(win32api.NameSamCompatible))
2928

win32/test/test_win32file.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import win32pipe
1818
import win32timezone
1919
import winerror
20-
from pywin32_testutil import TestSkipped, testmain
20+
from pywin32_testutil import testmain
2121

2222

2323
class TestReadBuffer(unittest.TestCase):
@@ -802,15 +802,17 @@ def test_connect_with_payload(self):
802802
except win32file.error as exc:
803803
win32event.SetEvent(giveup_event)
804804
if exc.winerror == 10022: # WSAEINVAL
805-
raise TestSkipped("ConnectEx is not available on this platform")
805+
raise unittest.SkipTest("ConnectEx is not available on this platform")
806806
raise # some error error we don't expect.
807807
# We occasionally see ERROR_CONNECTION_REFUSED in automation
808808
try:
809809
win32file.GetOverlappedResult(s2.fileno(), ol, 1)
810810
except win32file.error as exc:
811811
win32event.SetEvent(giveup_event)
812812
if exc.winerror == winerror.ERROR_CONNECTION_REFUSED:
813-
raise TestSkipped("Assuming ERROR_CONNECTION_REFUSED is transient")
813+
raise unittest.SkipTest(
814+
"Assuming ERROR_CONNECTION_REFUSED is transient"
815+
)
814816
raise
815817
ol = pywintypes.OVERLAPPED()
816818
buff = win32file.AllocateReadBuffer(1024)
@@ -837,15 +839,17 @@ def test_connect_without_payload(self):
837839
except win32file.error as exc:
838840
win32event.SetEvent(giveup_event)
839841
if exc.winerror == 10022: # WSAEINVAL
840-
raise TestSkipped("ConnectEx is not available on this platform")
842+
raise unittest.SkipTest("ConnectEx is not available on this platform")
841843
raise # some error error we don't expect.
842844
# We occasionally see ERROR_CONNECTION_REFUSED in automation
843845
try:
844846
win32file.GetOverlappedResult(s2.fileno(), ol, 1)
845847
except win32file.error as exc:
846848
win32event.SetEvent(giveup_event)
847849
if exc.winerror == winerror.ERROR_CONNECTION_REFUSED:
848-
raise TestSkipped("Assuming ERROR_CONNECTION_REFUSED is transient")
850+
raise unittest.SkipTest(
851+
"Assuming ERROR_CONNECTION_REFUSED is transient"
852+
)
849853
raise
850854

851855
ol = pywintypes.OVERLAPPED()

win32/test/test_win32inet.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import unittest
22

33
import winerror
4-
from pywin32_testutil import TestSkipped, testmain
4+
from pywin32_testutil import testmain
55
from win32inet import (
66
FtpCommand,
77
InternetCanonicalizeUrl,
@@ -101,7 +101,7 @@ def testFtpCommand(self):
101101
finally:
102102
hcon.Close()
103103
except error as e:
104-
raise TestSkipped(e)
104+
raise unittest.SkipTest(str(e))
105105

106106

107107
if __name__ == "__main__":

win32/test/test_win32trace.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,21 @@
55
import unittest
66

77
import win32trace
8-
from pywin32_testutil import TestSkipped
98

109
if __name__ == "__main__":
1110
this_file = sys.argv[0]
1211
else:
1312
this_file = __file__
1413

1514

16-
def SkipIfCI():
17-
# This test often fails in CI, probably when it is being run multiple times
18-
# (ie, for different Python versions)
19-
# Github actions always have a `CI` variable.
15+
def SkipIfCI() -> None:
16+
"""For tests that often fails in CI, probably when it is being run multiple times
17+
(ie, for different Python versions)
18+
19+
Github actions always have a `CI` variable.
20+
"""
2021
if "CI" in os.environ:
21-
raise TestSkipped("We skip this test on CI")
22+
raise unittest.SkipTest("We skip this test on CI")
2223

2324

2425
def CheckNoOtherReaders():

0 commit comments

Comments
 (0)