<commit_before>/**
 * Behaviours - UML-like graphic programming language
 * Copyright (C) 2013 Coralbits SL & AISoy Robotics.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **/

#include <Python.h>
#include <wchar.h>

#include <ab/action.h>
#include <ab/factory.h>
#include <ab/manager.h>
#include <ab/log.h>
#include <ab/object_basic.h>

#include "python2.hpp"
namespace AB{
namespace Python2{
	extern Manager *ab_module_manager;
	static PyObject *manager_error;

	typedef struct{
		PyObject_HEAD
		Node *node;
	} NodeObject;

	typedef struct{
		PyObject_HEAD
	} NodesObject;
	
	
	static PyObject *ab_manager_resolve(PyObject *self, PyObject *args);
	static PyObject *ab_manager_resolve(PyObject *self, char *name);
	static PyObject *ab_manager_resolve(PyObject *self, const std::string &name);
	
	static PyObject *node_getattr(PyObject *self, char *attr){
		NodeObject *oself=(NodeObject*)self;
		try{
			auto v=oself->node->attr(attr);
			return object2pyobject(v);
		}
		catch(const AB::attribute_not_found &a){
			return NULL;
		}
	}
	static int node_setattr(PyObject *self, char *attr, PyObject *value){
		NodeObject *oself=(NodeObject*)self;
		try{
			oself->node->setAttr(attr, to_object(value));
			return 0;
		}
		catch(const AB::attribute_not_found &a){
			return -1;
		}
	}
	
	static PyObject *node_dir(PyObject *self){
		NodeObject *oself=(NodeObject*)self;
		try{
			auto attrlist=oself->node->attrList();
			auto I=attrlist.begin(), endI=attrlist.end();
			PyObject *ret=PyList_New(attrlist.size());
			int i;
			for(i=0;I!=endI;++i,++I){
				PyObject *name=PyUnicode_FromString((*I).c_str());
				PyList_SetItem(ret, i, name);
			}
			return ret;
		}
		catch(const AB::attribute_not_found &a){
			return NULL;
		}
	}
	
	static PyObject *node_notify(PyObject *self,PyObject *args,PyObject *kwargs){
		NodeObject *oself=(NodeObject*)self;
		ab_module_manager->notify(oself->node);
		Py_INCREF(Py_None);
		return Py_None;
	}
	
	static PyObject *nodes_getattr(PyObject *self,char *attr){
		return ab_manager_resolve(self, attr);
	}
	static PyObject *nodes_getitem(PyObject *self,PyObject *attr){
		Py_ssize_t size;
		const char *str;
		PyObject_AsCharBuffer(attr, &str, &size);
		std::string s{str};
		//wcstombs( str8, str, wcslen(str) );
		PyMem_Free((void*)str);
		return ab_manager_resolve(self, s.c_str());
	}
	
	static PyTypeObject NodeObjectType = {
			PyVarObject_HEAD_INIT(NULL,0)
			"ab.node",             /*tp_name*/
			sizeof(NodeObject), /*tp_basicsize*/
			0,                         /*tp_itemsize*/
			0,                         /*tp_dealloc*/
			0,                         /*tp_print*/
			node_getattr,                         /*tp_getattr*/
			node_setattr,                         /*tp_setattr*/
			0,                         /*tp_compare*/
			0,                         /*tp_repr*/
			0,                         /*tp_as_number*/
			0,                         /*tp_as_sequence*/
			0,                         /*tp_as_mapping*/
			0,                         /*tp_hash */
			node_notify,                         /*tp_call*/
			0,                         /*tp_str*/
			0,                         /*tp_getattro*/
			0,                         /*tp_setattro*/
			0,                         /*tp_as_buffer*/
			Py_TPFLAGS_DEFAULT,        /*tp_flags*/
			"Node objects",           /* tp_doc */
	};

	static PyTypeObject NodesObjectType = {
			PyVarObject_HEAD_INIT(NULL,0)
			"ab.nodes",             /*tp_name*/
			sizeof(NodesObject), /*tp_basicsize*/
			0,                         /*tp_itemsize*/
			0,                         /*tp_dealloc*/
			0,                         /*tp_print*/
			nodes_getattr,             /*tp_getattr*/
			0,                         /*tp_setattr*/
			0,                         /*tp_compare*/
			0,                         /*tp_repr*/
			0,                         /*tp_as_number*/
			0,                         /*tp_as_sequence*/
			0,                         /*tp_as_mapping*/
			0,                         /*tp_hash */
			0,                         /*tp_call*/
			0,                         /*tp_str*/
			0,                         /*tp_getattro*/
			0,                         /*tp_setattro*/
			0,                         /*tp_as_buffer*/
			Py_TPFLAGS_DEFAULT,        /*tp_flags*/
			"Nodes easy access",           /* tp_doc */
	};
	
