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

Is there a working example of how to use this project anywhere? #16

Open
jfly opened this issue Jan 12, 2024 · 6 comments
Open

Is there a working example of how to use this project anywhere? #16

jfly opened this issue Jan 12, 2024 · 6 comments
Labels
documentation Improvements or additions to documentation

Comments

@jfly
Copy link
Contributor

jfly commented Jan 12, 2024

I've been trying to follow the README, and have run into a couple of issues:

  1. The globs in the README example didn't work for me. I think that's just a simple typo, which I've attempted to fix here: Fix broken globs in example #15
  2. It's not immediately obvious to me what the correct way to configure the proto_path and output_path is to ensure that the generated files are included in a built wheel.

The one example I've been able to find that uses setuptools-grpc is https://github.com/mlcommons/chakra, which chooses to set proto_path and output_path to the same thing, which is not something I'd have ever expected to do.

I think a simple, working example of one correct way of using this tool would go a long way towards clearing up any confusion.

@stinovlas
Copy link
Member

We do use it in a multiple projects, although with the same input and output path. Take a look here:

https://gitlab.nic.cz/fred/api/messenger (or any other project in the same group)

As for setuptools picking up the generated modules, this may require setting options.packages = find_namespace: if there are no __init__.py modules present. I did think about adding generating of __init__.py to the setuptools-grpc as well, so you wouldn't have to use namespace packages, but so far no one requested that and we actually benefit from having namespace packages, since we have a top level fred_api namespace for all APIs in the group.

I agree that it makes sense to add examples directory with some sample configurations.

@stinovlas stinovlas added the documentation Improvements or additions to documentation label Jan 12, 2024
@stinovlas
Copy link
Member

