Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use typed_kwargs with dependency() #13995

Open
wants to merge 46 commits into
base: master
Choose a base branch
from

Conversation

dcbaker
Copy link
Member

@dcbaker dcbaker commented Dec 9, 2024

This only converts the keyword arguments that are defined in the interpreter, which means that many arguments that are specific to certain dependencies are not covered here, and continue to rely on being handled further down the stack. That is a problem I'd like to address, but this is already 31 commits, and I don't want to make it even harder to review. This also attempts to minimize changes below the interpreter (with the exception of updating the dependency key generating function), again, for the purposes of making review easier and not creating too large of a change all at once. This means in some cases we now awkwardly handle the type we really want to see, as well as the raw type from the DSL that we don't want in the lower levels (bool vs MachineChoice as pretty obvious example).

I have made an effort to make this easier to review and bisect by having numerous small patches. This should also make it possible to merge this series in pieces if that's desirable, because I've tried very hard to make everything work at all points in the series.

@dcbaker dcbaker requested a review from jpakkane as a code owner December 9, 2024 23:04
mesonbuild/interpreter/dependencyfallbacks.py Dismissed Show dismissed Hide dismissed
mesonbuild/interpreter/interpreter.py Dismissed Show dismissed Hide dismissed
@dcbaker
Copy link
Member Author

dcbaker commented Dec 9, 2024

I noticed that some of the linters are failing, and I have fixups for those locally, but to avoid spamming CI I'll wait to push those until after I've seen what tests fail in CI that passed locally.

@dcbaker dcbaker force-pushed the submit/use-typed-kwargs-for-dependency branch 2 times, most recently from 11f34e7 to 2914829 Compare December 9, 2024 23:32
'default_options', 'not_found_message', 'include_type'}
valid_keys = [n for n in DEPENDENCY_KWS
if n.name not in invalid_keys]
for dep in valid_keys:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you like the continue? In this form, the list of keys needs to be iterated twice, which seems wasteful.

I would have written:

for dep in DEPENDECY_KWS:
    if dep.name in invalid_keys:
        continue
    ...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this simplifies the loop body, and I generally prefer that. I don't know that it really matters either way though?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it does not matter. I was just curious because you mentioned the elimination of the continue in the commit message as it was something important. I prefer the code as I wrote it before, but it is mostly personal preference, I guess.

Copy link
Member Author

@dcbaker dcbaker Dec 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that comment is a little out of date, and the continue I was calling attention to isn't removed (or added) anymore! Originally in this commit I changed the function to always include all of the relevant keys, but that broke previous commits, so this commit got split from one commit at the end of the series to two, one at the end and one at the beginning.

@dcbaker dcbaker force-pushed the submit/use-typed-kwargs-for-dependency branch 5 times, most recently from 79d0290 to 0d7dee8 Compare December 10, 2024 19:26
run_project_tests.py Outdated Show resolved Hide resolved
@@ -62,7 +62,7 @@ def get_dep_identifier(name: str, kwargs: T.Dict[str, T.Any]) -> 'TV_DepID':
assert isinstance(i, str), i
value = tuple(frozenset(listify(value)))
else:
assert isinstance(value, (str, bool, int)), value
assert value is None or isinstance(value, (str, bool, int)), value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isinstance(value, (types.NoneType, str, bool, int)), value ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the idiomatic way to do it, though I do like the less typing of the single isinstance check. I wonder if anyone else has opinions?

mesonbuild/modules/python.py Outdated Show resolved Hide resolved
@dcbaker dcbaker force-pushed the submit/use-typed-kwargs-for-dependency branch 2 times, most recently from 086e36d to 2f556cc Compare December 11, 2024 20:46
Comment on lines 410 to 411
if not isinstance(static, bool):
raise DependencyException('Static keyword must be boolean')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is it possible for it to be something other than (NoneType, bool) now that we typecheck this?

