-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
78aea4c
commit 5bc72b4
Showing
8 changed files
with
420 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#include <Python.h> | ||
|
||
#include "pool/pool_manager.hpp" | ||
|
||
#include <giomm/init.h> | ||
|
||
#include "util.hpp" | ||
#include "schematic.hpp" | ||
#include "project.hpp" | ||
|
||
PyDoc_STRVAR(module_doc, "Parts of horizon as a module"); | ||
|
||
static struct PyModuleDef horizonmodule = { | ||
PyModuleDef_HEAD_INIT, "horizon", module_doc, -1, NULL, NULL, NULL, NULL, NULL}; | ||
|
||
extern "C" { | ||
PyMODINIT_FUNC PyInit_horizon(void); | ||
} | ||
|
||
PyMODINIT_FUNC PyInit_horizon(void) | ||
{ | ||
Gio::init(); | ||
horizon::PoolManager::init(); | ||
|
||
if (PyType_Ready(&ProjectType) < 0) | ||
return NULL; | ||
|
||
if (PyType_Ready(&SchematicType) < 0) | ||
return NULL; | ||
|
||
if (!json_init()) | ||
return NULL; | ||
|
||
PyObject *m; | ||
|
||
m = PyModule_Create(&horizonmodule); | ||
if (m == NULL) | ||
return NULL; | ||
|
||
Py_INCREF(&ProjectType); | ||
PyModule_AddObject(m, "Project", (PyObject *)&ProjectType); | ||
return m; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
#include "project.hpp" | ||
#include "schematic.hpp" | ||
#include "pool/pool_manager.hpp" | ||
|
||
ProjectWrapper::ProjectWrapper(const std::string &path) : project(horizon::Project::new_from_file(path)) | ||
{ | ||
} | ||
|
||
static PyObject *PyProject_get_name(PyObject *pself) | ||
{ | ||
auto self = reinterpret_cast<PyProject *>(pself); | ||
return PyUnicode_FromString(self->project->project.name.c_str()); | ||
} | ||
|
||
static PyObject *PyProject_get_title(PyObject *pself) | ||
{ | ||
auto self = reinterpret_cast<PyProject *>(pself); | ||
return PyUnicode_FromString(self->project->project.title.c_str()); | ||
} | ||
|
||
static PyObject *PyProject_open_top_schematic(PyObject *pself) | ||
{ | ||
auto self = reinterpret_cast<PyProject *>(pself); | ||
if (horizon::PoolManager::get().get_by_uuid(self->project->project.pool_uuid) == nullptr) { | ||
PyErr_SetString(PyExc_FileNotFoundError, "pool not found"); | ||
return NULL; | ||
} | ||
SchematicWrapper *schematic = nullptr; | ||
try { | ||
auto top_block = self->project->project.get_top_block(); | ||
schematic = new SchematicWrapper(self->project->project, top_block.uuid); | ||
} | ||
catch (const std::exception &e) { | ||
PyErr_SetString(PyExc_IOError, e.what()); | ||
return NULL; | ||
} | ||
catch (...) { | ||
PyErr_SetString(PyExc_IOError, "unknown exception"); | ||
return NULL; | ||
} | ||
|
||
PySchematic *sch = PyObject_New(PySchematic, &SchematicType); | ||
sch->schematic = schematic; | ||
return reinterpret_cast<PyObject *>(sch); | ||
} | ||
|
||
|
||
static PyObject *PyProject_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||
{ | ||
PyProject *self; | ||
self = (PyProject *)type->tp_alloc(type, 0); | ||
if (self != NULL) { | ||
self->project = nullptr; | ||
} | ||
return (PyObject *)self; | ||
} | ||
|
||
static void PyProject_dealloc(PyObject *pself) | ||
{ | ||
auto self = reinterpret_cast<PyProject *>(pself); | ||
delete self->project; | ||
Py_TYPE(self)->tp_free((PyObject *)self); | ||
} | ||
|
||
static int PyProject_init(PyObject *pself, PyObject *args, PyObject *kwds) | ||
{ | ||
auto self = reinterpret_cast<PyProject *>(pself); | ||
const char *path; | ||
if (!PyArg_ParseTuple(args, "s", &path)) | ||
return -1; | ||
ProjectWrapper *new_project = nullptr; | ||
try { | ||
new_project = new ProjectWrapper(path); | ||
} | ||
catch (const std::exception &e) { | ||
PyErr_SetString(PyExc_IOError, e.what()); | ||
return -1; | ||
} | ||
catch (...) { | ||
PyErr_SetString(PyExc_IOError, "unknown exception"); | ||
return -1; | ||
} | ||
delete self->project; | ||
self->project = new_project; | ||
return 0; | ||
} | ||
|
||
static PyMethodDef PyProject_methods[] = { | ||
{"get_name", (PyCFunction)PyProject_get_name, METH_NOARGS, "Return project name"}, | ||
{"get_title", (PyCFunction)PyProject_get_title, METH_NOARGS, "Return project title"}, | ||
{"open_top_schematic", (PyCFunction)PyProject_open_top_schematic, METH_NOARGS, "Open top block"}, | ||
{NULL} /* Sentinel */ | ||
}; | ||
|
||
|
||
PyTypeObject ProjectType = { | ||
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "horizon.Project", | ||
.tp_basicsize = sizeof(PyProject), | ||
|
||
.tp_itemsize = 0, | ||
.tp_dealloc = PyProject_dealloc, | ||
.tp_flags = Py_TPFLAGS_DEFAULT, | ||
.tp_doc = "Project", | ||
|
||
.tp_methods = PyProject_methods, | ||
.tp_init = PyProject_init, | ||
.tp_new = PyProject_new, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#pragma once | ||
#include <Python.h> | ||
#include "project/project.hpp" | ||
|
||
extern PyTypeObject ProjectType; | ||
|
||
class ProjectWrapper { | ||
public: | ||
ProjectWrapper(const std::string &path); | ||
horizon::Project project; | ||
}; | ||
|
||
typedef struct { | ||
PyObject_HEAD | ||
/* Type-specific fields go here. */ | ||
ProjectWrapper *project; | ||
} PyProject; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
#include "schematic.hpp" | ||
#include "project/project.hpp" | ||
#include "pool/pool_manager.hpp" | ||
#include "block/block.hpp" | ||
#include "schematic/schematic.hpp" | ||
#include "pool/pool_cached.hpp" | ||
#include "nlohmann/json.hpp" | ||
#include "export_pdf/export_pdf.hpp" | ||
#include "export_bom/export_bom.hpp" | ||
#include "util.hpp" | ||
#include <podofo/podofo.h> | ||
|
||
SchematicWrapper::SchematicWrapper(const horizon::Project &prj, const horizon::UUID &block_uuid) | ||
: pool(horizon::PoolManager::get().get_by_uuid(prj.pool_uuid)->base_path, prj.pool_cache_directory), | ||
block(horizon::Block::new_from_file(prj.blocks.at(block_uuid).block_filename, pool)), | ||
schematic(horizon::Schematic::new_from_file(prj.blocks.at(block_uuid).schematic_filename, block, pool)) | ||
{ | ||
schematic.expand(); | ||
} | ||
|
||
|
||
static PyObject *PySchematic_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||
{ | ||
PySchematic *self; | ||
self = (PySchematic *)type->tp_alloc(type, 0); | ||
if (self != NULL) { | ||
self->schematic = nullptr; | ||
} | ||
return (PyObject *)self; | ||
} | ||
|
||
static void PySchematic_dealloc(PyObject *pself) | ||
{ | ||
auto self = reinterpret_cast<PySchematic *>(pself); | ||
delete self->schematic; | ||
Py_TYPE(self)->tp_free((PyObject *)self); | ||
} | ||
|
||
|
||
static PyObject *PySchematic_get_pdf_export_settings(PyObject *pself) | ||
{ | ||
auto self = reinterpret_cast<PySchematic *>(pself); | ||
auto settings = self->schematic->schematic.pdf_export_settings.serialize(); | ||
return py_from_json(settings); | ||
} | ||
|
||
static PyObject *PySchematic_export_pdf(PyObject *pself, PyObject *args) | ||
{ | ||
auto self = reinterpret_cast<PySchematic *>(pself); | ||
PyObject *py_export_settings = nullptr; | ||
if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &py_export_settings)) | ||
return NULL; | ||
try { | ||
auto settings_json = json_from_py(py_export_settings); | ||
horizon::PDFExportSettings settings(settings_json); | ||
horizon::export_pdf(self->schematic->schematic, settings, nullptr); | ||
} | ||
catch (const std::exception &e) { | ||
PyErr_SetString(PyExc_IOError, e.what()); | ||
return NULL; | ||
} | ||
catch (const PoDoFo::PdfError &e) { | ||
PyErr_SetString(PyExc_IOError, e.what()); | ||
return NULL; | ||
} | ||
catch (...) { | ||
PyErr_SetString(PyExc_IOError, "unknown exception"); | ||
return NULL; | ||
} | ||
Py_RETURN_NONE; | ||
} | ||
|
||
|
||
static PyObject *PySchematic_get_bom_export_settings(PyObject *pself) | ||
{ | ||
auto self = reinterpret_cast<PySchematic *>(pself); | ||
auto settings = self->schematic->block.bom_export_settings.serialize(); | ||
return py_from_json(settings); | ||
} | ||
|
||
static PyObject *PySchematic_export_bom(PyObject *pself, PyObject *args) | ||
{ | ||
auto self = reinterpret_cast<PySchematic *>(pself); | ||
PyObject *py_export_settings = nullptr; | ||
if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &py_export_settings)) | ||
return NULL; | ||
try { | ||
auto settings_json = json_from_py(py_export_settings); | ||
horizon::BOMExportSettings settings(settings_json); | ||
horizon::export_BOM(settings.output_filename, self->schematic->block, settings); | ||
} | ||
catch (const std::exception &e) { | ||
PyErr_SetString(PyExc_IOError, e.what()); | ||
return NULL; | ||
} | ||
catch (...) { | ||
PyErr_SetString(PyExc_IOError, "unknown exception"); | ||
return NULL; | ||
} | ||
|
||
Py_RETURN_NONE; | ||
} | ||
|
||
|
||
static PyMethodDef PySchematic_methods[] = { | ||
{"get_pdf_export_settings", (PyCFunction)PySchematic_get_pdf_export_settings, METH_NOARGS, | ||
"Return pdf export settings"}, | ||
{"get_bom_export_settings", (PyCFunction)PySchematic_get_bom_export_settings, METH_NOARGS, | ||
"Return bom export settings"}, | ||
{"export_pdf", (PyCFunction)PySchematic_export_pdf, METH_VARARGS, "Export as pdf"}, | ||
{"export_bom", (PyCFunction)PySchematic_export_bom, METH_VARARGS, "Export BOM"}, | ||
{NULL} /* Sentinel */ | ||
}; | ||
|
||
PyTypeObject SchematicType = { | ||
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "horizon.Schematic", | ||
.tp_basicsize = sizeof(PySchematic), | ||
|
||
.tp_itemsize = 0, | ||
.tp_dealloc = PySchematic_dealloc, | ||
.tp_flags = Py_TPFLAGS_DEFAULT, | ||
.tp_doc = "Schematic", | ||
|
||
.tp_methods = PySchematic_methods, | ||
.tp_new = PySchematic_new, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#pragma once | ||
#include <Python.h> | ||
#include "block/block.hpp" | ||
#include "schematic/schematic.hpp" | ||
#include "project/project.hpp" | ||
#include "pool/pool_cached.hpp" | ||
|
||
extern PyTypeObject SchematicType; | ||
|
||
class SchematicWrapper { | ||
public: | ||
SchematicWrapper(const horizon::Project &prj, const horizon::UUID &block_uuid); | ||
horizon::PoolCached pool; | ||
horizon::Block block; | ||
horizon::Schematic schematic; | ||
}; | ||
|
||
typedef struct { | ||
PyObject_HEAD | ||
/* Type-specific fields go here. */ | ||
SchematicWrapper *schematic; | ||
} PySchematic; |
Oops, something went wrong.
5bc72b4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very nice!
And a good demonstration of how well though out the the Horizon implementation is: zero changes of the Horizon internals needed for this feature. Thanks!