Skip to content

Commit

Permalink
Merge branch 'main' into Drop-Python-3.8-support
Browse files Browse the repository at this point in the history
  • Loading branch information
Avasam authored Jan 8, 2025
2 parents 1a9831b + 0ea624e commit 3b09520
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 59 deletions.
18 changes: 13 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,18 @@ jobs:
# This needs to happen *after* installing pywin32 since
# AutoDuck/py2d.py currently relies on runtime imports for introspection
# This isn't included in the wheel (TODO: could we?)
# and only servces as a PR test for the docs.yaml workflow
# and only serves as a PR test for the docs.yaml workflow
- name: Generate PyWin32.chm help file
run: python AutoDuck/make.py

# Smokescreen test to validate it doesn't crash and dlls can be found
- name: Run postinstall install/remove
run: |
$UserSite = "$(python -m site --user-site)"
cd "$UserSite/.."
python Scripts/pywin32_postinstall.py -install -destination "$UserSite"
python Scripts/pywin32_postinstall.py -remove -destination "$UserSite"
- name: Run tests
# Run the tests directly from the source dir so support files (eg, .wav files etc)
# can be found - they aren't installed into the Python tree.
Expand Down Expand Up @@ -119,9 +127,9 @@ jobs:
cache-dependency-path: .github/workflows/main.yml
- run: pip install clang-format==18.1.* pycln
- run: pycln . --config=pycln.toml --check
- uses: astral-sh/ruff-action@v2
- uses: astral-sh/ruff-action@v3
with:
version: "0.8.2"
version: "0.8.4"
- run: ruff format --check
- run:
| # Too many files to fit in a single command, also exclude vendored Scintilla and MAPIStubLibrary
Expand All @@ -145,7 +153,7 @@ jobs:
cache: pip
cache-dependency-path: .github/workflows/main.yml
check-latest: true
- run: pip install types-setuptools PyOpenGL mypy==1.11
- run: pip install types-setuptools PyOpenGL mypy[faster-cache]==1.14.*
- run: mypy . --python-version=${{ matrix.python-version }}

pyright:
Expand All @@ -168,5 +176,5 @@ jobs:
- uses: jakebailey/pyright-action@v2
with:
python-version: ${{ matrix.python-version }}
version: "1.1.358"
version: "1.1.389"
annotate: errors
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ win32/src/win32service_messages.h
win32/src/win32evtlog_messages.h
isapi/src/pyISAPI_messages.h

# VC2003 and up project files
# Visual Studio project files
*.sln
*.suo
*.vcproj
Expand Down
13 changes: 7 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# You can run this locally with `pre-commit run [--all]`
# You can run this locally with `pre-commit run --all`
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v5.0.0
hooks:
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
Expand All @@ -10,10 +10,11 @@ repos:
args: [--fix=crlf]
- id: check-case-conflict
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.13.0
rev: v2.14.0
hooks:
- id: pretty-format-toml
args: [--autofix, --trailing-commas, --inline-comment-spaces, "1", --no-sort]
# Has unsafe autofixes. Let's find a better formatter: macisamuele/language-formatters-pre-commit-hooks#202
# - id: pretty-format-toml
# args: [--autofix, --trailing-commas, --inline-comment-spaces, "1", --no-sort]
- id: pretty-format-yaml
args: [--autofix, --indent, "2", --offset, "2", --preserve-quotes]
- id: pretty-format-ini
Expand All @@ -25,7 +26,7 @@ repos:
args: [--config=pycln.toml]
verbose: true
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.2
rev: v0.8.4
hooks:
- id: ruff # Run the linter.
args: [--fix]
Expand Down
5 changes: 1 addition & 4 deletions adodbapi/quick_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,7 @@ where "click to buy" versions of Office have been removed, but are still
blocking installation of the redistributable provider.

- To use any ODBC driver from 64 bit Python, you also need the MSDASQL
provider. It is shipped with Server 2008, and Vista and later. For
Server 2003, You will have to [download
it](http://www.microsoft.com/en-us/download/details.aspx?id=20065) [from
Microsoft.]{lang="en-US"}
provider. It is shipped with Server 2008, and Vista and later.

- MySQL driver <http://dev.mysql.com/downloads/connector/odbc/>
or MariaDB driver <https://downloads.mariadb.org/connector-odbc/>
Expand Down
24 changes: 22 additions & 2 deletions com/win32com/client/gencache.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

from __future__ import annotations

import contextlib
import glob
import os
import sys
Expand All @@ -34,6 +35,7 @@
import pywintypes
import win32com
import win32com.client
import win32event

from . import CLSIDToClass

Expand Down Expand Up @@ -134,6 +136,22 @@ def _LoadDicts():
f.close()


@contextlib.contextmanager
def ModuleMutex(module_name):
"""Given the output of GetGeneratedFilename, acquire a named mutex for that module
This is required so that writes (generation) don't interfere with each other and with reads (import)
"""
mutex = win32event.CreateMutex(None, False, module_name)
with contextlib.closing(mutex):
# acquire mutex
win32event.WaitForSingleObject(mutex, win32event.INFINITE)
try:
yield
finally:
win32event.ReleaseMutex(mutex)


