-
-
Notifications
You must be signed in to change notification settings - Fork 632
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
Partially type check help
, ivy
, task
, and backend target
and subsystem
folders
#8635
Conversation
See https://docs.google.com/spreadsheets/d/1MKg82Fs3uIMOZDoWeNUBD-VirVkOzHU8Tte7oY6ypP0/edit#gid=1479336346 for the current status. The biggest blocker now is that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!!
return Linker( | ||
path_entries=self.path_entries, | ||
exe_filename=platform.match({ | ||
Platform.darwin: "ld64.lld", | ||
Platform.linux: "lld", | ||
}), | ||
library_dirs=[], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for fixing this!! Could you please add a TODO
here pointing to #5663 and mentioning that this is currently dead code? Sorry for not doing this myself!!
@@ -59,7 +59,6 @@ def ivy_resolution_cache_dir(self): | |||
"""Returns the ivy cache dir used by this `Ivy` instance.""" | |||
return self._ivy_resolution_cache_dir | |||
|
|||
@property |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this necessary for typechecking, or is it a style change? I'm very fine with it either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Necessary for type checking. Apparently it's bad to use @property
and @contextmanager
on the same function. MyPy complains about doing that.
c9f6946
to
ed3883c
Compare
I believe the following diff should fix the CI failure: diff --git a/src/python/pants/backend/native/config/environment.py b/src/python/pants/backend/native/config/environment.py
index 811eeaf29..5b0d04aa2 100644
--- a/src/python/pants/backend/native/config/environment.py
+++ b/src/python/pants/backend/native/config/environment.py
@@ -47,9 +47,9 @@ class _ExtensibleAlgebraic(ABC):
cur_value = getattr(self, field_name)
if prepend:
- new_value = list_value + cur_value
+ new_value = tuple(list_value) + tuple(cur_value)
else:
- new_value = cur_value + list_value
+ new_value = tuple(cur_value) + tuple(list_value)
arg_dict = {field_name: new_value}
return self.copy(**arg_dict)
@@ -93,7 +93,7 @@ class _ExtensibleAlgebraic(ABC):
for list_field_name in shared_list_fields:
lhs_value = getattr(self, list_field_name)
rhs_value = getattr(other, list_field_name)
- overwrite_kwargs[list_field_name] = lhs_value + rhs_value
+ overwrite_kwargs[list_field_name] = tuple(lhs_value) + tuple(rhs_value)
return self.copy(**overwrite_kwargs)
@@ -212,7 +212,7 @@ class _LinkerMixin(_Executable):
def invocation_environment_dict(self):
ret = super(_LinkerMixin, self).invocation_environment_dict.copy()
- full_library_path_dirs = self.linking_library_dirs + [
+ full_library_path_dirs = list(self.linking_library_dirs) + [
os.path.dirname(f) for f in self.extra_object_files
]
diff --git a/src/python/pants/backend/native/tasks/link_shared_libraries.py b/src/python/pants/backend/native/tasks/link_shared_libraries.py
index 72a32d4fa..85a16c368 100644
--- a/src/python/pants/backend/native/tasks/link_shared_libraries.py
+++ b/src/python/pants/backend/native/tasks/link_shared_libraries.py
@@ -169,7 +169,7 @@ class LinkSharedLibraries(NativeTask):
self.platform.match(
{Platform.darwin: ['-Wl,-dylib'], Platform.linux: ['-shared']}
) +
- linker.extra_args +
+ list(linker.extra_args) +
['-o', os.path.abspath(resulting_shared_lib_path)] +
['-L{}'.format(lib_dir) for lib_dir in link_request.external_lib_dirs] +
['-l{}'.format(lib_name) for lib_name in link_request.external_lib_names] +
diff --git a/src/python/pants/backend/native/tasks/native_compile.py b/src/python/pants/backend/native/tasks/native_compile.py
index 13abecae6..1a5665845 100644
--- a/src/python/pants/backend/native/tasks/native_compile.py
+++ b/src/python/pants/backend/native/tasks/native_compile.py
@@ -208,10 +208,10 @@ class NativeCompile(NativeTask, metaclass=ABCMeta):
# TODO: add -v to every compiler and linker invocation!
argv = (
[compiler.exe_filename] +
- compiler.extra_args +
+ list(compiler.extra_args) +
# TODO: If we need to produce static libs, don't add -fPIC! (could use Variants -- see #5788).
['-c', '-fPIC'] +
- compiler_options +
+ list(compiler_options) +
[
'-I{}'.format(os.path.join(buildroot, inc_dir))
for inc_dir in compile_request.include_dirs |
One last time should do the trick!! Sorry for not checking the subsystem tests too! diff --git a/tests/python/pants_test/backend/native/subsystems/test_native_toolchain.py b/tests/python/pants_test/backend/native/subsystems/test_native_toolchain.py
index 758d4c6a3..a1308a12f 100644
--- a/tests/python/pants_test/backend/native/subsystems/test_native_toolchain.py
+++ b/tests/python/pants_test/backend/native/subsystems/test_native_toolchain.py
@@ -121,7 +121,7 @@ class TestNativeToolchain(TestBase, SchedulerTestBase):
yield toolchain
def _invoke_compiler(self, compiler, args):
- cmd = [compiler.exe_filename] + compiler.extra_args + args
+ cmd = [compiler.exe_filename] + list(compiler.extra_args) + args
env = compiler.invocation_environment_dict
# TODO: add an `extra_args`-like field to `Executable`s which allows for overriding env vars
# like this, but declaratively!
@@ -129,7 +129,7 @@ class TestNativeToolchain(TestBase, SchedulerTestBase):
return self._invoke_capturing_output(cmd, env)
def _invoke_linker(self, linker, args):
- cmd = [linker.exe_filename] + linker.extra_args + args
+ cmd = [linker.exe_filename] + list(linker.extra_args) + args
return self._invoke_capturing_output(
cmd,
linker.invocation_environment_dict) |
b40b56c
to
50c2990
Compare
### Problem Fixes #7077. See #8635 (comment). As of #8330, we annotate all `@rule`s with a single return type, even for rules which call `yield Get(...)` within the method body. MyPy doesn't like this, and requests that rules be given a `Generator` or `Iterable` return type. This blocks type-checking (even partially) for many targets which define rules. ### Solution - Expand `_RuleVisitor` in `rules.py` to extract `Get` calls from `async def` rules. - Add an `__await__()` method to `Get` and create `MultiGet` to allow awaiting on multiple `Get`s in parallel (named to match the corresponding rust type). - Lists cannot be `await`ed in the way that it is possible to `yield [Get(...) ...]` -- the expression must be *awaitable* -- see https://www.python.org/dev/peps/pep-0492/#await-expression. In this case, `MultiGet` wrapping an iterable of `Get`s and exposing an `__await__()` method is a complete replacement for the previous `yield [Get(...) ...]` syntax. - Edit `native.py` to allow for `@rule` coroutine methods to `return` at the end instead of `yield`. - Convert the `@rule`s in `build_files.py` into `async` methods, and type-check the `:build_files` target! ### Result `@rule`s can now be defined with `async`/`await` syntax: ```python @rule async def hydrate_struct(address_mapper: AddressMapper, address: Address) -> HydratedStruct: # ... address_family: AddressFamily = await Get(AddressFamily, Dir(address.spec_path)) # ... hydrated_inline_dependencies: Tuple[HydratedStruct, ...] = await MultiGet(Get(HydratedStruct, Address, a) for a in inline_dependencies) # ... return HydratedStruct(consume_dependencies(struct, args={"address": address})) ``` As a result, plugins and backends that define `@rule`s can now be checked with MyPy! #### Alternative Solution: Returning `Generator[Any, Any, T]` In [the first few commits of this PR](https://github.com/pantsbuild/pants/pull/8639/files/43f73f1ac2d1e86301936a895ef08ffe8787d0f7..f7e8534c72965c5e6daa143ccefcdc7428192291), MyPy type annotations were added to `build_files.py` without adding any support for `async` methods. This worked by first adding support for `return` at the end of an `@rule` body in `native.py`, as in this PR, and annotating `@rule`s with the return type `-> Generator[Any, Any, T]`, `T` being the rule's actual return type. This worked, but required a lot of extra effort to extract the return type `T` from the `Generator[Any, Any, T]` annotation, so this was discarded because `async def` rules require no additional work to extract the output type. For the record, this would have looked like: ```python @rule def hydrate_struct(address_mapper: AddressMapper, address: Address) -> Generator[Any, Any, HydratedStruct]: # ... address_family: AddressFamily address_family = yield Get(AddressFamily, Dir(address.spec_path)) # ... hydrated_inline_dependencies: Tuple[HydratedStruct, ...] hydrated_inline_dependencies = yield [Get(HydratedStruct, Address, a) for a in inline_dependencies] # ... return HydratedStruct(consume_dependencies(struct, args={"address": address})) ``` Note that `x: X = yield Get(X, Y(...))` is not a valid python expression -- this is another benefit of the `async`/`await` approach. #### Follow-Up Extension: Type-Checked `await Get[X](...)` Another alternative extending the `await Get()` syntax was proposed in order to automatically type-check the result of the `await` call. This would have looked like: ```python @rule async def hydrate_struct(address_mapper: AddressMapper, address: Address) -> HydratedStruct: # ... address_family = await Get[AddressFamily](Dir(address.spec_path)) # ... hydrated_inline_dependencies = await MultiGet(Get[HydratedStruct](Address, a) for a in inline_dependencies) # ... return HydratedStruct(consume_dependencies(struct, args={"address": address})) ``` **Note that the `await Get[X](...)` calls are type-checked to return the type `X`!** This means that mypy can check that later uses of the `address_family` and `hydrated_inline_dependencies` objects above are correct, which it couldn't do without a separate redundant `address_family: AddressFamily` annotation before. The syntax extension for `Get[X](...)` was reverted in e92fecb in order to reduce complexity of the initial implementation.
As with prior PRs, the focus is on getting as many targets passing with
partially_type_checked
as possible, rather than adding comprehensive type checks at this stage.