Just to be clear, if you would benefit from generating empty __init__.py files in the output dirs, so that you don't need to use namespace packages, I'm fine with adding that as a feature (probably opt-in, so we don't break people depending on namespace packaging). So far no one requested that and I didn't want to implement it just for the sake of it. But if there is a demand, it should be fairly easy to add.

jfly added a commit to jfly/setuptools-grpc-demo that referenced this issue Jan 12, 2024
This is me attempting to follow the advice on
CZ-NIC/setuptools-grpc#16 (comment),
but this doesn't really work.

First build doesn't work (note that there are no `module1_pb2.*` files):

    $ pip install . && pip show -f jfly
    Processing /home/jeremy/tmp/setuptools-grpc-demo
      Installing build dependencies ... done
      Getting requirements to build wheel ... done
      Installing backend dependencies ... done
      Preparing metadata (pyproject.toml) ... done
    Building wheels for collected packages: jfly
      Building wheel for jfly (pyproject.toml) ... done
      Created wheel for jfly: filename=jfly-0.0.1-py3-none-any.whl size=904 sha256=c7eed92a4897aca10015c53a8a81b552a36bb2b5629561a37643829907516819
      Stored in directory: /home/jeremy/.cache/pip/wheels/94/3f/96/34cbbd64f469cfadb00e57c6f6651a098fe76c85f79dbb0e9c
    Successfully built jfly
    Installing collected packages: jfly
    Successfully installed jfly-0.0.1

    [notice] A new release of pip is available: 23.2.1 -> 23.3.2
    [notice] To update, run: pip install --upgrade pip
    Name: jfly
    Version: 0.0.1
    Summary:
    Home-page:
    Author:
    Author-email:
    License:
    Location: /home/jeremy/tmp/setuptools-grpc-demo/.direnv/python-3.11/lib/python3.11/site-packages
    Requires:
    Required-by:
    Files:
      jfly-0.0.1.dist-info/INSTALLER
      jfly-0.0.1.dist-info/METADATA
      jfly-0.0.1.dist-info/RECORD
      jfly-0.0.1.dist-info/REQUESTED
      jfly-0.0.1.dist-info/WHEEL
      jfly-0.0.1.dist-info/direct_url.json
      jfly-0.0.1.dist-info/top_level.txt

Second build *does* work (note that there are `module1_pb2.*` files):

    $ pip install . && pip show -f jfly
    Processing /home/jeremy/tmp/setuptools-grpc-demo
      Installing build dependencies ... done
      Getting requirements to build wheel ... done
      Installing backend dependencies ... done
      Preparing metadata (pyproject.toml) ... done
    Building wheels for collected packages: jfly
      Building wheel for jfly (pyproject.toml) ... done
      Created wheel for jfly: filename=jfly-0.0.1-py3-none-any.whl size=2905 sha256=45e70cd416572af4c4df2fa9d4b293f2df863ae46525b868a97ffd9900b75eba
      Stored in directory: /home/jeremy/.cache/pip/wheels/94/3f/96/34cbbd64f469cfadb00e57c6f6651a098fe76c85f79dbb0e9c
    Successfully built jfly
    Installing collected packages: jfly
      Attempting uninstall: jfly
        Found existing installation: jfly 0.0.1
        Uninstalling jfly-0.0.1:
          Successfully uninstalled jfly-0.0.1
    Successfully installed jfly-0.0.1

    [notice] A new release of pip is available: 23.2.1 -> 23.3.2
    [notice] To update, run: pip install --upgrade pip
    Name: jfly
    Version: 0.0.1
    Summary:
    Home-page:
    Author:
    Author-email:
    License:
    Location: /home/jeremy/tmp/setuptools-grpc-demo/.direnv/python-3.11/lib/python3.11/site-packages
    Requires:
    Required-by:
    Files:
      jfly-0.0.1.dist-info/INSTALLER
      jfly-0.0.1.dist-info/METADATA
      jfly-0.0.1.dist-info/RECORD
      jfly-0.0.1.dist-info/REQUESTED
      jfly-0.0.1.dist-info/WHEEL
      jfly-0.0.1.dist-info/direct_url.json
      jfly-0.0.1.dist-info/top_level.txt
      out/foo/__pycache__/module1_pb2.cpython-311.pyc
      out/foo/__pycache__/module1_pb2_grpc.cpython-311.pyc
      out/foo/module1_pb2.py
      out/foo/module1_pb2.pyi
      out/foo/module1_pb2_grpc.py

I haven't read all the relevant setuptools code yet, but I believe
setuptools does its package autodiscovery (possibly during the `egg_info` command?)
*before* invoking the `build` command, so on the first run, it doesn't
find any packages, and on the second run (with the `output_path` already
populated), it does discover the files.

I briefly played with a couple of ideas:

1. Explicitly listing the packages.
  - This doesn't work: the `egg_info` command crashes complaining that
    these package directories don't exist in the `out` directory.
2. Trying to hook earlier into the build process (before the `egg_info`
   command).
   - This didn't immediately work. I don't know enough about the details
     of python packaging to know if this idea has legs.
@jfly
Copy link
Contributor Author

jfly commented Jan 12, 2024

Thanks for the info. I'm trying to put together an example with different input and output paths, and I can't get it to work. See https://github.com/jfly/setuptools-grpc-demo/tree/broken-different-proto-and-output-paths (in particular this commit message). Also here's a quick demo:

Trying to install this in a fresh venv (`pip install 'jfly @ git+https://github.com/jfly/setuptools-grpc-demo.git@broken-different-proto-and-output-paths'`)
$ pip install 'jfly @ git+https://github.com/jfly/setuptools-grpc-demo.git@broken-different-proto-and-output-paths' -vvv
Using pip 23.2.1 from /home/jeremy/tmp/2024-01-12-pyhack-2/.direnv/python-3.11/lib/python3.11/site-packages/pip (python 3.11)
Non-user install because user site-packages disabled
Created temporary directory: /run/user/1000/pip-build-tracker-1esenusq
Initialized build tracking at /run/user/1000/pip-build-tracker-1esenusq
Created build tracker: /run/user/1000/pip-build-tracker-1esenusq
Entered build tracker: /run/user/1000/pip-build-tracker-1esenusq
Created temporary directory: /run/user/1000/pip-install-qoucadyw
Created temporary directory: /run/user/1000/pip-ephem-wheel-cache-0koqn4fr
Collecting jfly@ git+https://github.com/jfly/setuptools-grpc-demo.git@broken-different-proto-and-output-paths
  Cloning https://github.com/jfly/setuptools-grpc-demo.git (to revision broken-different-proto-and-output-paths) to /run/user/1000/pip-install-qoucadyw/jfly_8df21ecae779444e991200dc438863ae
  Running command git version
  git version 2.42.0
  Running command git clone --filter=blob:none --verbose --progress https://github.com/jfly/setuptools-grpc-demo.git /run/user/1000/pip-install-qoucadyw/jfly_8df21ecae779444e991200dc438863ae
  Cloning into '/run/user/1000/pip-install-qoucadyw/jfly_8df21ecae779444e991200dc438863ae'...
  POST git-upload-pack (175 bytes)
  POST git-upload-pack (322 bytes)
  remote: Enumerating objects: 7, done.
  remote: Counting objects:  14% (1/7)
  remote: Counting objects:  28% (2/7)
  remote: Counting objects:  42% (3/7)
  remote: Counting objects:  57% (4/7)
  remote: Counting objects:  71% (5/7)
  remote: Counting objects:  85% (6/7)
  remote: Counting objects: 100% (7/7)
  remote: Counting objects: 100% (7/7), done.
  remote: Compressing objects:  25% (1/4)
  remote: Compressing objects:  50% (2/4)
  remote: Compressing objects:  75% (3/4)
  remote: Compressing objects: 100% (4/4)
  remote: Compressing objects: 100% (4/4), done.
  remote: Total 7 (delta 1), reused 6 (delta 0), pack-reused 0
  Receiving objects:  14% (1/7)
  Receiving objects:  28% (2/7)
  Receiving objects:  42% (3/7)
  Receiving objects:  57% (4/7)
  Receiving objects:  71% (5/7)
  Receiving objects:  85% (6/7)
  Receiving objects: 100% (7/7)
  Receiving objects: 100% (7/7), done.
  Resolving deltas:   0% (0/1)
  Resolving deltas: 100% (1/1)
  Resolving deltas: 100% (1/1), done.
  Running command git show-ref broken-different-proto-and-output-paths
  650848228143e7ef54f3bcab53f8945a3fc0f471 refs/remotes/origin/broken-different-proto-and-output-paths
  Rev options <RevOptions git: rev='650848228143e7ef54f3bcab53f8945a3fc0f471'>, branch_name broken-different-proto-and-output-paths
  Running command git symbolic-ref -q HEAD
  refs/heads/working-same-proto-and-output-paths
  Running command git checkout -b broken-different-proto-and-output-paths --track origin/broken-different-proto-and-output-paths
  Switched to a new branch 'broken-different-proto-and-output-paths'
  branch 'broken-different-proto-and-output-paths' set up to track 'origin/broken-different-proto-and-output-paths'.
  Resolved https://github.com/jfly/setuptools-grpc-demo.git to commit 650848228143e7ef54f3bcab53f8945a3fc0f471
  Running command git rev-parse HEAD
  650848228143e7ef54f3bcab53f8945a3fc0f471
  Added jfly@ git+https://github.com/jfly/setuptools-grpc-demo.git@broken-different-proto-and-output-paths from git+https://github.com/jfly/setuptools-grpc-demo.git@broken-different-proto-and-output-paths to build tracker '/run/user/1000/pip-build-tracker-1esenusq'
  Created temporary directory: /run/user/1000/pip-build-env-tst4wk_e
  Running command pip subprocess to install build dependencies
  Using pip 23.2.1 from /home/jeremy/tmp/2024-01-12-pyhack-2/.direnv/python-3.11/lib/python3.11/site-packages/pip (python 3.11)
  Collecting setuptools
    Obtaining dependency information for setuptools from https://files.pythonhosted.org/packages/55/3a/5121b58b578a598b269537e09a316ad2a94fdd561a2c6eb75cd68578cc6b/setuptools-69.0.3-py3-none-any.whl.metadata
    Using cached setuptools-69.0.3-py3-none-any.whl.metadata (6.3 kB)
  Collecting setuptools-grpc
    Obtaining dependency information for setuptools-grpc from https://files.pythonhosted.org/packages/cf/2f/d332a2265239ddb2a0a3fd4af2b5fd9eb862eba2d870c397562995605fa8/setuptools_grpc-0.5-py3-none-any.whl.metadata
    Using cached setuptools_grpc-0.5-py3-none-any.whl.metadata (5.4 kB)
  Collecting grpcio-tools~=1.49 (from setuptools-grpc)
    Obtaining dependency information for grpcio-tools~=1.49 from https://files.pythonhosted.org/packages/29/0f/fdfa88aff42abc0caa29f74cfa47e77ea1d6385c073c082fef582ac0ec9f/grpcio_tools-1.60.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata
    Using cached grpcio_tools-1.60.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (6.2 kB)
  Collecting protobuf<5.0dev,>=4.21.6 (from grpcio-tools~=1.49->setuptools-grpc)
    Obtaining dependency information for protobuf<5.0dev,>=4.21.6 from https://files.pythonhosted.org/packages/81/9e/63501b8d5b4e40c7260049836bd15ec3270c936e83bc57b85e4603cc212c/protobuf-4.25.2-cp37-abi3-manylinux2014_x86_64.whl.metadata
    Using cached protobuf-4.25.2-cp37-abi3-manylinux2014_x86_64.whl.metadata (541 bytes)
  Collecting grpcio>=1.60.0 (from grpcio-tools~=1.49->setuptools-grpc)
    Obtaining dependency information for grpcio>=1.60.0 from https://files.pythonhosted.org/packages/de/01/a8d9bcc59526f22b8fef29c234cc63434f05dae1154d979222c02b31a557/grpcio-1.60.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata
    Using cached grpcio-1.60.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.0 kB)
  Using cached setuptools-69.0.3-py3-none-any.whl (819 kB)
  Using cached setuptools_grpc-0.5-py3-none-any.whl (17 kB)
  Using cached grpcio_tools-1.60.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB)
  Using cached grpcio-1.60.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.4 MB)
  Using cached protobuf-4.25.2-cp37-abi3-manylinux2014_x86_64.whl (294 kB)
  Installing collected packages: setuptools, protobuf, grpcio, grpcio-tools, setuptools-grpc
  Successfully installed grpcio-1.60.0 grpcio-tools-1.60.0 protobuf-4.25.2 setuptools-69.0.3 setuptools-grpc-0.5

  [notice] A new release of pip is available: 23.2.1 -> 23.3.2
  [notice] To update, run: pip install --upgrade pip
  Installing build dependencies ... done
  Running command Getting requirements to build wheel
  running egg_info
  creating jfly.egg-info
  writing jfly.egg-info/PKG-INFO
  writing dependency_links to jfly.egg-info/dependency_links.txt
  writing top-level names to jfly.egg-info/top_level.txt
  writing manifest file 'jfly.egg-info/SOURCES.txt'
  reading manifest file 'jfly.egg-info/SOURCES.txt'
  writing manifest file 'jfly.egg-info/SOURCES.txt'
  Getting requirements to build wheel ... done
  Running command pip subprocess to install backend dependencies
  Using pip 23.2.1 from /home/jeremy/tmp/2024-01-12-pyhack-2/.direnv/python-3.11/lib/python3.11/site-packages/pip (python 3.11)
  Collecting wheel
    Obtaining dependency information for wheel from https://files.pythonhosted.org/packages/c7/c3/55076fc728723ef927521abaa1955213d094933dc36d4a2008d5101e1af5/wheel-0.42.0-py3-none-any.whl.metadata
    Using cached wheel-0.42.0-py3-none-any.whl.metadata (2.2 kB)
  Using cached wheel-0.42.0-py3-none-any.whl (65 kB)
  Installing collected packages: wheel
    Creating /run/user/1000/pip-build-env-tst4wk_e/normal/bin
    changing mode of /run/user/1000/pip-build-env-tst4wk_e/normal/bin/wheel to 755
  Successfully installed wheel-0.42.0

  [notice] A new release of pip is available: 23.2.1 -> 23.3.2
  [notice] To update, run: pip install --upgrade pip
  Installing backend dependencies ... done
  Created temporary directory: /run/user/1000/pip-modern-metadata-welukk06
  Running command Preparing metadata (pyproject.toml)
  running dist_info
  creating /run/user/1000/pip-modern-metadata-welukk06/jfly.egg-info
  writing /run/user/1000/pip-modern-metadata-welukk06/jfly.egg-info/PKG-INFO
  writing dependency_links to /run/user/1000/pip-modern-metadata-welukk06/jfly.egg-info/dependency_links.txt
  writing top-level names to /run/user/1000/pip-modern-metadata-welukk06/jfly.egg-info/top_level.txt
  writing manifest file '/run/user/1000/pip-modern-metadata-welukk06/jfly.egg-info/SOURCES.txt'
  reading manifest file '/run/user/1000/pip-modern-metadata-welukk06/jfly.egg-info/SOURCES.txt'
  writing manifest file '/run/user/1000/pip-modern-metadata-welukk06/jfly.egg-info/SOURCES.txt'
  creating '/run/user/1000/pip-modern-metadata-welukk06/jfly-0.0.1.dist-info'
  Preparing metadata (pyproject.toml) ... done
  Source in /run/user/1000/pip-install-qoucadyw/jfly_8df21ecae779444e991200dc438863ae has version 0.0.1, which satisfies requirement jfly@ git+https://github.com/jfly/setuptools-grpc-demo.git@broken-different-proto-and-output-paths from git+https://github.com/jfly/setuptools-grpc-demo.git@broken-different-proto-and-output-paths
  Removed jfly@ git+https://github.com/jfly/setuptools-grpc-demo.git@broken-different-proto-and-output-paths from git+https://github.com/jfly/setuptools-grpc-demo.git@broken-different-proto-and-output-paths from build tracker '/run/user/1000/pip-build-tracker-1esenusq'
