Skip to content

cythonize_setup

setuptools.cythonize_setup

parse_compile_list

parse_compile_list(module: str) -> List[str]

returns python files to be built by recursively parsing import phrases.

Reference

https://github.com/andrewp-as-is/list-imports.py/blob/master/list_imports/init.py

Example

from SaigeToolkit.setuptools.import_parser import parse_compile_list ... compile_list = parse_compile_list("deploy_demo.py")

Note

file/dir의 존재 유무를 isfile/isdir 함수에서 glob의 string comapre로 변경한 이유.

이슈 window에서는 filename의 대소문자를 구분하지 않음, "A.py", "a.Py", "a.PY"가 모두 같은 file. os.path.isfile/isdir 함수 또한 대소문자를 구분하지 않음, "A"가 존재할 때 isfile("a")을 호출시 True return. 따라서 폴더 내부가 다음과 같이 되어있고, import A를 했다면 ├── A │ └── init.py └── a.py linux의 경우는 A.py가 없기 때문에, A directory를 잘 찾지만, window의 경우에는 isfile(A.py)가 True이기 때문에 logic에 문제가 발생.

해결 방법 glob로 모든 file name, directory name을 가져온 뒤, string compare 진행.

unresolved issue glob가 모든 파일 리스트를 읽어오기 때문에, 폴더 내에 파일이 많은 경우 속도가 느려지는 이슈.

Source code in SaigeToolkit/setuptools/import_parser.py
def parse_compile_list(module: str) -> List[str]:
    """returns python files to be built by recursively parsing `import` phrases.

    Reference:
        https://github.com/andrewp-as-is/list-imports.py/blob/master/list_imports/__init__.py

    Example:
        >>> from SaigeToolkit.setuptools.import_parser import parse_compile_list
        ... compile_list = parse_compile_list("deploy_demo.py")

    Note:
        file/dir의 존재 유무를 isfile/isdir 함수에서 glob의 string comapre로 변경한 이유.

        이슈
            window에서는 filename의 대소문자를 구분하지 않음,
                "A.py", "a.Py", "a.PY"가 모두 같은 file.
            os.path.isfile/isdir 함수 또한 대소문자를 구분하지 않음,
                "A"가 존재할 때 isfile("a")을 호출시 True return.
            따라서 폴더 내부가 다음과 같이 되어있고, import A를 했다면
            ├── A
            │   └── __init__.py
            └── a.py
            linux의 경우는 A.py가 없기 때문에, A directory를 잘 찾지만,
            window의 경우에는 isfile(A.py)가 True이기 때문에 logic에 문제가 발생.

        해결 방법
            glob로 모든 file name, directory name을 가져온 뒤, string compare 진행.

        unresolved issue
            glob가 모든 파일 리스트를 읽어오기 때문에, 폴더 내에 파일이 많은 경우 속도가 느려지는 이슈.
    """
    compile_list = []
    all_existing_files = glob("**", recursive=True)
    all_existing_directories = glob("**" + os.sep, recursive=True)

    def _parse_compile_list(module: str) -> None:
        import_list = get_import_module_list(module)

        # recursively update compile list
        for imp in import_list:
            import_path = imp.replace(".", os.path.sep)

            if import_path + ".py" in all_existing_files and imp not in compile_list:
                compile_list.append(imp)
                _parse_compile_list(imp)

            elif (
                import_path + os.sep in all_existing_directories
                and imp + ".__init__" not in compile_list
            ):
                compile_list.append(imp + ".__init__")
                _parse_compile_list(imp + ".__init__")

    _parse_compile_list(module)

    return sorted(list(set(compile_list)))

make_extension

make_extension(ext_name: str) -> Extension
Source code in SaigeToolkit/setuptools/cythonize_setup.py
def make_extension(ext_name: str) -> Extension:
    ext_path = ext_name.replace(".", os.path.sep) + ".py"
    return Extension(
        ext_name,
        [ext_path],
        include_dirs=["."],
    )

cythonize_setup

cythonize_setup(target: str, name: str, **setup_args: Dict[str, Any]) -> None

cythonize and setup target python files

Parameters:

  • target (str) –

    base setup target file, which is input to parsing function

  • name (str) –

    library name

  • setup_args (Dict[str, Any], default: {} ) –

    other library setup keywords

Example

from SaigeToolkit.setuptools.cythonize_setup import cythonize_setup ... cythonize_setup(target="deploy_demo.py", name="Saige", version="1.0")

Source code in SaigeToolkit/setuptools/cythonize_setup.py
def cythonize_setup(target: str, name: str, **setup_args: Dict[str, Any]) -> None:
    """cythonize and setup target python files

    Args:
        target (str): base setup target file, which is input to parsing function
        name (str): library name
        setup_args (Dict[str, Any]): other library setup keywords

    Example:
        >>> from SaigeToolkit.setuptools.cythonize_setup import cythonize_setup
        ... cythonize_setup(target="deploy_demo.py", name="Saige", version="1.0")
    """
    compile_list = sorted(parse_compile_list(target))

    if platform.system() == "Windows":
        """To compile __init__.py on Windows

        Reference: https://stackoverflow.com/a/58826688
        """

        def get_export_symbols_fixed(self, ext):
            return []

        build_ext.get_export_symbols = get_export_symbols_fixed

    extensions = []
    for file in compile_list:
        if os.path.isfile(file.replace(".", os.path.sep) + ".py"):
            extensions.append(make_extension(file))
            print(f"[SETUP] {file}")
    print(f"[SETUP] {len(extensions)} Files")

    setup(
        name=name,
        ext_modules=cythonize(
            extensions,
            compiler_directives={"language_level": "3"},
        ),
        **setup_args,
    )