Skip to content

Commit 69998f8

Browse files
gsohlergusohlert-paul
authored
Python in OpenSCAD (openscad#5690)
Add first python module (`cube()`). Switch hash library from crypto++ to nettle. --------- Co-authored-by: Guenther Sohler <guenther.sohler@photeon.com> Co-authored-by: Torsten Paul <Torsten.Paul@gmx.de>
1 parent 91070a0 commit 69998f8

File tree

10 files changed

+711
-64
lines changed

10 files changed

+711
-64
lines changed

CMakeLists.txt

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -465,12 +465,17 @@ target_link_libraries(OpenSCAD PRIVATE ${LIBXML2_LIBRARIES})
465465

466466
if(ENABLE_PYTHON)
467467
find_package(Python REQUIRED COMPONENTS Interpreter Development)
468-
find_package(CryptoPP REQUIRED)
469-
message(STATUS "Python enabled, using Crypto++ ${PC_CRYPTOPP_VERSION}")
470-
target_include_directories(OpenSCAD PRIVATE ${Python_INCLUDE_DIRS})
471-
target_include_directories(OpenSCAD PRIVATE ${CRYPTOPP_INCLUDE_DIRS})
472-
target_link_libraries(OpenSCAD PRIVATE ${Python_LIBRARIES})
473-
target_link_libraries(OpenSCAD PRIVATE ${CRYPTOPP_LIBRARIES})
468+
find_package(Nettle 3.4)
469+
if(NOT Nettle_FOUND)
470+
message(WARNING "Nettle not found, disabling python support.")
471+
set(ENABLE_PYTHON OFF CACHE BOOL "" FORCE)
472+
else()
473+
message(STATUS "Python enabled, using Nettle ${Nettle_VERSION}")
474+
target_include_directories(OpenSCAD PRIVATE ${Python_INCLUDE_DIRS})
475+
target_link_libraries(OpenSCAD PRIVATE ${Python_LIBRARIES})
476+
target_include_directories(OpenSCAD PRIVATE ${Nettle_INCLUDE_DIRS})
477+
target_link_libraries(OpenSCAD PRIVATE ${Nettle_LIBRARIES})
478+
endif()
474479
endif()
475480

476481
if(ENABLE_HIDAPI)
@@ -900,7 +905,8 @@ set(CORE_SOURCES
900905
${BISON_comment_parser_OUTPUTS})
901906
if(ENABLE_PYTHON)
902907
list(APPEND CORE_SOURCES
903-
src/core/pyopenscad.cc )
908+
src/python/pyopenscad.cc
909+
src/python/pyfunctions.cc )
904910
target_compile_definitions(OpenSCAD PRIVATE ENABLE_PYTHON)
905911
endif()
906912