Created temporary directory: /run/user/1000/pip-unpack-kfess7h3
Building wheels for collected packages: jfly
  Running command git rev-parse HEAD
  650848228143e7ef54f3bcab53f8945a3fc0f471
  Created temporary directory: /run/user/1000/pip-wheel-3_863fyq
  Destination directory: /run/user/1000/pip-wheel-3_863fyq
  Running command Building wheel for jfly (pyproject.toml)
  running bdist_wheel
  running build
  running build_grpc
  building protos
  generating foo/module1.proto → foo/module1_pb2.py
  building grpc
  generating foo/module1.proto → foo/module1_pb2_grpc.py
  running build_py
  running egg_info
  writing jfly.egg-info/PKG-INFO
  writing dependency_links to jfly.egg-info/dependency_links.txt
  writing top-level names to jfly.egg-info/top_level.txt
  reading manifest file 'jfly.egg-info/SOURCES.txt'
  writing manifest file 'jfly.egg-info/SOURCES.txt'
  installing to build/bdist.linux-x86_64/wheel
  running install
  running install_lib
  warning: install_lib: 'build/lib' does not exist -- no Python modules to install

  running install_egg_info
  Copying jfly.egg-info to build/bdist.linux-x86_64/wheel/jfly-0.0.1-py3.11.egg-info
  running install_scripts
  creating build/bdist.linux-x86_64/wheel/jfly-0.0.1.dist-info/WHEEL
  creating '/run/user/1000/pip-wheel-3_863fyq/.tmp-o6ahiqsk/jfly-0.0.1-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it
  adding 'jfly-0.0.1.dist-info/METADATA'
  adding 'jfly-0.0.1.dist-info/WHEEL'
  adding 'jfly-0.0.1.dist-info/top_level.txt'
  adding 'jfly-0.0.1.dist-info/RECORD'
  removing build/bdist.linux-x86_64/wheel
  Building wheel for jfly (pyproject.toml) ... done
  Created wheel for jfly: filename=jfly-0.0.1-py3-none-any.whl size=904 sha256=c7eed92a4897aca10015c53a8a81b552a36bb2b5629561a37643829907516819
  Stored in directory: /run/user/1000/pip-ephem-wheel-cache-0koqn4fr/wheels/4c/25/e6/5c477311458918af6e1b244dd9c80b43a75e862fd4787c43cc
