solver.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /*-----------------------------------------------------------------------------
  2. | Copyright (c) 2013-2019, Nucleic Development Team.
  3. |
  4. | Distributed under the terms of the Modified BSD License.
  5. |
  6. | The full license is in the file LICENSE, distributed with this software.
  7. |----------------------------------------------------------------------------*/
  8. #include <cppy/cppy.h>
  9. #include <kiwi/kiwi.h>
  10. #include "types.h"
  11. #include "util.h"
  12. namespace kiwisolver
  13. {
  14. namespace
  15. {
  16. PyObject*
  17. Solver_new( PyTypeObject* type, PyObject* args, PyObject* kwargs )
  18. {
  19. if( PyTuple_GET_SIZE( args ) != 0 || ( kwargs && PyDict_Size( kwargs ) != 0 ) )
  20. return cppy::type_error( "Solver.__new__ takes no arguments" );
  21. PyObject* pysolver = PyType_GenericNew( type, args, kwargs );
  22. if( !pysolver )
  23. return 0;
  24. Solver* self = reinterpret_cast<Solver*>( pysolver );
  25. new( &self->solver ) kiwi::Solver();
  26. return pysolver;
  27. }
  28. void
  29. Solver_dealloc( Solver* self )
  30. {
  31. self->solver.~Solver();
  32. Py_TYPE( self )->tp_free( pyobject_cast( self ) );
  33. }
  34. PyObject*
  35. Solver_addConstraint( Solver* self, PyObject* other )
  36. {
  37. if( !Constraint::TypeCheck( other ) )
  38. return cppy::type_error( other, "Constraint" );
  39. Constraint* cn = reinterpret_cast<Constraint*>( other );
  40. try
  41. {
  42. self->solver.addConstraint( cn->constraint );
  43. }
  44. catch( const kiwi::DuplicateConstraint& )
  45. {
  46. PyErr_SetObject( DuplicateConstraint, other );
  47. return 0;
  48. }
  49. catch( const kiwi::UnsatisfiableConstraint& )
  50. {
  51. PyErr_SetObject( UnsatisfiableConstraint, other );
  52. return 0;
  53. }
  54. Py_RETURN_NONE;
  55. }
  56. PyObject*
  57. Solver_removeConstraint( Solver* self, PyObject* other )
  58. {
  59. if( !Constraint::TypeCheck( other ) )
  60. return cppy::type_error( other, "Constraint" );
  61. Constraint* cn = reinterpret_cast<Constraint*>( other );
  62. try
  63. {
  64. self->solver.removeConstraint( cn->constraint );
  65. }
  66. catch( const kiwi::UnknownConstraint& )
  67. {
  68. PyErr_SetObject( UnknownConstraint, other );
  69. return 0;
  70. }
  71. Py_RETURN_NONE;
  72. }
  73. PyObject*
  74. Solver_hasConstraint( Solver* self, PyObject* other )
  75. {
  76. if( !Constraint::TypeCheck( other ) )
  77. return cppy::type_error( other, "Constraint" );
  78. Constraint* cn = reinterpret_cast<Constraint*>( other );
  79. return cppy::incref( self->solver.hasConstraint( cn->constraint ) ? Py_True : Py_False );
  80. }
  81. PyObject*
  82. Solver_addEditVariable( Solver* self, PyObject* args )
  83. {
  84. PyObject* pyvar;
  85. PyObject* pystrength;
  86. if( !PyArg_ParseTuple( args, "OO", &pyvar, &pystrength ) )
  87. return 0;
  88. if( !Variable::TypeCheck( pyvar ) )
  89. return cppy::type_error( pyvar, "Variable" );
  90. double strength;
  91. if( !convert_to_strength( pystrength, strength ) )
  92. return 0;
  93. Variable* var = reinterpret_cast<Variable*>( pyvar );
  94. try
  95. {
  96. self->solver.addEditVariable( var->variable, strength );
  97. }
  98. catch( const kiwi::DuplicateEditVariable& )
  99. {
  100. PyErr_SetObject( DuplicateEditVariable, pyvar );
  101. return 0;
  102. }
  103. catch( const kiwi::BadRequiredStrength& e )
  104. {
  105. PyErr_SetString( BadRequiredStrength, e.what() );
  106. return 0;
  107. }
  108. Py_RETURN_NONE;
  109. }
  110. PyObject*
  111. Solver_removeEditVariable( Solver* self, PyObject* other )
  112. {
  113. if( !Variable::TypeCheck( other ) )
  114. return cppy::type_error( other, "Variable" );
  115. Variable* var = reinterpret_cast<Variable*>( other );
  116. try
  117. {
  118. self->solver.removeEditVariable( var->variable );
  119. }
  120. catch( const kiwi::UnknownEditVariable& )
  121. {
  122. PyErr_SetObject( UnknownEditVariable, other );
  123. return 0;
  124. }
  125. Py_RETURN_NONE;
  126. }
  127. PyObject*
  128. Solver_hasEditVariable( Solver* self, PyObject* other )
  129. {
  130. if( !Variable::TypeCheck( other ) )
  131. return cppy::type_error( other, "Variable" );
  132. Variable* var = reinterpret_cast<Variable*>( other );
  133. return cppy::incref( self->solver.hasEditVariable( var->variable ) ? Py_True : Py_False );
  134. }
  135. PyObject*
  136. Solver_suggestValue( Solver* self, PyObject* args )
  137. {
  138. PyObject* pyvar;
  139. PyObject* pyvalue;
  140. if( !PyArg_ParseTuple( args, "OO", &pyvar, &pyvalue ) )
  141. return 0;
  142. if( !Variable::TypeCheck( pyvar ) )
  143. return cppy::type_error( pyvar, "Variable" );
  144. double value;
  145. if( !convert_to_double( pyvalue, value ) )
  146. return 0;
  147. Variable* var = reinterpret_cast<Variable*>( pyvar );
  148. try
  149. {
  150. self->solver.suggestValue( var->variable, value );
  151. }
  152. catch( const kiwi::UnknownEditVariable& )
  153. {
  154. PyErr_SetObject( UnknownEditVariable, pyvar );
  155. return 0;
  156. }
  157. Py_RETURN_NONE;
  158. }
  159. PyObject*
  160. Solver_updateVariables( Solver* self )
  161. {
  162. self->solver.updateVariables();
  163. Py_RETURN_NONE;
  164. }
  165. PyObject*
  166. Solver_reset( Solver* self )
  167. {
  168. self->solver.reset();
  169. Py_RETURN_NONE;
  170. }
  171. PyObject*
  172. Solver_dump( Solver* self )
  173. {
  174. cppy::ptr dump_str( PyUnicode_FromString( self->solver.dumps().c_str() ) );
  175. PyObject_Print( dump_str.get(), stdout, 0 );
  176. Py_RETURN_NONE;
  177. }
  178. PyObject*
  179. Solver_dumps( Solver* self )
  180. {
  181. return PyUnicode_FromString( self->solver.dumps().c_str() );
  182. }
  183. static PyMethodDef
  184. Solver_methods[] = {
  185. { "addConstraint", ( PyCFunction )Solver_addConstraint, METH_O,
  186. "Add a constraint to the solver." },
  187. { "removeConstraint", ( PyCFunction )Solver_removeConstraint, METH_O,
  188. "Remove a constraint from the solver." },
  189. { "hasConstraint", ( PyCFunction )Solver_hasConstraint, METH_O,
  190. "Check whether the solver contains a constraint." },
  191. { "addEditVariable", ( PyCFunction )Solver_addEditVariable, METH_VARARGS,
  192. "Add an edit variable to the solver." },
  193. { "removeEditVariable", ( PyCFunction )Solver_removeEditVariable, METH_O,
  194. "Remove an edit variable from the solver." },
  195. { "hasEditVariable", ( PyCFunction )Solver_hasEditVariable, METH_O,
  196. "Check whether the solver contains an edit variable." },
  197. { "suggestValue", ( PyCFunction )Solver_suggestValue, METH_VARARGS,
  198. "Suggest a desired value for an edit variable." },
  199. { "updateVariables", ( PyCFunction )Solver_updateVariables, METH_NOARGS,
  200. "Update the values of the solver variables." },
  201. { "reset", ( PyCFunction )Solver_reset, METH_NOARGS,
  202. "Reset the solver to the initial empty starting condition." },
  203. { "dump", ( PyCFunction )Solver_dump, METH_NOARGS,
  204. "Dump a representation of the solver internals to stdout." },
  205. { "dumps", ( PyCFunction )Solver_dumps, METH_NOARGS,
  206. "Dump a representation of the solver internals to a string." },
  207. { 0 } // sentinel
  208. };
  209. static PyType_Slot Solver_Type_slots[] = {
  210. { Py_tp_dealloc, void_cast( Solver_dealloc ) }, /* tp_dealloc */
  211. { Py_tp_methods, void_cast( Solver_methods ) }, /* tp_methods */
  212. { Py_tp_new, void_cast( Solver_new ) }, /* tp_new */
  213. { Py_tp_alloc, void_cast( PyType_GenericAlloc ) }, /* tp_alloc */
  214. { Py_tp_free, void_cast( PyObject_Del ) }, /* tp_free */
  215. { 0, 0 },
  216. };
  217. } // namespace
  218. // Initialize static variables (otherwise the compiler eliminates them)
  219. PyTypeObject* Solver::TypeObject = NULL;
  220. PyType_Spec Solver::TypeObject_Spec = {
  221. "kiwisolver.Solver", /* tp_name */
  222. sizeof( Solver ), /* tp_basicsize */
  223. 0, /* tp_itemsize */
  224. Py_TPFLAGS_DEFAULT|
  225. Py_TPFLAGS_BASETYPE, /* tp_flags */
  226. Solver_Type_slots /* slots */
  227. };
  228. bool Solver::Ready()
  229. {
  230. // The reference will be handled by the module to which we will add the type
  231. TypeObject = pytype_cast( PyType_FromSpec( &TypeObject_Spec ) );
  232. if( !TypeObject )
  233. {
  234. return false;
  235. }
  236. return true;
  237. }
  238. PyObject* DuplicateConstraint;
  239. PyObject* UnsatisfiableConstraint;
  240. PyObject* UnknownConstraint;
  241. PyObject* DuplicateEditVariable;
  242. PyObject* UnknownEditVariable;
  243. PyObject* BadRequiredStrength;
  244. bool init_exceptions()
  245. {
  246. DuplicateConstraint = PyErr_NewException(
  247. const_cast<char*>( "kiwisolver.DuplicateConstraint" ), 0, 0 );
  248. if( !DuplicateConstraint )
  249. {
  250. return false;
  251. }
  252. UnsatisfiableConstraint = PyErr_NewException(
  253. const_cast<char*>( "kiwisolver.UnsatisfiableConstraint" ), 0, 0 );
  254. if( !UnsatisfiableConstraint )
  255. {
  256. return false;
  257. }
  258. UnknownConstraint = PyErr_NewException(
  259. const_cast<char*>( "kiwisolver.UnknownConstraint" ), 0, 0 );
  260. if( !UnknownConstraint )
  261. {
  262. return false;
  263. }
  264. DuplicateEditVariable = PyErr_NewException(
  265. const_cast<char*>( "kiwisolver.DuplicateEditVariable" ), 0, 0 );
  266. if( !DuplicateEditVariable )
  267. {
  268. return false;
  269. }
  270. UnknownEditVariable = PyErr_NewException(
  271. const_cast<char*>( "kiwisolver.UnknownEditVariable" ), 0, 0 );
  272. if( !UnknownEditVariable )
  273. {
  274. return false;
  275. }
  276. BadRequiredStrength = PyErr_NewException(
  277. const_cast<char*>( "kiwisolver.BadRequiredStrength" ), 0, 0 );
  278. if( !BadRequiredStrength )
  279. {
  280. return false;
  281. }
  282. return true;
  283. }
  284. } // namespace