cmake/Modules/FindNettle.cmake

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Copyright (C) 2020 Dieter Baron and Thomas Klausner
2+
#
3+
# The authors can be contacted at <info@libzip.org>
4+
#
5+
# Redistribution and use in source and binary forms, with or without
6+
# modification, are permitted provided that the following conditions
7+
# are met:
8+
#
9+
# 1. Redistributions of source code must retain the above copyright
10+
# notice, this list of conditions and the following disclaimer.
11+
#
12+
# 2. Redistributions in binary form must reproduce the above copyright
13+
# notice, this list of conditions and the following disclaimer in
14+
# the documentation and/or other materials provided with the
15+
# distribution.
16+
#
17+
# 3. The names of the authors may not be used to endorse or promote
18+
# products derived from this software without specific prior
19+
# written permission.
20+
#
21+
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22+
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24+
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27+
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29+
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30+
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31+
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32+
33+
#[=======================================================================[.rst:
34+
FindNettle
35+
-------
36+
37+
Finds the Nettle library.
38+
39+
Imported Targets
40+
^^^^^^^^^^^^^^^^
41+
42+
This module provides the following imported targets, if found:
43+
44+
``Nettle::Nettle``
45+
The Nettle library
46+
47+
Result Variables
48+
^^^^^^^^^^^^^^^^
49+
50+
This will define the following variables:
51+
52+
``Nettle_FOUND``
53+
True if the system has the Nettle library.
54+
``Nettle_VERSION``
55+
The version of the Nettle library which was found.
56+
``Nettle_INCLUDE_DIRS``
57+
Include directories needed to use Nettle.
58+
``Nettle_LIBRARIES``
59+
Libraries needed to link to Nettle.
60+
61+
Cache Variables
62+
^^^^^^^^^^^^^^^
63+
64+
The following cache variables may also be set:
65+
66+
``Nettle_INCLUDE_DIR``
67+
The directory containing ``nettle/aes.h``.
68+
``Nettle_LIBRARY``
69+
The path to the Nettle library.
70+
71+
#]=======================================================================]
72+
73+
find_package(PkgConfig)
74+
pkg_check_modules(PC_Nettle QUIET nettle)
75+
76+
find_path(Nettle_INCLUDE_DIR
77+
NAMES nettle/aes.h nettle/md5.h nettle/pbkdf2.h nettle/ripemd160.h nettle/sha.h
78+
PATHS ${PC_Nettle_INCLUDE_DIRS}
79+
)
80+
find_library(Nettle_LIBRARY
81+
NAMES nettle
82+
PATHS ${PC_Nettle_LIBRARY_DIRS}
83+
)
84+
85+
# Extract version information from the header file
86+
if(Nettle_INCLUDE_DIR)
87+
# This file only exists in nettle>=3.0
88+
if(EXISTS ${Nettle_INCLUDE_DIR}/nettle/version.h)
89+
file(STRINGS ${Nettle_INCLUDE_DIR}/nettle/version.h _ver_major_line
90+
REGEX "^#define NETTLE_VERSION_MAJOR *[0-9]+"
91+
LIMIT_COUNT 1)
92+
string(REGEX MATCH "[0-9]+"
93+
Nettle_MAJOR_VERSION "${_ver_major_line}")
94+
file(STRINGS ${Nettle_INCLUDE_DIR}/nettle/version.h _ver_minor_line
95+
REGEX "^#define NETTLE_VERSION_MINOR *[0-9]+"
96+
LIMIT_COUNT 1)
97+
string(REGEX MATCH "[0-9]+"
98+
Nettle_MINOR_VERSION "${_ver_minor_line}")
99+
set(Nettle_VERSION "${Nettle_MAJOR_VERSION}.${Nettle_MINOR_VERSION}")
100+
unset(_ver_major_line)
101+
unset(_ver_minor_line)
102+
else()
103+
if(PC_Nettle_VERSION)
104+
set(Nettle_VERSION ${PC_Nettle_VERSION})
105+
else()
106+
set(Nettle_VERSION "1.0")
107+
endif()
108+
endif()
109+
endif()
110+
111+
include(FindPackageHandleStandardArgs)
112+
find_package_handle_standard_args(Nettle
113+
FOUND_VAR Nettle_FOUND
114+
REQUIRED_VARS
115+
Nettle_LIBRARY
116+
Nettle_INCLUDE_DIR
117+
VERSION_VAR Nettle_VERSION
118+
)
119+
120+
if(Nettle_FOUND)
121+
set(Nettle_LIBRARIES ${Nettle_LIBRARY})
122+
set(Nettle_INCLUDE_DIRS ${Nettle_INCLUDE_DIR})
123+
set(Nettle_DEFINITIONS ${PC_Nettle_CFLAGS_OTHER})
124+
endif()
125+
126+
if(Nettle_FOUND AND NOT TARGET Nettle::Nettle)
127+
add_library(Nettle::Nettle UNKNOWN IMPORTED)
128+
set_target_properties(Nettle::Nettle PROPERTIES
129+
IMPORTED_LOCATION "${Nettle_LIBRARY}"
130+
INTERFACE_COMPILE_OPTIONS "${PC_Nettle_CFLAGS_OTHER}"
131+
INTERFACE_INCLUDE_DIRECTORIES "${Nettle_INCLUDE_DIR}"
132+
)
133+
endif()
134+
135+
mark_as_advanced(
136+
Nettle_INCLUDE_DIR
137+
Nettle_LIBRARY
138+
)
139+
140+
# compatibility variables
141+
set(Nettle_VERSION_STRING ${Nettle_VERSION})