	static PyMappingMethods nodes_mapping = {
		NULL, 
		nodes_getitem,
		NULL
	};


	PyObject *object2pyobject(AB::Object &obj){
		auto t=obj->type();
		if (t==AB::Integer::type)
				return PyLong_FromLong(object2int(obj));
		if (t==AB::Float::type)
				return PyFloat_FromDouble(object2float(obj));
		if (t==AB::String::type)
				return PyUnicode_FromString(object2string(obj).c_str());
		
		try{
			NodeObject *no=PyObject_New(NodeObject, &NodeObjectType);
			no->node=object2node(obj);
			return (PyObject*)(no);
		}
		catch(const AB::object_not_convertible &exc){
		}
		
		
		DEBUG("Create node %s failed", obj->type());
		return NULL;
	}
	
	Object to_object(PyObject *obj){
		if (PyBool_Check(obj))
			return AB::to_object( obj == Py_True );
		if (PyFloat_Check(obj))
			return AB::to_object( PyFloat_AsDouble(obj) );
		if (PyLong_Check(obj))
			return AB::to_object( (int)PyLong_AsLong(obj) );
		if (PyUnicode_Check(obj)){
			Py_ssize_t size;
			const char *str;
			PyObject_AsCharBuffer(obj, &str, &size);
			std::string str8{str};
			PyMem_Free((void*)str);

			return AB::to_object( str8 );
		}
		
		throw(AB::object_not_convertible( obj->ob_type->tp_name, "Object"));
	}

	/// Define a new class for the manager. 
	static PyObject *ab_manager_resolve(PyObject *self, PyObject *args){
		char *name;
		
		if (!PyArg_ParseTuple(args, "s", &name)){
			return NULL;
		}
		return ab_manager_resolve(self, name);
	}
	<commit_msg>Added straight conversion from python int objects. There was a long conversion, but not all ints are long in python2.<commit_after>/**
 * Behaviours - UML-like graphic programming language
 * Copyright (C) 2013 Coralbits SL & AISoy Robotics.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **/

#include <Python.h>
#include <wchar.h>

#include <ab/action.h>
#include <ab/factory.h>
#include <ab/manager.h>
#include <ab/log.h>
#include <ab/object_basic.h>

#include "python2.hpp"
namespace AB{
namespace Python2{
	extern Manager *ab_module_manager;
	static PyObject *manager_error;

	typedef struct{
		PyObject_HEAD
		Node *node;
	} NodeObject;

	typedef struct{
		PyObject_HEAD
	} NodesObject;
	
	
	static PyObject *ab_manager_resolve(PyObject *self, PyObject *args);
	static PyObject *ab_manager_resolve(PyObject *self, char *name);
	static PyObject *ab_manager_resolve(PyObject *self, const std::string &name);
	
	static PyObject *node_getattr(PyObject *self, char *attr){
		NodeObject *oself=(NodeObject*)self;
		try{
			auto v=oself->node->attr(attr);
			return object2pyobject(v);
		}
		catch(const AB::attribute_not_found &a){
			return NULL;
		}
	}
	static int node_setattr(PyObject *self, char *attr, PyObject *value){
		NodeObject *oself=(NodeObject*)self;
		try{
			oself->node->setAttr(attr, to_object(value));
			return 0;
		}
		catch(const AB::attribute_not_found &a){
			return -1;
		}
	}
	
	static PyObject *node_dir(PyObject *self){
		NodeObject *oself=(NodeObject*)self;
		try{
			auto attrlist=oself->node->attrList();
			auto I=attrlist.begin(), endI=attrlist.end();
			PyObject *ret=PyList_New(attrlist.size());
			int i;
			for(i=0;I!=endI;++i,++I){
				PyObject *name=PyUnicode_FromString((*I).c_str());
				PyList_SetItem(ret, i, name);
			}
			return ret;
		}
		catch(const AB::attribute_not_found &a){
			return NULL;
		}
	}
	
	static PyObject *node_notify(PyObject *self,PyObject *args,PyObject *kwargs){
		NodeObject *oself=(NodeObject*)self;
		ab_module_manager->notify(oself->node);
		Py_INCREF(Py_None);
		return Py_None;
	}
	
