Skip to content

Commit 6cac3cb

Browse files
committed
fix(python): fix errors
1 parent 79b9748 commit 6cac3cb

File tree

9 files changed

+100
-40
lines changed

9 files changed

+100
-40
lines changed

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ out/
1414
*.dylib
1515
*.dll
1616

17+
# Python
18+
__pycache__/
19+
*.pyc
20+
*.pyo
21+
*.pyd
22+
*.pyw
23+
*.pyz
24+
1725
# Debug and temporary files
1826
*.log
1927
*.tmp

.vscode/settings.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
"cmake.automaticReconfigure": true,
1919
"cmake.configureOnEdit": true,
2020
"cmake.configureOnOpen": true,
21+
"cursorpyright.analysis.extraPaths": [
22+
"build/debug/binding",
23+
"build/release/binding"
24+
],
2125
"editor.codeActionsOnSave": {
2226
"source.fixAll.clangd": "explicit",
2327
"source.organizeImports": "explicit"
@@ -27,7 +31,6 @@
2731
"enabled": true
2832
},
2933
"editor.suggest.insertMode": "replace",
30-
"editor.tabSize": 2,
3134
"files.associations": {
3235
"*.cpp": "cpp",
3336
"*.h": "cpp",

binding/memory_binding.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@ void bind_memory(py::module &m) {
3030
return self.CreateUnique<Rectangle>(width, height);
3131
},
3232
py::return_value_policy::take_ownership)
33-
.def("create_shared_circle",
34-
[](ResourceManager &self, double radius) { return self.CreateShared<Circle>(radius); })
35-
.def("create_shared_rectangle",
36-
[](ResourceManager &self, double width, double height) {
37-
return self.CreateShared<Rectangle>(width, height);
38-
})
33+
.def(
34+
"create_shared_circle",
35+
[](ResourceManager &self, double radius) { return self.CreateShared<Circle>(radius); },
36+
py::return_value_policy::reference)
37+
.def(
38+
"create_shared_rectangle",
39+
[](ResourceManager &self, double width, double height) {
40+
return self.CreateShared<Rectangle>(width, height);
41+
},
42+
py::return_value_policy::reference)
3943
.def("register_cleanup",
4044
[](ResourceManager &self, std::function<void()> cleanup_func) {
4145
self.RegisterCleanup<int>(cleanup_func);

binding/shapes_binding.cpp

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,21 @@ void bind_shapes(py::module &m) {
1919
using namespace cpp_features::shapes;
2020

2121
// Bind the abstract Shape base class
22-
py::class_<Shape>(m, "Shape", "Abstract base class for geometric shapes")
22+
py::class_<Shape, std::shared_ptr<Shape>>(m, "Shape", "Abstract base class for geometric shapes")
2323
.def("get_area", &Shape::GetArea, "Calculate the area of the shape")
2424
.def("get_perimeter", &Shape::GetPerimeter, "Calculate the perimeter of the shape")
2525
.def("draw", &Shape::Draw, "Draw the shape")
26-
.def("get_name", &Shape::GetName, "Get the name of the shape")
26+
.def(
27+
"get_name", [](const Shape &s) { return std::string{s.GetName()}; },
28+
"Get the name of the shape")
2729
.def("__str__", [](const Shape &s) { return std::string{s.GetName()}; })
2830
.def("__repr__", [](const Shape &s) {
2931
return std::format("<{} at {}>", s.GetName(), static_cast<const void *>(&s));
3032
});
3133

3234
// Bind Circle class
33-
py::class_<Circle, Shape>(m, "Circle", "Circle shape with radius-based geometry")
35+
py::class_<Circle, Shape, std::shared_ptr<Circle>>(m, "Circle",
36+
"Circle shape with radius-based geometry")
3437
.def(py::init<double>(), py::arg("radius"), "Construct a circle with the specified radius")
3538
.def("get_radius", &Circle::GetRadius, "Get the radius of the circle")
3639
.def("__eq__", [](const Circle &self, const Circle &other) { return self == other; })
@@ -60,7 +63,8 @@ void bind_shapes(py::module &m) {
6063
});
6164

6265
// Bind Rectangle class
63-
py::class_<Rectangle, Shape>(m, "Rectangle", "Rectangle shape with width and height geometry")
66+
py::class_<Rectangle, Shape, std::shared_ptr<Rectangle>>(
67+
m, "Rectangle", "Rectangle shape with width and height geometry")
6468
.def(py::init<Rectangle::Dimensions>(), py::arg("dimensions"),
6569
"Construct a rectangle from a Dimensions structure")
6670
.def(py::init<double, double>(), py::arg("width"), py::arg("height"),
@@ -91,36 +95,34 @@ void bind_shapes(py::module &m) {
9195
// Bind factory functions
9296
m.def(
9397
"create_circle",
94-
[](double radius) -> std::unique_ptr<Circle> { return CreateCircle(radius); },
95-
py::arg("radius"), "Factory function for creating Circle objects",
96-
py::return_value_policy::take_ownership);
98+
[](double radius) -> std::shared_ptr<Circle> { return std::make_shared<Circle>(radius); },
99+
py::arg("radius"), "Factory function for creating Circle objects");
97100

98101
m.def(
99102
"create_rectangle",
100-
[](double width, double height) -> std::unique_ptr<Rectangle> {
101-
return CreateRectangle(width, height);
103+
[](double width, double height) -> std::shared_ptr<Rectangle> {
104+
return std::make_shared<Rectangle>(width, height);
102105
},
103-
py::arg("width"), py::arg("height"), "Factory function for creating Rectangle objects",
104-
py::return_value_policy::take_ownership);
106+
py::arg("width"), py::arg("height"), "Factory function for creating Rectangle objects");
105107

106108
m.def(
107-
"create_square", [](double side) -> std::unique_ptr<Rectangle> { return CreateSquare(side); },
108-
py::arg("side"), "Factory function for creating square Rectangle objects",
109-
py::return_value_policy::take_ownership);
109+
"create_square",
110+
[](double side) -> std::shared_ptr<Rectangle> { return std::make_shared<Rectangle>(side); },
111+
py::arg("side"), "Factory function for creating square Rectangle objects");
110112

111113
m.def(
112114
"create_shape",
113-
[](const std::string &shape_type, py::args args) -> std::unique_ptr<Shape> {
115+
[](const std::string &shape_type, py::args args) -> std::shared_ptr<Shape> {
114116
if (shape_type == "circle") {
115117
if (args.size() != 1) {
116118
throw std::invalid_argument("Circle requires exactly 1 argument (radius)");
117119
}
118-
return CreateCircle(args[0].cast<double>());
120+
return std::make_shared<Circle>(args[0].cast<double>());
119121
} else if (shape_type == "rectangle") {
120122
if (args.size() == 1) {
121-
return CreateSquare(args[0].cast<double>());
123+
return std::make_shared<Rectangle>(args[0].cast<double>());
122124
} else if (args.size() == 2) {
123-
return CreateRectangle(args[0].cast<double>(), args[1].cast<double>());
125+
return std::make_shared<Rectangle>(args[0].cast<double>(), args[1].cast<double>());
124126
} else {
125127
throw std::invalid_argument(
126128
"Rectangle requires 1 argument (side) or 2 arguments (width, height)");

include/timing/timer.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,26 @@ class ScopedTimer {
234234
template <concepts::TimerCallback Func>
235235
explicit ScopedTimer(std::string_view name, Func callback) : name_{name}, callback_{callback} {}
236236

237+
/**
238+
* @brief Copy constructor is deleted - ScopedTimer should not be copied
239+
*/
240+
ScopedTimer(const ScopedTimer &) = delete;
241+
242+
/**
243+
* @brief Copy assignment operator is deleted - ScopedTimer should not be copied
244+
*/
245+
auto operator=(const ScopedTimer &) -> ScopedTimer & = delete;
246+
247+
/**
248+
* @brief Move constructor is default - ScopedTimer can be moved
249+
*/
250+
ScopedTimer(ScopedTimer &&) = default;
251+
252+
/**
253+
* @brief Move assignment operator is default - ScopedTimer can be moved
254+
*/
255+
auto operator=(ScopedTimer &&) -> ScopedTimer & = default;
256+
237257
/**
238258
* @brief Destructor that automatically prints timing results
239259
*

python/algorithms.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ def sort_inplace(data: list[T] | Container[T]) -> None:
2929
"""
3030
match data:
3131
case list():
32-
_algorithms.sort_container(data)
32+
# Ensure the original Python list is sorted in place
33+
data.sort()
3334
case Container():
3435
_algorithms.sort_container(data._container)
3536
case _:
@@ -77,7 +78,19 @@ def transform(data: Iterable[T], func: Callable[[T], U]) -> list[U]:
7778
"""
7879
match data:
7980
case list() | tuple():
80-
return _algorithms.transform_to_vector(list(data), func)
81+
items = list(data)
82+
if not items:
83+
return []
84+
sample_out = func(items[0])
85+
# Prefer fast C++ path for numeric transforms we support
86+
if all(isinstance(x, int) for x in items) and isinstance(sample_out, int):
87+
return _algorithms.transform_to_vector(items, func) # list[int] -> list[int]
88+
if all(isinstance(x, int) for x in items) and isinstance(sample_out, float):
89+
return _algorithms.transform_to_vector(items, func) # list[int] -> list[float]
90+
if all(isinstance(x, float) for x in items) and isinstance(sample_out, float):
91+
return _algorithms.transform_to_vector(items, func) # list[float] -> list[float]
92+
# Fallback to Python for other types (e.g., str)
93+
return [func(item) for item in items]
8194
case Container():
8295
return _algorithms.transform_to_vector(data._container, func)
8396
case _:
@@ -99,12 +112,21 @@ def find_min_max(data: Sequence[T]) -> tuple[T, T]:
99112
"""
100113
match data:
101114
case list() | tuple():
102-
return _algorithms.find_min_max(list(data))
115+
if not data:
116+
raise ValueError('find_min_max requires a non-empty sequence')
117+
if all(isinstance(x, int) for x in data) or all(isinstance(x, float) for x in data):
118+
return _algorithms.find_min_max(list(data))
119+
# Fallback for strings or mixed types using Python semantics
120+
return (min(data), max(data))
103121
case Container():
104122
return _algorithms.find_min_max(data._container)
105123
case _:
106124
items = list(data)
107-
return _algorithms.find_min_max(items)
125+
if not items:
126+
raise ValueError('find_min_max requires a non-empty sequence')
127+
if all(isinstance(x, (int, float)) for x in items):
128+
return _algorithms.find_min_max(items)
129+
return (min(items), max(items))
108130

109131

110132
def pipeline(*functions: Callable[[Any], Any]) -> Callable[[Any], Any]:

python/containers.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,14 @@ def __init__(self, container_type: type[T], data: Iterable[T] | None = None):
2828
"""Initialize container with specific type."""
2929
self._type = container_type
3030

31-
match container_type:
32-
case int:
33-
self._container = _containers.IntContainer(list(data) if data else [])
34-
case float:
35-
self._container = _containers.DoubleContainer(list(data) if data else [])
36-
case str:
37-
self._container = _containers.StringContainer(list(data) if data else [])
38-
case _:
39-
raise ValueError(f'Unsupported container type: {container_type}')
31+
if container_type is int:
32+
self._container = _containers.IntContainer(list(data) if data else [])
33+
elif container_type is float:
34+
self._container = _containers.DoubleContainer(list(data) if data else [])
35+
elif container_type is str:
36+
self._container = _containers.StringContainer(list(data) if data else [])
37+
else:
38+
raise ValueError(f'Unsupported container type: {container_type}')
4039

4140
def add(self, item: T) -> None:
4241
"""Add item to container.

python/memory.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def create_circle(self, radius: float) -> Circle:
3434
Circle
3535
Created circle instance
3636
"""
37-
return self._manager.create_unique_circle(radius)
37+
return self._manager.create_shared_circle(radius)
3838

3939
def create_rectangle(self, width: float, height: float) -> Rectangle:
4040
"""Create a Rectangle using the resource manager.
@@ -51,7 +51,7 @@ def create_rectangle(self, width: float, height: float) -> Rectangle:
5151
Rectangle
5252
Created rectangle instance
5353
"""
54-
return self._manager.create_unique_rectangle(width, height)
54+
return self._manager.create_shared_rectangle(width, height)
5555

5656
def create_shared_circle(self, radius: float) -> Circle:
5757
"""Create a shared Circle.

python/random.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ def sample(population: list[T], k: int) -> list[T]:
240240
list[T]
241241
Sampled elements
242242
"""
243+
if k > len(population):
244+
raise ValueError('Sample size cannot exceed population size')
243245
match population:
244246
case list() if all(isinstance(x, int) for x in population):
245247
return _random_cpp.sample_from_range(population, k)

0 commit comments

Comments
 (0)