Hello, I previously had some plugins built on Pant...
# general
c
Hello, I previously had some plugins built on Pants 2.13.0rc1. After trying to upgrade to 2.14.1, these plugins don’t seem to work anymore when running
./pants --changed-since=origin/master dependees
. The error I’m seeing is the following.
Copy code
AttributeError: type object 'PythonSourceField' has no attribute 'is_applicable'
Happy to provide code snippets or other additional details
f
Have you updated your plugin for API changes as per https://www.pantsbuild.org/v2.14/docs/plugin-upgrade-guide ?
c
ahh, i haven’t seen that. will take a look and report back!
f
(that exception suggests an API change is the issue since
is_applicable
is a method on
FieldSet
)
c
thank you :)
Then for each
InferDependenciesRequest
, the
infer_from
class variable should now point to a relevant
FieldSet
subclass type.
My code looks as follows.
Copy code
class MyInferDependenciesRequest(InferDependenciesRequest):
    infer_from = PythonSourceField
What should the new
infer_from
point to?
Would it be
pants.backend.python.goals.run_python_source.PythonSourceFieldSet
?
If I do that, I get a new error
Copy code
AttributeError: 'MyInferDependenciesRequest' object has no attribute 'sources_field
f
What does your code look like now? The
infer_from
should be a subclass of
FieldSet
with whatever fields you need to access on the target in order to implement your dependency inference rule.
c
right now, i have infer_from pointing to
pants.backend.python.goals.run_python_source.PythonSourceFieldSet
f
ah I assume you chose that because you need some of the run-related fields to exist on the target?
it would be useful if you could paste the full error and more of the relevant source
c
This is what the relevant request and corresponding rule originally looked like.
Copy code
from pathlib import PurePath
from typing import Iterable

from pants.backend.python.target_types import PythonSourceField
from pants.engine.rules import Get, Rule, rule
from pants.engine.target import AllTargets, AllTargetsRequest, InferDependenciesRequest, InferredDependencies
from pants.engine.unions import UnionRule

from front_porch.modules.package_management.constants import PACKAGE_CONFIG_FILENAME, PACKAGE_CONFIG_UTIL_PATH


class InferPackageConfigDependenciesRequest(InferDependenciesRequest):
    infer_from = PythonSourceField  # noqa


@rule(desc="Inferring Python package config dependencies by analyzing source")
async def infer_python_package_config_dependencies(
    request: InferPackageConfigDependenciesRequest,
) -> InferredDependencies:
    """
    Infers dependencies on all `_package_config.py` targets for the Python module located at
    `PACKAGE_CONFIG_UTIL_PATH`.
    """
    if request.sources_field.file_path != PACKAGE_CONFIG_UTIL_PATH:
        return InferredDependencies([])

    package_config_targets = set()
    all_targets = await Get(AllTargets, AllTargetsRequest())

    for target in all_targets:
        if (
            target.has_field(PythonSourceField)
            and PurePath(target[PythonSourceField].file_path).name == PACKAGE_CONFIG_FILENAME
        ):
            package_config_targets.add(target)

    if len(package_config_targets) == 0:
        return InferredDependencies([])

    return InferredDependencies(target.address for target in package_config_targets)


def rules() -> Iterable[Rule]:
    return [
        infer_python_package_config_dependencies,
        UnionRule(InferDependenciesRequest, InferPackageConfigDependenciesRequest),
    ]
Now that
PythonSourceField
needs to be changed to the corresponding
FieldSet
, I’m not sure what to use, exactly. I found
PythonSourceFieldSet
arbitrarily in the source code, but that was only by randomly searching for things that looked similar. Since it’s under the run goal, it feels like it’s not exactly right here (?)
To experiment, I replaced
PythonSourceField
with
PythonSourceFieldSet
, and the full output I received was only the following.
Copy code
If set to true, removing the option will cause directory arguments like `./pants test project/dir` to now match all files and targets in the directory, whereas before it matched the target `project/dir:dir`. To keep the old semantics, use the explicit address syntax.
17:54:17.02 [INFO] Initializing scheduler...
17:54:17.21 [INFO] Scheduler initialized.
17:54:31.09 [ERROR] 1 Exception encountered:

  AttributeError: 'InferPackageConfigDependenciesRequest' object has no attribute 'sources_field'
Just following up here! Is there any recommendation @fast-nail-55400?
f
Copy code
if request.sources_field.file_path != PACKAGE_CONFIG_UTIL_PATH:
        return InferredDependencies([])
s/sources_field/field_set/
and of course index into the
request.field_set
for the particular field you need
c
Hmm, I’m getting a different error now.
Copy code
AttributeError: 'PythonSourceFieldSet' object has no attribute 'file_path'
I tried deleting as much of my code as possible and then slowly adding things in to see what could be breaking it, but even with a super minimal request, I still get the same error.
Copy code
from typing import Iterable

from pants.backend.python.goals.run_python_source import PythonSourceFieldSet
from pants.engine.rules import Rule, rule
from pants.engine.target import InferDependenciesRequest, InferredDependencies
from pants.engine.unions import UnionRule


class InferMyDependenciesRequest(InferDependenciesRequest):
    infer_from = PythonSourceFieldSet  # noqa


@rule(desc="...")
async def infer_my_dependencies(
    request: InferMyDependenciesRequest,
) -> InferredDependencies:
    return InferredDependencies([])


def rules() -> Iterable[Rule]:
    return [
        infer_my_dependencies,
        UnionRule(InferDependenciesRequest, InferMyDependenciesRequest),
    ]
figured this out, by the way! Thank you! 🙂
f
What was the issue?
c
pants.backend.python.goals.run_python_source.PythonSourceFieldSet
wasn’t the correct one to be using. I should’ve been using
pants.backend.python.dependency_inference.rules.PythonImportDependenciesInferenceFieldSet