	static PyObject *nodes_getattr(PyObject *self,char *attr){
		return ab_manager_resolve(self, attr);
	}
	static PyObject *nodes_getitem(PyObject *self,PyObject *attr){
		Py_ssize_t size;
		const char *str;
		PyObject_AsCharBuffer(attr, &str, &size);
		std::string s{str};
		//wcstombs( str8, str, wcslen(str) );
		PyMem_Free((void*)str);
		return ab_manager_resolve(self, s.c_str());
	}
	
	static PyTypeObject NodeObjectType = {
			PyVarObject_HEAD_INIT(NULL,0)
			"ab.node",             /*tp_name*/
			sizeof(NodeObject), /*tp_basicsize*/
			0,                         /*tp_itemsize*/
			0,                         /*tp_dealloc*/
			0,                         /*tp_print*/
			node_getattr,                         /*tp_getattr*/
			node_setattr,                         /*tp_setattr*/
			0,                         /*tp_compare*/
			0,                         /*tp_repr*/
			0,                         /*tp_as_number*/
			0,                         /*tp_as_sequence*/
			0,                         /*tp_as_mapping*/
			0,                         /*tp_hash */
			node_notify,                         /*tp_call*/
			0,                         /*tp_str*/
			0,                         /*tp_getattro*/
			0,                         /*tp_setattro*/
			0,                         /*tp_as_buffer*/
			Py_TPFLAGS_DEFAULT,        /*tp_flags*/
			"Node objects",           /* tp_doc */
	};

	static PyTypeObject NodesObjectType = {
			PyVarObject_HEAD_INIT(NULL,0)
			"ab.nodes",             /*tp_name*/
			sizeof(NodesObject), /*tp_basicsize*/
			0,                         /*tp_itemsize*/
			0,                         /*tp_dealloc*/
			0,                         /*tp_print*/
			nodes_getattr,             /*tp_getattr*/
			0,                         /*tp_setattr*/
			0,                         /*tp_compare*/
			0,                         /*tp_repr*/
			0,                         /*tp_as_number*/
			0,                         /*tp_as_sequence*/
			0,                         /*tp_as_mapping*/
			0,                         /*tp_hash */
			0,                         /*tp_call*/
			0,                         /*tp_str*/
			0,                         /*tp_getattro*/
			0,                         /*tp_setattro*/
			0,                         /*tp_as_buffer*/
			Py_TPFLAGS_DEFAULT,        /*tp_flags*/
			"Nodes easy access",           /* tp_doc */
	};
	
	static PyMappingMethods nodes_mapping = {
		NULL, 
		nodes_getitem,
		NULL
	};


	PyObject *object2pyobject(AB::Object &obj){
		auto t=obj->type();
		if (t==AB::Integer::type)
				return PyLong_FromLong(object2int(obj));
		if (t==AB::Float::type)
				return PyFloat_FromDouble(object2float(obj));
		if (t==AB::String::type)
				return PyUnicode_FromString(object2string(obj).c_str());
		
		try{
			NodeObject *no=PyObject_New(NodeObject, &NodeObjectType);
			no->node=object2node(obj);
			return (PyObject*)(no);
		}
		catch(const AB::object_not_convertible &exc){
		}
		
		
		DEBUG("Create node %s failed", obj->type());
		return NULL;
	}
	
	Object to_object(PyObject *obj){
		if (PyBool_Check(obj))
			return AB::to_object( obj == Py_True );
		if (PyFloat_Check(obj))
			return AB::to_object( PyFloat_AsDouble(obj) );
		if (PyLong_Check(obj))
			return AB::to_object( (int)PyLong_AsLong(obj) );
		if (PyInt_Check(obj))
			return AB::to_object( (int)PyInt_AsLong(obj) );
		if (PyUnicode_Check(obj)){
			Py_ssize_t size;
			const char *str;
			PyObject_AsCharBuffer(obj, &str, &size);
			std::string str8{str};
			PyMem_Free((void*)str);

			return AB::to_object( str8 );
		}
		
		throw(AB::object_not_convertible( obj->ob_type->tp_name, "Object"));
	}

	/// Define a new class for the manager. 
	static PyObject *ab_manager_resolve(PyObject *self, PyObject *args){
		char *name;
		
		if (!PyArg_ParseTuple(args, "s", &name)){
			return NULL;
		}
		return ab_manager_resolve(self, name);
	}
	
{'fraction_non_alphanumeric': 0.12710745085851916, 'fraction_numerical': 0.007691710045839484, 'mean_word_length': 2.3269578702507108, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '944407', 'n_tokens_mistral': 4675, 'n_tokens_neox': 4178, 'n_words': 970}