Skip to content

Commit 6f59e85

Browse files
committed
Switch from raw dataclasses to pydantic for validation
1 parent 8252257 commit 6f59e85

File tree

3 files changed

+38
-84
lines changed

3 files changed

+38
-84
lines changed

hatch_cpp/plugin.py

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
import logging
44
import os
55
import typing as t
6-
from dataclasses import fields
76

87
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
98

10-
from .structs import HatchCppBuildConfig, HatchCppBuildPlan, HatchCppLibrary, HatchCppPlatform
9+
from .structs import HatchCppBuildConfig, HatchCppBuildPlan
1110

1211
__all__ = ("HatchCppBuildHook",)
1312

@@ -30,18 +29,10 @@ def initialize(self, version: str, _: dict[str, t.Any]) -> None:
3029
self._logger.info("Skipping the build hook since SKIP_HATCH_CPP was set")
3130
return
3231

33-
kwargs = {k.replace("-", "_"): v if not isinstance(v, bool) else str(v) for k, v in self.config.items()}
34-
available_fields = [f.name for f in fields(HatchCppBuildConfig)]
35-
for key in list(kwargs):
36-
if key not in available_fields:
37-
del kwargs[key]
38-
config = HatchCppBuildConfig(**kwargs)
32+
config = HatchCppBuildConfig(**self.config)
3933

40-
library_kwargs = [
41-
{k.replace("-", "_"): v if not isinstance(v, bool) else str(v) for k, v in library_kwargs.items()} for library_kwargs in config.libraries
42-
]
43-
libraries = [HatchCppLibrary(**library_kwargs) for library_kwargs in library_kwargs]
44-
platform = HatchCppPlatform.default()
34+
libraries = config.libraries
35+
platform = config.platform
4536
if config.toolchain == "raw":
4637
build_plan = HatchCppBuildPlan(libraries=libraries, platform=platform)
4738
build_plan.generate()
@@ -51,39 +42,5 @@ def initialize(self, version: str, _: dict[str, t.Any]) -> None:
5142
build_plan.execute()
5243
build_plan.cleanup()
5344

54-
# build_kwargs = config.build_kwargs
55-
# if version == "editable":
56-
# build_kwargs = config.editable_build_kwargs or build_kwargs
57-
58-
# should_skip_build = False
59-
# if not config.build_function:
60-
# log.warning("No build function found")
61-
# should_skip_build = True
62-
63-
# elif config.skip_if_exists and version == "standard":
64-
# should_skip_build = should_skip(config.skip_if_exists)
65-
# if should_skip_build:
66-
# log.info("Skip-if-exists file(s) found")
67-
68-
# # Get build function and call it with normalized parameter names.
69-
# if not should_skip_build and config.build_function:
70-
# build_func = get_build_func(config.build_function)
71-
# build_kwargs = normalize_kwargs(build_kwargs)
72-
# log.info("Building with %s", config.build_function)
73-
# log.info("With kwargs: %s", build_kwargs)
74-
# try:
75-
# build_func(self.target_name, version, **build_kwargs)
76-
# except Exception as e:
77-
# if version == "editable" and config.optional_editable_build.lower() == "true":
78-
# warnings.warn(f"Encountered build error:\n{e}", stacklevel=2)
79-
# else:
80-
# raise e
81-
# else:
82-
# log.info("Skipping build")
83-
84-
# # Ensure targets in distributable dists.
85-
# if version == "standard":
86-
# ensure_targets(config.ensured_targets)
87-
8845
self._logger.info("Finished running hatch-cpp")
8946
return

hatch_cpp/structs.py

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
from __future__ import annotations
22

3-
from dataclasses import dataclass, field
43
from os import environ, system
54
from pathlib import Path
65
from sys import executable, platform as sys_platform
76
from sysconfig import get_path
8-
from typing import Literal
7+
from typing import List, Literal, Optional
98

10-
from hatchling.builders.config import BuilderConfig
9+
from pydantic import BaseModel, Field
1110

1211
__all__ = (
1312
"HatchCppBuildConfig",
@@ -25,42 +24,26 @@
2524
}
2625

2726

