diff --git a/CHANGES.txt b/CHANGES.txt index 0e11d0643..5613709da 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -15,6 +15,7 @@ Coming in build 307, as yet unreleased -------------------------------------- ### pywin32 +* Fixed import issues in ocx and app pywin Demos (#2291, @Avasam) * Add RealGetWindowClass (#2299, @CristiFati) * Make it compile on Python 3.13 (#2260, @clin1234) * Fixed accidentally trying to raise a `str` instead of an `Exception` in (#2270, @Avasam) diff --git a/Pythonwin/pywin/Demos/app/customprint.py b/Pythonwin/pywin/Demos/app/customprint.py index 4a666ca41..5682585de 100644 --- a/Pythonwin/pywin/Demos/app/customprint.py +++ b/Pythonwin/pywin/Demos/app/customprint.py @@ -7,7 +7,7 @@ import win32con import win32ui -from pywin.framework import app +from pywin.framework.app import CApp from pywin.mfc import afxres, dialog, docview PRINTDLGORD = 1538 @@ -134,10 +134,7 @@ def OnPrint(self, dc, pInfo): y += cyChar -class PrintDemoApp(app.CApp): - def __init__(self): - app.CApp.__init__(self) - +class PrintDemoApp(CApp): def InitInstance(self): template = PrintDemoTemplate(None, None, None, PrintDemoView) self.AddDocTemplate(template) @@ -175,11 +172,12 @@ def OnOK(self): if __name__ == "__main__": - # Running under Pythonwin + def test(): template = PrintDemoTemplate(None, None, None, PrintDemoView) template.OpenDocumentFile(None) test() else: + # Running under Pythonwin app = PrintDemoApp() diff --git a/Pythonwin/pywin/Demos/app/demoutils.py b/Pythonwin/pywin/Demos/app/demoutils.py index ee1fefcfa..171549a0e 100644 --- a/Pythonwin/pywin/Demos/app/demoutils.py +++ b/Pythonwin/pywin/Demos/app/demoutils.py @@ -60,6 +60,4 @@ def NeedApp(): if __name__ == "__main__": - import demoutils - - demoutils.NotAScript() + NotAScript() diff --git a/Pythonwin/pywin/Demos/cmdserver.py b/Pythonwin/pywin/Demos/cmdserver.py index 4ec6e49b3..3ea93c695 100644 --- a/Pythonwin/pywin/Demos/cmdserver.py +++ b/Pythonwin/pywin/Demos/cmdserver.py @@ -107,7 +107,7 @@ def ServerThread(myout, cmd, title, bCloseOnEnd): # assist for reloading (when debugging) - use only 1 tracer object, # else a large chain of tracer objects will exist. try: - writer + writer # type: ignore[has-type, used-before-def] except NameError: writer = ThreadWriter() if __name__ == "__main__": diff --git a/Pythonwin/pywin/Demos/menutest.py b/Pythonwin/pywin/Demos/menutest.py index d2ba65b6d..6117b7acd 100644 --- a/Pythonwin/pywin/Demos/menutest.py +++ b/Pythonwin/pywin/Demos/menutest.py @@ -5,7 +5,7 @@ if __name__ == "__main__": import demoutils - if demoutils.NeedGoodGUI(): + if demoutils.NeedGoodGUI() and interact.edit is not None: win = interact.edit.currentView.GetParent() menu = win.GetSystemMenu() id = menu.GetMenuItemID(6) diff --git a/Pythonwin/pywin/Demos/ocx/__init__.py b/Pythonwin/pywin/Demos/ocx/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/Pythonwin/pywin/Demos/ocx/demoutils.py b/Pythonwin/pywin/Demos/ocx/demoutils.py index 80d8c2450..171549a0e 100644 --- a/Pythonwin/pywin/Demos/ocx/demoutils.py +++ b/Pythonwin/pywin/Demos/ocx/demoutils.py @@ -60,6 +60,4 @@ def NeedApp(): if __name__ == "__main__": - from . import demoutils - - demoutils.NotAScript() + NotAScript() diff --git a/Pythonwin/pywin/Demos/ocx/ocxserialtest.py b/Pythonwin/pywin/Demos/ocx/ocxserialtest.py index 326d312c8..ae17127ec 100644 --- a/Pythonwin/pywin/Demos/ocx/ocxserialtest.py +++ b/Pythonwin/pywin/Demos/ocx/ocxserialtest.py @@ -127,7 +127,7 @@ def test(): if __name__ == "__main__": - from . import demoutils + import demoutils if demoutils.NeedGoodGUI(): test() diff --git a/Pythonwin/pywin/Demos/ocx/ocxtest.py b/Pythonwin/pywin/Demos/ocx/ocxtest.py index 695f708b8..31a63a3e1 100644 --- a/Pythonwin/pywin/Demos/ocx/ocxtest.py +++ b/Pythonwin/pywin/Demos/ocx/ocxtest.py @@ -238,7 +238,7 @@ def demo(): if __name__ == "__main__": - from . import demoutils + import demoutils if demoutils.NeedGoodGUI(): testall() diff --git a/mypy.ini b/mypy.ini index a93198a2f..a7fdeaea8 100644 --- a/mypy.ini +++ b/mypy.ini @@ -10,10 +10,15 @@ implicit_reexport = true explicit_package_bases = true ; Must specify top-level packages and scripts folders for mypy to work with explicit_package_bases mypy_path = + $MYPY_CONFIG_FILE_DIR/AutoDuck, $MYPY_CONFIG_FILE_DIR/com, - $MYPY_CONFIG_FILE_DIR/win32/Lib, $MYPY_CONFIG_FILE_DIR/Pythonwin, - $MYPY_CONFIG_FILE_DIR/AutoDuck, + $MYPY_CONFIG_FILE_DIR/Pythonwin/pywin/Demos, + $MYPY_CONFIG_FILE_DIR/win32/Demos, + $MYPY_CONFIG_FILE_DIR/win32/Demos/security, + $MYPY_CONFIG_FILE_DIR/win32/Demos/service, + $MYPY_CONFIG_FILE_DIR/win32/Demos/win32wnet, + $MYPY_CONFIG_FILE_DIR/win32/Lib, $MYPY_CONFIG_FILE_DIR/win32/scripts/VersionStamp, ; TODO: Gradually type classes and functions until we can turn back check_untyped_defs to true. @@ -41,18 +46,19 @@ exclude = (?x)( ; Forked IDLE extensions predating Python 2.3. They now live in idlelib in https://github.com/python/cpython/tree/main/Lib/idlelib | ^Pythonwin/pywin/idle/ ; TODO: Ignoring non-public APIs until all public API is typed - | ([Tt]est|[Dd]emos?)/ + | ([Tt]est|demos?)/ ) ; C-modules that will need type-stubs -[mypy-adsi.*,dde,exchange,exchdapi,mapi,perfmon,servicemanager,win32api,win32console,win32clipboard,win32comext.adsi.adsi,win32event,win32evtlog,win32file,win32gui,win32help,win32pdh,win32process,win32ras,win32security,win32service,win32trace,win32ui,win32uiole,win32wnet,_win32sysloader,_winxptheme] +[mypy-adsi.*,dde,exchange,exchdapi,mapi,mmapfile,perfmon,servicemanager,timer,win32api,win32console,win32clipboard,win32comext.adsi.adsi,win32cred,win32event,win32evtlog,win32file,win32gui,win32help,win32net,win32pdh,win32pipe,win32print,win32process,win32profile,win32ras,win32security,win32service,win32trace,win32transaction,win32ts,win32ui,win32uiole,win32wnet,_win32sysloader,_winxptheme] ignore_missing_imports = True +; pywin32_system32 is an empty module created in setup.py to store dlls +; OpenGL is untyped +; Test is a local untyped module in win32comext.axdebug ; verstamp is installed from win32verstamp.py called in setup.py ; Most of win32com re-exports win32comext -; Test is a local untyped module in win32comext.axdebug -; pywin32_system32 is an empty module created in setup.py to store dlls -[mypy-verstamp,win32com.*,Test,pywin32_system32] +[mypy-pywin32_system32,OpenGL.*,Test,verstamp,win32com.*] ignore_missing_imports = True ; Distutils being removed from stdlib currently causes some issues on Python 3.12 diff --git a/win32/Demos/EvtSubscribe_push.py b/win32/Demos/EvtSubscribe_push.py index 519ef0d72..7bc5de42b 100644 --- a/win32/Demos/EvtSubscribe_push.py +++ b/win32/Demos/EvtSubscribe_push.py @@ -1,4 +1,6 @@ ## Demonstrates a "push" subscription with a callback function +from __future__ import annotations + import win32evtlog query_text = '*[System[Provider[@Name="Microsoft-Windows-Winlogon"]]]' @@ -15,7 +17,7 @@ def c(reason, context, evt): return 0 -evttext = [] +evttext: list[str] = [] s = win32evtlog.EvtSubscribe( "System", win32evtlog.EvtSubscribeStartAtOldestRecord, diff --git a/win32/Demos/FileSecurityTest.py b/win32/Demos/FileSecurityTest.py index 4cb1aea2d..b76e60129 100644 --- a/win32/Demos/FileSecurityTest.py +++ b/win32/Demos/FileSecurityTest.py @@ -1,4 +1,6 @@ # Contributed by Kelly Kranabetter. +from __future__ import annotations + import os import sys @@ -116,7 +118,7 @@ "GENERIC_ALL", ) if os.path.isfile(name): - permissions = permissions_file + permissions: tuple[str, ...] = permissions_file else: permissions = permissions_dir # directories also contain an ACE that is inherited by children (files) within them diff --git a/win32/Demos/OpenEncryptedFileRaw.py b/win32/Demos/OpenEncryptedFileRaw.py index 5e2a929f0..25efe303e 100644 --- a/win32/Demos/OpenEncryptedFileRaw.py +++ b/win32/Demos/OpenEncryptedFileRaw.py @@ -30,37 +30,34 @@ def WriteCallback(output_buffer, data, buflen): ## create an encrypted file fname = win32api.GetTempFileName(dst_dir, "ref")[0] print("orig file:", fname) -f = open(fname, "w") -f.write("xxxxxxxxxxxxxxxx\n" * 32768) -f.close() +with open(fname, "w") as f: + f.write("xxxxxxxxxxxxxxxx\n" * 32768) ## add a couple of extra data streams -f = open(fname + ":stream_y", "w") -f.write("yyyyyyyyyyyyyyyy\n" * 32768) -f.close() -f = open(fname + ":stream_z", "w") -f.write("zzzzzzzzzzzzzzzz\n" * 32768) -f.close() +with open(fname + ":stream_y", "w") as f: + f.write("yyyyyyyyyyyyyyyy\n" * 32768) +with open(fname + ":stream_z", "w") as f: + f.write("zzzzzzzzzzzzzzzz\n" * 32768) win32file.EncryptFile(fname) ## backup raw data of encrypted file bkup_fname = win32api.GetTempFileName(dst_dir, "bef")[0] print("backup file:", bkup_fname) -f = open(bkup_fname, "wb") +fw = open(bkup_fname, "wb") ctxt = win32file.OpenEncryptedFileRaw(fname, 0) try: - win32file.ReadEncryptedFileRaw(ReadCallback, (fname, bkup_fname, f), ctxt) + win32file.ReadEncryptedFileRaw(ReadCallback, (fname, bkup_fname, fw), ctxt) finally: ## if context is not closed, file remains locked even if calling process is killed win32file.CloseEncryptedFileRaw(ctxt) - f.close() + fw.close() ## restore data from backup to new encrypted file dst_fname = win32api.GetTempFileName(dst_dir, "wef")[0] print("restored file:", dst_fname) -f = open(bkup_fname, "rb") +fr = open(bkup_fname, "rb") ctxtout = win32file.OpenEncryptedFileRaw(dst_fname, win32file.CREATE_FOR_IMPORT) try: - win32file.WriteEncryptedFileRaw(WriteCallback, (bkup_fname, dst_fname, f), ctxtout) + win32file.WriteEncryptedFileRaw(WriteCallback, (bkup_fname, dst_fname, fr), ctxtout) finally: win32file.CloseEncryptedFileRaw(ctxtout) - f.close() + fr.close() diff --git a/win32/Demos/desktopmanager.py b/win32/Demos/desktopmanager.py index ff2441e06..139a09b1e 100644 --- a/win32/Demos/desktopmanager.py +++ b/win32/Demos/desktopmanager.py @@ -1,4 +1,5 @@ # Demonstrates using a taskbar icon to create and navigate between desktops +from __future__ import annotations import _thread import io @@ -115,7 +116,7 @@ def new_icon(hdesk, desktop_name): flags, win32con.WM_USER + 20, hicon, - "Desktop Manager (%s)" % desktop_name, + f"Desktop Manager ({desktop_name})", ) window_info[hwnd] = notify_info ## wait for explorer to initialize system tray for new desktop @@ -221,7 +222,7 @@ def icon_wndproc(hwnd, msg, wp, lp): return win32gui.DefWindowProc(hwnd, msg, wp, lp) -window_info = {} +window_info: dict[int, tuple[int, int, int, int, int, str]] = {} origin_desktop = win32service.OpenInputDesktop(0, True, win32con.MAXIMUM_ALLOWED) origin_desktop_name = win32service.GetUserObjectInformation( origin_desktop, win32service.UOI_NAME diff --git a/win32/Demos/security/explicit_entries.py b/win32/Demos/security/explicit_entries.py index be37ee047..9a8bff988 100644 --- a/win32/Demos/security/explicit_entries.py +++ b/win32/Demos/security/explicit_entries.py @@ -69,101 +69,86 @@ ## MultipleTrustee,MultipleTrusteeOperation,TrusteeForm,TrusteeType,Identifier ## first two are ignored -my_trustee = {} -my_trustee["MultipleTrustee"] = None -my_trustee["MultipleTrusteeOperation"] = 0 -my_trustee["TrusteeForm"] = TRUSTEE_FORM.TRUSTEE_IS_SID -my_trustee["TrusteeType"] = TRUSTEE_TYPE.TRUSTEE_IS_USER -my_trustee["Identifier"] = my_sid - -tmp_trustee = {} -tmp_trustee["MultipleTrustee"] = None -tmp_trustee["MultipleTrusteeOperation"] = 0 -tmp_trustee["TrusteeForm"] = TRUSTEE_FORM.TRUSTEE_IS_NAME -tmp_trustee["TrusteeType"] = TRUSTEE_TYPE.TRUSTEE_IS_USER -tmp_trustee["Identifier"] = "rupole\\tmp" - -pwr_trustee = {} -pwr_trustee["MultipleTrustee"] = None -pwr_trustee["MultipleTrusteeOperation"] = 0 -pwr_trustee["TrusteeForm"] = TRUSTEE_FORM.TRUSTEE_IS_SID -pwr_trustee["TrusteeType"] = TRUSTEE_TYPE.TRUSTEE_IS_USER -pwr_trustee["Identifier"] = pwr_sid - -expl_list = [] -expl_list.append( +my_trustee = { + "MultipleTrustee": None, + "MultipleTrusteeOperation": 0, + "TrusteeForm": TRUSTEE_FORM.TRUSTEE_IS_SID, + "TrusteeType": TRUSTEE_TYPE.TRUSTEE_IS_USER, + "Identifier": my_sid, +} + +tmp_trustee = { + "MultipleTrustee": None, + "MultipleTrusteeOperation": 0, + "TrusteeForm": TRUSTEE_FORM.TRUSTEE_IS_NAME, + "TrusteeType": TRUSTEE_TYPE.TRUSTEE_IS_USER, + "Identifier": "rupole\\tmp", +} + +pwr_trustee = { + "MultipleTrustee": None, + "MultipleTrusteeOperation": 0, + "TrusteeForm": TRUSTEE_FORM.TRUSTEE_IS_SID, + "TrusteeType": TRUSTEE_TYPE.TRUSTEE_IS_USER, + "Identifier": pwr_sid, +} + +expl_list = [ { "Trustee": my_trustee, "Inheritance": ACE_FLAGS.NO_INHERITANCE, "AccessMode": ACCESS_MODE.SET_AUDIT_SUCCESS, ##|ACCESS_MODE.SET_AUDIT_FAILURE, "AccessPermissions": win32con.GENERIC_ALL, - } -) - -expl_list.append( + }, { "Trustee": my_trustee, "Inheritance": ACE_FLAGS.NO_INHERITANCE, "AccessMode": ACCESS_MODE.SET_AUDIT_FAILURE, "AccessPermissions": win32con.GENERIC_ALL, - } -) - -expl_list.append( + }, { "Trustee": tmp_trustee, "Inheritance": ACE_FLAGS.NO_INHERITANCE, "AccessMode": ACCESS_MODE.SET_AUDIT_SUCCESS, "AccessPermissions": win32con.GENERIC_ALL, - } -) - -expl_list.append( + }, { "Trustee": tmp_trustee, "Inheritance": ACE_FLAGS.NO_INHERITANCE, "AccessMode": ACCESS_MODE.SET_AUDIT_FAILURE, "AccessPermissions": win32con.GENERIC_ALL, - } -) + }, +] old_sacl.SetEntriesInAcl(expl_list) -expl_list = [] -expl_list.append( +expl_list = [ { "Trustee": tmp_trustee, "Inheritance": ACE_FLAGS.NO_INHERITANCE, "AccessMode": ACCESS_MODE.DENY_ACCESS, "AccessPermissions": win32con.DELETE, - } -) - -expl_list.append( + }, { "Trustee": tmp_trustee, "Inheritance": ACE_FLAGS.NO_INHERITANCE, "AccessMode": ACCESS_MODE.GRANT_ACCESS, "AccessPermissions": win32con.WRITE_OWNER, - } -) -expl_list.append( + }, { "Trustee": pwr_trustee, "Inheritance": ACE_FLAGS.NO_INHERITANCE, "AccessMode": ACCESS_MODE.GRANT_ACCESS, "AccessPermissions": win32con.GENERIC_READ, - } -) -expl_list.append( + }, { "Trustee": my_trustee, "Inheritance": ACE_FLAGS.NO_INHERITANCE, "AccessMode": ACCESS_MODE.GRANT_ACCESS, "AccessPermissions": win32con.GENERIC_ALL, - } -) - + }, +] old_dacl.SetEntriesInAcl(expl_list) + sd.SetSecurityDescriptorSacl(1, old_sacl, 1) sd.SetSecurityDescriptorDacl(1, old_dacl, 1) sd.SetSecurityDescriptorOwner(pwr_sid, 1) diff --git a/win32/Lib/win32serviceutil.py b/win32/Lib/win32serviceutil.py index 2871b9056..eb79a9933 100644 --- a/win32/Lib/win32serviceutil.py +++ b/win32/Lib/win32serviceutil.py @@ -5,11 +5,13 @@ # (which is win32service.error, pywintypes.error, etc) # when things go wrong - eg, not enough permissions to hit the # registry etc. +from __future__ import annotations import importlib.machinery import os import sys import warnings +from typing import ClassVar import pywintypes import win32api @@ -965,9 +967,9 @@ class ServiceFramework: # Optional Attributes: _svc_deps_ = None # sequence of service names on which this depends - _exe_name_ = None # Default to PythonService.exe - _exe_args_ = None # Default to no arguments - _svc_description_ = ( + _exe_name_: ClassVar[str | None] = None # Default to PythonService.exe + _exe_args_: ClassVar[str | None] = None # Default to no arguments + _svc_description_: ClassVar[str | None] = ( None # Only exists on Windows 2000 or later, ignored on windows NT )