Skip to content

Commit

Permalink
remove deprecated Record usage
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfikl authored and inducer committed Mar 1, 2024
1 parent 0e7a88a commit 05ee666
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 45 deletions.
23 changes: 15 additions & 8 deletions codepy/jit.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
"""

import logging

from pytools import Record
from dataclasses import dataclass
from typing import List, NamedTuple

from codepy import CompileError

Expand Down Expand Up @@ -214,8 +214,16 @@ class _InvalidInfoFile(RuntimeError):
pass


class _SourceInfo(Record):
pass
class _Dependency(NamedTuple):
name: str
mtime: int
md5: str


@dataclass(frozen=True)
class _SourceInfo:
dependencies: List[NamedTuple]
source_name: str


def compile_from_string(toolchain, name, source_string,
Expand Down Expand Up @@ -311,10 +319,9 @@ def get_file_md5sum(fname):
return checksum.hexdigest()

def get_dep_structure(source_paths):
deps = list(toolchain.get_dependencies(source_paths))
deps.sort()
return [(dep, os.stat(dep).st_mtime, get_file_md5sum(dep)) for dep in deps
if dep not in source_paths]
deps = toolchain.get_dependencies(source_paths)
return [_Dependency(dep, os.stat(dep).st_mtime, get_file_md5sum(dep))
for dep in sorted(deps) if dep not in source_paths]

def write_source(name):
for i, source in enumerate(source_string):
Expand Down
110 changes: 73 additions & 37 deletions codepy/toolchain.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Toolchains for Just-in-time Python extension compilation."""


__copyright__ = """
"Copyright (C) 2008,9 Andreas Kloeckner, Bryan Catanzaro
"""
Expand All @@ -25,29 +24,40 @@
THE SOFTWARE.
"""


from pytools import Record
from abc import ABC, abstractmethod
from dataclasses import dataclass, replace
from typing import AbstractSet, Any, List

from codepy import CompileError


class Toolchain(Record):
@dataclass(frozen=True)
class Toolchain(ABC):
"""Abstract base class for tools used to link dynamic Python modules."""

def __init__(self, *args, **kwargs):
if "features" not in kwargs:
kwargs["features"] = set()
Record.__init__(self, *args, **kwargs)
#: A list of directories where libraries are found.
library_dirs: List[str]
#: A list of libraries used.
libraries: List[str]
#: A list of directories from which to include header files.
include_dirs: List[str]

features: AbstractSet[str]

def copy(self, **kwargs: Any) -> "Toolchain":
from warnings import warn
warn(f"'{type(self).__name__}.copy' is deprecated. This is now a "
"dataclass and should be used with the standard 'replace'.",
DeprecationWarning, stacklevel=2)

return replace(self, **kwargs)

@abstractmethod
def get_version(self):
"""Return a string describing the exact version of the tools (compilers etc.)
involved in this toolchain.
Implemented by subclasses.
"""

raise NotImplementedError

def abi_id(self):
"""Return a picklable Python object that describes the ABI (Python version,
compiler versions, etc.) against which a Python module is compiled.
Expand Down Expand Up @@ -81,50 +91,38 @@ def add_library(self, feature, include_dirs, library_dirs, libraries):

self.libraries = libraries + self.libraries

@abstractmethod
def get_dependencies(self, source_files):
"""Return a list of header files referred to by *source_files.
Implemented by subclasses.
"""

raise NotImplementedError
"""Return a list of header files referred to by *source_files*."""

@abstractmethod
def build_extension(self, ext_file, source_files, debug=False):
"""Create the extension file *ext_file* from *source_files*
by invoking the toolchain. Raise :exc:`~codepy.jit.CompileError` in
case of error.
If *debug* is True, print the commands executed.
Implemented by subclasses.
"""

raise NotImplementedError

@abstractmethod
def build_object(self, obj_file, source_files, debug=False):
"""Build a compiled object *obj_file* from *source_files*
by invoking the toolchain. Raise :exc:`CompileError` in
case of error.
If *debug* is True, print the commands executed.
Implemented by subclasses.
"""

