diff --git a/.gitignore b/.gitignore index a0f1bd8..c2c0b03 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ -.project -.pydevproject -*.pyc +/.eggs/ +/.idea/ +/build/ +/*.egg-info/ +__pycache__/ +*.c *.o +*.pyc *.so -build - diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..73706ac --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include LICENSE +include mondemand_build.py diff --git a/Makefile b/Makefile deleted file mode 100644 index 556efee..0000000 --- a/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -PKG_CONFIG_PATH=/usr/lib/pkgconfig -SWIG_EXE=/usr/local/bin/swig -CFLAGS=`PKG_CONFIG_PATH=/usr/lib/pkgconfig pkg-config mondemand-4.0 --cflags` -LIBS=`PKG_CONFIG_PATH=/usr/lib/pkgconfig pkg-config mondemand-4.0 --libs` -PYFLAGS=`python-config --includes` -PYSITE_PACKAGES=`python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"` - -BUILD_DIR=build -LIB_NAME=mondemand -RMFLAGS='-rvf' - -.PHONY: directories - -all: build -build: directories - @echo "Building mondemand swig python wrapper." - @$(SWIG_EXE) -module mondemand -python mondemand.i - @mv mondemand.py $(BUILD_DIR)/$(LIB_NAME)/__init__.py - @gcc -fPIC $(CFLAGS) $(PYFLAGS) -c mondemand_wrap.c - @gcc -shared mondemand_wrap.o -o $(BUILD_DIR)/$(LIB_NAME)/_mondemand.so $(LIBS) -install: - @echo "Installing mondemand python client." - @echo "$(BUILD_DIR)/$(LIB_NAME) to $(PYSITE_PACKAGES)" - @if [ -d $(BUILD_DIR)/$(LIB_NAME) ]; then mv $(BUILD_DIR)/$(LIB_NAME)/ $(PYSITE_PACKAGES); \ - else echo "No build found"; fi; -directories: - @mkdir -p $(BUILD_DIR)/$(LIB_NAME) -clean: - @rm $(RMFLAGS) *.o *.so mondemand.py *.pyc *_wrap.c - @if [ -d $(BUILD_DIR)/$(LIB_NAME) ]; then rm $(RMFLAGS) $(BUILD_DIR)/$(LIB_NAME); fi; - @if [ -d $(BUILD_DIR) ]; then rm $(RMFLAGS) build; fi; -uninstall: clean - @echo "removing mondemand python client." - @if [ -d $(PYSITE_PACKAGES)/$(LIB_NAME) ]; then rm $(RMFLAGS) $(PYSITE_PACKAGES)/$(LIB_NAME); \ - else echo "No install found"; fi; diff --git a/README.md b/README.md index 8f17c19..630d52c 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,11 @@ REQUIREMENTS ============ * [mondemand library](https://github.com/mondemand/mondemand) * [lwes library](https://github.com/lwes) -* [swig](https://github.com/swig/swig) INSTALL ======= -Run `make` and `make install`. +Run `pip install .` Example Run =========== @@ -17,7 +16,7 @@ Start lwes-event-printing-listener to echo out all data that the lwes receives from the mondemand client. ```shell -lwes-event-printing-listener -m 0.0.0.0 -p 42042 +lwes-event-printing-listener -m 0.0.0.0 -p 10201 python demo.py ``` diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..1a525e0 --- /dev/null +++ b/default.nix @@ -0,0 +1,24 @@ +{ + nixpkgs ? import , +}: + +let + pkgs = nixpkgs {}; + pythonPackages = pkgs.pythonPackages; + callPackage = pkgs.lib.callPackageWith (pkgs // localPkgs); + localPkgs = { + lwes = callPackage ./nix/lwes.nix {}; + mondemand = callPackage ./nix/mondemand.nix {}; + }; +in pkgs.pythonPackages.buildPythonPackage { + pname = "mondemand"; + version = "1.0.0"; + src = ./.; + propagatedBuildInputs = [ + localPkgs.mondemand + pythonPackages.cffi + pythonPackages.six + pythonPackages.typing + ]; + nativeBuildInputs = [ pkgs.pkgconfig ]; +} diff --git a/demo.py b/demo.py index 82cd074..19f227e 100644 --- a/demo.py +++ b/demo.py @@ -1,23 +1,21 @@ -import mondemand +from mondemand.client import MondemandClient +from mondemand.lwes_transport import LwesTransport # create the client -client = mondemand.client_create("python_client") +client = MondemandClient("python_client") # create a transport to send data -transport = mondemand.transport_lwes_create("127.0.0.1", 25552, None, 0, 60) +transport = LwesTransport('127.0.0.1', 10201, heartbeat_flag=0, heartbeat_frequency=60) # attach the transport to the client -mondemand.add_transport(client, transport) +client.add_transport(transport) # add some contextual information to the client -mondemand.set_context(client, "cluster_id", "12345") +client.set_context("cluster_id", "12345") -# set some stats -mondemand.stats_set(client, "demo.py", 1, "stat_1", 1234) -mondemand.stats_inc(client, "demo.py", 1, "stat_2", 1) +# log some stats +client.stats_set("stat_1", 1234) +client.stats_inc("stat_2", 1) # send it to the network -mondemand.flush(client) - -# send some annotations -mondemand.flush_annotation('', 1234567890, 'test', 'test desc', [], 0, client) +client.flush_stats() diff --git a/mondemand.i b/mondemand.i deleted file mode 100644 index a27f80f..0000000 --- a/mondemand.i +++ /dev/null @@ -1,282 +0,0 @@ -%module mondemand -%feature("autodoc", "1"); -%{ - #include "mondemand.h" - #define MONDEMAND_UNKNOWN 0 - #define MONDEMAND_GAUGE 1 - #define MONDEMAND_COUNTER 2 - #define MONDEMAND_INC 0 - #define MONDEMAND_DEC 1 - #define MONDEMAND_SET 2 - typedef long long MStatCounter; -%} - -// This tells SWIG to treat char ** as a special case, needed for the -// char ** in flush_annotations. See goo.gl/EfhRZr -%typemap(in) char ** { - /* Check if is a list */ - if (PyList_Check($input)) { - int size = PyList_Size($input); - int i = 0; - $1 = (char **) malloc((size+1)*sizeof(char *)); - for (i = 0; i < size; i++) { - PyObject *o = PyList_GetItem($input,i); - if (PyString_Check(o)) - $1[i] = PyString_AsString(PyList_GetItem($input,i)); - else { - PyErr_SetString(PyExc_TypeError,"list must contain strings"); - free($1); - return NULL; - } - } - $1[i] = 0; - } else { - PyErr_SetString(PyExc_TypeError,"not a list"); - return NULL; - } -} - -// This cleans up the char ** array we malloc'd before the function call -%typemap(freearg) char ** { - free((char *) $1); -} - -%inline %{ - -struct mondemand_client * -client_create(const char *program_identifier) -{ - return mondemand_client_create(program_identifier); -} - -void -client_destroy(struct mondemand_client *client) -{ - return mondemand_client_destroy(client); -} - -void -set_immediate_send_level(struct mondemand_client *client, - const int level) -{ - return mondemand_set_immediate_send_level(client, level); -} - -void -set_no_send_level(struct mondemand_client *client, const int level) -{ - return mondemand_set_no_send_level(client, level); -} - -const char * -get_context(struct mondemand_client *client, const char *key) -{ - return mondemand_get_context(client, key); -} - -const char ** -get_context_keys(struct mondemand_client *client) -{ - return mondemand_get_context_keys(client); -} - -int -set_context(struct mondemand_client *client, const char *key, - const char *value) -{ - return mondemand_set_context(client, key, value); -} - -void -remove_context(struct mondemand_client *client, const char *key) -{ - return mondemand_remove_context(client, key); -} - -void -remove_all_contexts(struct mondemand_client *client) -{ - return mondemand_remove_all_contexts(client); -} - -int -add_transport(struct mondemand_client *client, - struct mondemand_transport *transport) -{ - return mondemand_add_transport(client, transport); -} - -int -level_is_enabled(struct mondemand_client *client, - const int log_level) -{ - return mondemand_level_is_enabled(client, log_level); -} - -int -flush_logs(struct mondemand_client *client) -{ - return mondemand_flush_logs(client); -} - -int -flush_stats(struct mondemand_client *client) -{ - return mondemand_flush_stats(client); -} - -int -reset_stats(struct mondemand_client *client) -{ - return mondemand_reset_stats(client); -} - -int -flush(struct mondemand_client *client) -{ - return mondemand_flush(client); -} - -int -log_level_from_string(const char *level) -{ - return mondemand_log_level_from_string(level); -} - -MondemandStatType -stat_type_from_string(const char *type) -{ - return mondemand_stat_type_from_string(type); -} - -int -initialize_trace(struct mondemand_client *client, - const char *owner, - const char *trace_id, - const char *message) -{ - return mondemand_initialize_trace(client, owner, - trace_id, message); -} - -void -clear_trace(struct mondemand_client *client) -{ - return mondemand_clear_trace(client); -} - -const char * -get_trace(struct mondemand_client *client, const char *key) -{ - return mondemand_get_trace(client, key); -} - -const char ** -get_trace_keys(struct mondemand_client *client) -{ - return mondemand_get_trace_keys(client); -} - -int -set_trace(struct mondemand_client *client, - const char *key, const char *value) -{ - return mondemand_set_trace(client, key, value); -} - -void -remove_trace(struct mondemand_client *client, const char *key) -{ - return mondemand_remove_trace(client, key); -} - -void -remove_all_traces(struct mondemand_client *client) -{ - return mondemand_remove_all_traces(client); -} - -int -flush_trace(struct mondemand_client *client) -{ - return mondemand_flush_trace(client); -} - -struct mondemand_transport * -transport_lwes_create(const char *address, const int port, - const char *interface, int emit_heartbeat, - int heartbeat_frequency) -{ - return mondemand_transport_lwes_create(address, port, - interface, emit_heartbeat, heartbeat_frequency); -} - -int -stats_inc(struct mondemand_client *client, - const char *filename, const int line, - const char *key, const long value) -{ - return mondemand_stats_perform_op (client, filename, line, - MONDEMAND_INC, MONDEMAND_COUNTER, key, value); -} - -int -stats_dec(struct mondemand_client *client, const char *filename, - const int line, const char *key, - const long value) -{ - return mondemand_stats_perform_op (client, filename, line, - MONDEMAND_DEC, MONDEMAND_COUNTER, key, value * (-1)); -} - -int -stats_set(struct mondemand_client *client, const char *filename, - const int line, const char *key, - const long value) -{ - return mondemand_stats_perform_op(client, filename, line, - MONDEMAND_SET, MONDEMAND_GAUGE, key, value); -} - -int -initialize_performance_trace (struct mondemand_client *client, - const char *id, - const char *caller_label) -{ - return mondemand_initialize_performance_trace(client, id, caller_label); -} - -int -add_performance_trace_timing (struct mondemand_client *client, - const char *label, - const long long int start, - const long long int end) -{ - return mondemand_add_performance_trace_timing(client, label, start, end); -} - -void -clear_performance_trace (struct mondemand_client *client) -{ - return mondemand_clear_performance_trace(client); -} - -int -flush_performance_trace(struct mondemand_client *client) -{ - return mondemand_flush_performance_trace(client); -} - -int -flush_annotation (const char* id, - const long long int timestamp, - const char* description, - const char* text, - const char** tags, - const int num_tags, - struct mondemand_client *client) -{ - return mondemand_flush_annotation(id, timestamp, description, text, tags, num_tags, client); -} - -%} diff --git a/mondemand/__init__.py b/mondemand/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mondemand/client.py b/mondemand/client.py new file mode 100644 index 0000000..3ecba08 --- /dev/null +++ b/mondemand/client.py @@ -0,0 +1,213 @@ +from __future__ import absolute_import + +from functools import partial +from inspect import getframeinfo, stack +from typing import AnyStr, List + +from ._mondemand import ffi, lib +from .lwes_transport import LwesTransport +from .utils import text_to_cstring +from . import utils + +_cstring_to_text = partial(utils.cstring_to_text, ffi) +_string_array_to_text_list = partial(utils.string_array_to_text_list, ffi) + + +class MondemandClient(object): + def __init__(self, program_id): + # type: (AnyStr) -> None + """ + Create a client with the given program_id + """ + client = lib.mondemand_client_create(text_to_cstring(program_id)) + if client == ffi.NULL: + raise MemoryError('Unable to create mondemand client') + + self.client = ffi.gc(client, lib.mondemand_client_destroy) + self.transport = None + + def set_immediate_send_level(self, level): + # type: (int) -> None + """Set the immediate send level, which defines the minimum level where + events are sent as soon as they are received (as opposed to being bundled). + Out of range values are ignored.""" + lib.mondemand_set_immediate_send_level(self.client, level) + + def set_no_send_level(self, level): + # type: (int) -> None + """Set the no send level, which defines the minimum log level where events + are sent at all. Anything lower than this defined level will be suppressed. + Out of range values are ignored.""" + lib.mondemand_set_no_send_level(self.client, level) + + def level_is_enabled(self, level): + # type: (int) -> bool + """Checks if a log level is enabled, which is useful to callers in case they want + to check whether or not to bother to log.""" + return bool(lib.mondemand_level_is_enabled(self.client, level)) + + def initialize_trace(self, trace_owner, trace_id, trace_message): + # type: (AnyStr, AnyStr, AnyStr) -> int + """ + Initialize a trace with the given owner, id, and message + """ + return lib.mondemand_initialize_trace(self.client, text_to_cstring(trace_owner), + text_to_cstring(trace_id), text_to_cstring(trace_message)) + + def clear_trace(self): + # type: () -> None + """ + Remove all trace keys/values and remove the trace owner/id information + """ + lib.mondemand_clear_trace(self.client) + + def get_trace(self, key): + # type: (AnyStr) -> str + """ + Return the value for the given trace key + """ + return _cstring_to_text(lib.mondemand_get_trace(self.client, text_to_cstring(key))) + + def get_trace_keys(self): + # type: () -> List[str] + """ + Return all the trace keys for the client + """ + response = ffi.gc(lib.mondemand_get_trace_keys(self.client), lib.free) + return _string_array_to_text_list(response) + + def set_trace(self, key, value): + # type: (AnyStr, AnyStr) -> int + """ + Set the trace with the given key to the given value + """ + return lib.mondemand_set_trace(self.client, text_to_cstring(key), text_to_cstring(value)) + + def remove_trace(self, key): + # type: (AnyStr) -> None + """ + Remove the trace under the given key + """ + lib.mondemand_remove_trace(self.client, text_to_cstring(key)) + + def remove_all_traces(self): + # type: () -> None + """ + Remove all traces from the client + """ + lib.mondemand_remove_all_traces(self.client) + + def get_context(self, key): + # type: (AnyStr) -> str + """ + Get the value for the context with the given key + """ + return _cstring_to_text(lib.mondemand_get_context(self.client, text_to_cstring(key))) + + def get_context_keys(self): + # type: () -> List[str] + """ + Return all the context keys for the client + """ + response = ffi.gc(lib.mondemand_get_context_keys(self.client), lib.free) + return _string_array_to_text_list(response) + + def set_context(self, key, value): + # type: (AnyStr, AnyStr) -> int + """ + Set the context with the given key to the given value + """ + return lib.mondemand_set_context(self.client, text_to_cstring(key), + text_to_cstring(value)) + + def remove_context(self, key): + # type: (AnyStr) -> None + """ + Remove the context stored under the given key + """ + lib.mondemand_remove_context(self.client, text_to_cstring(key)) + + def remove_all_contexts(self): + # type: () -> None + """ + Remove all context information from the client + """ + lib.mondemand_remove_all_contexts(self.client) + + def reset_stats(self): + # type: () -> int + """ + Reset all stat counters and gauges to 0 + """ + return lib.mondemand_reset_stats(self.client) + + def stats_inc(self, key, value=1): + # type: (AnyStr, int) -> int + """ + Increment the given COUNTER stat by the given value. If no value + is passed in, increment by 1. + """ + caller = getframeinfo(stack()[1][0]) + filename = text_to_cstring('%s:%s' % (caller.filename, caller.function)) + return lib.mondemand_stats_perform_op(self.client, filename, caller.lineno, + lib.MONDEMAND_INC, lib.MONDEMAND_COUNTER, text_to_cstring(key), + value) + + def stats_dec(self, key, value=1): + # type: (AnyStr, int) -> int + """ + Decrement the given COUNTER stat by the given value. If no value + is passed in, decrement by 1. + """ + caller = getframeinfo(stack()[1][0]) + filename = text_to_cstring('%s:%s' % (caller.filename, caller.function)) + return lib.mondemand_stats_perform_op(self.client, filename, caller.lineno, + lib.MONDEMAND_DEC, lib.MONDEMAND_COUNTER, text_to_cstring(key), + value) + + def stats_set(self, key, value): + # type: (AnyStr, int) -> int + """ + Set the given GAUGE stat to the given value. + """ + caller = getframeinfo(stack()[1][0]) + filename = text_to_cstring('%s:%s' % (caller.filename, caller.function)) + return lib.mondemand_stats_perform_op(self.client, filename, caller.lineno, + lib.MONDEMAND_SET, lib.MONDEMAND_COUNTER, text_to_cstring(key), + value) + + def flush(self): + # type: () -> int + """ + Send all current trace, stats, and log data using the mondemand client + """ + return lib.mondemand_flush(self.client) + + def flush_logs(self): + # type: () -> int + """ + Send all current log data using the mondemand client + """ + return lib.mondemand_flush_logs(self.client) + + def flush_stats(self): + # type: () -> int + """ + Send all current stats data using the mondemand client + """ + return lib.mondemand_flush_stats(self.client) + + def flush_trace(self): + # type: () -> int + """ + Send all current trace data using the mondemand client + """ + return lib.mondemand_flush_trace(self.client) + + def add_transport(self, transport): + # type: (LwesTransport) -> int + """ + Add a transport to the mondemand client + """ + self.transport = transport.transport + return lib.mondemand_add_transport(self.client, self.transport) diff --git a/mondemand/lwes_transport.py b/mondemand/lwes_transport.py new file mode 100644 index 0000000..2458d3b --- /dev/null +++ b/mondemand/lwes_transport.py @@ -0,0 +1,21 @@ +from __future__ import absolute_import + +from ._mondemand import ffi, lib +from .utils import text_to_cstring + + +class LwesTransport(object): + def __init__(self, address, port, interface=None, heartbeat_flag=0, + heartbeat_frequency=0, ttl=30): + + transport = lib.mondemand_transport_lwes_create_with_ttl( + text_to_cstring(address), port, text_to_cstring(interface) if interface else ffi.NULL, + heartbeat_flag, heartbeat_frequency, ttl + ) + + if transport == ffi.NULL: + raise MemoryError('Unable to create LWES transport') + + # self.transport = ffi.gc(transport, lib.mondemand_transport_lwes_destroy) + # TODO: mondemand frees all added transports; make sure to free transports that are not added + self.transport = transport diff --git a/mondemand/utils.py b/mondemand/utils.py new file mode 100644 index 0000000..e078eac --- /dev/null +++ b/mondemand/utils.py @@ -0,0 +1,32 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +from typing import Text, Union, Optional + +import six + + +def text_to_cstring(s): + # type: (Optional[Union[Text, str, bytes]]) -> Optional[bytes] + + if s is None or isinstance(s, six.binary_type): + return s + + return s.encode() + + +def cstring_to_text(ffi, s): + return ffi.string(s).decode() + ## type: (Optional[Union[Text, bytes]]) -> Optional[Text] + # if s is None or isinstance(s, six.text_type): + # return s + + +def string_array_to_text_list(ffi, s): + result = [] + + i = 0 + while s[i] != ffi.NULL: + result.append(cstring_to_text(ffi, s[i])) + i += 1 + + return result diff --git a/mondemand_build.py b/mondemand_build.py new file mode 100644 index 0000000..58fa718 --- /dev/null +++ b/mondemand_build.py @@ -0,0 +1,147 @@ +import shlex +import subprocess +import sys + +from cffi import FFI + + +def pkgconfig(flags, *pkgs): + """Obtain informations through pkg-config""" + cmd = ['pkg-config', flags] + cmd.extend(pkgs) + try: + out = subprocess.check_output(cmd) + except subprocess.CalledProcessError as e: + sys.exit(e.returncode) + else: + if isinstance(out, bytes): + out = out.decode(sys.getfilesystemencoding()) + + return shlex.split(out) + + +ffibuilder = FFI() + +ffibuilder.cdef(""" +/* Types */ +typedef long long MondemandStatValue; + +typedef enum { + MONDEMAND_UNKNOWN = ..., + MONDEMAND_GAUGE = ..., + MONDEMAND_COUNTER = ... +} MondemandStatType; + +typedef enum { + MONDEMAND_INC = ..., + MONDEMAND_DEC = ..., + MONDEMAND_SET = ... +} MondemandOp; + +/* LWES */ +struct mondemand_transport * +mondemand_transport_lwes_create( + const char *address, const int port, const char *interface, int emit_heartbeat, + int heartbeat_frequency); + +struct mondemand_transport * +mondemand_transport_lwes_create_with_ttl( + const char *address, const int port, const char *interface, int emit_heartbeat, + int heartbeat_frequency, int ttl); + +void +mondemand_transport_lwes_destroy(struct mondemand_transport *transport); + +/* Mondemand */ +struct mondemand_client * +mondemand_client_create(const char *program_identifier); + +void mondemand_client_destroy(struct mondemand_client *client); + +void +mondemand_set_immediate_send_level(struct mondemand_client *client, + const int level); + +void +mondemand_set_no_send_level(struct mondemand_client *client, const int level); + +int +mondemand_level_is_enabled(struct mondemand_client *client, const int log_level); + +int +mondemand_initialize_trace(struct mondemand_client *client, const char *owner, + const char *trace_id, const char *message); + +void +mondemand_clear_trace(struct mondemand_client *client); + +const char * +mondemand_get_trace(struct mondemand_client *client, const char *key); + +const char ** +mondemand_get_trace_keys(struct mondemand_client *client); + +int +mondemand_set_trace(struct mondemand_client *client, const char *key, + const char *value); + +void +mondemand_remove_trace(struct mondemand_client *client, const char *key); + +void +mondemand_remove_all_traces(struct mondemand_client *client); + +const char * +mondemand_get_context(struct mondemand_client *client, const char *key); + +const char ** +mondemand_get_context_keys(struct mondemand_client *client); + +int +mondemand_set_context(struct mondemand_client *client, const char *key, + const char *value); + +void +mondemand_remove_context(struct mondemand_client *client, const char *key); + +void +mondemand_remove_all_contexts(struct mondemand_client *client); + +int +mondemand_reset_stats(struct mondemand_client *client); + +int +mondemand_stats_perform_op(struct mondemand_client *client, + const char *filename, const int line, const MondemandOp op, + const MondemandStatType type, const char *key, + const MondemandStatValue value); + +int +mondemand_flush(struct mondemand_client *client); + +int +mondemand_flush_logs(struct mondemand_client *client); + +int +mondemand_flush_stats(struct mondemand_client *client); + +int +mondemand_flush_trace(struct mondemand_client *client); + +int +mondemand_add_transport(struct mondemand_client *client, + struct mondemand_transport *transport); + +void +free(void *ptr); +""") + +ffibuilder.set_source('mondemand._mondemand', """ + #include "mondemand.h" +""", + extra_compile_args=pkgconfig('--cflags', 'mondemand-4'), + extra_link_args=pkgconfig('--libs', 'mondemand-4') +) + +if __name__ == '__main__': + ffibuilder.compile(verbose=True, debug=True) diff --git a/nix/lwes.nix b/nix/lwes.nix new file mode 100644 index 0000000..5cc487c --- /dev/null +++ b/nix/lwes.nix @@ -0,0 +1,20 @@ +{ stdenv, fetchurl, perl, bison }: + +stdenv.mkDerivation rec { + name = "lwes-${version}"; + version = "1.1.2"; + + src = fetchurl { + url = "https://github.com/lwes/lwes/releases/download/${version}/lwes-${version}.tar.gz"; + sha256 = "fbd8d3bd9153a8fa6286865b4527692683e87f30cf715170fef72659fa5383bd"; + }; + + buildInputs = [ perl bison ]; + enableParallelBuilding = true; + + meta = { + description = "Light Weight Event System C library"; + homepage = http://lwes.github.io/; + license = stdenv.lib.licenses.bsd3; + }; +} diff --git a/nix/mondemand.nix b/nix/mondemand.nix new file mode 100644 index 0000000..2433eb4 --- /dev/null +++ b/nix/mondemand.nix @@ -0,0 +1,21 @@ +{ stdenv, fetchurl, lwes, perl, pkgconfig }: + +stdenv.mkDerivation rec { + name = "mondemand-${version}"; + version = "4.4.2"; + + src = fetchurl { + url = "https://github.com/mondemand/mondemand/releases/download/${version}/mondemand-${version}.tar.gz"; + sha256 = "b137bd25cdd7f6b8cf4314af62c9b6706a35b845901dde2f1a62bb847684c9f9"; + }; + + buildInputs = [ perl pkgconfig ]; + propagatedBuildInputs = [ lwes ]; + enableParallelBuilding = true; + + meta = { + description = "Mondemand C library"; + homepage = http://mondemand.github.io; + license = stdenv.lib.licenses.bsd3; + }; +} diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..0259f4d --- /dev/null +++ b/setup.cfg @@ -0,0 +1,35 @@ +[metadata] +name=mondemand +url=https://github.com/mondemand/mondemand-python +description=MonDemand python bindings +long_description=file:README.md +license=BSD +maintainer=Derek Kulinski +maintainer_email=d@kulinski.us +platforms= + POSIX +classifiers= + Development Status :: 4 - Beta + Intended Audience :: Developers + License :: OSI Approved :: BSD License + Operating System :: Unix + Programming Language :: Python + Programming Language :: Python :: 2 + Programming Language :: Python :: 2.7 + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Topic :: Software Development :: Libraries :: Python Modules + +[options] +python_requires= >=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4 +zip_safe=false +setup_requires= + setuptools_scm + cffi ~= 1.11.5 +install_requires= + cffi ~= 1.11.5 + six + typing +packages=find: diff --git a/setup.py b/setup.py old mode 100644 new mode 100755 index 8a0da0c..5c44867 --- a/setup.py +++ b/setup.py @@ -1,71 +1,8 @@ #!/usr/bin/env python -""" -setup.py file for Mondemand binding -""" - -from distutils import sysconfig -from distutils import log -from distutils.core import setup -from distutils.core import Command - -import os -from subprocess import call, Popen, PIPE - -BASEPATH = os.path.dirname(os.path.abspath(__file__)) -USER_OPTIONS = [('bs', None, None)] - -def runner(cmd, skip_errors=False): - resp = Popen(cmd, - cwd=BASEPATH, stdout=PIPE, stderr=PIPE).communicate() - log.info(resp[0]) - if resp[1] and not skip_errors: - log.error(resp[1]) - -class MakeCommand(Command): - user_options = USER_OPTIONS - def initialize_options(self): - pass - def finalize_options(self): - pass - -class MakeAll(MakeCommand): - def run(self): - runner(['make', 'all']) - -class MakeBuild(MakeCommand): - user_options = USER_OPTIONS - def run(self): - runner(['make', 'build']) - -class MakeInstall(MakeCommand): - user_options = USER_OPTIONS - def run(self): - runner(['make', 'install']) - -class MakeClean(MakeCommand): - user_options = USER_OPTIONS - def run(self): - runner(['make', 'clean'], skip_errors=True) +from setuptools import setup setup( - name='mondemand', - version='0.0.2', - description='MonDemand python bindings', - license='BSD', - url='http://www.mondemand.org/', - long_description=open(os.path.join(os.path.dirname(__file__), 'README.md')).read(), - classifiers=[ - 'Intended Audience :: Developers', - 'License :: OSI Approved :: BSD License', - 'Operating System :: Unix', - 'Programming Language :: Python', - ], - - cmdclass={ - 'all': MakeAll, - 'build': MakeBuild, - 'install': MakeInstall, - 'clean': MakeClean, - } + use_scm_version=True, + cffi_modules=['mondemand_build.py:ffibuilder'] )