Skip to content

Commit

Permalink
Merge pull request #2555 from linas/ntoxeg
Browse files Browse the repository at this point in the history
Port to python3
  • Loading branch information
linas authored Apr 28, 2020
2 parents 1d607ec + e4f9358 commit 77c997b
Show file tree
Hide file tree
Showing 38 changed files with 274 additions and 203 deletions.
29 changes: 15 additions & 14 deletions cmake/OpenCogCython.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@
# Additional arguments are dependencies

MACRO(CYTHON_ADD_MODULE_PYX name)
SET(DEPENDS ${name}.pyx)
SET(DEPENDS ${name}.pyx)

IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.pxd)
SET(DEPENDS ${DEPENDS} ${name}.pxd)
ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.pxd)
IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.pxd)
SET(DEPENDS ${DEPENDS} ${name}.pxd)
ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.pxd)

# Allow the user to specify dependencies as optional arguments
SET(DEPENDS ${DEPENDS} ${ARGN})
# Allow the user to specify dependencies as optional arguments
SET(DEPENDS ${DEPENDS} ${ARGN})

ADD_CUSTOM_COMMAND(
OUTPUT ${name}.cpp
COMMAND ${CYTHON_EXECUTABLE}
ARGS ${CYTHON_FLAGS} -I ${PROJECT_BINARY_DIR} -o ${name}.cpp
--cplus ${CMAKE_CURRENT_SOURCE_DIR}/${name}.pyx
DEPENDS ${DEPENDS}
COMMENT "Cythonizing ${name}.pyx")
ADD_CUSTOM_COMMAND(
OUTPUT ${name}.cpp
COMMAND ${CYTHON_EXECUTABLE}
ARGS ${CYTHON_FLAGS} -I ${PROJECT_BINARY_DIR}
-I ${CMAKE_CURRENT_SOURCE_DIR} -o ${name}.cpp
--cplus ${CMAKE_CURRENT_SOURCE_DIR}/${name}.pyx
DEPENDS ${DEPENDS}
COMMENT "Cythonizing ${name}.pyx")

list(APPEND ADDITIONAL_MAKE_CLEAN_FILES "${name}.cpp")
list(APPEND ADDITIONAL_MAKE_CLEAN_FILES "${name}.cpp")
ENDMACRO(CYTHON_ADD_MODULE_PYX)
2 changes: 1 addition & 1 deletion examples/python/ground/ground.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from opencog.atomspace import AtomSpace, TruthValue
from opencog.atomspace import types
from opencog.type_constructors import *
from opencog.bindlink import execute_atom
from opencog.exec import execute_atom

import mymodule as mm

