Skip to content

Commit 0f22b25

Browse files
Keller Fabian Rudolf (CC-AD/EYC3)Keller Fabian Rudolf (CC-AD/EYC3)
authored andcommitted
make pybind11 test fixture fully self-contained
1 parent ad177f9 commit 0f22b25

File tree

7 files changed

+225
-5
lines changed

7 files changed

+225
-5
lines changed

misc/test-stubgenc.sh

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
#!/bin/bash
2-
# This script is expected to be run from root of the mypy repo
2+
3+
cd "$(dirname $0)/.."
34

45
# Install dependencies, demo project and mypy
56
python -m pip install -r test-requirements.txt
6-
python -m pip install pybind11-mypy-demo==0.0.1
7+
python -m pip install test-data/pybind11_mypy_demo
78
python -m pip install .
89

910
# Remove expected stubs and generate new inplace
10-
rm -rf test-data/stubgen/pybind11_mypy_demo
11-
stubgen -p pybind11_mypy_demo -o test-data/stubgen/
11+
STUBGEN_OUTPUT_FOLDER=test-data/pybind11_mypy_demo/stubgen
12+
rm -rf $STUBGEN_OUTPUT_FOLDER/*
13+
stubgen -p pybind11_mypy_demo -o $STUBGEN_OUTPUT_FOLDER
1214

1315
# Compare generated stubs to expected ones
14-
git diff --exit-code test-data/stubgen/pybind11_mypy_demo
16+
git diff --exit-code $STUBGEN_OUTPUT_FOLDER

test-data/pybind11_mypy_demo/LICENSE

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
Copyright (c) 2016 The Pybind Development Team, All rights reserved.
2+
3+
Redistribution and use in source and binary forms, with or without
4+
modification, are permitted provided that the following conditions are met:
5+
6+
1. Redistributions of source code must retain the above copyright notice, this
7+
list of conditions and the following disclaimer.
8+
9+
2. Redistributions in binary form must reproduce the above copyright notice,
10+
this list of conditions and the following disclaimer in the documentation
11+
and/or other materials provided with the distribution.
12+
13+
3. Neither the name of the copyright holder nor the names of its contributors
14+
may be used to endorse or promote products derived from this software
15+
without specific prior written permission.
16+
17+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27+
28+
You are under no obligation whatsoever to provide any bug fixes, patches, or
29+
upgrades to the features, functionality or performance of the source code
30+
("Enhancements") to anyone; however, if you choose to make your Enhancements
31+
available either publicly, or directly to the author of this software, without
32+
imposing a separate written license agreement for such Enhancements, then you
33+
hereby grant the following license: a non-exclusive, royalty-free perpetual
34+
license to install, use, modify, prepare derivative works, incorporate into
35+
other computer software, distribute, and sublicense such enhancements or
36+
derivative works thereof, in binary and source code form.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[build-system]
2+
requires = [
3+
"setuptools>=42",
4+
"wheel",
5+
"pybind11>=2.6.0",
6+
]
7+
8+
build-backend = "setuptools.build_meta"

test-data/pybind11_mypy_demo/setup.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import sys
2+
3+
from pybind11 import get_cmake_dir
4+
# Available at setup time due to pyproject.toml
5+
from pybind11.setup_helpers import Pybind11Extension, build_ext
6+
from setuptools import setup
7+
8+
__version__ = "0.0.1"
9+
10+
# The main interface is through Pybind11Extension.
11+
# * You can add cxx_std=11/14/17, and then build_ext can be removed.
12+
# * You can set include_pybind11=false to add the include directory yourself,
13+
# say from a submodule.
14+
#
15+
# Note:
16+
# Sort input source files if you glob sources to ensure bit-for-bit
17+
# reproducible builds (https://github.com/pybind/python_example/pull/53)
18+
19+
ext_modules = [
20+
Pybind11Extension(
21+
"pybind11_mypy_demo",
22+
["src/main.cpp"],
23+
# Example: passing in the version to the compiled code
24+
define_macros=[('VERSION_INFO', __version__)],
25+
),
26+
]
27+
28+
setup(
29+
name="pybind11-mypy-demo",
30+
version=__version__,
31+
author="Sergei Izmailov",
32+
author_email="[email protected]", # Subject to change
33+
url="https://github.com/sizmailov/pybind11-mypy-demo", # Subject to change
34+
description="A demo project using pybind11 to test mypy stubgen",
35+
long_description="",
36+
ext_modules=ext_modules,
37+
extras_require={"test": "pytest"},
38+
# Currently, build_ext only provides an optional "highest supported C++
39+
# level" feature, but in the future it may provide more features.
40+
cmdclass={"build_ext": build_ext},
41+
zip_safe=False,
42+
)
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#include <cmath>
2+
#include <pybind11/pybind11.h>
3+
4+
namespace py = pybind11;
5+
6+
namespace basics {
7+
8+
int answer() {
9+
return 42;
10+
}
11+
12+
int sum(int a, int b) {
13+
return a + b;
14+
}
15+
16+
double midpoint(double left, double right){
17+
return left + (right - left)/2;
18+
}
19+
20+
double weighted_midpoint(double left, double right, double alpha=0.5) {
21+
return left + (right - left) * alpha;
22+
}
23+
24+
struct Point {
25+
26+
enum class LengthUnit {
27+
mm=0,
28+
pixel,
29+
inch
30+
};
31+
32+
enum class AngleUnit {
33+
radian=0,
34+
degree
35+
};
36+
37+
Point() : Point(0, 0) {}
38+
Point(double x, double y) : x(x), y(y) {}
39+
40+
static const Point origin;
41+
static const Point x_axis;
42+
static const Point y_axis;
43+
44+
static LengthUnit length_unit;
45+
static AngleUnit angle_unit;
46+
47+
double length() const {
48+
return std::sqrt(x * x + y * y);
49+
}
50+
51+
double distance_to(double other_x, double other_y) const {
52+
double dx = x - other_x;
53+
double dy = y - other_y;
54+
return std::sqrt(dx*dx + dy*dy);
55+
}
56+
57+
double distance_to(const Point& other) const {
58+
return distance_to(other.x, other.y);
59+
}
60+
61+
double x, y;
62+
};
63+
64+
const Point Point::origin = Point(0, 0);
65+
const Point Point::x_axis = Point(1, 0);
66+
const Point Point::y_axis = Point(0, 1);
67+
68+
Point::LengthUnit Point::length_unit = Point::LengthUnit::mm;
69+
Point::AngleUnit Point::angle_unit = Point::AngleUnit::radian;
70+
71+
}
72+
73+
void bind_basics(py::module& basics) {
74+
75+
using namespace basics;
76+
77+
// Functions
78+
basics.def("answer", &answer);
79+
basics.def("sum", &sum);
80+
basics.def("midpoint", &midpoint, py::arg("left"), py::arg("right"));
81+
basics.def("weighted_midpoint", weighted_midpoint, py::arg("left"), py::arg("right"), py::arg("alpha")=0.5);
82+
83+
84+
// Classes
85+
py::class_<Point> pyPoint(basics, "Point");
86+
py::enum_<Point::LengthUnit> pyLengthUnit(pyPoint, "LengthUnit");
87+
py::enum_<Point::AngleUnit> pyAngleUnit(pyPoint, "AngleUnit");
88+
89+
pyPoint
90+
.def(py::init<>())
91+
.def(py::init<double, double>(), py::arg("x"), py::arg("y"))
92+
.def("distance_to", py::overload_cast<double, double>(&Point::distance_to, py::const_), py::arg("x"), py::arg("y"))
93+
.def("distance_to", py::overload_cast<const Point&>(&Point::distance_to, py::const_), py::arg("other"))
94+
.def_readwrite("x", &Point::x)
95+
.def_property("y",
96+
[](Point& self){ return self.y; },
97+
[](Point& self, double value){ self.y = value; }
98+
)
99+
.def_property_readonly("length", &Point::length)
100+
.def_property_readonly_static("x_axis", [](py::object cls){return Point::x_axis;})
101+
.def_property_readonly_static("y_axis", [](py::object cls){return Point::y_axis;})
102+
.def_readwrite_static("length_unit", &Point::length_unit)
103+
.def_property_static("angle_unit",
104+
[](py::object& /*cls*/){ return Point::angle_unit; },
105+
[](py::object& /*cls*/, Point::AngleUnit value){ Point::angle_unit = value; }
106+
)
107+
;
108+
109+
pyPoint.attr("origin") = Point::origin;
110+
111+
pyLengthUnit
112+
.value("mm", Point::LengthUnit::mm)
113+
.value("pixel", Point::LengthUnit::pixel)
114+
.value("inch", Point::LengthUnit::inch)
115+
;
116+
117+
pyAngleUnit
118+
.value("radian", Point::AngleUnit::radian)
119+
.value("degree", Point::AngleUnit::degree)
120+
;
121+
122+
// Module-level attributes
123+
basics.attr("PI") = std::acos(-1);
124+
basics.attr("__version__") = "0.0.1";
125+
}
126+
127+
PYBIND11_MODULE(pybind11_mypy_demo, m) {
128+
129+
auto basics = m.def_submodule("basics");
130+
bind_basics(basics);
131+
132+
}

0 commit comments

Comments
 (0)