28-
@dataclass
29-
class HatchCppBuildConfig(BuilderConfig):
30-
"""Build config values for Hatch C++ Builder."""
31-
32-
toolchain: str | None = field(default="raw")
33-
libraries: list[dict[str, str]] = field(default_factory=list)
34-
verbose: bool | None = field(default=False)
35-
# build_function: str | None = None
36-
# build_kwargs: t.Mapping[str, str] = field(default_factory=dict)
37-
# editable_build_kwargs: t.Mapping[str, str] = field(default_factory=dict)
38-
# ensured_targets: list[str] = field(default_factory=list)
39-
# skip_if_exists: list[str] = field(default_factory=list)
40-
41-
42-
@dataclass
43-
class HatchCppLibrary(object):
27+
class HatchCppLibrary(BaseModel):
4428
"""A C++ library."""
4529

4630
name: str
47-
sources: list[str]
31+
sources: List[str]
4832

49-
include_dirs: list[str] = field(default_factory=list)
50-
library_dirs: list[str] = field(default_factory=list)
51-
libraries: list[str] = field(default_factory=list)
52-
extra_compile_args: list[str] = field(default_factory=list)
53-
extra_link_args: list[str] = field(default_factory=list)
54-
extra_objects: list[str] = field(default_factory=list)
55-
define_macros: list[str] = field(default_factory=list)
56-
undef_macros: list[str] = field(default_factory=list)
33+
include_dirs: List[str] = Field(default_factory=list, alias="include-dirs")
34+
library_dirs: List[str] = Field(default_factory=list, alias="library-dirs")
35+
libraries: List[str] = Field(default_factory=list)
36+
extra_compile_args: List[str] = Field(default_factory=list, alias="extra-compile-args")
37+
extra_link_args: List[str] = Field(default_factory=list, alias="extra-link-args")
38+
extra_objects: List[str] = Field(default_factory=list, alias="extra-objects")
39+
define_macros: List[str] = Field(default_factory=list, alias="define-macros")
40+
undef_macros: List[str] = Field(default_factory=list, alias="undef-macros")
5741

58-
export_symbols: list[str] = field(default_factory=list)
59-
depends: list[str] = field(default_factory=list)
42+
export_symbols: List[str] = Field(default_factory=list, alias="export-symbols")
43+
depends: List[str] = Field(default_factory=list)
6044

6145

62-
@dataclass
63-
class HatchCppPlatform(object):
46+
class HatchCppPlatform(BaseModel):
6447
cc: str
6548
cxx: str
6649
platform: Platform
@@ -133,11 +116,10 @@ def get_link_flags(self, library: HatchCppLibrary) -> str:
133116
return flags
134117

135118

136-
@dataclass
137-
class HatchCppBuildPlan(object):
138-
libraries: list[HatchCppLibrary] = field(default_factory=list)
139-
platform: HatchCppPlatform = field(default_factory=HatchCppPlatform.default)
140-
commands: list[str] = field(default_factory=list)
119+
class HatchCppBuildPlan(BaseModel):
120+
libraries: List[HatchCppLibrary] = Field(default_factory=list)
121+
platform: HatchCppPlatform = Field(default_factory=HatchCppPlatform.default)
122+
commands: List[str] = Field(default_factory=list)
141123

142124
def generate(self):
143125
self.commands = []
@@ -157,3 +139,17 @@ def cleanup(self):
157139
temp_obj = Path(f"{library.name}.obj")
158140
if temp_obj.exists():
159141
temp_obj.unlink()
142+
143+
144+
class HatchCppBuildConfig(BaseModel):
145+
"""Build config values for Hatch C++ Builder."""
146+
147+
toolchain: Optional[str] = Field(default="raw")
148+
libraries: List[HatchCppLibrary] = Field(default_factory=list)
149+
verbose: Optional[bool] = Field(default=False)
150+
platform: Optional[HatchCppPlatform] = Field(default_factory=HatchCppPlatform.default)
151+
# build_function: str | None = None
152+
# build_kwargs: t.Mapping[str, str] = field(default_factory=dict)
153+
# editable_build_kwargs: t.Mapping[str, str] = field(default_factory=dict)
154+
# ensured_targets: list[str] = field(default_factory=list)
155+
# skip_if_exists: list[str] = field(default_factory=list)

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ classifiers = [
3333

3434
dependencies = [
3535
"hatchling>=1.20",
36+
"pydantic",
3637
]
3738

3839
[project.optional-dependencies]

0 commit comments

Comments
 (0)