Successfully built jfly
Installing collected packages: jfly

Successfully installed jfly-0.0.1
Remote version of pip: 23.3.2
Local version of pip:  23.2.1
Was pip installed by pip? True

[notice] A new release of pip is available: 23.2.1 -> 23.3.2
[notice] To update, run: pip install --upgrade pip
Removed build tracker: '/run/user/1000/pip-build-tracker-1esenusq'

Note how there are no module1_pb2.* files:

$ pip show -f jfly
Name: jfly
Version: 0.0.1
Summary:
Home-page:
Author:
Author-email:
License:
Location: /home/jeremy/tmp/2024-01-12-pyhack-2/.direnv/python-3.11/lib/python3.11/site-packages
Requires:
Required-by:
Files:
  jfly-0.0.1.dist-info/INSTALLER
  jfly-0.0.1.dist-info/METADATA
  jfly-0.0.1.dist-info/RECORD
  jfly-0.0.1.dist-info/REQUESTED
  jfly-0.0.1.dist-info/WHEEL
  jfly-0.0.1.dist-info/direct_url.json
  jfly-0.0.1.dist-info/top_level.txt

Is this possible? From the experimentation I've been doing, it feels to me like the directory structure must be in place before build_grpc even runs.

@stinovlas
Copy link
Member

So, first thing I see is that you need to add include_package_data = true to your your setup.cfg (section options) and also indicate in MANIFEST.in that you want to include all proto files (for example with graft src).

@stinovlas
Copy link
Member

I usually use pyhon -m build to test the build itself. In this case, the setuptools complain about this:

error: error in 'output_path' option: './out' does not exist or is not a directory

However, this directory actually does exist. I'm not sure why setuptools don't recognize it, but we use Command.ensure_dirname("output_path") for this check. I'll try to look into it and find out what it is that setuptools ignore this directory.

@stinovlas
Copy link
Member

OK, I get it now. The problem is that out directory does not contain any python modules and is therefore not included in the sdist befor building the wheel from it. This should fix it:

setup.cfg

[options]
packages = find_namespace:
include_package_data = true

[build_grpc]
proto_files = **/*.proto
grpc_files = **/*.proto
proto_path = ./src
output_path = ./out

MANIFEST.in

graft src
graft out

Now, as you said, the directory structure indeed has to be in place at the moment. grpc_tools.protoc does not create the output dir if not present, but I wonder whether setuptools_grpc should. It's definitely something to think about.

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

No branches or pull requests

2 participants