From 60af0f6ab6a0fb8193b906f100afb640fb0b8250 Mon Sep 17 00:00:00 2001 From: Tim Paine <3105306+timkpaine@users.noreply.github.com> Date: Mon, 27 Jul 2026 16:39:18 -0400 Subject: [PATCH] Fix Ruff lint violations Signed-off-by: Tim Paine <3105306+timkpaine@users.noreply.github.com> --- hatch_cpp/config.py | 19 +++-- hatch_cpp/hooks.py | 4 +- hatch_cpp/plugin.py | 2 +- hatch_cpp/tests/test_projects.py | 1 - hatch_cpp/toolchains/cmake.py | 16 ++-- hatch_cpp/toolchains/common.py | 135 ++++++++++++++----------------- hatch_cpp/toolchains/vcpkg.py | 16 ++-- hatch_cpp/utils.py | 4 +- 8 files changed, 89 insertions(+), 108 deletions(-) diff --git a/hatch_cpp/config.py b/hatch_cpp/config.py index 805faec..089c762 100644 --- a/hatch_cpp/config.py +++ b/hatch_cpp/config.py @@ -2,7 +2,6 @@ from os import environ, system as system_call from pathlib import Path -from typing import List, Optional from pkn import getSimpleLogger from pydantic import BaseModel, Field, model_validator @@ -21,13 +20,13 @@ class HatchCppBuildConfig(BaseModel): """Build config values for Hatch C++ Builder.""" - verbose: Optional[bool] = Field(default=False) - skip: Optional[bool] = Field(default=False) - name: Optional[str] = Field(default=None) - libraries: List[HatchCppLibrary] = Field(default_factory=list) - cmake: Optional[HatchCppCmakeConfiguration] = Field(default=None) - platform: Optional[HatchCppPlatform] = Field(default_factory=HatchCppPlatform.default) - vcpkg: Optional[HatchCppVcpkgConfiguration] = Field(default_factory=HatchCppVcpkgConfiguration) + verbose: bool | None = Field(default=False) + skip: bool | None = Field(default=False) + name: str | None = Field(default=None) + libraries: list[HatchCppLibrary] = Field(default_factory=list) + cmake: HatchCppCmakeConfiguration | None = Field(default=None) + platform: HatchCppPlatform | None = Field(default_factory=HatchCppPlatform.default) + vcpkg: HatchCppVcpkgConfiguration | None = Field(default_factory=HatchCppVcpkgConfiguration) @model_validator(mode="wrap") @classmethod @@ -56,9 +55,9 @@ def validate_model(cls, data, handler): class HatchCppBuildPlan(HatchCppBuildConfig): build_type: BuildType = "release" - commands: List[str] = Field(default_factory=list) + commands: list[str] = Field(default_factory=list) - _active_toolchains: List[Toolchain] = [] + _active_toolchains: list[Toolchain] = [] def generate(self): self.commands = [] diff --git a/hatch_cpp/hooks.py b/hatch_cpp/hooks.py index fb1aee0..b5c632b 100644 --- a/hatch_cpp/hooks.py +++ b/hatch_cpp/hooks.py @@ -1,10 +1,8 @@ -from typing import Type - from hatchling.plugin import hookimpl from .plugin import HatchCppBuildHook @hookimpl -def hatch_register_build_hook() -> Type[HatchCppBuildHook]: +def hatch_register_build_hook() -> type[HatchCppBuildHook]: return HatchCppBuildHook diff --git a/hatch_cpp/plugin.py b/hatch_cpp/plugin.py index 76914ac..c486584 100644 --- a/hatch_cpp/plugin.py +++ b/hatch_cpp/plugin.py @@ -82,7 +82,7 @@ def initialize(self, version: str, build_data: dict[str, Any]) -> None: os_name = "linux" else: os_name = "win" - if all([lib.py_limited_api for lib in build_plan.libraries]): + if all(lib.py_limited_api for lib in build_plan.libraries): build_data["tag"] = f"cp{version_major}{version_minor}-abi3-{os_name}_{machine}" else: build_data["tag"] = f"cp{version_major}{version_minor}-cp{version_major}{version_minor}-{os_name}_{machine}" diff --git a/hatch_cpp/tests/test_projects.py b/hatch_cpp/tests/test_projects.py index 968248d..31c54d6 100644 --- a/hatch_cpp/tests/test_projects.py +++ b/hatch_cpp/tests/test_projects.py @@ -14,7 +14,6 @@ class TestProject: [ "test_project_basic", "test_project_override_classes", - "test_project_override_classes", "test_project_override_toolchain", "test_project_pybind", "test_project_pybind_vcpkg", diff --git a/hatch_cpp/toolchains/cmake.py b/hatch_cpp/toolchains/cmake.py index 01e1f53..bc53568 100644 --- a/hatch_cpp/toolchains/cmake.py +++ b/hatch_cpp/toolchains/cmake.py @@ -3,7 +3,7 @@ from os import environ from pathlib import Path from sys import version_info -from typing import Any, Dict, Optional, Union +from typing import Any from pydantic import BaseModel, Field @@ -23,17 +23,17 @@ class HatchCppCmakeConfiguration(BaseModel): - root: Optional[Path] = None + root: Path | None = None build: Path = Field(default_factory=lambda: Path("build")) - install: Optional[Path] = Field(default=None) + install: Path | None = Field(default=None) - cmake_arg_prefix: Optional[str] = Field(default=None) - cmake_args: Dict[str, str] = Field(default_factory=dict) - cmake_env_args: Dict[Platform, Dict[str, str]] = Field(default_factory=dict) + cmake_arg_prefix: str | None = Field(default=None) + cmake_args: dict[str, str] = Field(default_factory=dict) + cmake_env_args: dict[Platform, dict[str, str]] = Field(default_factory=dict) - include_flags: Optional[Dict[str, Union[str, int, float, bool]]] = Field(default=None) + include_flags: dict[str, str | int | float | bool] | None = Field(default=None) - def generate(self, config) -> Dict[str, Any]: + def generate(self, config) -> dict[str, Any]: commands = [] # Derive prefix diff --git a/hatch_cpp/toolchains/common.py b/hatch_cpp/toolchains/common.py index 5373001..1ddac0b 100644 --- a/hatch_cpp/toolchains/common.py +++ b/hatch_cpp/toolchains/common.py @@ -6,20 +6,20 @@ from shutil import which from sys import base_exec_prefix, exec_prefix, executable, platform as sys_platform from sysconfig import get_config_var, get_path -from typing import Any, List, Literal, Optional +from typing import Any, Literal from pydantic import AliasChoices, BaseModel, Field, field_validator, model_validator __all__ = ( + "Binding", "BuildType", "CompilerToolchain", - "Toolchain", + "HatchCppLibrary", + "HatchCppPlatform", "Language", - "Binding", "Platform", "PlatformDefaults", - "HatchCppLibrary", - "HatchCppPlatform", + "Toolchain", "_normalize_rpath", ) @@ -41,63 +41,62 @@ class HatchCppLibrary(BaseModel, validate_assignment=True): """A C++ library.""" name: str - sources: List[str] + sources: list[str] language: Language = "c++" binding: Binding = "cpython" - std: Optional[str] = None + std: str | None = None - include_dirs: List[str] = Field(default_factory=list, alias=AliasChoices("include_dirs", "include-dirs")) - include_dirs_linux: List[str] = Field(default_factory=list, alias=AliasChoices("include_dirs_linux", "include-dirs-linux")) - include_dirs_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("include_dirs_darwin", "include-dirs-darwin")) - include_dirs_win32: List[str] = Field(default_factory=list, alias=AliasChoices("include_dirs_win32", "include-dirs-win32")) + include_dirs: list[str] = Field(default_factory=list, alias=AliasChoices("include_dirs", "include-dirs")) + include_dirs_linux: list[str] = Field(default_factory=list, alias=AliasChoices("include_dirs_linux", "include-dirs-linux")) + include_dirs_darwin: list[str] = Field(default_factory=list, alias=AliasChoices("include_dirs_darwin", "include-dirs-darwin")) + include_dirs_win32: list[str] = Field(default_factory=list, alias=AliasChoices("include_dirs_win32", "include-dirs-win32")) - library_dirs: List[str] = Field(default_factory=list, alias=AliasChoices("library_dirs", "library-dirs")) - library_dirs_linux: List[str] = Field(default_factory=list, alias=AliasChoices("library_dirs_linux", "library-dirs-linux")) - library_dirs_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("library_dirs_darwin", "library-dirs-darwin")) - library_dirs_win32: List[str] = Field(default_factory=list, alias=AliasChoices("library_dirs_win32", "library-dirs-win32")) + library_dirs: list[str] = Field(default_factory=list, alias=AliasChoices("library_dirs", "library-dirs")) + library_dirs_linux: list[str] = Field(default_factory=list, alias=AliasChoices("library_dirs_linux", "library-dirs-linux")) + library_dirs_darwin: list[str] = Field(default_factory=list, alias=AliasChoices("library_dirs_darwin", "library-dirs-darwin")) + library_dirs_win32: list[str] = Field(default_factory=list, alias=AliasChoices("library_dirs_win32", "library-dirs-win32")) - libraries: List[str] = Field(default_factory=list) - libraries_linux: List[str] = Field(default_factory=list, alias=AliasChoices("libraries_linux", "libraries-linux")) - libraries_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("libraries_darwin", "libraries-darwin")) - libraries_win32: List[str] = Field(default_factory=list, alias=AliasChoices("libraries_win32", "libraries-win32")) + libraries: list[str] = Field(default_factory=list) + libraries_linux: list[str] = Field(default_factory=list, alias=AliasChoices("libraries_linux", "libraries-linux")) + libraries_darwin: list[str] = Field(default_factory=list, alias=AliasChoices("libraries_darwin", "libraries-darwin")) + libraries_win32: list[str] = Field(default_factory=list, alias=AliasChoices("libraries_win32", "libraries-win32")) - extra_compile_args: List[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args", "extra-compile-args")) - extra_compile_args_linux: List[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args_linux", "extra-compile-args-linux")) - extra_compile_args_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args_darwin", "extra-compile-args-darwin")) - extra_compile_args_win32: List[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args_win32", "extra-compile-args-win32")) + extra_compile_args: list[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args", "extra-compile-args")) + extra_compile_args_linux: list[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args_linux", "extra-compile-args-linux")) + extra_compile_args_darwin: list[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args_darwin", "extra-compile-args-darwin")) + extra_compile_args_win32: list[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args_win32", "extra-compile-args-win32")) - extra_link_args: List[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args", "extra-link-args")) - extra_link_args_linux: List[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args_linux", "extra-link-args-linux")) - extra_link_args_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args_darwin", "extra-link-args-darwin")) - extra_link_args_win32: List[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args_win32", "extra-link-args-win32")) + extra_link_args: list[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args", "extra-link-args")) + extra_link_args_linux: list[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args_linux", "extra-link-args-linux")) + extra_link_args_darwin: list[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args_darwin", "extra-link-args-darwin")) + extra_link_args_win32: list[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args_win32", "extra-link-args-win32")) - extra_objects: List[str] = Field(default_factory=list, alias=AliasChoices("extra_objects", "extra-objects")) - extra_objects_linux: List[str] = Field(default_factory=list, alias=AliasChoices("extra_objects_linux", "extra-objects-linux")) - extra_objects_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("extra_objects_darwin", "extra-objects-darwin")) - extra_objects_win32: List[str] = Field(default_factory=list, alias=AliasChoices("extra_objects_win32", "extra-objects-win32")) + extra_objects: list[str] = Field(default_factory=list, alias=AliasChoices("extra_objects", "extra-objects")) + extra_objects_linux: list[str] = Field(default_factory=list, alias=AliasChoices("extra_objects_linux", "extra-objects-linux")) + extra_objects_darwin: list[str] = Field(default_factory=list, alias=AliasChoices("extra_objects_darwin", "extra-objects-darwin")) + extra_objects_win32: list[str] = Field(default_factory=list, alias=AliasChoices("extra_objects_win32", "extra-objects-win32")) - define_macros: List[str] = Field(default_factory=list, alias=AliasChoices("define_macros", "define-macros")) - define_macros_linux: List[str] = Field(default_factory=list, alias=AliasChoices("define_macros_linux", "define-macros-linux")) - define_macros_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("define_macros_darwin", "define-macros-darwin")) - define_macros_win32: List[str] = Field(default_factory=list, alias=AliasChoices("define_macros_win32", "define-macros-win32")) + define_macros: list[str] = Field(default_factory=list, alias=AliasChoices("define_macros", "define-macros")) + define_macros_linux: list[str] = Field(default_factory=list, alias=AliasChoices("define_macros_linux", "define-macros-linux")) + define_macros_darwin: list[str] = Field(default_factory=list, alias=AliasChoices("define_macros_darwin", "define-macros-darwin")) + define_macros_win32: list[str] = Field(default_factory=list, alias=AliasChoices("define_macros_win32", "define-macros-win32")) - undef_macros: List[str] = Field(default_factory=list, alias=AliasChoices("undef_macros", "undef-macros")) - undef_macros_linux: List[str] = Field(default_factory=list, alias=AliasChoices("undef_macros_linux", "undef-macros-linux")) - undef_macros_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("undef_macros_darwin", "undef-macros-darwin")) - undef_macros_win32: List[str] = Field(default_factory=list, alias=AliasChoices("undef_macros_win32", "undef-macros-win32")) + undef_macros: list[str] = Field(default_factory=list, alias=AliasChoices("undef_macros", "undef-macros")) + undef_macros_linux: list[str] = Field(default_factory=list, alias=AliasChoices("undef_macros_linux", "undef-macros-linux")) + undef_macros_darwin: list[str] = Field(default_factory=list, alias=AliasChoices("undef_macros_darwin", "undef-macros-darwin")) + undef_macros_win32: list[str] = Field(default_factory=list, alias=AliasChoices("undef_macros_win32", "undef-macros-win32")) - export_symbols: List[str] = Field(default_factory=list, alias=AliasChoices("export_symbols", "export-symbols")) - depends: List[str] = Field(default_factory=list) + export_symbols: list[str] = Field(default_factory=list, alias=AliasChoices("export_symbols", "export-symbols")) + depends: list[str] = Field(default_factory=list) - py_limited_api: Optional[str] = Field(default="", alias=AliasChoices("py_limited_api", "py-limited-api")) + py_limited_api: str | None = Field(default="", alias=AliasChoices("py_limited_api", "py-limited-api")) @field_validator("py_limited_api", mode="before") @classmethod def check_py_limited_api(cls, value: Any) -> Any: - if value: - if not match(r"cp3\d", value): - raise ValueError("py-limited-api must be in the form of cp3X") + if value and not match(r"cp3\d", value): + raise ValueError("py-limited-api must be in the form of cp3X") return value def get_qualified_name(self, platform): @@ -122,7 +121,7 @@ def check_binding_and_py_limited_api(self): raise ValueError("Generic binding can not support Py_LIMITED_API") return self - def get_effective_link_args(self, platform: Platform) -> List[str]: + def get_effective_link_args(self, platform: Platform) -> list[str]: """Get link args merged with platform-specific link args.""" args = list(self.extra_link_args) if platform == "linux": @@ -133,7 +132,7 @@ def get_effective_link_args(self, platform: Platform) -> List[str]: args.extend(self.extra_link_args_win32) return args - def get_effective_include_dirs(self, platform: Platform) -> List[str]: + def get_effective_include_dirs(self, platform: Platform) -> list[str]: """Get include dirs merged with platform-specific include dirs.""" dirs = list(self.include_dirs) if platform == "linux": @@ -144,7 +143,7 @@ def get_effective_include_dirs(self, platform: Platform) -> List[str]: dirs.extend(self.include_dirs_win32) return dirs - def get_effective_library_dirs(self, platform: Platform) -> List[str]: + def get_effective_library_dirs(self, platform: Platform) -> list[str]: """Get library dirs merged with platform-specific library dirs.""" dirs = list(self.library_dirs) if platform == "linux": @@ -155,7 +154,7 @@ def get_effective_library_dirs(self, platform: Platform) -> List[str]: dirs.extend(self.library_dirs_win32) return dirs - def get_effective_libraries(self, platform: Platform) -> List[str]: + def get_effective_libraries(self, platform: Platform) -> list[str]: """Get libraries merged with platform-specific libraries.""" libs = list(self.libraries) if platform == "linux": @@ -166,7 +165,7 @@ def get_effective_libraries(self, platform: Platform) -> List[str]: libs.extend(self.libraries_win32) return libs - def get_effective_compile_args(self, platform: Platform) -> List[str]: + def get_effective_compile_args(self, platform: Platform) -> list[str]: """Get compile args merged with platform-specific compile args.""" args = list(self.extra_compile_args) if platform == "linux": @@ -177,7 +176,7 @@ def get_effective_compile_args(self, platform: Platform) -> List[str]: args.extend(self.extra_compile_args_win32) return args - def get_effective_extra_objects(self, platform: Platform) -> List[str]: + def get_effective_extra_objects(self, platform: Platform) -> list[str]: """Get extra objects merged with platform-specific extra objects.""" objs = list(self.extra_objects) if platform == "linux": @@ -188,7 +187,7 @@ def get_effective_extra_objects(self, platform: Platform) -> List[str]: objs.extend(self.extra_objects_win32) return objs - def get_effective_define_macros(self, platform: Platform) -> List[str]: + def get_effective_define_macros(self, platform: Platform) -> list[str]: """Get define macros merged with platform-specific define macros.""" macros = list(self.define_macros) if platform == "linux": @@ -199,7 +198,7 @@ def get_effective_define_macros(self, platform: Platform) -> List[str]: macros.extend(self.define_macros_win32) return macros - def get_effective_undef_macros(self, platform: Platform) -> List[str]: + def get_effective_undef_macros(self, platform: Platform) -> list[str]: """Get undef macros merged with platform-specific undef macros.""" macros = list(self.undef_macros) if platform == "linux": @@ -274,12 +273,11 @@ def default() -> HatchCppPlatform: @classmethod def validate_model(cls, data, handler): model = handler(data) - if which("ccache") and not model.disable_ccache: - if model.toolchain in ["gcc", "clang"]: - if not model.cc.startswith("ccache "): - model.cc = f"ccache {model.cc}" - if not model.cxx.startswith("ccache "): - model.cxx = f"ccache {model.cxx}" + if which("ccache") and not model.disable_ccache and model.toolchain in ["gcc", "clang"]: + if not model.cc.startswith("ccache "): + model.cc = f"ccache {model.cc}" + if not model.cxx.startswith("ccache "): + model.cxx = f"ccache {model.cxx}" return model @staticmethod @@ -316,7 +314,7 @@ def get_compile_flags(self, library: HatchCppLibrary, build_type: BuildType = "r if not library.std: library.std = "c++17" library.sources.append(str(Path(nanobind.include_dir()).parent / "src" / "nb_combined.cpp")) - effective_include_dirs.append(str((Path(nanobind.include_dir()).parent / "ext" / "robin_map" / "include"))) + effective_include_dirs.append(str(Path(nanobind.include_dir()).parent / "ext" / "robin_map" / "include")) if library.py_limited_api: if library.binding == "pybind11": @@ -367,20 +365,7 @@ def get_link_flags(self, library: HatchCppLibrary, build_type: BuildType = "rele # Normalize rpath values ($ORIGIN <-> @loader_path) and escape for shell effective_link_args = [_normalize_rpath(arg, self.platform) for arg in effective_link_args] - if self.toolchain == "gcc": - flags += " -shared" - flags += " " + " ".join(effective_link_args) - flags += " " + " ".join(effective_extra_objects) - flags += " " + " ".join(f"-l{lib}" for lib in effective_libraries) - flags += " " + " ".join(f"-L{lib}" for lib in effective_library_dirs) - flags += f" -o {library.get_qualified_name(self.platform)}" - if self.platform == "darwin": - flags += " -undefined dynamic_lookup" - if "mold" in self.ld: - flags += f" -fuse-ld={self.ld}" - elif "lld" in self.ld: - flags += " -fuse-ld=lld" - elif self.toolchain == "clang": + if self.toolchain == "gcc" or self.toolchain == "clang": flags += " -shared" flags += " " + " ".join(effective_link_args) flags += " " + " ".join(effective_extra_objects) @@ -411,7 +396,7 @@ def get_link_flags(self, library: HatchCppLibrary, build_type: BuildType = "rele ] for libs_path in python_libs_paths: if libs_path.exists(): - flags += f" /LIBPATH:{str(libs_path)}" + flags += f" /LIBPATH:{libs_path!s}" break flags += " " + " ".join(f"{lib}.lib" for lib in effective_libraries) flags += " " + " ".join(f"/LIBPATH:{lib}" for lib in effective_library_dirs) diff --git a/hatch_cpp/toolchains/vcpkg.py b/hatch_cpp/toolchains/vcpkg.py index 530df98..ccebeb7 100644 --- a/hatch_cpp/toolchains/vcpkg.py +++ b/hatch_cpp/toolchains/vcpkg.py @@ -5,7 +5,7 @@ from pathlib import Path from platform import machine as platform_machine from sys import platform as sys_platform -from typing import Literal, Optional +from typing import Literal from pydantic import BaseModel, Field @@ -40,7 +40,7 @@ } -def _read_vcpkg_ref_from_gitmodules(vcpkg_root: Path) -> Optional[str]: +def _read_vcpkg_ref_from_gitmodules(vcpkg_root: Path) -> str | None: """Read the branch/ref for vcpkg from .gitmodules if it exists. Looks for a submodule whose path matches ``vcpkg_root`` and returns @@ -61,11 +61,11 @@ def _read_vcpkg_ref_from_gitmodules(vcpkg_root: Path) -> Optional[str]: class HatchCppVcpkgConfiguration(BaseModel): - vcpkg: Optional[str] = Field(default="vcpkg.json") - vcpkg_root: Optional[Path] = Field(default=Path("vcpkg")) - vcpkg_repo: Optional[str] = Field(default="https://github.com/microsoft/vcpkg.git") - vcpkg_triplet: Optional[VcpkgTriplet] = Field(default=None) - vcpkg_ref: Optional[str] = Field( + vcpkg: str | None = Field(default="vcpkg.json") + vcpkg_root: Path | None = Field(default=Path("vcpkg")) + vcpkg_repo: str | None = Field(default="https://github.com/microsoft/vcpkg.git") + vcpkg_triplet: VcpkgTriplet | None = Field(default=None) + vcpkg_ref: str | None = Field( default=None, description="Branch, tag, or commit SHA to checkout after cloning vcpkg. " "If not set, falls back to the branch specified in .gitmodules for the vcpkg submodule.", @@ -73,7 +73,7 @@ class HatchCppVcpkgConfiguration(BaseModel): # TODO: overlay - def _resolve_vcpkg_ref(self) -> Optional[str]: + def _resolve_vcpkg_ref(self) -> str | None: """Return the ref to checkout: explicit config takes priority, then .gitmodules.""" if self.vcpkg_ref is not None: return self.vcpkg_ref diff --git a/hatch_cpp/utils.py b/hatch_cpp/utils.py index 0efb237..c32d84c 100644 --- a/hatch_cpp/utils.py +++ b/hatch_cpp/utils.py @@ -1,12 +1,12 @@ from __future__ import annotations -from functools import lru_cache +from functools import cache from pydantic import ImportString, TypeAdapter _import_string_adapter = TypeAdapter(ImportString) -@lru_cache(maxsize=None) +@cache def import_string(input_string: str): return _import_string_adapter.validate_python(input_string)