Is there some plan to add pants command to read/up...
# general
r
Is there some plan to add pants command to read/update the
version
of a python package? Like for semantic versioning
Copy code
./pants version minor <python_package>
c
Not that I’m aware of, but I love the idea.
r
I am trying to bring all the
poetry
functionality here 😄
😁 1
c
What we’ve done, is to have the version as an input env variable, and then a with a custom plugin inject that into the python dist version field.
(as we already have tooling that calculates the version to build “externally” up-front before the build starts)
r
Is there an example of how to pass version as an input?
c
Not that I know of.. but I can share what we have internally for this:
Copy code
import os
from os.path import expandvars
from typing import Any

from pants.backend.python.goals.setup_py import SetupKwargs, SetupKwargsRequest
from pants.engine.environment import Environment, EnvironmentRequest
from pants.engine.rules import Get, collect_rules, rule
from pants.engine.target import Target
from pants.engine.unions import UnionRule

SETUP_VARS = [
    "APPLICATION",
    "AUTHOR",
    "AUTHOR_EMAIL",
    "PROJECT_URL",
    "VERSION_PYTHON",
]


class CustomSetupKwargsRequest(SetupKwargsRequest):
    @classmethod
    def is_applicable(cls, _: Target) -> bool:
        # Apply to all targets
        return True


def maybe_expand(key: str, val: Any) -> Any:
    if not isinstance(val, str):
        return val

    maybe_expanded = expandvars(val)
    if "$" in maybe_expanded:
        raise ValueError(f"All environment variables not expanded in {key}: {maybe_expanded!r}")
    return maybe_expanded


@rule
async def customize_setup_kwargs(request: CustomSetupKwargsRequest) -> SetupKwargs:
    environ = await Get(Environment, EnvironmentRequest(SETUP_VARS))
    os.environ.update(environ)

    try:
        return SetupKwargs(
            {key: maybe_expand(key, val) for key, val in request.explicit_kwargs.items()},
            address=request.target.address,
        )
    except ValueError as e:
        raise ValueError(
            f"Invalid distribution configuration for {request.target.address}\n\n" f"Error: {e}"
        )


def rules():
    return [
        *collect_rules(),
        UnionRule(SetupKwargsRequest, CustomSetupKwargsRequest),
    ]
Which can then be used like this:
Copy code
python_distribution(
    name="...",
    provides=python_artifact(
        name="...",
        version="$VERSION_PYTHON",
    ),
...
🙌 1
If you have a mono repo with tons of different versions, it doesn’t really scale, though..
h
To clarify, is this to set versions of your own packages, so that it creates a distribution with that version number?
Oh, looks like this is for editing pyproject.toml?
I think we'd probably recommend just editing pyproject.toml... The problem with this sort of thing in Pants is that there are a few different ways your requirements can be specified (pyproject.toml, requirements.txt, a handwritten python_requirement target) and auto-editing them is tricky.
c
No, it's for the version field of a
python_artifact
, so should be fine.
👍 1
h
Oh, then I've misread the
poetry version
docs
c
Ah, I think we may be speaking past each other. Poetry does keep this information in
pyproject.toml
, but for us in the pants setting, I imagine it is the
version
field on the
python_artefact
of the
python_distribution
that we want to tweak. Oh, unless you go with a handcrafted setup.py file… right, and then that could be tricky indeed. My bad.
(so, could support it for when we generate the setup.py file, being the “easy” case)
h
well, even if you use a handcrafted setup.py you have to provide the version in the BUILD file, so Pants can reason about what version a dependee should declare
e
IIUC we don't want to emulate poetry here because poetry doesn't actually handle multiple in-repo projects at all. Say you have a 2 project repo with a library "util" and another library "baz" that depends on it. If you change util but don't publish it and then change baz to use the util change, then when you go to publish baz, you must also publish util or else the published baz is broken. Pants used to handle this sort of thing for jvm publishing. I'm not sure if we handle it for Python publishing right now or if we expect you to manually keep track of all this and do the right thing on your own.
h
but then updating that automatically but not the handcrafted setup.py leaves you with potential mismatches
c
I don't see how it makes any difference if I edit a file by hand or use a command to have it edited for me. The trick is what edit to make where.
h
Right, but with handwritten setup there is probably redundancy, because you have to specify the project name and version in two places (the BUILD file, so Pants can consume it for dep calculation reasons) and the setup
c
Indeed. So I see that as a +1 for tool support, if we can figure out all places that needs updating reliably; as that would help avoid potential mistakes.
h
My point is that it's not possible in general to do so because we don't know the structure of the setup information except in special cases (such as pyproject.toml)
c
Hmm…
h
And honestly that functionality seems more cutsey than necessary...
c
Yes and no. If you run the command manually, then yes, but if it is part of some automated pipeline, that would save you from having to implement this yourself.. (all hypothetical here..)
But I think cutsey can sell, too 😉