Repository: numba/numba

Issue:
Obsolete pycc script/code
Since `pycc.main()` has been deprecated for almost 7 years (https://github.com/numba/numba/commit/7342cb9aa7aded02209605299dbbdbe377794078), it seems that the `pycc` script (shown below) should be removed or at least be archived in a way that does not deploy it to new installations. For that matter, is there a reason to keep `pycc.main()` around, or should removal/archival of the function be considered?

https://github.com/numba/numba/blob/61ec1fd0f69aeadece218dccf4c39ebc5c7dfbc4/numba/pycc/pycc#L1-L3

https://github.com/numba/numba/blob/61ec1fd0f69aeadece218dccf4c39ebc5c7dfbc4/numba/pycc/__init__.py#L26-L100


Discussion:
@firai thank you for this suggestion. As discussed in the developer meeting last night (https://github.com/numba/numba/wiki/Minutes_2022_08_09) this can indeed be removed.

Resolving patch:
diff --git a/numba/pycc/__init__.py b/numba/pycc/__init__.py
--- a/numba/pycc/__init__.py
+++ b/numba/pycc/__init__.py
@@ -1,100 +1,5 @@
 # -*- coding: utf-8 -*-
 
-
-import os
-import logging
-import subprocess
-import tempfile
-import sys
-
 # Public API
 from .cc import CC
 from .decorators import export, exportmany
-
-
-def get_ending(args):
-    if args.llvm:
-        return ".bc"
-    elif args.olibs:
-        return ".o"
-    elif args.python:
-        return find_pyext_ending()
-    else:
-        return find_shared_ending()
-
-
-def main(args=None):
-    import argparse
-
-    from .compiler import ModuleCompiler
-    from .platform import Toolchain, find_shared_ending, find_pyext_ending
-    from numba.pycc import decorators
-
-    parser = argparse.ArgumentParser(
-        description="DEPRECATED - Compile Python modules to a single shared library")
-    parser.add_argument("inputs", nargs='+', help="Input file(s)")
-    parser.add_argument("-o", nargs=1, dest="output",
-                        help="Output file  (default is name of first input -- with new ending)")
-
-    group = parser.add_mutually_exclusive_group()
-    group.add_argument("-c", action="store_true", dest="olibs",
-                       help="Create object file from each input instead of shared-library")
-    group.add_argument("--llvm", action="store_true",
-                       help="Emit llvm instead of native code")
-
-    parser.add_argument('--header', action="store_true",
-                        help="Emit C header file with function signatures")
-    parser.add_argument('--python', action='store_true',
-                        help='Emit additionally generated Python wrapper and '
-                        'extension module code in output')
-    parser.add_argument('-d', '--debug', action='store_true',
-                        help='Print extra debug information')
-
-    args = parser.parse_args(args)
-
-    logger = logging.getLogger(__name__)
-    if args.debug:
-        logger.setLevel(logging.DEBUG)
-
-    logger.warn("The 'pycc' script is DEPRECATED; "
-                "please use the numba.pycc.CC API instead")
-
-    if args.output:
-        args.output = args.output[0]
-        output_base = os.path.split(args.output)[1]
-        module_name = os.path.splitext(output_base)[0]
-    else:
-        input_base = os.path.splitext(args.inputs[0])[0]
-        module_name = os.path.split(input_base)[1]
-        args.output = input_base + get_ending(args)
-    logger.debug('args.output --> %s', args.output)
-
-    if args.header:
-        print('ERROR: pycc --header has been disabled in this release due to a known issue')
-        sys.exit(1)
-
-    logger.debug('inputs --> %s', args.inputs)
-    decorators.process_input_files(args.inputs)
-
-    compiler = ModuleCompiler(decorators.export_registry, module_name=module_name)
-    if args.llvm:
-        logger.debug('emit llvm')
-        compiler.write_llvm_bitcode(args.output, wrap=args.python)
-    elif args.olibs:
-        logger.debug('emit object file')
-        compiler.write_native_object(args.output, wrap=args.python)
-    else:
-        logger.debug('emit shared library')
-        logger.debug('write to temporary object file %s', tempfile.gettempdir())
-
-        toolchain = Toolchain()
-        toolchain.debug = args.debug
-        temp_obj = (tempfile.gettempdir() + os.sep +
-                    os.path.basename(args.output) + '.o')
-        compiler.write_native_object(temp_obj, wrap=args.python)
-        libraries = toolchain.get_python_libraries()
-        toolchain.link_shared(args.output, [temp_obj],
-                              toolchain.get_python_libraries(),
-                              toolchain.get_python_library_dirs(),
-                              export_symbols=compiler.dll_exports)
-        os.remove(temp_obj)
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -397,7 +397,7 @@ def check_file_at_path(path2file):
         "numba.misc": ["cmdlang.gdb"],
         "numba.typed": ["py.typed"],
     },
-    scripts=["numba/pycc/pycc", "bin/numba"],
+    scripts=["bin/numba"],
     url="https://numba.pydata.org",
     packages=packages,
     setup_requires=build_requires,


Test patch:
diff --git a/numba/tests/test_pycc.py b/numba/tests/test_pycc.py
--- a/numba/tests/test_pycc.py
+++ b/numba/tests/test_pycc.py
@@ -13,7 +13,6 @@
 import llvmlite.binding as ll
 
 from numba.core import utils
-from numba.pycc import main
 from numba.pycc.decorators import clear_export_registry
 from numba.pycc.platform import find_shared_ending, find_pyext_ending
 from numba.pycc.platform import _external_compiler_ok
@@ -85,79 +84,6 @@ def check_c_ext(self, extdir, name):
             sys.modules.pop(name, None)
 
 
-@needs_external_compilers
-class TestLegacyAPI(BasePYCCTest):
-
-    def test_pycc_ctypes_lib(self):
-        """
-        Test creating a C shared library object using pycc.
-        """
-        source = os.path.join(base_path, 'compile_with_pycc.py')
-        cdll_modulename = 'test_dll_legacy' + find_shared_ending()
-        cdll_path = os.path.join(self.tmpdir, cdll_modulename)
-        if os.path.exists(cdll_path):
-            os.unlink(cdll_path)
-
-        main(args=['--debug', '-o', cdll_path, source])
-        lib = CDLL(cdll_path)
-        lib.mult.argtypes = [POINTER(c_double), c_void_p,
-                             c_double, c_double]
-        lib.mult.restype = c_int
-
-        lib.multf.argtypes = [POINTER(c_float), c_void_p,
-                              c_float, c_float]
-        lib.multf.restype = c_int
-
-        res = c_double()
-        lib.mult(byref(res), None, 123, 321)
-        self.assertEqual(res.value, 123 * 321)
-
-        res = c_float()
-        lib.multf(byref(res), None, 987, 321)
-        self.assertEqual(res.value, 987 * 321)
-
-    def test_pycc_pymodule(self):
-        """
-        Test creating a CPython extension module using pycc.
-        """
-        self.skipTest("lack of environment can make the extension crash")
-
-        source = os.path.join(base_path, 'compile_with_pycc.py')
-        modulename = 'test_pyext_legacy'
-        out_modulename = os.path.join(self.tmpdir,
-                                      modulename + find_pyext_ending())
-        if os.path.exists(out_modulename):
-            os.unlink(out_modulename)
-
-        main(args=['--debug', '--python', '-o', out_modulename, source])
-
-        with self.check_c_ext(self.tmpdir, modulename) as lib:
-            res = lib.multi(123, 321)
-            self.assertPreciseEqual(res, 123 * 321)
-            res = lib.multf(987, 321)
-            self.assertPreciseEqual(res, 987.0 * 321.0)
-
-    def test_pycc_bitcode(self):
-        """
-        Test creating a LLVM bitcode file using pycc.
-        """
-        modulename = os.path.join(base_path, 'compile_with_pycc')
-        bitcode_modulename = os.path.join(self.tmpdir, 'test_bitcode_legacy.bc')
-        if os.path.exists(bitcode_modulename):
-            os.unlink(bitcode_modulename)
-
-        main(args=['--debug', '--llvm', '-o', bitcode_modulename,
-                   modulename + '.py'])
-
-        # Sanity check bitcode file contents
-        with open(bitcode_modulename, "rb") as f:
-            bc = f.read()
-
-        bitcode_wrapper_magic = b'\xde\xc0\x17\x0b'
-        bitcode_magic = b'BC\xc0\xde'
-        self.assertTrue(bc.startswith((bitcode_magic, bitcode_wrapper_magic)), bc)
-
-
 @needs_external_compilers
 class TestCC(BasePYCCTest):