raise NotImplementedError

@abstractmethod
def link_extension(self, ext_file, object_files, debug=False):
"""Create the extension file *ext_file* from *object_files*
by invoking the toolchain. Raise :exc:`CompileError` in
case of error.
If *debug* is True, print the commands executed.
Implemented by subclasses.
"""

raise NotImplementedError

@abstractmethod
def with_optimization_level(self, level, **extra):
"""Return a new Toolchain object with the optimization level
set to `level` , on the scale defined by the gcc -O option.
Expand All @@ -134,16 +132,36 @@ def with_optimization_level(self, level, **extra):
simply ignore it.
Level may also be "debug" to specify a debug build.
Implemented by subclasses.
"""

raise NotImplementedError


# {{{ gcc-like tool chain

@dataclass(frozen=True)
class GCCLikeToolchain(Toolchain):
#: Path to the C compiler.
cc: str
#: Path to linker.
ld: str

#: A list of flags to pass to the C compiler.
cflags: List[str]
#: A list of linker flags.
ldflags: List[str]

#: A list of defines to pass to the C compiler.
defines: List[str]
# A list of variables to undefine.
undefines: List[str]

#: Extension for shared library generated by the compiler.
so_ext: str
#: Extension of the object file generated by the compiler.
o_ext: str

def _cmdline(self, source_files, object=False):
raise NotImplementedError

def get_version(self):
result, stdout, stderr = call_capture_output([self.cc, "--version"])
if result != 0:
Expand Down Expand Up @@ -234,6 +252,7 @@ def link_extension(self, ext_file, object_files, debug=False):

# {{{ gcc toolchain

@dataclass(frozen=True)
class GCCToolchain(GCCLikeToolchain):
def get_version_tuple(self):
ver = self.get_version()
Expand Down Expand Up @@ -289,13 +308,14 @@ def remove_prefix(flags, prefix):
if level >= 2 and self.get_version_tuple() >= (4, 3):
oflags.extend(["-march=native", "-mtune=native", ])

return self.copy(cflags=cflags + oflags)
return replace(self, cflags=cflags + oflags)

# }}}


# {{{ nvcc

@dataclass(frozen=True)
class NVCCToolchain(GCCLikeToolchain):
def get_version_tuple(self):
ver = self.get_version()
Expand Down Expand Up @@ -359,6 +379,9 @@ def build_object(self, ext_file, source_files, debug=False):
file=sys.stderr)
raise CompileError("module compilation failed")

def with_optimization_level(self, level, **extra):
raise NotImplementedError

# }}}


Expand Down Expand Up @@ -413,6 +436,7 @@ def _guess_toolchain_kwargs_from_python_config():
"o_ext": object_suffix,
"defines": defines,
"undefines": undefines,
"features": set(),
}


Expand Down Expand Up @@ -448,7 +472,20 @@ def guess_toolchain():
if sys.maxsize == 0x7fffffff:
kwargs["cflags"].extend(["-arch", "i386"])

return GCCToolchain(**kwargs)
return GCCToolchain(
cc=kwargs["cc"],
ld=kwargs["ld"],
library_dirs=kwargs["library_dirs"],
libraries=kwargs["libraries"],
include_dirs=kwargs["include_dirs"],
cflags=kwargs["cflags"],
ldflags=kwargs["ldflags"],
defines=kwargs["defines"],
undefines=kwargs["undefines"],
so_ext=kwargs["so_ext"],
o_ext=kwargs["o_ext"],
features=set(),
)
else:
raise ToolchainGuessError(
"Unable to determine compiler. Tried running "
Expand All @@ -471,7 +508,6 @@ def guess_nvcc_toolchain():
"undefines": gcc_kwargs["undefines"],
}
kwargs.setdefault("undefines", []).append("__BLOCKS__")
kwargs["cc"] = "nvcc"

return NVCCToolchain(**kwargs)

Expand Down

0 comments on commit 05ee666

Please sign in to comment.