scripts/github-ci-linux-get-dependencies.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ QT="$1"
55
DIST=$(. /etc/os-release; echo $VERSION_CODENAME)
66

77
PACKAGES1="build-essential bison cmake curl flex gettext git imagemagick ghostscript"
8-
PACKAGES2="libboost-program-options-dev libboost-regex-dev libboost-system-dev libeigen3-dev libcrypto++-dev"
8+
PACKAGES2="libboost-program-options-dev libboost-regex-dev libboost-system-dev libeigen3-dev nettle-dev"
99
PACKAGES3="libxi-dev libxmu-dev qtbase5-dev qtmultimedia5-dev libqt5opengl5-dev libqt5svg5-dev libqscintilla2-qt5-dev"
1010
PACKAGES4="libcairo2-dev libcgal-dev libglew-dev libgmp-dev libmpfr-dev libegl-dev libegl1-mesa-dev libxml2-dev"
1111
PACKAGES5="libdouble-conversion-dev libfontconfig-dev libharfbuzz-dev libopencsg-dev lib3mf-dev libtbb-dev libzip-dev"

src/core/pyopenscad.cc

Lines changed: 0 additions & 36 deletions
This file was deleted.

src/gui/MainWindow.cc

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -143,24 +143,26 @@
143143
#include "gui/QSettingsCached.h"
144144

145145
#ifdef ENABLE_PYTHON
146-
extern std::shared_ptr<AbstractNode> python_result_node;
147-
std::string evaluatePython(const std::string& code, double time);
148-
extern bool python_trusted;
149-
150-
#include "cryptopp/sha.h"
151-
#include "cryptopp/filters.h"
152-
#include "cryptopp/base64.h"
146+
#include "python/python_public.h"
147+
#include "nettle/sha2.h"
148+
#include "nettle/base64.h"
153149

154150
std::string SHA256HashString(std::string aString){
155-
std::string digest;
156-
CryptoPP::SHA256 hash;
151+
uint8_t digest[SHA256_DIGEST_SIZE];
152+
sha256_ctx sha256_ctx;
153+
154+
sha256_init(&sha256_ctx);
155+
sha256_update(&sha256_ctx, aString.length(), (uint8_t *) aString.c_str());
156+
sha256_digest(&sha256_ctx, SHA256_DIGEST_SIZE, digest);
157157

158-
CryptoPP::StringSource foo(aString, true,
159-
new CryptoPP::HashFilter(hash,
160-
new CryptoPP::Base64Encoder(
161-
new CryptoPP::StringSink(digest))));
158+
base64_encode_ctx base64_ctx;
159+
char digest_base64[BASE64_ENCODE_LENGTH(SHA256_DIGEST_SIZE)+1];
160+
memset(digest_base64,0,sizeof(digest_base64));
162161

163-
return digest;
162+
base64_encode_init(&base64_ctx);
163+
base64_encode_update(&base64_ctx, digest_base64, SHA256_DIGEST_SIZE, digest);
164+
base64_encode_final(&base64_ctx, digest_base64);
165+
return digest_base64;
164166
}
165167

166168
#endif // ifdef ENABLE_PYTHON
@@ -1885,7 +1887,8 @@ void MainWindow::parseTopLevelDocument()
18851887
auto fulltext_py =
18861888
std::string(this->lastCompiledDoc.toUtf8().constData());
18871889

1888-
auto error = evaluatePython(fulltext_py, this->animateWidget->getAnimTval());
1890+
initPython(this->animateWidget->getAnimTval());
1891+
auto error = evaluatePython(fulltext_py, false);
18891892
if (error.size() > 0) LOG(message_group::Error, Location::NONE, "", error.c_str());
18901893
fulltext = "\n";
18911894
}

src/openscad.cc

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,7 @@
8787

8888

8989
#ifdef ENABLE_PYTHON
90-
extern std::shared_ptr<AbstractNode> python_result_node;
91-
std::string evaluatePython(const std::string &code, double time);
92-
bool python_active = false;
93-
bool python_trusted = false;
90+
#include "python/python_public.h"
9491
#endif
9592