Expand Down
2 changes: 1 addition & 1 deletion examples/python/stop_go.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"""

from opencog.atomspace import AtomSpace, TruthValue, types, get_type_name
from opencog.bindlink import satisfaction_link
from opencog.exec import satisfaction_link
from opencog.type_constructors import *
from opencog.logger import Logger, log

Expand Down
3 changes: 3 additions & 0 deletions opencog/cython/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ INCLUDE_DIRECTORIES(
FILE(MAKE_DIRECTORY opencog)
FILE(COPY opencog/__init__.py DESTINATION opencog)

# Legacy bindlink
FILE(COPY opencog/bindlink.py DESTINATION opencog)

ADD_LIBRARY(PythonEval
PythonEval.cc
)
Expand Down
29 changes: 18 additions & 11 deletions opencog/cython/opencog/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_BINARY_DIR}
)

SET(CYTHON_FLAGS "-2" "-f")
SET(CYTHON_FLAGS "-3" "-f")

# Use this as a guide:
# https://github.com/OpenKinect/libfreenect/blob/master/wrappers/python/CMakeLists.txt
Expand Down Expand Up @@ -85,6 +85,7 @@ SET_TARGET_PROPERTIES(atomspace_cython PROPERTIES
INSTALL (FILES
__init__.py
atomspace.pxd
value_types.pxd
DESTINATION "include/opencog/cython/opencog"
)

Expand Down Expand Up @@ -132,36 +133,42 @@ SET_TARGET_PROPERTIES(utilities_cython PROPERTIES
PREFIX ""
OUTPUT_NAME utilities)

############################## bindlink #####################
############################## bindlink (exec module) #####################

CYTHON_ADD_MODULE_PYX(bindlink
CYTHON_ADD_MODULE_PYX(exec
"atomspace.pxd"
opencog_atom_types
)

ADD_LIBRARY(bindlink_cython
BindlinkStub.cc
bindlink.cpp
ADD_LIBRARY(exec_cython
"BindlinkStub.cc"
"exec.cpp"
)

TARGET_LINK_LIBRARIES(bindlink_cython
TARGET_LINK_LIBRARIES(exec_cython
atomspace_cython
atomspace
${PYTHON_LIBRARIES}
)

SET_TARGET_PROPERTIES(bindlink_cython PROPERTIES
SET_TARGET_PROPERTIES(exec_cython PROPERTIES
PREFIX ""
OUTPUT_NAME bindlink)
OUTPUT_NAME exec)

INSTALL (TARGETS
### install the modules ###
INSTALL(TARGETS
atomspace_cython
bindlink_cython
exec_cython
logger_cython
type_constructors
utilities_cython
DESTINATION "${PYTHON_DEST}")

# install the legacy bindlink module
INSTALL(FILES
"bindlink.py"
DESTINATION "${PYTHON_DEST}")

IF (HAVE_GUILE)
############################## scheme wrapper #####################

Expand Down
132 changes: 66 additions & 66 deletions opencog/cython/opencog/atom.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,64 @@ from cpython cimport PyLong_FromLongLong
from cpython.object cimport Py_LT, Py_EQ, Py_GT, Py_LE, Py_NE, Py_GE
from libcpp.set cimport set as cpp_set

# from atomspace cimport Atom

# Atom wrapper object
cdef class Atom(Value):

@staticmethod
cdef Atom createAtom(const cHandle& handle):
return Atom(PtrHolder.create(<shared_ptr[void]&>handle))

def __init__(self, ptr_holder):
super(Atom, self).__init__(ptr_holder)
def __cinit__(self, PtrHolder ptr_holder, *args, **kwargs):
self.handle = <cHandle*>&((<PtrHolder>ptr_holder).shared_ptr)
# cache the results after first retrieval of
# immutable properties
self._atom_type = None
self._name = None
self._outgoing = None

@staticmethod
cdef Atom createAtom(const cHandle& handle):
return Atom(PtrHolder.create(<shared_ptr[void]&>handle))

cdef cHandle get_c_handle(Atom self):
"""Return C++ shared_ptr from PtrHolder instance"""
return <cHandle&>(self.ptr_holder.shared_ptr)

property atomspace:
def __get__(self):
cdef cAtomSpace* a = self.get_c_handle().get().getAtomSpace()
return AtomSpace_factory(a)

property name:
def __get__(self):
cdef cAtom* atom_ptr
if self._name is None:
atom_ptr = self.handle.atom_ptr()
if atom_ptr == NULL: # avoid null-pointer deref
return None
if atom_ptr.is_node():
self._name = atom_ptr.get_name().decode('UTF-8')
else:
self._name = ""
return self._name

property tv:
def __get__(self):
cdef cAtom* atom_ptr = self.handle.atom_ptr()
cdef tv_ptr tvp
@property
def atomspace(self):
cdef cAtomSpace* a = self.get_c_handle().get().getAtomSpace()
return AtomSpace_factory(a)

@property
def name(self):
cdef cAtom* atom_ptr
if self._name is None:
atom_ptr = self.handle.atom_ptr()
if atom_ptr == NULL: # avoid null-pointer deref
return None
tvp = atom_ptr.getTruthValue()
if (not tvp.get()):
raise AttributeError('cAtom returned NULL TruthValue pointer')
return createTruthValue(tvp.get().get_mean(), tvp.get().get_confidence())

def __set__(self, truth_value):
try:
assert isinstance(truth_value, TruthValue)
except AssertionError:
raise TypeError("atom.tv property needs a TruthValue object")
cdef cAtom* atom_ptr = self.handle.atom_ptr()
if atom_ptr == NULL: # avoid null-pointer deref
return
atom_ptr.setTruthValue(deref((<TruthValue>truth_value)._tvptr()))
if atom_ptr.is_node():
self._name = atom_ptr.get_name().decode('UTF-8')
else:
self._name = ""
return self._name

@property
def tv(self):
cdef cAtom* atom_ptr = self.handle.atom_ptr()
cdef tv_ptr tvp
if atom_ptr == NULL: # avoid null-pointer deref
return None
tvp = atom_ptr.getTruthValue()
if (not tvp.get()):
raise AttributeError('cAtom returned NULL TruthValue pointer')
return createTruthValue(tvp.get().get_mean(), tvp.get().get_confidence())

@tv.setter
def tv(self, truth_value):
try:
assert isinstance(truth_value, TruthValue)
except AssertionError:
raise TypeError("atom.tv property needs a TruthValue object")
cdef cAtom* atom_ptr = self.handle.atom_ptr()
if atom_ptr == NULL: # avoid null-pointer deref
return
atom_ptr.setTruthValue(deref((<TruthValue>truth_value)._tvptr()))

def set_value(self, key, value):
if not isinstance(key, Atom):
Expand Down Expand Up @@ -90,30 +90,30 @@ cdef class Atom(Value):
cdef vector[cHandle] handle_vector = atom_ptr.getOutgoingSet()
return convert_handle_seq_to_python_list(handle_vector)

property out:
def __get__(self):
if self._outgoing is None:
atom_ptr = self.handle.atom_ptr()
if atom_ptr == NULL: # avoid null-pointer deref
return None
if atom_ptr.is_link():
self._outgoing = self.get_out()
else:
self._outgoing = []
return self._outgoing

property arity:
def __get__(self):
return len(self.out)

property incoming:
def __get__(self):
cdef vector[cHandle] handle_vector
cdef cAtom* atom_ptr = self.handle.atom_ptr()
@property
def out(self):
if self._outgoing is None:
atom_ptr = self.handle.atom_ptr()
if atom_ptr == NULL: # avoid null-pointer deref
return None
atom_ptr.getIncomingSet(back_inserter(handle_vector))
return convert_handle_seq_to_python_list(handle_vector)
if atom_ptr.is_link():
self._outgoing = self.get_out()
else:
self._outgoing = []
return self._outgoing

@property
def arity(self):
return len(self.out)

@property
def incoming(self):
cdef vector[cHandle] handle_vector
cdef cAtom* atom_ptr = self.handle.atom_ptr()
if atom_ptr == NULL: # avoid null-pointer deref
return None
atom_ptr.getIncomingSet(back_inserter(handle_vector))
return convert_handle_seq_to_python_list(handle_vector)

def incoming_by_type(self, Type type):
cdef vector[cHandle] handle_vector
Expand Down
16 changes: 13 additions & 3 deletions opencog/cython/opencog/atomspace.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ from libcpp.set cimport set as cpp_set
from libcpp.string cimport string
from cython.operator cimport dereference as deref


cdef extern from "Python.h":
# Tacky hack to pass atomspace pointer to AtomSpace ctor.
cdef void* PyLong_AsVoidPtr(object)
Expand Down Expand Up @@ -55,12 +56,14 @@ cdef extern from "opencog/atoms/value/Value.h" namespace "opencog":

cdef class PtrHolder:
cdef shared_ptr[void] shared_ptr

@staticmethod
cdef PtrHolder create(shared_ptr[void]& ptr)

cdef class Value:
cdef PtrHolder ptr_holder
cdef cValuePtr get_c_value_ptr(self)

@staticmethod
cdef Value create(cValuePtr& ptr)

Expand Down Expand Up @@ -96,9 +99,9 @@ cdef extern from "opencog/atoms/truthvalue/SimpleTruthValue.h" namespace "openco
bint operator!=(cTruthValue h)

cdef class TruthValue(Value):
cdef _mean(self)
cdef _confidence(self)
cdef _count(self)
cdef strength_t _mean(self)
cdef confidence_t _confidence(self)
cdef count_t _count(self)
cdef cTruthValue* _ptr(self)
cdef tv_ptr* _tvptr(self)

Expand Down Expand Up @@ -207,6 +210,7 @@ cdef extern from "opencog/atomspace/AtomSpace.h" namespace "opencog":

cdef AtomSpace_factory(cAtomSpace *to_wrap)


cdef class AtomSpace:
cdef cAtomSpace *atomspace
cdef bint owns_atomspace
Expand All @@ -215,22 +219,28 @@ cdef class AtomSpace:

cdef create_python_value_from_c_value(const cValuePtr& value)


# FloatValue
cdef extern from "opencog/atoms/value/FloatValue.h" namespace "opencog":
cdef cppclass cFloatValue "opencog::FloatValue":
cFloatValue(double value)
cFloatValue(const vector[double]& values)
const vector[double]& value() const


# StringValue
cdef extern from "opencog/atoms/value/StringValue.h" namespace "opencog":
cdef cppclass cStringValue "opencog::StringValue":
cStringValue(const string& value)
cStringValue(const vector[string]& values)
const vector[string]& value() const


# LinkValue
cdef extern from "opencog/atoms/value/LinkValue.h" namespace "opencog":
cdef cppclass cLinkValue "opencog::LinkValue":
cLinkValue(const vector[cValuePtr]& values)
const vector[cValuePtr]& value() const


include "value_types.pxd"
8 changes: 4 additions & 4 deletions opencog/cython/opencog/atomspace.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
# Note that the ordering of include statements may influence whether
# things work or not

include "nameserver.pyx"
include "truth_value.pyx"
include "atomspace_details.pyx"
include "atom.pyx"
include "value.pyx"
include "atomspace_details.pyx"
include "truth_value.pyx"
include "float_value.pyx"
include "string_value.pyx"
include "atom.pyx"
include "nameserver.pyx"
include "link_value.pyx"
3 changes: 2 additions & 1 deletion opencog/cython/opencog/atomspace_details.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ from libcpp.set cimport set as cpp_set
from libcpp.vector cimport vector
from cython.operator cimport dereference as deref, preincrement as inc

from atomspace cimport *
# from atomspace cimport *


# @todo use the guide here to separate out into a hierarchy
# http://wiki.cython.org/PackageHierarchy
Expand Down
Loading

0 comments on commit 77c997b

Please sign in to comment.