@@ -857,4 +857,5 @@ def _pkgconfig_define_convertor(x: T.List[str]) -> PkgConfigDefineType:
DEFAULT_OPTIONS.evolve(since='0.38.0'),
KwargInfo('allow_fallback', (bool, NoneType), since='0.56.0'),
KwargInfo('cmake_args', ContainerTypeInfo(list, str), listify=True, default=[], since='0.50.0'),
KwargInfo('cmake_module_path', ContainerTypeInfo(list, str), listify=True, default=[], since='0.50.0'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surely we should be e.g. removing mesonbuild/dependencies/cmake.py:

cm_path = stringlistify(extract_as_list(kwargs, 'cmake_module_path'))

and just using kwargs.get('cmake_module_path', []) (assuming we can construct it from places other than func_dependency())

Copy link
Member

@eli-schwartz eli-schwartz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not going to do a full review, a cursory inspection reveals this PR has the same problems that plagued the previous big typed_kwargs rewrite: general failure to demonstrate that the typed_kwargs are equal to what we had before by cross-comparing to our existing handrolled build layer checks and removing the obsolete bits.

Trying to review that PR just got me ignored, so I have no motivation to review this one.

@dcbaker
Copy link
Member Author

dcbaker commented Dec 12, 2024

@eli-schwartz I'm not really sure what the way forward is then. The last time I made a PR like this I did makes changes to the mid and lower lyayrs to make sure everything worked correctly, it was hundreds of patches, and each one was huge. So that went around and around in review, having to be rebased several times, often leading to days of work trying to get everything correctly again after the rebase, only to have to repeat it again a week later. That was super frustrating and de-motivating.

I tried this time to do the opposite, very small self contained changes that were conservative by leaving the lower level valadation in place until we could move to mypy based checking for those and remove the run time validation since we had static analysis to help ensure that the lower levels weren't getting invalid information.

What approach would make this better to review from your point of view?

@dcbaker dcbaker force-pushed the submit/use-typed-kwargs-for-dependency branch from 2f556cc to a9d130b Compare December 13, 2024 22:22
@dcbaker
Copy link
Member Author

dcbaker commented Dec 13, 2024

@eli-schwartz is this the sort of work you'd like to see? (I'm aware the names of some of the commits are not suitable for merging)


class ExternalDependency(Dependency, HasNativeKwarg):
def __init__(self, type_name: DependencyTypeName, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None):
class ExternalDependency(Dependency):

Check warning

Code scanning / CodeQL

`__eq__` not overridden when adding attributes Warning

The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
env
.
The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
name
.
The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
is_found
.
The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
language
.
The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
version_reqs
.
The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
required
.
The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
silent
.
The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
static
.
The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
libtype
.
The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
for_machine
.
The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
clib_compiler
.
The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
is_found
.
The class 'ExternalDependency' does not override
'__eq__'
, but adds the new attribute
is_found
.
@@ -17,6 +17,7 @@
import typing as T

if T.TYPE_CHECKING:
from .base import DependencyKWs

Check failure

Code scanning / CodeQL

Module-level cyclic import Error

'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.cmake
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.cmake.
if T.TYPE_CHECKING:
from .base import DependencyKWs

Check failure

Code scanning / CodeQL

Module-level cyclic import Error

'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.configtool
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.configtool.
@@ -6,16 +6,17 @@
import collections, functools, importlib
import typing as T

from .base import ExternalDependency, DependencyException, DependencyMethods, NotFoundDependency
from .base import ExternalDependency, DependencyException, NotFoundDependency

Check failure

Code scanning / CodeQL

Module-level cyclic import Error

'ExternalDependency' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of ExternalDependency occurs after the cyclic
import
of mesonbuild.dependencies.detect.
'ExternalDependency' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of ExternalDependency occurs after the cyclic
import
of mesonbuild.dependencies.detect.
'ExternalDependency' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of ExternalDependency occurs after the cyclic
import
of mesonbuild.dependencies.detect.
'ExternalDependency' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of ExternalDependency occurs after the cyclic
import
of mesonbuild.dependencies.detect.
'ExternalDependency' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of ExternalDependency occurs after the cyclic
import
of mesonbuild.dependencies.detect.
'ExternalDependency' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of ExternalDependency occurs after the cyclic
import
of mesonbuild.dependencies.detect.
'ExternalDependency' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of ExternalDependency occurs after the cyclic
import
of mesonbuild.dependencies.detect.
@@ -6,16 +6,17 @@
import collections, functools, importlib
import typing as T

from .base import ExternalDependency, DependencyException, DependencyMethods, NotFoundDependency
from .base import ExternalDependency, DependencyException, NotFoundDependency

Check failure

Code scanning / CodeQL

Module-level cyclic import Error

'DependencyException' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of DependencyException occurs after the cyclic
import
of mesonbuild.dependencies.detect.
'DependencyException' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of DependencyException occurs after the cyclic
import
of mesonbuild.dependencies.detect.
'DependencyException' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of DependencyException occurs after the cyclic
import
of mesonbuild.dependencies.detect.
'DependencyException' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of DependencyException occurs after the cyclic
import
of mesonbuild.dependencies.detect.
'DependencyException' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of DependencyException occurs after the cyclic
import
of mesonbuild.dependencies.detect.
'DependencyException' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of DependencyException occurs after the cyclic
import
of mesonbuild.dependencies.detect.
'DependencyException' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.detect
, as the
definition
of DependencyException occurs after the cyclic
import
of mesonbuild.dependencies.detect.
import typing as T

if T.TYPE_CHECKING:
from .base import DependencyKWs

Check failure

Code scanning / CodeQL

Module-level cyclic import Error

'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.framework
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.framework.
@@ -19,6 +19,7 @@
import typing as T

if T.TYPE_CHECKING:
from .base import DependencyKWs

Check failure

Code scanning / CodeQL

Module-level cyclic import Error

'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.dependencies.pkgconfig
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.dependencies.pkgconfig.
@@ -29,6 +29,8 @@
import typing as T