9693
namespace po = boost::program_options;
@@ -602,7 +599,8 @@ int cmdline(const CommandLine& cmd)
602599

603600
if(python_active) {
604601
auto fulltext_py = text;
605-
auto error = evaluatePython(fulltext_py, 0.0);
602+
initPython(0.0);
603+
auto error = evaluatePython(fulltext_py, false);
606604
if(error.size() > 0) LOG(error.c_str());
607605
text ="\n";
608606
}

src/python/pyfunctions.cc

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* OpenSCAD (www.openscad.org)
3+
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
4+
* Marius Kintel <marius@kintel.net>
5+
*
6+
* This program is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* As a special exception, you have permission to link this program
12+
* with the CGAL library and distribute executables, as long as you
13+
* follow the requirements of the GNU GPL in regard to all of the
14+
* software in the executable aside from CGAL.
15+
*
16+
* This program is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU General Public License
22+
* along with this program; if not, write to the Free Software
23+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24+
*
25+
*/
26+
27+
#include <Python.h>
28+
#include "src/python/pyopenscad.h"
29+
#include "src/core/primitives.h"
30+
31+
PyObject *python_cube(PyObject *self, PyObject *args, PyObject *kwargs)
32+
{
33+
DECLARE_INSTANCE
34+
auto node = std::make_shared<CubeNode>(instance);
35+
36+
char *kwlist[] = {"size", "center", NULL};
37+
PyObject *size = NULL;
38+
39+
PyObject *center = NULL;
40+
41+
42+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", kwlist,
43+
&size,
44+
&center)){
45+
PyErr_SetString(PyExc_TypeError, "Error during parsing cube(size)");
46+
return NULL;
47+
}
48+
49+
if (size != NULL) {
50+
if (python_vectorval(size, 3, 3, &(node->x), &(node->y), &(node->z))) {
51+
PyErr_SetString(PyExc_TypeError, "Invalid Cube dimensions");
52+
return NULL;
53+
}
54+
}
55+
if(node->x <= 0 || node->y <= 0 || node ->z <= 0) {
56+
PyErr_SetString(PyExc_TypeError, "Cube Dimensions must be positive");
57+
return NULL;
58+
}
59+
node->center = false;
60+
if (center == Py_False || center == NULL ) ;
61+
else if (center == Py_True){
62+
for(int i=0;i<3;i++) node->center=true;
63+
} else {
64+
PyErr_SetString(PyExc_TypeError, "Unknown Value for center parameter");
65+
return NULL;
66+
}
67+
return PyOpenSCADObjectFromNode(&PyOpenSCADType, node);
68+
}
69+
70+
PyObject *python_show_core(PyObject *obj)
71+
{
72+
std::shared_ptr<AbstractNode> child = PyOpenSCADObjectToNode(obj);
73+
if (child == NULL) {
74+
PyErr_SetString(PyExc_TypeError, "Invalid type for Object in output");
75+
return NULL;
76+
}
77+
PyObject *key, *value;
78+
Py_ssize_t pos = 0;
79+
python_result_node = child;
80+
return Py_None;
81+
}
82+
83+
PyObject *python_show(PyObject *self, PyObject *args, PyObject *kwargs)
84+
{
85+
PyObject *obj = NULL;
86+
char *kwlist[] = {"obj", NULL};
87+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist,
88+
&obj
89+
)) {
90+
PyErr_SetString(PyExc_TypeError, "Error during parsing output(object)");
91+
return NULL;
92+
}
93+
return python_show_core(obj);
94+
}
95+
96+
PyMethodDef PyOpenSCADFunctions[] = {
97+
{"cube", (PyCFunction) python_cube, METH_VARARGS | METH_KEYWORDS, "Create Cube."},
98+
{"show", (PyCFunction) python_show, METH_VARARGS | METH_KEYWORDS, "Show the result."},
99+
{NULL, NULL, 0, NULL}
100+
};
101+

0 commit comments

Comments
 (0)