Skip to content
Snippets Groups Projects
Commit 0cddffd9 authored by dmitriy.gerasimov's avatar dmitriy.gerasimov
Browse files

Merge branch 'features-2466' into 'master'

Features 2466

See merge request !1
parents e8d7f4e8 77a5f2a4
No related branches found
No related tags found
1 merge request!1Features 2466
[submodule "libdap"]
path = libdap
url = https://github.com/cellframe/libdap.git
[submodule "libdap-crypto"]
path = libdap-crypto
url = https://github.com/cellframe/libdap-crypto.git
url = https://gitlab.demlabs.net/cellframe/libdap.git
......@@ -4,21 +4,26 @@ cmake_minimum_required(VERSION 2.8)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_COLOR_MAKEFILE ON)
set(CMAKE_C_STANDARD 11)
set(SUBMODULES_NO_BUILD ON)
add_subdirectory(libdap)
add_subdirectory(libdap-crypto)
add_definitions("-fpic")
if(NOT (${SUBMODULES_NO_BUILD} MATCHES ON))
if (NOT (TARGET dap_core))
add_subdirectory(libdap)
target_compile_options(
dap_core PRIVATE
"-fpic"
)
endif()
endif()
file(GLOB CORE_SRCS src/*.c)
file(GLOB CORE_HEADERS src/*.h)
set(Python_ADDITIONAL_VERSIONS 3.7)
find_package (PythonLibs REQUIRED)
#find_package(PkgConfig)
#pkg_check_modules(PC_JSON-C REQUIRED json-c)
include_directories(${PYTHON_INCLUDE_DIR})
add_library(${PROJECT_NAME} SHARED ${CORE_SRCS} ${CORE_UNIX_SRCS})
add_library(${PROJECT_NAME} STATIC ${CORE_SRCS} ${CORE_UNIX_SRCS})
target_link_libraries(${PROJECT_NAME} ${PYTHON_LIBRARIES})
......@@ -27,18 +32,13 @@ target_compile_options(
"-fpic"
)
target_link_libraries(${PROJECT_NAME} dap_core dap_crypto)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/libdapConnector.py
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
target_link_libraries(${PROJECT_NAME} dap_core)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/main_test.py
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
target_include_directories(${PROJECT_NAME} PUBLIC src/ )
if(BUILD_DAP_TESTS)
if(BUILD_DAP_PYTHON_TESTS)
add_subdirectory(test)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/main_test.py
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
enable_testing()
#add_subdirectory(test)
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/test/)
endif()
......@@ -2,3 +2,14 @@
Python binding for libdap
[![Build Status](https://travis-ci.com/cellframe/libdap-python.svg?branch=master)](https://travis-ci.com/cellframe/libdap-python)
## Build and Run tests:
```
git submodule update --init
mkdir build
cd build
cmake -DBUILD_DAP_PYTHON_TESTS=ON ../
make
cd test
python3.7 main_test.py
```
Subproject commit d37b2aa26d2a7cc068529db343a87fd728904d33
Subproject commit 69f41c4decd2b84752fdb8a213d7fb0b860b80f5
Subproject commit ff63d762657f9687173db825705b8bf4b958abee
#include "libdap-python.h"
static PyObject *dap_init(PyObject *self, PyObject *args){
//const char *data;
const char *system_configs_dir;
const char *dap_app_name;
char *dap_app_name_logs;
if (!PyArg_ParseTuple(args, "s|s", &system_configs_dir, &dap_app_name))
return NULL;
int len_dap_app_name = strlen(dap_app_name);
dap_app_name_logs = calloc((len_dap_app_name+9), sizeof(char));
memcpy(dap_app_name_logs, dap_app_name, len_dap_app_name);
const char* log = "_logs.txt";
memcpy(dap_app_name_logs+len_dap_app_name, log,9);
dap_config_init(system_configs_dir);
if ((g_config = dap_config_open(dap_app_name) ) == NULL){
log_it(L_CRITICAL, "Can't init general configurations");
return PyLong_FromLong(-1);
}
if (dap_common_init(dap_app_name_logs)!=0){
log_it(L_CRITICAL, "Can't init common functions module");
return PyLong_FromLong(-2);
}
dap_log_level_set( dap_config_get_item_bool_default(g_config,"general","debug_mode", false)? L_DEBUG: L_NOTICE );
return PyLong_FromLong(0);
}
static PyObject *dap_deinit(){
log_it(L_DEBUG, "Running function dap_deinit");
dap_config_close(g_config);
log_it(L_DEBUG, "Config file closed.");
dap_config_deinit();
log_it(L_DEBUG, "Function dap_config_deinit done.");
log_it(L_DEBUG, "Function dap_deinit done.");
return PyLong_FromLong(0);
}
static PyObject *dap_set_log_level(PyObject *self, PyObject *args){
PyObject *dap_set_log_level(PyObject *self, PyObject *args){
short int new_log_level;
if (!PyArg_ParseTuple(args, "h", &new_log_level))
return NULL;
if (new_log_level < 0 || new_log_level > 5 ) {
if (new_log_level < 0 || new_log_level > 10 ) {
return PyLong_FromLong(-1);
} else {
dap_log_level_set(new_log_level);
......@@ -47,12 +12,12 @@ static PyObject *dap_set_log_level(PyObject *self, PyObject *args){
}
}
static PyObject* dap_log_it(PyObject* self, PyObject* args){
PyObject* dap_log_it(PyObject* self, PyObject* args){
short int log_level;
const char* string_output;
if (!PyArg_ParseTuple(args, "h|s", &log_level, &string_output))
return NULL;
if (log_level < 0 || log_level > 5 ) {
if (log_level < 0 || log_level > 10 ) {
return PyLong_FromLong(-1);
} else {
log_it(log_level, string_output);
......@@ -60,7 +25,80 @@ static PyObject* dap_log_it(PyObject* self, PyObject* args){
}
}
static PyObject* py_m_dap_config_get_item(PyObject *self, PyObject *args){
PyObject* dap_log_it_debug(PyObject* self, PyObject* args){
const char* string_output;
if (!PyArg_ParseTuple(args, "s", &string_output)){
return NULL;
}
log_it(L_DEBUG, string_output);
return PyLong_FromLong(0);
}
PyObject* dap_log_it_info(PyObject* self, PyObject* args){
const char* string_output;
if (!PyArg_ParseTuple(args, "s", &string_output)){
return NULL;
}
log_it(L_INFO, string_output);
return PyLong_FromLong(0);
}
PyObject* dap_log_it_notice(PyObject* self, PyObject* args){
const char* string_output;
if (!PyArg_ParseTuple(args, "s", &string_output)){
return NULL;
}
log_it(L_NOTICE, string_output);
return PyLong_FromLong(0);
}
PyObject* dap_log_it_message(PyObject* self, PyObject* args){
const char* string_output;
if (!PyArg_ParseTuple(args, "s", &string_output)){
return NULL;
}
log_it(L_MSG, string_output);
return PyLong_FromLong(0);
}
PyObject* dap_log_it_dap(PyObject* self, PyObject* args){
const char* string_output;
if (!PyArg_ParseTuple(args, "s", &string_output)){
return NULL;
}
log_it(L_DAP, string_output);
return PyLong_FromLong(0);
}
PyObject* dap_log_it_warning(PyObject* self, PyObject* args){
const char* string_output;
if (!PyArg_ParseTuple(args, "s", &string_output)){
return NULL;
}
log_it(L_WARNING, string_output);
return PyLong_FromLong(0);
}
PyObject* dap_log_it_att(PyObject* self, PyObject* args){
const char* string_output;
if (!PyArg_ParseTuple(args, "s", &string_output)){
return NULL;
}
log_it(L_ATT, string_output);
return PyLong_FromLong(0);
}
PyObject* dap_log_it_error(PyObject* self, PyObject* args){
const char* string_output;
if (!PyArg_ParseTuple(args, "s", &string_output)){
return NULL;
}
log_it(L_ERROR, string_output);
return PyLong_FromLong(0);
}
PyObject* dap_log_it_critical(PyObject* self, PyObject* args){
const char* string_output;
if (!PyArg_ParseTuple(args, "s", &string_output)){
return NULL;
}
log_it(L_CRITICAL, string_output);
return PyLong_FromLong(0);
}
PyObject* py_m_dap_config_get_item(PyObject *self, PyObject *args){
const char *section_path;
const char *item_name;
if (!PyArg_ParseTuple(args, "s|s", &section_path, &item_name))
......@@ -73,7 +111,7 @@ static PyObject* py_m_dap_config_get_item(PyObject *self, PyObject *args){
return Py_BuildValue("s", res);
}
static PyObject* py_m_dap_config_get_item_default(PyObject *self, PyObject *args){
PyObject* py_m_dap_config_get_item_default(PyObject *self, PyObject *args){
const char *section_path;
const char *item_name;
const char *def;
......@@ -82,32 +120,3 @@ static PyObject* py_m_dap_config_get_item_default(PyObject *self, PyObject *args
const char *res = dap_config_get_item_str_default(g_config, section_path, item_name, def);
return Py_BuildValue("s", res);
}
PyMODINIT_FUNC PyInit_libdap_python_module(void){
return PyModule_Create(&dapmodule);
}
int main(int argc, char **argv) {
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
/* Add a built-in module, before Py_Initialize */
PyImport_AppendInittab("libdap_python_module", PyInit_libdap_python_module);
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(program);
/* Initialize the Python interpreter. Required. */
Py_Initialize();
/* Optionally import the module; alternatively,
import can be deferred until the embedded script
imports it. */
PyImport_ImportModule("libdap_python_module");
PyMem_RawFree(program);
return 0;
}
#pragma once
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "dap_config.h"
......@@ -9,39 +10,74 @@ extern "C" {
#define LOG_TAG "libdap-python"
static PyObject *dap_init(PyObject *self, PyObject *args);
typedef struct PyDap{
PyObject_HEAD
}PyDapObject;
static PyObject *dap_deinit();
PyObject *dap_set_log_level(PyObject *self, PyObject *args);
static PyObject *dap_set_log_level(PyObject *self, PyObject *args);
PyObject* dap_log_it(PyObject* self, PyObject* args);
static PyObject* dap_log_it(PyObject* self, PyObject* args);
PyObject* dap_log_it_debug(PyObject* self, PyObject* args);
PyObject* dap_log_it_info(PyObject* self, PyObject* args);
PyObject* dap_log_it_notice(PyObject* self, PyObject* args);
PyObject* dap_log_it_message(PyObject* self, PyObject* args);
PyObject* dap_log_it_dap(PyObject* self, PyObject* args);
PyObject* dap_log_it_warning(PyObject* self, PyObject* args);
PyObject* dap_log_it_att(PyObject* self, PyObject* args);
PyObject* dap_log_it_error(PyObject* self, PyObject* args);
PyObject* dap_log_it_critical(PyObject* self, PyObject* args);
static PyObject* py_m_dap_config_get_item(PyObject *self, PyObject *args);
PyObject* py_m_dap_config_get_item(PyObject *self, PyObject *args);
static PyObject* py_m_dap_config_get_item_default(PyObject *self, PyObject *args);
PyObject* py_m_dap_config_get_item_default(PyObject *self, PyObject *args);
static PyMethodDef DapMethods[] = {
{"init", dap_init, METH_VARARGS, "Initialization of the DAP (Deus Applicaions Prototypes) library"},
{"deinit", dap_deinit, METH_NOARGS, "Deinitialization of the DAP (Deus Applicaions Prototypes) library"},
{"setLogLevel", dap_set_log_level, METH_VARARGS, "Setting the logging level"},
{"logIt", dap_log_it, METH_VARARGS, "The wrapper of the log_it function for the libdap library"},
{"configGetItem", py_m_dap_config_get_item, METH_VARARGS, ""},
{"configGetItemDefault", py_m_dap_config_get_item_default, METH_VARARGS, ""},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef dapmodule = {
PyModuleDef_HEAD_INIT,
"libdap_python_module", /* name of module */
NULL, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
DapMethods
static PyTypeObject DapObject_DapObjectType = {
PyVarObject_HEAD_INIT(NULL, 0)
"CellFrame.Dap", /* tp_name */
sizeof(PyDapObject), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
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 |
Py_TPFLAGS_BASETYPE, /* tp_flags */
"Dap objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
DapMethods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew, /* tp_new */
};
PyMODINIT_FUNC PyInit_libdap_python_module(void);
#ifdef __cplusplus
}
#endif
import json
from enum import Enum
import libdap_python_module
class DapIniException(Exception):
pass
class LogLevel(Enum):
L_CRITICAL=5
L_ERROR=4
L_WARNING=3
L_NOTICE=2
L_INFO=1
L_DEBUG=0
def init(data):
res = json.loads(data)
modules=res['modules']
config_dir=res['dap']['config_dir']
log_level=res['dap']['log_level']
application_name=res['dap']['application_name']
res_init = libdap_python_module.init(config_dir, application_name)
if res_init == -1 or res_init == -2:
raise DapIniException("Initialization erorr")
if log_level != LogLevel.L_NOTICE.name:
setLogLevel(LogLevel[log_level])
def deInit():
libdap_python_module.deinit()
def setLogLevel(logLevel):
res_setLogLevel = libdap_python_module.setLogLevel(logLevel.value)
if res_setLogLevel == -1:
raise DapIniException("Failed to set the logging level, perhaps you did not correctly specify the name of the level")
def logIt(logLevel, data):
res_log_it = libdap_python_module.logIt(logLevel.value, data)
if res_log_it == -1:
raise DapIniException("Could not execute log_it function. Perhaps you did not correctly specify the name of the logging level or did not leave the information that needs to be displayed")
def configGetItem(section_path, item_name):
res = libdap_python_module.configGetItem(section_path, item_name)
return res
def configGetItemDefault(section_path, item_name, default):
return libdap_python_module.configGetItemDefault(section_path, item_name, default)
project(TPO C)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_COLOR_MAKEFILE ON)
set(CMAKE_C_STANDARD 11)
set(Python_ADDITIONAL_VERSIONS 3.7)
find_package (PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIR} include/)
file(GLOB TPO_INCLUDES include/*.h)
file(GLOB TPO_SRCS src/*.c)
add_library(${PROJECT_NAME} SHARED ${TPO_INCLUDES} ${TPO_SRCS} )
target_link_libraries(${PROJECT_NAME} ${PYTHON_LIBRARIES})
target_link_libraries(${PROJECT_NAME} dap_python_module)
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "libdap-python.h"
#ifdef __cplusplus
extern "C" {
#endif
PyObject *TPO_init(PyObject *self, PyObject *args);
PyObject *TPO_deinit(PyObject *self, PyObject *args);
static PyMethodDef TPOPythonMethods[] = {
{"init", TPO_init, METH_VARARGS, "Initialization of the python-cellframe interface DAP (Deus Applicaions Prototypes)"},
{"deinit", TPO_deinit, METH_VARARGS, "Deinitialization of the python-cellframe interface DAP (Deus Applicaions Prototypes)"},
{"setLogLevel", (PyCFunction)dap_set_log_level, METH_VARARGS, "Setting the logging level"},
{"logIt", (PyCFunction)dap_log_it, METH_VARARGS, "The wrapper of the log_it function for the libdap library"},
{"logItDebug", (PyCFunction)dap_log_it_debug, METH_VARARGS, "The log_it wrapper for the libdap library displays information with the logging level DEBUG"},
{"logItInfo", (PyCFunction)dap_log_it_info, METH_VARARGS, "The log_it wrapper for the libdap library displays information with the logging level INFO"},
{"logItNotice", (PyCFunction)dap_log_it_notice, METH_VARARGS, "The log_it wrapper for the libdap library displays information with the logging level NOTICE"},
{"logItMessage", (PyCFunction)dap_log_it_message, METH_VARARGS, "The log_it wrapper for the libdap library displays information with the logging level MESSAGE"},
{"logItDap", (PyCFunction)dap_log_it_dap, METH_VARARGS, "The log_it wrapper for the libdap library displays information with the logging level DAP"},
{"logItWarning", (PyCFunction)dap_log_it_warning, METH_VARARGS, "The log_it wrapper for the libdap library displays information with the logging level WARNING"},
{"logItAtt", (PyCFunction)dap_log_it_att, METH_VARARGS, "The log_it wrapper for the libdap library displays information with the logging level ATT"},
{"logItError", (PyCFunction)dap_log_it_error, METH_VARARGS, "The log_it wrapper for the libdap library displays information with the logging level ERROR"},
{"logItCritical", (PyCFunction)dap_log_it_critical, METH_VARARGS, "The log_it wrapper for the libdap library displays information with the logging level CRITICAL"},
{"configGetItem", (PyCFunction)py_m_dap_config_get_item, METH_VARARGS, ""},
{"configGetItemDefault", (PyCFunction)py_m_dap_config_get_item_default, METH_VARARGS, ""},
//{"deinit", dap_server_core_deinit, METH_NOARGS, "Deinitialization of the DAP (Deus Applicaions Prototypes) server core library"},
//{"loop", dap_server_core_loop, METH_VARARGS, ""},
//{"listen", dap_server_core_listen, METH_VARARGS, ""},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef TPOModule = {
PyModuleDef_HEAD_INIT,
"libTPO", /* name of module */
NULL, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
TPOPythonMethods
};
PyMODINIT_FUNC PyInit_libTPO(void);
#ifdef __cplusplus
}
#endif
from libdapConnector import *
from libTPO import *
import os
import sys
......@@ -7,36 +7,28 @@ def create_config_file(app_name):
f.write("[server]\nlisten_address=0.0.0.0\n")
f.close()
logIt(LogLevel.L_INFO,"Start main test")
print("Start main test")
app_name = "TestAPP"
logIt(LogLevel.L_INFO, "Create config file")
print("Create config file")
create_config_file(app_name)
path = os.getcwd()
json_string = """{
"modules": "",
"dap": {
"config_dir": \""""+os.getcwd()+"""\",
"log_level": \""""+LogLevel.L_DEBUG.name+"""\",
"application_name": \""""+app_name+"""\"
}
}"""
init(json_string)
logIt(LogLevel.L_INFO, "Initialization of the DAP done")
setLogLevel(LogLevel.L_DEBUG)
logIt(LogLevel.L_INFO,"Level logging ""DEBUG"" done")
logIt(LogLevel.L_DEBUG, "Test. Outputting a string using the log_it function in the libdap library")
logIt(LogLevel.L_INFO,"Outputting a string using the log_it function done")
init(app_name, app_name, path, "DEBUG")
logIt(INFO, "Initialization of the DAP done")
setLogLevel(DEBUG)
logIt(INFO,"Level logging ""DEBUG"" done")
logIt(DEBUG, "Test. Outputting a string using the log_it function in the libdap library")
logIt(INFO,"Outputting a string using the log_it function done")
res1 = configGetItem("server", "listen_address")
logIt(LogLevel.L_INFO, "Output [server] 'listen_address' = "+res1+"\n")
logIt(INFO, "Output [server] 'listen_address' = "+res1+"\n")
res2 = configGetItemDefault("server1", "listen_address", "8.8.8.8")
logIt(LogLevel.L_INFO, "Output default value '8.8.8.8' [server1] 'listen_address' = "+res2+"\n")
logIt(LogLevel.L_INFO, "TEST. Get default config done")
deInit()
logIt(LogLevel.L_INFO, "Deinitialization done")
logIt(INFO, "Output default value '8.8.8.8' [server1] 'listen_address' = "+res2+"\n")
logIt(INFO, "TEST. Get default config done")
deinit()
logIt(INFO, "Deinitialization done")
os.remove(app_name+".cfg")
logIt(LogLevel.L_INFO, "Dellete config file")
logIt(LogLevel.L_INFO, "Main test done");
logIt(INFO, "Dellete config file")
logIt(INFO, "Main test done");
sys.exit(0)
#include "tpo.h"
PyObject *TPO_init(PyObject *self, PyObject *args){
const char *app_name, *file_name_log, *config_dir, *s_log_level;
if (!PyArg_ParseTuple(args, "s|s|s|s", &app_name, &file_name_log, &config_dir, &s_log_level)){
return NULL;
}
if (dap_common_init(app_name, file_name_log) != 0){
return NULL;
}
dap_config_init(config_dir);
if ((g_config = dap_config_open(app_name) ) == NULL){
return NULL;
}
if (strcmp(s_log_level, "DEBUG") == 0 ){
dap_log_level_set(L_DEBUG);
} else if (strcmp(s_log_level, "INFO") == 0) {
dap_log_level_set(L_INFO);
} else if (strcmp(s_log_level, "NOTICE") == 0) {
dap_log_level_set(L_NOTICE);
}else if (strcmp(s_log_level, "MESSAGE") == 0) {
dap_log_level_set(L_MSG);
}else if (strcmp(s_log_level, "DAP") == 0) {
dap_log_level_set(L_DAP);
}else if (strcmp(s_log_level, "WARNING") == 0) {
dap_log_level_set(L_WARNING);
}else if (strcmp(s_log_level, "ATT") == 0) {
dap_log_level_set(L_ATT);
}else if (strcmp(s_log_level, "ERROR") == 0) {
dap_log_level_set(L_ERROR);
} else if (strcmp(s_log_level, "CRITICAL") == 0) {
dap_log_level_set(L_CRITICAL);
} else {
dap_log_level_set(L_DEBUG);
}
return PyLong_FromLong(0);
}
PyObject *TPO_deinit(PyObject *self, PyObject *args){
dap_config_close(g_config);
dap_config_deinit();
return PyLong_FromLong(0);
}
PyMODINIT_FUNC PyInit_libTPO(void){
if (PyType_Ready(&DapObject_DapObjectType) < 0 )
return NULL;
PyObject *module = PyModule_Create(&TPOModule);
PyModule_AddObject(module, "DEBUG", PyLong_FromLong(L_DEBUG));
PyModule_AddObject(module, "INFO", PyLong_FromLong(L_INFO));
PyModule_AddObject(module, "NOTICE", PyLong_FromLong(L_NOTICE));
PyModule_AddObject(module, "MESSAGE", PyLong_FromLong(L_MSG));
PyModule_AddObject(module, "DAP", PyLong_FromLong(L_DAP));
PyModule_AddObject(module, "WARNING", PyLong_FromLong(L_WARNING));
PyModule_AddObject(module, "ATT", PyLong_FromLong(L_ATT));
PyModule_AddObject(module, "ERROR", PyLong_FromLong(L_ERROR));
PyModule_AddObject(module, "CRITICAL", PyLong_FromLong(L_CRITICAL));
return module;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment