18799: Run discovery2pydoc as part of SDK build
authorBrett Smith <brett.smith@curii.com>
Thu, 13 Apr 2023 13:56:27 +0000 (09:56 -0400)
committerBrett Smith <brett.smith@curii.com>
Thu, 13 Apr 2023 13:56:27 +0000 (09:56 -0400)
Arvados-DCO-1.1-Signed-off-by: Brett Smith <brett.smith@curii.com>

sdk/python/setup.py

index 1c65c4ced8ac8a61b6552279aee9584ef48c3b66..b03b650d6b6d373d2c6ece43608d077ed3b0411e 100644 (file)
@@ -4,10 +4,13 @@
 # SPDX-License-Identifier: Apache-2.0
 
 from __future__ import absolute_import
+import distutils.command.build
 import os
+import setuptools
 import sys
 import re
 
+from pathlib import Path
 from setuptools import setup, find_packages
 
 SETUP_DIR = os.path.dirname(__file__) or '.'
@@ -21,6 +24,77 @@ if '--short-tests-only' in sys.argv:
     short_tests_only = True
     sys.argv.remove('--short-tests-only')
 
+class BuildDiscoveryPydoc(setuptools.Command):
+    """Run discovery2pydoc as part of the build process
+
+    This class implements a setuptools subcommand, so it follows
+    [the SubCommand protocol][1]. Most of these methods are required by that
+    protocol, except `should_run`, which we register as the subcommand
+    predicate.
+
+    [1]: https://setuptools.pypa.io/en/latest/userguide/extension.html#setuptools.command.build.SubCommand
+    """
+    DEFAULT_JSON_PATH = Path(SETUP_DIR, '..', '..', 'doc', 'arvados-v1-discovery.json')
+    DEFAULT_OUTPUT_PATH = Path('arvados', 'api_resources.py')
+    NAME = 'discovery2pydoc'
+    description = "build skeleton Python from the Arvados discovery document"
+    editable_mode = False
+    user_options = [
+        ('discovery-json=', 'J', 'JSON discovery document used to build pydoc'),
+        ('discovery-output=', 'O', 'relative path to write discovery document pydoc'),
+    ]
+
+    def initialize_options(self):
+        self.build_lib = None
+        self.discovery_json = None
+        self.discovery_output = str(self.DEFAULT_OUTPUT_PATH)
+
+    def finalize_options(self):
+        # Set self.build_lib to match whatever the build_py subcommand uses.
+        self.set_undefined_options('build_py', ('build_lib', 'build_lib'))
+        if self.discovery_json is None and self.DEFAULT_JSON_PATH.exists():
+            self.discovery_json = str(self.DEFAULT_JSON_PATH)
+        out_path = Path(self.discovery_output)
+        if out_path.is_absolute():
+            raise Exception("--discovery-output should be a relative path")
+        else:
+            self.out_path = Path(self.build_lib, out_path)
+
+    def run(self):
+        import discovery2pydoc
+        self.mkpath(str(self.out_path.parent))
+        arglist = ['--output-file', str(self.out_path)]
+        if self.discovery_json is None:
+            print(
+                "warning: trying to load a live discovery document from configuration",
+                file=sys.stderr,
+            )
+        else:
+            arglist.append(self.discovery_json)
+        returncode = discovery2pydoc.main(arglist)
+        if returncode != 0:
+            raise Exception(f"discovery2pydoc exited {returncode}")
+
+    def should_run(self):
+        return True
+
+    # The protocol docs say that get_outputs should list *all* outputs, while
+    # get_output_mapping maps get_source_files to output file paths. Since we
+    # are generating files from outside the source tree, we should just return
+    # our output, with the source file list and output mapping both empty.
+    def get_outputs(self):
+        return [str(self.out_path)]
+
+    def get_source_files(self):
+        return []
+
+    def get_output_mapping(self):
+        return {}
+# Run discovery2pydoc as the first subcommand of build.
+distutils.command.build.build.sub_commands.insert(
+    0, (BuildDiscoveryPydoc.NAME, BuildDiscoveryPydoc.should_run),
+)
+
 setup(name='arvados-python-client',
       version=version,
       description='Arvados client library',
@@ -30,6 +104,9 @@ setup(name='arvados-python-client',
       url="https://arvados.org",
       download_url="https://github.com/arvados/arvados.git",
       license='Apache 2.0',
+      cmdclass={
+          BuildDiscoveryPydoc.NAME: BuildDiscoveryPydoc,
+      },
       packages=find_packages(),
       scripts=[
           'bin/arv-copy',