def GetGeneratedFileName(clsid, lcid, major, minor):
"""Given the clsid, lcid, major and minor for a type lib, return
the file name (no extension) providing this support.
Expand Down Expand Up @@ -259,7 +277,8 @@ class which wraps the COM object.
if sub_mod is not None:
sub_mod_name = mod.__name__ + "." + sub_mod
try:
__import__(sub_mod_name)
with ModuleMutex(mod.__name__.split(".")[-1]):
__import__(sub_mod_name)
except ImportError:
info = typelibCLSID, lcid, major, minor
# Force the generation. If this typelibrary has explicitly been added,
Expand Down Expand Up @@ -731,7 +750,8 @@ def GetGeneratedInfos():
def _GetModule(fname):
"""Given the name of a module in the gen_py directory, import and return it."""
mod_name = "win32com.gen_py.%s" % fname
mod = __import__(mod_name)
with ModuleMutex(fname):
__import__(mod_name)
return sys.modules[mod_name]


Expand Down
36 changes: 8 additions & 28 deletions com/win32com/client/genpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
from itertools import chain

import pythoncom
import win32com

from . import build
from . import build, gencache

makepy_version = "0.5.01" # Written to generated file.

Expand Down Expand Up @@ -1017,35 +1016,15 @@ def open_writer(self, filename, encoding="utf-8"):

def finish_writer(self, filename, f, worked):
f.close()
try:
os.unlink(filename)
except OSError:
pass
temp_filename = self.get_temp_filename(filename)
if worked:
os.replace(temp_filename, filename)
else:
try:
os.rename(temp_filename, filename)
os.unlink(filename)
os.unlink(temp_filename)
except OSError:
# If we are really unlucky, another process may have written the
# file in between our calls to os.unlink and os.rename. So try
# again, but only once.
# There are still some race conditions, but they seem difficult to
# fix, and they probably occur much less frequently:
# * The os.rename failure could occur more than once if more than
# two processes are involved.
# * In between os.unlink and os.rename, another process could try
# to import the module, having seen that it already exists.
# * If another process starts a COM server while we are still
# generating __init__.py, that process sees that the folder
# already exists and assumes that __init__.py is already there
# as well.
try:
os.unlink(filename)
except OSError:
pass
os.rename(temp_filename, filename)
else:
os.unlink(temp_filename)
pass

def get_temp_filename(self, filename):
return "%s.%d.temp" % (filename, os.getpid())
Expand Down Expand Up @@ -1327,7 +1306,8 @@ def generate_child(self, child, dir):
self.progress.Tick()
worked = True
finally:
self.finish_writer(out_name, self.file, worked)
with gencache.ModuleMutex(self.base_mod_name.split(".")[-1]):
self.finish_writer(out_name, self.file, worked)
self.file = None
finally:
self.progress.Finished()
Expand Down
13 changes: 8 additions & 5 deletions com/win32com/client/makepy.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,10 +293,11 @@ def GenerateFromTypeLibSpec(
for typelib, info in typelibs:
gen = genpy.Generator(typelib, info.dll, progress, bBuildHidden=bBuildHidden)

this_name = gencache.GetGeneratedFileName(
info.clsid, info.lcid, info.major, info.minor
)

if file is None:
this_name = gencache.GetGeneratedFileName(
info.clsid, info.lcid, info.major, info.minor
)
full_name = os.path.join(gencache.GetGeneratePath(), this_name)
if bForDemand:
try:
Expand Down Expand Up @@ -327,7 +328,8 @@ def GenerateFromTypeLibSpec(
worked = True
finally:
if file is None:
gen.finish_writer(outputName, fileUse, worked)
with gencache.ModuleMutex(this_name):
gen.finish_writer(outputName, fileUse, worked)
importlib.invalidate_caches()
if bToGenDir:
progress.SetDescription("Importing module")
Expand Down Expand Up @@ -372,7 +374,8 @@ def GenerateChildFromTypeLibSpec(
gen.generate_child(child, dir_path_name)
progress.SetDescription("Importing module")
importlib.invalidate_caches()
__import__("win32com.gen_py." + dir_name + "." + child)
with gencache.ModuleMutex(dir_name):
__import__("win32com.gen_py." + dir_name + "." + child)
progress.Close()


Expand Down
7 changes: 0 additions & 7 deletions com/win32com/src/PyGatewayBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,6 @@ extern const GUID IID_IInternalUnwrapPythonObject = {
extern PyObject *g_obMissing;

#include <malloc.h>
// When building with the 2003 Platform SDK 64-bit compiloer, _MSC_VER is 1400,
// but _malloca is not defined
// #if _MSC_VER < 1400
#ifndef _malloca
// _malloca is the new 'safe' one
#define _malloca _alloca
#endif

// Internal ErrorUtil helpers we reach in for.
// Free the strings from an excep-info.
Expand Down
6 changes: 5 additions & 1 deletion ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ target-version = "py39" # Target the oldest supported version in editors and def
# This file is not UTF-8
extend-exclude = ["Pythonwin/pywin/test/_dbgscript.py"]

[format]
line-ending = "cr-lf"

[lint]
select = [
"C4", # flake8-comprehensions
Expand Down Expand Up @@ -37,10 +40,11 @@ extend-ignore = [
"UP015", # redundant-open-modes
# No such concerns for stdlib
"TC003", # typing-only-standard-library-import
# TODO: Consider passing exception around to ensure methods are only ever used within exception handlers
"PLE0704", # misplaced-bare-raise
# TODO: Still lots of manual fixes needed
"UP031", # Use format specifiers instead of percent format
"UP032", # Use f-string instead of format call
"PLE0704", # misplaced-bare-raise: TODO
]

[lint.per-file-ignores]
Expand Down

0 comments on commit 3b09520

Please sign in to comment.