hi all, i have a question about testing python whe...
# general
g
hi all, i have a question about testing python wheels produced by pants. i have a monorepo / and in /ponder/BUILD I have a
python_distribution
rule producing a wheel we call “ponder”. the goal is for users to be able to
pip install
the wheel and then use the
ponder
library in other python code. I have a unit test in /pushdown_service/test/subdir_b/test_astype.py that depends on /pushdown_service/test/subdir_b/common.py, which has the line
import ponder.subdir
, but the
ponder
there comes directly from the source files, specifically via
ponder/subdir/__init__.py
. i want to do 2 things: 1. have the test use the ponder wheel instead of the source files within
ponder
. My goal here is to check that the wheel is being built correctly. I have already seen an error where we didn’t specify the wheel’s dependencies correctly, so the wheel was broken, but our tests, which use the ponder from the snowflake folder directly rather than from wheel, didn’t detect the failure. a. i tried adding
"ponder:ponder_wheel"
as a dependency to
python_tests
. but then I got the errors shown at the end of this message. what was wrong? the msising depdencies are all transitive dependencies of the ponder wheel 2. prevent the test from being able to access targets in
ponder/
that are not the wheel, such as the
ponder/subdir/_init_.py
target that it’s using currently is testing the wheel this way reasonable? are 1) and 2) possible?
Copy code
pex.environment.ResolveError: Failed to resolve requirements from PEX environment @ /Users/maheshvashishtha/.cache/pants/named_caches/pex_root/unzipped_pexes/0b173c486d327c83c634831eb9c4ac34b76e61ae.
Needed cp310-cp310-macosx_12_0_x86_64 compatible dependencies for:
 1: boto3
    Required by:
      ponder 0.0.3
    But this pex had no ProjectName(raw='boto3', normalized='boto3') distributions.
 2: fsspec[http]
    Required by:
      ponder 0.0.3
    But this pex had no ProjectName(raw='fsspec', normalized='fsspec') distributions.
 3: lz4==4.0.2
    Required by:
      ponder 0.0.3
    But this pex had no ProjectName(raw='lz4', normalized='lz4') distributions.
 4: modin@ git+<https://github.com/devin-petersohn/modin.git@2ad8813ccf3cb263857478df951b8c7b4b7d4396>
    Required by:
      ponder 0.0.3
    But this pex had no ProjectName(raw='modin', normalized='modin') distributions.
 5: rpyc==5.2.3
    Required by:
      ponder 0.0.3
    But this pex had no ProjectName(raw='rpyc', normalized='rpyc') distributions.
cc @clever-hamburger-59716
h
Re “the goal is for users to be able to pip install the wheel and then use the ponder library in other python code.” - is that “other python code” in the repo, or outside it?
c
It’s in the same repo @happy-kitchen-89482 . @glamorous-accountant-97217 I would think we can use the same sources target that we use as dependency in the python_distribution target as a dependency in the service as well. This way there is 1:1; however, there is bloat. I don’t think this should be necessary though. We include a target (the only one needed from Ponder/) as a dependency in pushdown_service. I would argue this alone will import the sources and all the dependencies.
Sorry, to clarify @happy-kitchen-89482, the other python code is using this Ponder module as a client to connect to the service. Client and service are in the same repo. Other code is to be created by users of the Ponder client/library
h
Gotcha. So my first question would be, why consume
ponder
via a distribution at all? Why not let the client and service just depend on it in the repo? Does there actually need to be a
ponder
wheel for other reasons?
c
Sorry, that wasn't clear. In the monorepo, yes, they do. The `ponder`wheel has a python distribution target that depends on some
python_sources
target. say a,b, and c and the
ponder servcice
depends on b. Our goal is to distribute the client independently from the service. We would like to be able to inject the
ponder
wheel we are building as a dependency into the test targets of the `ponder service`so that we can do integration testing with the wheel (rather than have the sources be picked up from the repo).
👍 1
h
Ah, that makes sense. So there is code outside the repo that uses the client.
If the
python_tests
target has an explicit dependency on the
python_distribution
then it will build the wheel and depend on it, and subtract the corresponding loose sources from the deps, so they aren’t present twice on the sys.path.
So you can add that dep, and things should work the way you expect
at the cost of slowing down your tests, since now a wheel has to be built
but, you might also consider writing an integration test (or a few of them) just to test this aspect
rather than making every unit test also a test of the wheel-building
g
I tried that in first post on this thread, but had some dependency issues I Couldn’t figure out. any chance you can tell what’s wrong from the error messages?
h
So then only that integration test needs that explicit dep, and you can do a bunch of smoke testing in that integration test
g
@happy-kitchen-89482 we have several python_test targets that are almost integration tests, because they’re using the python sources instead of the wheel. we run all of them with
./pants test
in our CI. wouldn’t pants build the wheel just once for all the tests?
h
Oh, hmm, maybe we don’t pull in 3rdparty deps in this case
Yes, it would build it just once
👍 1
So that error message says that the wheel’s own third-party requirements aren’t being pulled in
How are you building that wheel? Does pants generate a setup.py, or are you hand-writing one?
g
we actually don’t have a setup.py. code generating the wheel is like
Copy code
python_distribution(
    name="ponder_wheel",
    entry_points={
     "console_scripts": {"ponder":"ponder.command_line:main"},
    },
    dependencies=["//:soda", ":command_line", "ponder/subdir:subdir", "ponder/utils:utils"],
    provides=python_artifact(
        name="ponder",
        version="0.0.3",
    ),
    sdist=False,
)
(I think) when i check the transitive dependencies of the wheel, I see those third party requirements-- will double check this
h
Which version of Pants is this? And are you using a lockfile?
And when you run the tests against the local sources, presumably those third party deps are present and the tests pass?
The weird thing is that using the local wheel build instead of the direct sources should not affect third-party deps at all
those should still be inferred as usual
so there is something odd going on
c
pants v2.13
h
I think the best way to debug is with a small, sanitized repo on github that reproduces the problem
g
Which version of Pants is this? And are you using a lockfile?
we do
./pants generate-lockfiles --resolve=pytest
before tests
And when you run the tests against the local sources, presumably those third party deps are present and the tests pass?
that’s right
i do see the third party dependencies as transitive dependencies when we add the wheel as a dependency of
python_tests
h
Ah, that is the lockfile for
pytest
itself, I mean a lockfile for your code (named typically something like
python-default
)
i do see the third party dependencies as transitive dependencies when we add the wheel as a dependency of python_tests
When you run
./pants dependencies path/to/test.py
you see the third-party deps listed?
So something odd is going on, and I think we’ll need a repro to get any further
c
Hi @happy-kitchen-89482, we are short of producing a stand alone repo yet; however, we do have an update. I was able to get this to work by using the wheel explicitly as a python_requirement and using that target as a dependency (and excluding the sources that were being pulled in). We will try to get a stand-alone repo going to close the loop here.
h
Glad it’s working! Would still love a repro when you have a moment
And a bug report to go along with it…
👍 1
c
For sure, after all its in our own interest 🙂!