OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-cogserver commits / 42cffd3

Remove the cython wrapper; use pure python
42cffd383eef20df2f678a10c1551fb36de9c666
by Linas Vepstas <linasvepstas@gmail.com> · 2025-12-14T23:09:35.000Z

Changed files (11) +128 -245

opencog/CMakeLists.txt +0 -3
……@@ -7,9 +7,6 @@ DECLARE_GUILE_CONFIG_TARGET(SCM_CONFIG "opencog cs-config" "OPENCOG_TEST")
77
88ADD_SUBDIRECTORY (network)
99ADD_SUBDIRECTORY (cogserver)
10IF(HAVE_CYTHON)
11 ADD_SUBDIRECTORY (cython)
12ENDIF(HAVE_CYTHON)
1310
1411WRITE_GUILE_CONFIG(${GUILE_BIN_DIR}/opencog/cs-config.scm SCM_CONFIG TRUE)
1512
opencog/cogserver/CMakeLists.txt +1 -0
……@@ -5,6 +5,7 @@ ADD_SUBDIRECTORY (atoms)
55ADD_SUBDIRECTORY (scm)
66ADD_SUBDIRECTORY (modules)
77ADD_SUBDIRECTORY (shell)
8ADD_SUBDIRECTORY (python)
89
910IF (HAVE_MCP)
1011 ADD_SUBDIRECTORY (mcp-docs)
opencog/cogserver/python/CMakeLists.txt +8 -0
……@@ -0,0 +1,8 @@
1#
2# Install pure Python cogserver module
3#
4INSTALL(FILES
5 __init__.py
6 cogserver.py
7 DESTINATION "${PYTHON_DEST}"
8)
opencog/cogserver/python/__init__.py +18 -0
……@@ -0,0 +1,18 @@
1from pkgutil import extend_path
2__path__ = extend_path(__path__, __name__)
3
4# Import and expose cogserver functions
5try:
6 from .cogserver import (
7 start_cogserver,
8 stop_cogserver,
9 is_cogserver_running,
10 )
11 __all__ = [
12 'start_cogserver',
13 'stop_cogserver',
14 'is_cogserver_running',
15 ]
16except ImportError:
17 # Module not fully installed yet
18 pass
opencog/cogserver/python/cogserver.py +101 -0
……@@ -0,0 +1,101 @@
1#
2# cogserver.py
3#
4# Pure Python wrapper for starting/stopping the CogServer.
5# This module provides a convenient Python API for controlling
6# the CogServer network server.
7#
8
9from opencog.type_constructors import get_thread_atomspace, FloatValue, VoidValue, Predicate
10from opencog.atomspace import types
11
12# Global server state
13_server_handle = None
14_server_running = False
15
16def start_cogserver(console_port=17001, web_port=18080, mcp_port=18888,
17 enable_console=True, enable_web=True, enable_mcp=True,
18 name="cogserver"):
19 """Start the CogServer with the specified configuration.
20
21 Args:
22 console_port (int, optional): Port for telnet console server. Default: 17001
23 web_port (int, optional): Port for web server. Default: 18080
24 mcp_port (int, optional): Port for MCP server. Default: 18888
25 enable_console (bool, optional): Enable telnet console server. Default: True
26 enable_web (bool, optional): Enable web server. Default: True
27 enable_mcp (bool, optional): Enable MCP server. Default: True
28 name (str, optional): Name for the CogServerNode. Default: "cogserver"
29
30 Returns:
31 bool: True if server started successfully, False otherwise.
32
33 Raises:
34 RuntimeError: If server is already running.
35 ValueError: If invalid ports are specified.
36 """
37 global _server_handle, _server_running
38
39 if _server_running:
40 raise RuntimeError("CogServer is already running")
41
42 # Validate ports
43 for port, pname in [(console_port, "console"), (web_port, "web"), (mcp_port, "mcp")]:
44 if not (1 <= port <= 65535):
45 raise ValueError(f"Invalid {pname} port: {port}. Must be between 1 and 65535")
46
47 # Get the thread atomspace and add the CogServerNode to it
48 atomspace = get_thread_atomspace()
49 _server_handle = atomspace.add_node(types.CogServerNode, name)
50
51 # Set non-default port values (0 disables a server)
52 effective_console = console_port if enable_console else 0
53 effective_web = web_port if enable_web else 0
54 effective_mcp = mcp_port if enable_mcp else 0
55
56 if effective_console != 17001:
57 key = Predicate("*-telnet-port-*")
58 atomspace.set_value(_server_handle, key, FloatValue(float(effective_console)))
59 if effective_web != 18080:
60 key = Predicate("*-web-port-*")
61 atomspace.set_value(_server_handle, key, FloatValue(float(effective_web)))
62 if effective_mcp != 18888:
63 key = Predicate("*-mcp-port-*")
64 atomspace.set_value(_server_handle, key, FloatValue(float(effective_mcp)))
65
66 # Start all servers (this also starts the server thread)
67 atomspace.set_value(_server_handle, Predicate("*-start-*"), VoidValue())
68
69 # Mark as initialized
70 _server_running = True
71
72 return True
73
74def stop_cogserver():
75 """Stop the running CogServer.
76
77 Returns:
78 bool: True if server was stopped, False if server was not running.
79 """
80 global _server_handle, _server_running
81
82 if not _server_running or _server_handle is None:
83 return False
84
85 # Stop the server
86 atomspace = get_thread_atomspace()
87 atomspace.set_value(_server_handle, Predicate("*-stop-*"), VoidValue())
88
89 _server_handle = None
90 _server_running = False
91
92 return True
93
94def is_cogserver_running():
95 """Check if the CogServer is currently running.
96
97 Returns:
98 bool: True if server is running, False otherwise.
99 """
100 global _server_running
101 return _server_running
opencog/cython/CMakeLists.txt +0 -6
……@@ -1,6 +0,0 @@
1#
2ADD_SUBDIRECTORY (opencog)
3
4# module init
5file(MAKE_DIRECTORY opencog)
6file(COPY opencog/__init__.py DESTINATION opencog)
opencog/cython/README.md +0 -45
……@@ -1,45 +0,0 @@
1CogServerNode Python Interface
2------------------------------
3
4The Python interface provides a very thin convenience wrapper around
5the CogServerNode. Users are encouraged to use the CogServerNode
6directly, instead of using this wrapper.
7
8```python
9from opencog.atomspace import AtomSpace
10from opencog.cogserver import start_cogserver, stop_cogserver
11
12# Option 1: Start with default AtomSpace
13start_cogserver()
14
15# Option 2: Start with custom AtomSpace
16my_atomspace = AtomSpace()
17start_cogserver(atomspace=my_atomspace)
18
19# Option 3: Start with custom ports
20start_cogserver(
21 console_port=17001, # Telnet console port
22 web_port=18080, # Web interface port
23 mcp_port=18888, # MCP server port
24 enable_console=True, # Enable telnet console
25 enable_web=False, # Disable web interface
26 enable_mcp=False # Disable MCP server
27)
28
29# Stop the server when done
30stop_cogserver()
31```
32
33## Available Functions ##
34
35The `opencog.cogserver` module provides:
36
37* `start_cogserver(atomspace=None, console_port=17001, web_port=18080, mcp_port=18888, enable_console=True, enable_web=False, enable_mcp=False)` - Start the CogServer
38* `stop_cogserver()` - Stop the running CogServer
39* `is_cogserver_running()` - Check if server is running
40
41## Tutorial ##
42
43The OpenCog wiki contains the Python tutorial:
44
45http://wiki.opencog.org/w/Python
opencog/cython/opencog/CMakeLists.txt +0 -53
……@@ -1,53 +0,0 @@
1
2# Need to use -fno-strict-aliasing when compiling cython code, in order
3# to avoid nasty compiler warnings about aliasing. Cython explicitly
4# performs aliasing, in order to emulate python object inheritance.
5# See, for example,
6# https://groups.google.com/forum/#!topic/cython-users/JV1-KvIUeIg
7#
8SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
9
10INCLUDE_DIRECTORIES(
11 ${ATOMSPACE_INCLUDE_DIR}
12 ${Python3_INCLUDE_DIRS}
13 ${CMAKE_CURRENT_SOURCE_DIR}
14 ${CMAKE_CURRENT_BINARY_DIR}
15)
16
17SET(CYTHON_FLAGS "-3" "-f" "-I" "${ATOMSPACE_INCLUDE_DIR}/opencog/cython")
18
19# Use this as a guide:
20# https://github.com/OpenKinect/libfreenect/blob/master/wrappers/python/CMakeLists.txt
21
22############################ cogserver #########################
23CYTHON_ADD_MODULE_PYX(cogserver
24 "${ATOMSPACE_INCLUDE_DIR}/opencog/cython/opencog/atomspace.pxd"
25)
26
27list(APPEND ADDITIONAL_MAKE_CLEAN_FILES "cogserver.cpp")
28
29# opencog.cogserver Python bindings
30ADD_LIBRARY(cogserver_cython SHARED
31 cogserver.cpp
32)
33
34TARGET_LINK_LIBRARIES(cogserver_cython
35 server
36 servernode
37 ${ATOMSPACE_LIBRARIES}
38 ${COGUTIL_LIBRARY}
39 ${Python3_LIBRARIES}
40)
41
42SET_TARGET_PROPERTIES(cogserver_cython PROPERTIES
43 PREFIX ""
44 OUTPUT_NAME cogserver)
45
46INSTALL (TARGETS cogserver_cython
47 DESTINATION "${PYTHON_DEST}")
48
49INSTALL (FILES __init__.py
50 DESTINATION "${PYTHON_DEST}")
51
52INSTALL (FILES cogserver.pxd
53 DESTINATION "${CMAKE_INSTALL_PREFIX}/include/opencog/cython/opencog")
opencog/cython/opencog/__init__.py +0 -20
……@@ -1,20 +0,0 @@
1from pkgutil import extend_path
2__path__ = extend_path(__path__, __name__)
3
4# Import and expose cogserver functions
5try:
6 from .cogserver import (
7 start_cogserver,
8 stop_cogserver,
9 is_cogserver_running,
10 get_server_atomspace
11 )
12 __all__ = [
13 'start_cogserver',
14 'stop_cogserver',
15 'is_cogserver_running',
16 'get_server_atomspace'
17 ]
18except ImportError:
19 # Module not built yet
20 pass
opencog/cython/opencog/cogserver.pxd +0 -11
……@@ -1,11 +0,0 @@
1# CogServer extern declarations
2from libcpp.string cimport string
3from libcpp.memory cimport shared_ptr
4from opencog.atomspace cimport cAtomSpacePtr, cHandle, cAtom
5
6cdef extern from "opencog/cogserver/atoms/CogServerNode.h" namespace "opencog":
7 cdef cppclass cCogServerNode "opencog::CogServerNode":
8 cAtomSpacePtr getAtomSpace()
9
10 ctypedef shared_ptr[cCogServerNode] cCogServerNodePtr "opencog::CogServerNodePtr"
11 cCogServerNodePtr CogServerNodeCast(const cHandle&)
opencog/cython/opencog/cogserver.pyx +0 -107
……@@ -1,107 +0,0 @@
1# distutils: language = c++
2# cython: language_level=3
3
4from opencog.cogserver cimport cCogServerNode, cCogServerNodePtr, CogServerNodeCast
5from opencog.atomspace cimport cHandle, Atom, handle_cast
6from opencog.type_constructors import get_thread_atomspace, FloatValue, VoidValue, Predicate
7from opencog.atomspace import types
8from cython.operator cimport dereference as deref
9from libcpp.string cimport string
10
11# Global server state
12cdef cCogServerNodePtr _server_ptr
13_server_handle = None # Keep Python reference to prevent GC
14_server_running = False
15
16def start_cogserver(console_port=17001, web_port=18080, mcp_port=18888,
17 enable_console=True, enable_web=True, enable_mcp=True,
18 name="cogserver"):
19 """Start the CogServer with the specified configuration.
20
21 Args:
22 console_port (int, optional): Port for telnet console server. Default: 17001
23 web_port (int, optional): Port for web server. Default: 18080
24 mcp_port (int, optional): Port for MCP server. Default: 18888
25 enable_console (bool, optional): Enable telnet console server. Default: True
26 enable_web (bool, optional): Enable web server. Default: True
27 enable_mcp (bool, optional): Enable MCP server. Default: True
28 name (str, optional): Name for the CogServerNode. Default: "cogserver"
29
30 Returns:
31 bool: True if server started successfully, False otherwise.
32
33 Raises:
34 RuntimeError: If server is already running.
35 ValueError: If invalid ports are specified.
36 """
37 global _server_ptr, _server_handle, _server_running
38
39 if _server_running:
40 raise RuntimeError("CogServer is already running")
41
42 # Validate ports
43 for port, pname in [(console_port, "console"), (web_port, "web"), (mcp_port, "mcp")]:
44 if not (1 <= port <= 65535):
45 raise ValueError(f"Invalid {pname} port: {port}. Must be between 1 and 65535")
46
47 # Get the thread atomspace and add the CogServerNode to it
48 atomspace = get_thread_atomspace()
49 _server_handle = atomspace.add_node(types.CogServerNode, name)
50
51 # Get the C++ CogServerNode pointer from the Python Atom
52 cdef Atom atom = <Atom>_server_handle
53 cdef cHandle chandle = handle_cast(atom.shared_ptr)
54 _server_ptr = CogServerNodeCast(chandle)
55
56 # Set non-default port values (0 disables a server)
57 effective_console = console_port if enable_console else 0
58 effective_web = web_port if enable_web else 0
59 effective_mcp = mcp_port if enable_mcp else 0
60
61 if effective_console != 17001:
62 key = Predicate("*-telnet-port-*")
63 atomspace.set_value(_server_handle, key, FloatValue(float(effective_console)))
64 if effective_web != 18080:
65 key = Predicate("*-web-port-*")
66 atomspace.set_value(_server_handle, key, FloatValue(float(effective_web)))
67 if effective_mcp != 18888:
68 key = Predicate("*-mcp-port-*")
69 atomspace.set_value(_server_handle, key, FloatValue(float(effective_mcp)))
70
71 # Start all servers (this also starts the server thread)
72 atomspace.set_value(_server_handle, Predicate("*-start-*"), VoidValue())
73
74 # Mark as initialized
75 _server_running = True
76
77 return True
78
79def stop_cogserver():
80 """Stop the running CogServer.
81
82 Returns:
83 bool: True if server was stopped, False if server was not running.
84 """
85 global _server_ptr, _server_handle, _server_running
86
87 if not _server_running or not _server_ptr:
88 return False
89
90 # Stop the server
91 atomspace = get_thread_atomspace()
92 atomspace.set_value(_server_handle, Predicate("*-stop-*"), VoidValue())
93
94 _server_ptr.reset()
95 _server_handle = None
96 _server_running = False
97
98 return True
99
100def is_cogserver_running():
101 """Check if the CogServer is currently running.
102
103 Returns:
104 bool: True if server is running, False otherwise.
105 """
106 global _server_running
107 return _server_running