if T.TYPE_CHECKING:
from typing_extensions import Literal

Check notice

Code scanning / CodeQL

Unused import Note

Import of 'Literal' is not used.
@@ -25,6 +25,7 @@
if T.TYPE_CHECKING:
from typing_extensions import Literal, TypedDict

from ..dependencies.base import DependencyKWs

Check notice

Code scanning / CodeQL

Unused import Note

Import of 'DependencyKWs' is not used.
@@ -25,6 +25,7 @@
if T.TYPE_CHECKING:
from typing_extensions import Literal, TypedDict

from ..dependencies.base import DependencyKWs

Check failure

Code scanning / CodeQL

Module-level cyclic import Error

'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
'DependencyKWs' may not be defined if module
mesonbuild.dependencies.base
is imported before module
mesonbuild.interpreter.mesonmain
, as the
definition
of DependencyKWs occurs after the cyclic
import
of mesonbuild.interpreter.mesonmain.
@dcbaker dcbaker force-pushed the submit/use-typed-kwargs-for-dependency branch 3 times, most recently from 0ec8cea to 1f622f6 Compare December 13, 2024 23:35
language = kwargs.get('language', 'c')
if language not in ('c', 'cpp', 'fortran'):
language = kwargs.get('language')
if language not in (None, 'c', 'cpp', 'fortran'):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit and the next commit use two different ways of dealing with the same issue. I prefer the approach of the next commit where None is explicitly translated to 'c'. It may be that you don't do that here because because the value is sent down the call stack. However translating None to 'c' here is a first small step to reduce the permeation of this weird convention.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I've changed them both to the if language is None: language = 'c' approach

@@ -328,7 +328,7 @@ def find_package_target(pkg: DubPackDesc) -> bool:
for lib in bs['libs']:
if os.name != 'nt':
# trying to add system libraries by pkg-config
pkgdep = PkgConfigDependency(lib, environment, {'required': 'true', 'silent': 'true'})
pkgdep = PkgConfigDependency(lib, environment, {'required': 'true', 'silent': True})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the use of the plural form in the commit message I have the impression that both of these were meant to be True and not 'true'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are both supposed to be true... something happened when I rebased this

For whatever reason Meson has always used None == <C Language>. This
doesn't make a lot of sense to me, but it's how things currently work,
and netcdf should handle that correctly.
I have not changed the underlying implementation, as there are more
paths to get there than there are in CMake, and I don't want to spend
hours fighting with all of that right now.
Static must be optional, because although the default is static=false,
we special case that static : false is different than static being not
set in a number of cases.
Since it's basically unusued, but the DEPENDENCY_KWS can be used instead
This gives us one source of truth, as well as ensure that an empty value
and a default value are treated the same.
There are a couple of annoyances around the way Python's TypedDicts work
that we should get out of the way:

1) A TypedDict keeps it's `total` status, so you can't do something
   like:
   ```python
   from interpreter.type_checking import FuncDependency

   class DependencyKWs(FuncDependency, total=False): pass
   ```

   All of the arguments from FuncDependency remain required.
2) The "functional" form of `TypedDict` requires a literal for it's
   arguments, so you can't do something like:
   ```python
   _VALUES = {...}
   FuncDependency = TypedDict('FuncDependency', _VALUES)
   DependencyKWs = TypedDict('DependencyKWs', _VALUES, total=False)

And, there are some arguments `dependency()` that are not passed to the
lower levels, but are interpreter constructs. Likewise, some of the
Dependency classes take additional kwargs that are not part of the
dependency() DSL API. So we have to have two different TypedDicts, which
is unfortunate.

Additionally, TypedDicts must define all allowed keys, there is no way
to define "extra keys". This means that implementing this change as a
series of small commits would would require hundreds of `# type: ignore`
comments to be introduced and removed across the range. That kind of
noise seems counterproductive to the purpose of having small commits,
since there will end up being loads of churn introduced by such a series
of commits.
@dcbaker dcbaker force-pushed the submit/use-typed-kwargs-for-dependency branch from 1f622f6 to 1a25f7e Compare December 14, 2024 00:19
static = self.env.coredata.get_option(OptionKey('prefer_static'))
self.static = T.cast('bool', static)
static = T.cast('bool', self.env.coredata.get_option(OptionKey('prefer_static')))
self.static = static
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not matter much, but unless there is something subtle going on that I don't see, this hunk seem to simply change on which line the cast is done and could be either squashed with a patch a few commits down the stack, or simply suppressed.

Copy link
Member Author

@dcbaker dcbaker Dec 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, so mypy complains it's a useless cast because if static comes from kwargs, it's bool, and that's what we cast to. But if it comes from options then it's int | bool | str | list[str], so we still have to cast to not have a mypy error about assigning a different type. I honestly feel like that's a mypy bug, it really should be complaining that static is changing types if you don't cast.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants