`inspect.isbuiltin` does not unwrap obj, but `inspect.signature` does,
which can result in a ValueError.
>>> wx.Bell
<built-in function Bell>
>>> bell #= dcor(wx.Bell)
<function Bell at 0x0000015E53D92B60>
>>> inspect.isbuiltin(bell)
False
>>> inspect.signature(bell)
... (snip) ...
ValueError: no signature found for builtin <built-in function Bell>
Due to there being multiple MSVC versions installed on the Azure images,
the build process seems to be getting parts of both of them, so remove
the older one.
Since this is used to not only generate the type-stubs, but also the actual
wx/core.py, we need to ensure TypeVar and ParamSpec are imported there as
well. So, move the imports to the wx/core.py generator definition, and
remove the imports from the type-stub generator (these imports are only
used by CallAfter and CallLater).
Named enums with 'Flags' in the name use `enum.IntFlag`, all other enums
use `enum.IntEnum`. We have to bring the enum members into the containing
scope to match the original behaviour. Further, since these enums are typing
information only, and not actually in wx proper, we prevent them from appearing
to leak the the user by marking as non-exported (prepend '_' to the name), then
make a TypeAlias to the enum or an int. This way type signatures still claim
to accept integers as appropriate.
I like this solution best, because we preserved the information about which
enum members are expected for method/function parameters, while not leaking
non-existant classes out of the type-stubs, and not complaining about using
integers.
There's still a few undefined but referenced enums (ex:
richtext.TextAttrDimensionFlags). These are most likely a union of some of
the other flags/enum types already defined, but the work to pull that information
from the C++ source is probably too much.
Use the more generic type rather than a literal type. Before, a type-checker
would infer an int defined this way as `Literal[0]` vs the more correctly
generic `int` for example.
By directly referencing their setter and getter methods,
and due to the typing work already done for methods, we now have
type information attached to properties.
There are a few edge cases of setters/getters not having the proper
number of arguments for a getter(0) or setter(1), but most cases are
handled. The incorrect number of arguments may be missing default
arguments from what the extraction code figures out from the C++ code?
With the work from the previous commits, it's as simple as
no longer lopping off the args string at the '->' marker.
(And one minor fixup to the makePyArgsString code).
These will be changing to annotation statements, so FixWxPrefix needs to
be able to detect this still (proper thing to look for in this case is
`ast.AnnAssign`).
One unexpected type of '...' required adding a new transformation
that modifies both the name and the type to just '*args', so added
a preferred method `FixWxPrefix.parseNameAndType` which processes
both strings at once.
Also fixes cleanType to recursively call cleanType on sub-types
(was improperly calling cleanName).
With this, method and function signatures now have type annotations
which are mostly correct (100% correct in the "it compiles" sense).
Thankfully, the incorrect type-hints don't cause errors due to using
stringized annotations (by importing annotations from __future__).
Importantly, the overload signatures now have been fully sanitized.
Before this, there was one instance of a variable named `is`, and another
named `/Transfer/` - both invalid identifiers. I stopped looking after
those. Since theses signatures are valid Python code, this opens up the
opportunity to use `typing.overload` to fully expose those.
Edge-cases in type-hints will be addressed in later commits.
Leverages the `writeSection` machinery, with a tweak to specify to add a
new section to the beginning of a file, after the header. This ensures
the required imports gets updated (and also only imported once per file)
if new imports are needed for type-hints. Hint: there's a few more to come.
This allows for building `FixWxPrefix.cleanType` on top of it, for use
in processing type-hint strings in the future. It also exposes the method
to `FunctionDef.makePyArgString` in the future, which has easier access to
the types of arguments and returns. And possibly further in the future,
other `***Def` classes can make use of it (constant definitions, etc).
The line-wrapping causes issues once the python signatures become too long,
as textwrap isn't smart enough to split the lines on valid continuation points
for code. I had one instance of splitting a line in the middle of a string ->
SyntaxError on next run of etg due to the generated PYI file having an
unterminated string.
Specificially, disable splitting for lines that start (ignoring spaces) with
a specific string - in this case any line starting with the name of the
function or method this is a docstring for.
The tarfile.extractall() filter argument was introduced in the most
recent CPython releases (e.g., 3.11.4) to avoid potential security
issues when extracting from potentially hostile tarballs. Let's use
this option if it is available and provide a warning if it is now.