danielgtaylor / python-betterproto

Clean, modern, Python 3.6+ code generator & library for Protobuf 3 and async gRPC
MIT License
1.45k stars 196 forks source link

How to wrap in a custom setuptools command? #219

Open dkbarn opened 3 years ago

dkbarn commented 3 years ago

Is it possible to compile .proto files with the betterproto plugin from a custom setuptools command? For example, python setup.py build_proto

This is what my setup.py looks like:

import os
import pkg_resources
from setuptools import Command, setup

class BuildProtoCommand(Command):
    """Command to generate project *_pb2.py modules from proto files."""

    description = "build grpc protobuf modules"
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        from grpc_tools import protoc

        proto_files = []
        inclusion_root = os.path.abspath(".")
        for root, _, files in os.walk(inclusion_root):
            for filename in files:
                if filename.endswith(".proto"):
                    proto_files.append(os.path.abspath(os.path.join(root, filename)))

        well_known_protos_include = pkg_resources.resource_filename("grpc_tools", "_proto")

        for proto_file in proto_files:
            proto_dir = os.path.dirname(proto_file)
            command = [
                "grpc_tools.protoc",
                f"--proto_path={proto_dir}",
                f"--proto_path={well_known_protos_include}",
                f"--python_betterproto_out={proto_dir}",
                proto_file,
            ]
            if protoc.main(command) != 0:
                raise Exception(f"error: {command} failed")

setup(
    name="mypackage",
    version="0.2.0",
    cmdclass={
        "build_proto": BuildProtoCommand,
    },
    packages=["mypackage"],
    setup_requires=[
        "betterproto[compiler]",
        "grpcio-tools",
    ],
)

The problem here is that calling python setup.py build_proto causes all of the setup_requires packages to be installed as .eggs, and the protoc-gen-python_betterproto executable is not found by protoc, so it doesn't know how to interpret the --python_betterproto_out flag.

I just wanted to double-check if this even supported functionality, or if betterproto is not intended to be used with setuptools at all and I need to migrate my package to pyproject.toml or something?

Gobot1234 commented 3 years ago

I think you need to use subprocess to install betterproto using pip at the top of your file but I might be wrong.

jameslan commented 3 years ago

You may want to check setuptools-proto.

Disclosure: I'm the author of it.