Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added a basic CFFI interface

Modify the build system for using the CFFI stuff
  • Loading branch information...
commit 7aaa0676c3b8d5f4705f1892035b2e0cf8e7a679 1 parent 7b710b6
Alvaro Saurin authored
View
94 Makefile
@@ -0,0 +1,94 @@
+
+# the python interpreter
+#PYTHON=python
+PYTHON=pypy
+
+# the libuv directory
+LIBUV_DIR=libuv
+
+
+##############################
+# building
+##############################
+
+all: build
+
+.PHONY: build
+build: setup.py
+ @echo ">>> Building up..."
+ $(PYTHON) setup.py build_ext $@
+
+##############################
+# testing
+##############################
+
+.PHONY: tests
+tests: test
+test:
+ @echo ">>> Running all tests..."
+ @PYTHONPATH=`pwd` nosetests -v --with-isolation -a '!perf' -w tests
+
+##############################
+# cleaning
+##############################
+
+clean:
+ @echo ">>> Cleaning up..."
+ rm -rf build dist *.so core.* pyuv/*.pyc pyuv/ffi/uv
+ rm -rf *.egg-info __pycache__ Library
+ rm -f `find . -name '*.pyc'` `find pyuv -name '*.so'` `find pyuv -name '*.a'`
+ rm -rf `find . -name '__pycache__'`
+
+distclean: clean
+ make -C libuv clean
+ rm -rf `find libuv -name '*.o'`
+
+##############################
+# documentations
+##############################
+
+.PHONY: doc
+doc: docs
+
+docs: docs-html
+
+docs-html: all
+ @echo ">>> Making HTML documentation..."
+ LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 make -C doc html
+
+##############################
+# redistribution
+##############################
+
+redist: dist
+
+.PHONY: dist
+dist:
+ @echo ">>> Making redistributable package..."
+ $(PYTHON) setup.py bdist
+ @echo ">>> redistributable package left in dist/"
+
+.PHONY: egg
+egg:
+ @echo ">>> Making redistributable egg..."
+ $(PYTHON) setup.py bdist_egg
+ @echo ">>> redistributable egg left in dist/"
+
+dist-debug: clean
+ DISTUTILS_DEBUG=1 make dist
+
+sdist:
+ @echo ">>> Making redistributable sources package..."
+ $(PYTHON) setup.py sdist
+ @echo ">>> redistributable package left in dist/"
+
+sdist-debug: clean
+ DISTUTILS_DEBUG=1 make sdist
+
+sdist-upload: sdist
+ @echo ">>> Uploading redistributable sources package to PyPI..."
+ $(PYTHON) setup.py sdist upload
+
+sdist-register: sdist
+ @echo ">>> Registering package at PyPI..."
+ $(PYTHON) setup.py register
View
35 pyuv/__init__.py
@@ -0,0 +1,35 @@
+#
+# python-uv
+#
+# Unless otherwise noted, the files in python-uv are under the following MIT license:
+#
+# Copyright (c) 2013, Alvaro Saurin
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+
+from loop import Loop
+from loop import UV_RUN_DEFAULT, UV_RUN_ONCE, UV_RUN_NOWAIT
+
+from tcp import TCP
+from udp import UDP
+from buffer import Buffer
+from timer import Timer
+from prepare import Prepare
View
103 pyuv/buffer.py
@@ -0,0 +1,103 @@
+#
+# Evy - a concurrent networking library for Python
+#
+# Unless otherwise noted, the files in Evy are under the following MIT license:
+#
+# Copyright (c) 2012, Alvaro Saurin
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+#
+
+
+from pyuv.ffi import C, ffi
+
+
+
+
+class Buffer(object):
+ """
+ Buffers for using with UV
+
+ In order to work with UV, we must keep references not only to the uv_buf_t, but also to the
+ memory allocated for the base. This class keeps both things together: the `uv_buffer_t` and the
+ `char*` that is the base...
+ """
+
+ __slots__ = ['_len', '_base', '_buffer']
+
+
+ def __init__(self, data = None, length = None):
+ if length:
+ self._len = length
+ else:
+ assert data is not None
+ self._len = len(data)
+
+ if data:
+ self._base = ffi.new("char[]", data[:self._len])
+ else:
+ self._base = ffi.new("char[%d]" % length)
+
+ buffer_def = {
+ 'base': self._base,
+ 'len': self._len,
+ }
+ self._buffer = ffi.new('uv_buf_t*', buffer_def)
+
+ @property
+ def ptr(self):
+ return self._buffer
+
+ @property
+ def data(self):
+ """
+ Return the data as a string
+ :return:
+ """
+ return self.__str__()
+
+ @property
+ def length(self):
+ return self._buffer[0].len
+
+ def as_struct(self):
+ return self._buffer[0]
+
+ def slice(self, datalen):
+ return ffi.string(self._buffer[0].base, datalen)
+
+ def __len__(self):
+ return self.length
+
+ def __call__(self, *args, **kwargs):
+ return self.ptr
+
+ def __getitem__(self, key):
+ return self.as_struct() ## we always return the same: the struct
+
+ def __str__(self):
+ return ffi.string(self._buffer[0].base, self.length)
+
+ def __repr__(self):
+ return '<uv_buffer with %s [%d bytes]>' % (repr(self._base), self._len)
+
+ def __eq__(self, other):
+ return (self._base == other._base) and (self._len == other._len)
+
View
125 pyuv/errors.py
@@ -0,0 +1,125 @@
+#
+# Evy - a concurrent networking library for Python
+#
+# Unless otherwise noted, the files in Evy are under the following MIT license:
+#
+# Copyright (c) 2012, Alvaro Saurin
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+#
+
+import os
+import errno
+import socket
+
+
+from pyuv.ffi import C, ffi
+
+
+#: the mapping between libuv errors and errno
+_UV_ERR_TO_ERRNO_MAP = {
+ 'UV_EACCES' : errno.EACCES ,
+ 'UV_EAGAIN' : errno.EAGAIN,
+ 'UV_EADDRINUSE' : errno.EADDRINUSE ,
+ 'UV_EADDRNOTAVAIL' : errno.EADDRNOTAVAIL,
+ 'UV_EAFNOSUPPORT' : errno.EAFNOSUPPORT,
+ 'UV_EALREADY' : errno.EALREADY,
+ 'UV_EBADF' : errno.EBADF,
+ 'UV_EBUSY' : errno.EBUSY,
+ 'UV_ECONNABORTED' : errno.ECONNABORTED,
+ 'UV_ECONNREFUSED' : errno.ECONNREFUSED ,
+ 'UV_ECONNRESET' : errno.ECONNRESET,
+ 'UV_EDESTADDRREQ' : errno.EDESTADDRREQ,
+ 'UV_EFAULT' : errno.EFAULT,
+ 'UV_EHOSTUNREACH' : errno.EHOSTUNREACH,
+ 'UV_EINTR' : errno.EINTR,
+ 'UV_EINVAL' : errno.EINVAL,
+ 'UV_EISCONN' : errno.EISCONN,
+ 'UV_EMFILE' : errno.EMFILE,
+ 'UV_EMSGSIZE' : errno.EMSGSIZE,
+ 'UV_ENETDOWN' : errno.ENETDOWN,
+ 'UV_ENETUNREACH' : errno.ENETUNREACH,
+ 'UV_ENFILE' : errno.ENFILE,
+ 'UV_ENOBUFS' : errno.ENOBUFS,
+ 'UV_ENOMEM' : errno.ENOMEM,
+ 'UV_ENOTDIR' : errno.ENOTDIR,
+ 'UV_EISDIR' : errno.EISDIR,
+ #'UV_ENONET' : errno.ENONET,
+ 'UV_ENOTCONN' : errno.ENOTCONN,
+ 'UV_ENOTSOCK' : errno.ENOTSOCK,
+ 'UV_ENOTSUP' : errno.ENOTSUP,
+ 'UV_ENOENT' : errno.ENOENT,
+ 'UV_ENOSYS' : errno.ENOSYS,
+ 'UV_EPIPE' : errno.EPIPE,
+ 'UV_EPROTO' : errno.EPROTO,
+ 'UV_EPROTONOSUPPORT' : errno.EPROTONOSUPPORT,
+ 'UV_EPROTOTYPE' : errno.EPROTOTYPE,
+ 'UV_ETIMEDOUT' : errno.ETIMEDOUT,
+ 'UV_ESHUTDOWN' : errno.ESHUTDOWN,
+ 'UV_EEXIST' : errno.EEXIST,
+ 'UV_ESRCH' : errno.ESRCH,
+ 'UV_ENAMETOOLONG' : errno.ENAMETOOLONG,
+ 'UV_EPERM' : errno.EPERM,
+ 'UV_ELOOP' : errno.ELOOP,
+ 'UV_EXDEV' : errno.EXDEV,
+ 'UV_ENOTEMPTY' : errno.ENOTEMPTY,
+ 'UV_ENOSPC' : errno.ENOSPC,
+ 'UV_EIO' : errno.EIO,
+ 'UV_EROFS' : errno.EROFS,
+ 'UV_ENODEV' : errno.ENODEV ,
+ 'UV_ESPIPE' : errno.ESPIPE ,
+ }
+
+def uv_error_to_errno(code, not_found = None):
+ """
+ Obtain the mapping between uv errors and errno
+ :param code: the uv code
+ :param not_found: the result if there is not valid mapping
+ :return: an errno
+ """
+ assert isinstance(code, str)
+ try:
+ return _UV_ERR_TO_ERRNO_MAP[code]
+ except KeyError:
+ return not_found
+
+def uv_last_error_str(loop):
+ return str(C.uv_last_error(loop).code)
+
+def uv_last_error(default_code = 0, default_str = 'none'):
+ """
+ Get the last libuv error that happened
+ :return: a tuple with the errno equivalent and the string representation
+ """
+ _errno = uv_error_to_errno(uv_last_error_str(), not_found = 0)
+
+ if _errno is 0: return default_code, default_str
+ else: return _errno, os.strerror(_errno)
+
+
+def last_socket_error(default_code = 0, default_str = 'none'):
+ """
+ Utility function for getting the last exception as a socket.error
+ """
+ return socket.error(*uv_last_error(default_code, default_str))
+
+
+
+
View
86 pyuv/ffi/__init__.py
@@ -0,0 +1,86 @@
+"""
+libuv ffi module
+
+Usage;
+
+>>> from uv.ffi import C
+>>> dir(C)
+['UV_EACCES', 'UV_EADDRINFO', 'UV_EADDRINUSE', 'UV_EADDRNOTAVAIL', 'UV_EAFNOSUPPORT', ...]
+"""
+
+
+
+
+from __future__ import absolute_import
+import sys, os
+
+from cffi import FFI
+
+
+
+__HERE__ = os.path.dirname(__file__)
+
+# where we have libuv installed
+LIBUV_DIR = os.path.join(__HERE__, '..', '..', 'deps', 'libuv')
+LIBUV_INC_DIR = os.path.join(LIBUV_DIR, 'include')
+LIBUV_LIB_DIR = LIBUV_DIR
+
+LIBUV_FFI_H_FILE = os.path.join(__HERE__, '_ffi.h')
+LIBUV_FFI_C_FILE = os.path.join(__HERE__, '_ffi.c')
+LIBUV_FFI_C_EXTRA_FILE = os.path.join(__HERE__, '_ffi_extra.c')
+
+FFI_SO = '_libuv.so'
+FULL_FFI_SO = os.path.join(os.path.dirname(__file__), FFI_SO)
+
+EXTENSION_PACKAGE = 'pyuv.ffi' # must match the package defined in setup.py
+
+
+_ffi_so = None
+C = None
+
+
+# check if we need any extra libraries...
+cflags = []
+ldflags = []
+extra_libs = []
+
+if sys.platform in ['linux', 'linux2']:
+ extra_libs += ['rt']
+
+if sys.platform in ['darwin']:
+ cflags += [' -arch x86_64 -arch i386 -framework CoreServices ']
+ ldflags += [' -framework CoreServices ']
+
+
+## NOTE: do not ask me why, but we need to set the env flags or distutils will ignore them...
+if len(cflags) > 0: os.environ["CFLAGS"] = ' '.join(cflags)
+if len(ldflags) > 0: os.environ["LDFLAGS"] = ' '.join(ldflags)
+
+
+ffi = FFI()
+ffi.cdef(open(LIBUV_FFI_H_FILE).read())
+
+## evaluate if we have already compiled the ffi... it should be done just once
+if _ffi_so is None:
+ _ffi_so = os.path.exists(FULL_FFI_SO)
+
+if C is None:
+ C = ffi.verify(open(LIBUV_FFI_C_FILE).read(),
+ include_dirs = [LIBUV_INC_DIR],
+ sources = [LIBUV_FFI_C_EXTRA_FILE],
+ libraries = ['uv'] + extra_libs,
+ library_dirs = [LIBUV_LIB_DIR],
+ ext_package = EXTENSION_PACKAGE)
+
+#version = 'libuv-%d.%02d' % (C.UV_VERSION_MAJOR, C.UV_VERSION_MINOR)
+
+#: cast to a handle
+as_handle = lambda h: ffi.cast('uv_handle_t *', h)
+
+handle_unref = lambda handle: ffi.uv_unref(as_handle(handle))
+
+#: Return TRUE if the handle is active
+handle_is_active = lambda handle :ffi.uv_is_active(as_handle(handle))
+
+
+
View
2  pyuv/ffi/_ffi.c
@@ -0,0 +1,2 @@
+#include <uv.h>
+
View
593 pyuv/ffi/_ffi.h
@@ -0,0 +1,593 @@
+/**
+* python-uv
+*
+* Unless otherwise noted, the files in python-uv are under the following MIT license:
+*
+* Copyright (c) 2012, Alvaro Saurin
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+**/
+
+
+/***************************************************************************************************
+ * stripped down version of the libuv header file
+ **************************************************************************************************/
+
+#define UV_VERSION_MAJOR ...
+#define UV_VERSION_MINOR ...
+
+
+/**
+ * some external definitions
+ */
+
+struct in_addr { ...; };
+struct in6_addr { ...; };
+struct sockaddr { ...; };
+
+struct sockaddr_in {
+ unsigned short sin_port;
+ struct in_addr sin_addr;
+ ...;
+};
+
+struct sockaddr_in6 {
+ uint16_t sin6_port;
+ struct in6_addr sin6_addr;
+ ...;
+};
+
+/**
+ * livuv definitions
+ */
+
+
+enum uv_err_code_e {
+ UV_UNKNOWN = -1,
+ UV_OK = 0,
+ UV_EOF,
+ UV_EADDRINFO,
+ UV_EACCES,
+ UV_EAGAIN,
+ UV_EADDRINUSE,
+ UV_EADDRNOTAVAIL,
+ UV_EAFNOSUPPORT,
+ UV_EALREADY,
+ UV_EBADF,
+ UV_EBUSY,
+ UV_ECONNABORTED,
+ UV_ECONNREFUSED,
+ UV_ECONNRESET,
+ UV_EDESTADDRREQ,
+ UV_EFAULT,
+ UV_EHOSTUNREACH,
+ UV_EINTR,
+ UV_EINVAL,
+ UV_EISCONN,
+ UV_EMFILE,
+ UV_EMSGSIZE,
+ UV_ENETDOWN,
+ UV_ENETUNREACH,
+ UV_ENFILE,
+ UV_ENOBUFS,
+ UV_ENOMEM,
+ UV_ENOTDIR,
+ UV_EISDIR,
+ UV_ENONET,
+ UV_ENOTCONN,
+ UV_ENOTSOCK,
+ UV_ENOTSUP,
+ UV_ENOENT,
+ UV_ENOSYS,
+ UV_EPIPE,
+ UV_EPROTO,
+ UV_EPROTONOSUPPORT,
+ UV_EPROTOTYPE,
+ UV_ETIMEDOUT,
+ UV_ECHARSET,
+ UV_EAIFAMNOSUPPORT,
+ UV_EAISERVICE,
+ UV_EAISOCKTYPE,
+ UV_ESHUTDOWN,
+ UV_EEXIST,
+ UV_ESRCH,
+ UV_ENAMETOOLONG,
+ UV_EPERM,
+ UV_ELOOP,
+ UV_EXDEV,
+ UV_ENOTEMPTY,
+ UV_ENOSPC,
+ UV_EIO,
+ UV_EROFS,
+ UV_ENODEV,
+ UV_ESPIPE,
+ UV_ECANCELED,
+ ...
+};
+
+typedef enum uv_err_code_e uv_err_code;
+
+typedef enum {
+ UV_RUN_DEFAULT = 0,
+ UV_RUN_ONCE,
+ UV_RUN_NOWAIT
+} uv_run_mode;
+
+
+enum uv_handle_type_e {
+ ...
+};
+
+typedef enum uv_handle_type_e uv_handle_type;
+
+typedef ... uv_req_type;
+typedef ... uv_os_sock_t;
+typedef ... uv_file;
+typedef ... uv_mutex_t;
+typedef ... uv_rwlock_t;
+typedef ... uv_sem_t;
+typedef ... uv_cond_t;
+typedef ... uv_barrier_t;
+typedef ... uv_thread_t;
+typedef ... uv_once_t;
+typedef ... uv_statbuf_t;
+typedef ... uv_fs_type;
+typedef ... uv_membership;
+
+typedef struct
+{
+ char * base;
+ size_t len;
+} uv_buf_t;
+
+
+struct uv_err_s {
+ uv_err_code code;
+ ...;
+};
+
+struct uv_loop_s {
+ unsigned int active_handles;
+ struct uv_err_s last_err;
+ ...;
+};
+
+
+struct uv_req_s {
+ void* data;
+ ...;
+};
+
+struct uv_shutdown_s {
+ void* data;
+ struct uv_stream_s* handle;
+ ...;
+};
+
+struct uv_handle_s {
+ void* data;
+ struct uv_loop_s* loop;
+ ...;
+};
+
+struct uv_stream_s {
+ size_t write_queue_size;
+ ...;
+};
+
+struct uv_write_s {
+ void* data;
+ ...;
+};
+
+struct uv_tcp_s {
+ ...;
+};
+
+struct uv_connect_s {
+ void* data;
+ struct uv_stream_s* handle;
+ ...;
+};
+
+struct uv_udp_s {
+ ...;
+};
+
+struct uv_udp_send_s {
+ void* data;
+ struct uv_udp_s* handle;
+ ...;
+};
+
+struct uv_tty_s {
+ ...;
+};
+
+struct uv_pipe_s {
+ ...;
+};
+
+struct uv_poll_s {
+ ...;
+};
+
+struct uv_prepare_s {
+ ...;
+};
+
+struct uv_check_s {
+ ...;
+};
+
+struct uv_idle_s {
+ ...;
+};
+
+struct uv_async_s {
+ ...;
+};
+
+struct uv_timer_s {
+ ...;
+};
+
+struct uv_getaddrinfo_s {
+ void* data;
+ struct uv_loop_s* loop;
+ ...;
+};
+
+
+struct uv_stdio_container_s {
+ ...;
+};
+
+struct uv_process_options_s {
+ ...;
+};
+
+struct uv_process_s {
+ ...;
+};
+
+struct uv_work_s {
+ void* data;
+ struct uv_loop_s* loop;
+ ...;
+};
+
+struct uv_cpu_info_s {
+ char* model;
+ int speed;
+ struct uv_cpu_times_s {
+ uint64_t user;
+ uint64_t nice;
+ uint64_t sys;
+ uint64_t idle;
+ uint64_t irq;
+ } cpu_times;
+};
+
+struct uv_interface_address_s {
+ char* name;
+ int is_internal;
+ ...;
+};
+
+struct uv_fs_s {
+ void* data;
+ struct uv_loop_s* loop;
+ ssize_t result;
+ void* ptr;
+ const char* path;
+ ...;
+};
+
+struct uv_fs_event_s {
+ char* filename;
+ ...;
+};
+
+struct uv_fs_poll_s {
+ ...;
+};
+
+struct uv_signal_s {
+ ...;
+};
+
+
+enum uv_fs_event {
+ ...
+};
+
+enum uv_fs_event_flags {
+ ...
+};
+
+enum uv_poll_event {
+ UV_READABLE,
+ UV_WRITABLE,
+ ...
+};
+
+enum uv_udp_flags {
+ ...
+};
+
+typedef ... uv_stdio_flags;
+
+enum uv_process_flags {
+ ...
+};
+
+
+typedef struct uv_loop_s uv_loop_t;
+typedef struct uv_err_s uv_err_t;
+typedef struct uv_handle_s uv_handle_t;
+typedef struct uv_stream_s uv_stream_t;
+typedef struct uv_tcp_s uv_tcp_t;
+typedef struct uv_udp_s uv_udp_t;
+typedef struct uv_pipe_s uv_pipe_t;
+typedef struct uv_tty_s uv_tty_t;
+typedef struct uv_poll_s uv_poll_t;
+typedef struct uv_timer_s uv_timer_t;
+typedef struct uv_prepare_s uv_prepare_t;
+typedef struct uv_check_s uv_check_t;
+typedef struct uv_idle_s uv_idle_t;
+typedef struct uv_async_s uv_async_t;
+typedef struct uv_process_s uv_process_t;
+typedef struct uv_fs_event_s uv_fs_event_t;
+typedef struct uv_fs_poll_s uv_fs_poll_t;
+typedef struct uv_signal_s uv_signal_t;
+
+typedef struct uv_req_s uv_req_t;
+typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
+typedef struct uv_shutdown_s uv_shutdown_t;
+typedef struct uv_write_s uv_write_t;
+typedef struct uv_connect_s uv_connect_t;
+typedef struct uv_udp_send_s uv_udp_send_t;
+typedef struct uv_fs_s uv_fs_t;
+typedef struct uv_work_s uv_work_t;
+
+typedef struct uv_stdio_container_s uv_stdio_container_t;
+typedef struct uv_process_options_s uv_process_options_t;
+
+typedef struct uv_cpu_info_s uv_cpu_info_t;
+typedef struct uv_interface_address_s uv_interface_address_t;
+
+
+/***************************************************************************************************
+ * uv function
+ **************************************************************************************************/
+
+uv_loop_t* uv_loop_new(void);
+void uv_loop_delete(uv_loop_t*);
+uv_loop_t* uv_default_loop(void);
+int uv_run(uv_loop_t*, uv_run_mode mode);
+void uv_ref(uv_handle_t*);
+void uv_unref(uv_handle_t*);
+
+void uv_update_time(uv_loop_t*);
+int64_t uv_now(uv_loop_t*);
+
+typedef uv_buf_t (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size);
+typedef void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, uv_buf_t buf);
+typedef void (*uv_read2_cb)(uv_pipe_t* pipe, ssize_t nread, uv_buf_t buf, uv_handle_type pending);
+typedef void (*uv_write_cb)(uv_write_t* req, int status);
+typedef void (*uv_connect_cb)(uv_connect_t* req, int status);
+typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status);
+typedef void (*uv_connection_cb)(uv_stream_t* server, int status);
+typedef void (*uv_close_cb)(uv_handle_t* handle);
+typedef void (*uv_poll_cb)(uv_poll_t* handle, int status, int events);
+typedef void (*uv_timer_cb)(uv_timer_t* handle, int status);
+typedef void (*uv_async_cb)(uv_async_t* handle, int status);
+typedef void (*uv_prepare_cb)(uv_prepare_t* handle, int status);
+typedef void (*uv_check_cb)(uv_check_t* handle, int status);
+typedef void (*uv_idle_cb)(uv_idle_t* handle, int status);
+typedef void (*uv_exit_cb)(uv_process_t*, int exit_status, int term_signal);
+typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg);
+typedef void (*uv_fs_cb)(uv_fs_t* req);
+typedef void (*uv_work_cb)(uv_work_t* req);
+typedef void (*uv_after_work_cb)(uv_work_t* req);
+typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req, int status, struct addrinfo* res);
+typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle, const char* filename, int events, int status);
+typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle, int status, const uv_statbuf_t* prev, const uv_statbuf_t* curr);
+
+typedef void (*uv_signal_cb)(uv_signal_t* handle, int signum);
+
+uv_err_t uv_last_error(uv_loop_t*);
+const char* uv_strerror(uv_err_t err);
+const char* uv_err_name(uv_err_t err);
+
+int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb);
+
+size_t uv_handle_size(uv_handle_type type);
+size_t uv_req_size(uv_req_type type);
+int uv_is_active(const uv_handle_t* handle);
+void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg);
+void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
+
+uv_buf_t uv_buf_init(char* base, unsigned int len);
+size_t uv_strlcpy(char* dst, const char* src, size_t size);
+size_t uv_strlcat(char* dst, const char* src, size_t size);
+
+int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
+int uv_accept(uv_stream_t* server, uv_stream_t* client);
+int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb);
+
+int uv_read_stop(uv_stream_t*);
+int uv_read2_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read2_cb read_cb);
+int uv_write(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt, uv_write_cb cb);
+int uv_write2(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt, uv_stream_t* send_handle, uv_write_cb cb);
+
+int uv_is_readable(const uv_stream_t* handle);
+int uv_is_writable(const uv_stream_t* handle);
+int uv_is_closing(const uv_handle_t* handle);
+
+int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle);
+int uv_tcp_open(uv_tcp_t* handle, int sock);
+int uv_tcp_nodelay(uv_tcp_t* handle, int enable);
+int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay);
+int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);
+int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in);
+int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6);
+int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen);
+int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, int* namelen);
+int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr_in address, uv_connect_cb cb);
+int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr_in6 address, uv_connect_cb cb);
+
+typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);
+typedef void (*uv_udp_recv_cb)(uv_udp_t* handle, ssize_t nread, uv_buf_t buf, struct sockaddr* addr, unsigned flags);
+
+int uv_udp_init(uv_loop_t*, uv_udp_t* handle);
+int uv_udp_open(uv_udp_t* handle, int sock);
+int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned flags);
+int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned flags);
+int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen);
+int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, const char* interface_addr, uv_membership membership);
+int uv_udp_set_multicast_loop(uv_udp_t* handle, int on);
+int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl);
+int uv_udp_set_broadcast(uv_udp_t* handle, int on);
+int uv_udp_set_ttl(uv_udp_t* handle, int ttl);
+int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], int bufcnt, struct sockaddr_in addr, uv_udp_send_cb send_cb);
+int uv_udp_send6(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], int bufcnt, struct sockaddr_in6 addr, uv_udp_send_cb send_cb);
+int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, uv_udp_recv_cb recv_cb);
+int uv_udp_recv_stop(uv_udp_t* handle);
+
+int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable);
+int uv_tty_set_mode(uv_tty_t*, int mode);
+void uv_tty_reset_mode(void);
+int uv_tty_get_winsize(uv_tty_t*, int* width, int* height);
+
+uv_handle_type uv_guess_handle(uv_file file);
+
+int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc);
+int uv_pipe_open(uv_pipe_t*, uv_file file);
+int uv_pipe_bind(uv_pipe_t* handle, const char* name);
+void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb);
+void uv_pipe_pending_instances(uv_pipe_t* handle, int count);
+
+int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd);
+int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, uv_os_sock_t socket);
+int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb);
+int uv_poll_stop(uv_poll_t* handle);
+
+int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare);
+int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb);
+int uv_prepare_stop(uv_prepare_t* prepare);
+
+//int uv_check_init(uv_loop_t*, uv_check_t* check);
+//int uv_check_start(uv_check_t* check, uv_check_cb cb);
+//int uv_check_stop(uv_check_t* check);
+
+int uv_idle_init(uv_loop_t*, uv_idle_t* idle);
+int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb);
+int uv_idle_stop(uv_idle_t* idle);
+
+int uv_timer_init(uv_loop_t*, uv_timer_t* timer);
+int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb, int64_t timeout, int64_t repeat);
+int uv_timer_stop(uv_timer_t* timer);
+int uv_timer_again(uv_timer_t* timer);
+void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat);
+int64_t uv_timer_get_repeat(uv_timer_t* timer);
+
+int uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* req, uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service, const struct addrinfo* hints);
+void uv_freeaddrinfo(struct addrinfo* ai);
+
+int uv_spawn(uv_loop_t*, uv_process_t*, uv_process_options_t options);
+int uv_process_kill(uv_process_t*, int signum);
+uv_err_t uv_kill(int pid, int signum);
+int uv_queue_work(uv_loop_t* loop, uv_work_t* req, uv_work_cb work_cb, uv_after_work_cb after_work_cb);
+
+char** uv_setup_args(int argc, char** argv);
+uv_err_t uv_get_process_title(char* buffer, size_t size);
+uv_err_t uv_set_process_title(const char* title);
+uv_err_t uv_resident_set_memory(size_t* rss);
+uv_err_t uv_uptime(double* uptime);
+
+uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
+void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
+
+uv_err_t uv_interface_addresses(uv_interface_address_t** addresses, int* count);
+void uv_free_interface_addresses(uv_interface_address_t* addresses, int count);
+
+#define UV_FS_SYMLINK_DIR ...
+#define UV_FS_SYMLINK_JUNCTION ...
+
+void uv_fs_req_cleanup(uv_fs_t* req);
+int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
+int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
+int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
+int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb);
+int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
+int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
+int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int64_t offset, uv_fs_cb cb);
+int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb);
+int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
+int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb);
+int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb);
+int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
+int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb);
+int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, const char* filename, uv_fs_event_cb cb, int flags);
+int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb);
+int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
+int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb);
+int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, int uid, int gid, uv_fs_cb cb);
+int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, int uid, int gid, uv_fs_cb cb);
+
+int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle);
+int uv_fs_poll_start(uv_fs_poll_t* handle, uv_fs_poll_cb poll_cb, const char* path, unsigned int interval);
+int uv_fs_poll_stop(uv_fs_poll_t* handle);
+
+int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle);
+int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum);
+int uv_signal_stop(uv_signal_t* handle);
+
+struct sockaddr_in uv_ip4_addr(const char* ip, int port);
+struct sockaddr_in6 uv_ip6_addr(const char* ip, int port);
+
+int uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size);
+int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size);
+
+uv_err_t uv_inet_ntop(int af, const void* src, char* dst, size_t size);
+uv_err_t uv_inet_pton(int af, const char* src, void* dst);
+
+int uv_exepath(char* buffer, size_t* size);
+
+uint64_t uv_get_free_memory(void);
+uint64_t uv_get_total_memory(void);
+
+uint64_t uv_hrtime(void);
+
+void uv_once(uv_once_t* guard, void *callback);
+
+int uv_thread_create(uv_thread_t *tid, void *entry, void *arg);
+unsigned long uv_thread_self(void);
+int uv_thread_join(uv_thread_t *tid);
+
+
+
+/***************************************************************************************************
+ * Custom functions, defined in the '_extra' file
+ **************************************************************************************************/
+
+int guess_ip_family(char *ip);
View
24 pyuv/ffi/_ffi_extra.c
@@ -0,0 +1,24 @@
+#include <uv.h>
+
+
+
+/* guess IP address family */
+int
+guess_ip_family(char *ip)
+{
+ struct in_addr addr4;
+ struct in6_addr addr6;
+ uv_err_t err;
+
+ err = uv_inet_pton(AF_INET, ip, &addr4);
+ if (err.code == UV_OK) {
+ return AF_INET;
+ } else {
+ err = uv_inet_pton(AF_INET6, ip, &addr6);
+ if (err.code == UV_OK) {
+ return AF_INET6;
+ }
+ }
+ return -1;
+}
+
View
95 pyuv/loop.py
@@ -0,0 +1,95 @@
+#
+# python-uv
+#
+# Unless otherwise noted, the files in python-uv are under the following MIT license:
+#
+# Copyright (c) 2013, Alvaro Saurin
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+
+from pyuv.ffi import C, ffi
+
+
+
+
+UV_RUN_DEFAULT = C.UV_RUN_DEFAULT
+UV_RUN_ONCE = C.UV_RUN_ONCE
+UV_RUN_NOWAIT = C.UV_RUN_NOWAIT
+
+
+
+_default_loop = None
+
+
+class Loop(object):
+
+ __slots__ = ['ptr']
+
+ def __init__(self, default = False):
+ global _default_loop
+ if default:
+ self.ptr = C.uv_default_loop()
+ else:
+ self.ptr = C.uv_loop_new()
+
+ if not self.ptr:
+ raise SystemError("uv_default_loop() failed")
+
+
+ @classmethod
+ def default_loop(cls):
+ global _default_loop
+ if not _default_loop:
+ _default_loop = Loop(default = True)
+ return _default_loop
+
+
+ def run(self, mode = UV_RUN_DEFAULT):
+ """
+ Run the loop
+ """
+ assert mode in [UV_RUN_DEFAULT, UV_RUN_ONCE, UV_RUN_NOWAIT]
+
+ C.uv_run(self.ptr, mode)
+
+ def update_time(self):
+ r = C.uv_update_time(self.ptr);
+ if r != 0:
+ last_err_code = C.uv_last_error(self.ptr)
+ desc = ffi.string(C.uv_strerror(last_err_code))
+ raise RuntimeError(desc)
+
+ def walk(self, callback):
+
+ @ffi.callback('uv_walk_cb')
+ def on_walk(handle, arg):
+ callback(self)
+
+ C.uv_walk(self.ptr, on_walk, None);
+
+ @property
+ def active_handles(self):
+ return self.ptr.active_handles
+
+ @property
+ def counters(self):
+ return 0
+
View
77 pyuv/prepare.py
@@ -0,0 +1,77 @@
+#
+# python-uv
+#
+# Unless otherwise noted, the files in python-uv are under the following MIT license:
+#
+# Copyright (c) 2013, Alvaro Saurin
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+
+from pyuv.ffi import C, ffi
+
+from watcher import Watcher
+
+
+class Prepare(Watcher):
+ """
+ Prepare handles are usually used together with Check handles. They run just before the event
+ loop ia about to block for I/O. The callback will be called once each loop iteration, before I/O.
+ """
+
+ __slots__ = ['loop', 'prepare_handle']
+
+ def __init__(self, loop):
+ self.loop = loop
+
+ self.prepare_handle = ffi.new('uv_prepare_t*')
+ r = C.uv_prepare_init(self.loop.ptr, self.prepare_handle)
+ if r != 0:
+ raise RuntimeError()
+
+
+ @property
+ def handle(self):
+ return ffi.cast('uv_handle_t*', self.prepare_handle)
+
+ def start(self, callback):
+ """
+ Start the Prepare handle.
+ """
+ assert not self.active
+
+ @ffi.callback('uv_prepare_cb')
+ def on_prepare(prepare_handle, status):
+ if prepare_handle == self.prepare_handle:
+ if callback:
+ callback(self)
+
+ r = C.uv_prepare_start(self.prepare_handle, on_prepare)
+ if r != 0:
+ raise RuntimeError()
+
+ def stop(self):
+ """
+ Stop the Prepare handle.
+ """
+ r = C.uv_prepare_stop(self.prepare_handle);
+ if r != 0:
+ raise RuntimeError()
+
View
99 pyuv/stream.py
@@ -0,0 +1,99 @@
+#
+# python-uv
+#
+# Unless otherwise noted, the files in python-uv are under the following MIT license:
+#
+# Copyright (c) 2013, Alvaro Saurin
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+
+from pyuv.ffi import C, ffi
+
+from buffer import Buffer
+from watcher import Watcher
+
+
+class Stream(Watcher):
+
+ @property
+ def stream_handle(self):
+ assert hasattr(self, 'handle')
+ return ffi.cast('uv_stream_t*', self.handle)
+
+
+ def start_recv(self, callback):
+
+ @ffi.callback("uv_alloc_cb")
+ def on_stream_alloc(handle, suggested_size):
+ self.read_buffer = Buffer(length = suggested_size)
+ return self.read_buffer.as_struct()
+
+ @ffi.callback("uv_read_cb")
+ def on_stream_read(stream_handle, nread, buf):
+ data = buf.base[:nread]
+ error = None
+ callback(stream_handle, data, error)
+
+ r = C.uv_read_start(self.stream_handle, on_stream_alloc, on_stream_read)
+ if r != 0:
+ raise RuntimeError()
+
+ def stop_recv(self):
+ r = C.uv_read_stop(self.stream_handle)
+ if r != 0:
+ raise Exception()
+
+
+
+ def write(self, data, callback):
+ self.write_req = ffi.new('uv_write_t*')
+ self.write_buffers = ffi.new('uv_buf_t[1]', [Buffer(data = data)])
+
+ @ffi.callback("uv_write_cb")
+ def on_write_done(_req, status):
+ if _req == self.write_req:
+ error = status
+ callback(self, error)
+
+ return C.uv_write(self.write_req, self.stream_handle, self.write_buffers, 1, on_write_done)
+
+
+ def writelines(self, seq, callback):
+ self.write_len = len(seq)
+ self.write_req = ffi.new('uv_write_t*')
+ self.write_buffers = ffi.new('uv_buf_t[%d]' % self.write_len,
+ [Buffer(data = x) for x in seq])
+
+ @ffi.callback("uv_write_cb")
+ def on_write_done(_req, status):
+ if _req == self.write_req:
+ error = status
+ callback(self, error)
+
+ return C.uv_write(self.write_req, self.stream_handle, self.write_buffers, self.write_len, on_write_done)
+
+ @property
+ def readable(self):
+ return bool(C.uv_is_readable(self.stream_handle))
+
+ @property
+ def writable(self):
+ return bool(C.uv_is_writable(self.stream_handle))
View
129 pyuv/tcp.py
@@ -0,0 +1,129 @@
+#
+# python-uv
+#
+# Unless otherwise noted, the files in python-uv are under the following MIT license:
+#
+# Copyright (c) 2013, Alvaro Saurin
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+
+from pyuv.ffi import C, ffi
+
+
+from stream import Stream
+from errors import last_socket_error
+
+
+
+class TCP(Stream):
+
+ def __init__(self, loop):
+ self.loop = loop
+
+ self.tcp_handle = ffi.new('uv_tcp_t*')
+ r = C.uv_tcp_init(self.loop.ptr, self.tcp_handle)
+ if r != 0:
+ raise RuntimeError()
+
+ @property
+ def handle(self):
+ return ffi.cast('uv_handle_t*', self.tcp_handle)
+
+ @property
+ def stream_handle(self):
+ return ffi.cast('uv_stream_t*', self.tcp_handle)
+
+
+
+ def bind(self, addr):
+ """
+ Bind to the specified IP address and port.
+ """
+ (ip, port) = addr
+
+ if port < 0 or port > 65535:
+ raise ValueError("port must be between 0 and 65535")
+
+ address_type = C.guess_ip_family(ip)
+ if address_type == C.AF_INET:
+ r = C.uv_tcp_bind(self.tcp_handle, C.uv_ip4_addr(ip, port));
+ else:
+ r = C.uv_tcp_bind6(self.tcp_handle, C.uv_ip6_addr(ip, port));
+
+
+ def listen(self, callback, backlog):
+ """
+ Start listening for new connections.
+ """
+ @ffi.callback("uv_connection_cb")
+ def on_accept(stream_handle, status):
+ callback(stream_handle, status)
+
+ C.uv_listen(self.stream_handle, backlog, on_accept)
+
+ def accept(self, client):
+ r = C.uv_accept(self.stream_handle, client.stream_handle)
+ if r != 0:
+ raise RuntimeError()
+
+ def connect(self, addr, callback):
+ (ip, port) = addr
+ self.connect_req = ffi.new('uv_connect_t*')
+
+ @ffi.callback('uv_connect_cb')
+ def on_connect(_req, status):
+ if _req == self.connect_req:
+ error = status
+ callback(self, error)
+
+ address_type = C.guess_ip_family(ip)
+ if address_type == C.AF_INET:
+ addr = C.uv_ip4_addr(ip, port)
+ r = C.uv_tcp_connect(self.connect_req, self.tcp_handle, addr, on_connect);
+ else:
+ addr = C.uv_ip6_addr(ip, port)
+ r = C.uv_tcp_connect6(self.connect_req, self.tcp_handle, addr, on_connect);
+
+
+ def getsockname(self):
+ pass
+
+ def getpeername(self):
+ pass
+
+
+ def nodelay(self, enable):
+ val = 1 if enable else 0
+ r = C.uv_tcp_nodelay(self.tcp_handle, val);
+ if r != 0:
+ raise RuntimeError()
+
+ def keepalive(self, enable, delay):
+ val = 1 if enable else 0
+ r = C.uv_tcp_keepalive(self.tcp_handle, val, delay);
+ if r != 0:
+ raise RuntimeError()
+
+ def simultaneous_accepts(self, enable):
+ val = 1 if enable else 0
+ r = C.uv_tcp_simultaneous_accepts(self.tcp_handle, val);
+ if r != 0:
+ raise RuntimeError()
View
77 pyuv/timer.py
@@ -0,0 +1,77 @@
+#
+# python-uv
+#
+# Unless otherwise noted, the files in python-uv are under the following MIT license:
+#
+# Copyright (c) 2013, Alvaro Saurin
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+
+from pyuv.ffi import C, ffi
+
+from watcher import Watcher
+
+
+class Timer(Watcher):
+
+ __slots__ = ['loop', 'timer_handle']
+
+ def __init__(self, loop):
+ self.loop = loop
+ self.timer_handle = ffi.new('uv_timer_t*')
+
+ r = C.uv_timer_init(self.loop.ptr, self.timer_handle)
+ if r != 0:
+ raise RuntimeError()
+
+ @property
+ def handle(self):
+ return ffi.cast('uv_handle_t*', self.timer_handle)
+
+ def start(self, callback, timeout, repeat):
+ @ffi.callback('uv_timer_cb')
+ def on_timer(timer_handle, status):
+ if callback:
+ callback(self)
+
+ timeout = ffi.cast("int64_t", timeout * 1000)
+ repeat = ffi.cast("int64_t", repeat * 1000)
+
+ r = C.uv_timer_start(self.timer_handle, on_timer, timeout, repeat)
+ if r != 0:
+ raise RuntimeError()
+
+ def stop(self):
+ r = C.uv_timer_stop(self.timer_handle)
+ if r != 0:
+ raise RuntimeError()
+
+ def again(self):
+ r = C.uv_timer_again(self.timer_handle)
+ if r != 0:
+ raise RuntimeError()
+
+ def _get_repeat(self): return C.uv_timer_get_repeat(self.timer_handle)
+ def _set_repeat(self, val): C.uv_timer_set_repeat(self.timer_handle, int(val * 1000));
+ repeat = property(_get_repeat, _set_repeat)
+
+
+
View
126 pyuv/udp.py
@@ -0,0 +1,126 @@
+#
+# python-uv
+#
+# Unless otherwise noted, the files in python-uv are under the following MIT license:
+#
+# Copyright (c) 2013, Alvaro Saurin
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+
+from pyuv.ffi import C, ffi
+
+
+from stream import Stream
+from buffer import Buffer
+
+
+class UDP(Stream):
+
+ def __init__(self, loop):
+ self.loop = loop
+
+ self.udp_handle = ffi.new('uv_udp_t*')
+ r = C.uv_udp_init(self.loop.ptr, self.udp_handle)
+ if r != 0:
+ raise RuntimeError()
+
+ @property
+ def handle(self):
+ return ffi.cast('uv_handle_t*', self.udp_handle)
+
+ @property
+ def stream_handle(self):
+ return ffi.cast('uv_stream_t*', self.udp_handle)
+
+
+
+
+ def bind(self, addr):
+ """
+ Bind to the specified IP address and port.
+ """
+ (ip, port) = addr
+ flags = 0
+
+ if port < 0 or port > 65535:
+ raise ValueError("port must be between 0 and 65535")
+
+ address_type = C.guess_ip_family(ip)
+ if address_type == C.AF_INET:
+ r = C.uv_udp_bind(self.udp_handle, C.uv_ip4_addr(ip, port), flags);
+ else:
+ r = C.uv_udp_bind6(self.udp_handle, C.uv_ip6_addr(ip, port), flags);
+
+
+
+ def getsockname(self):
+ pass
+
+
+ def send(self, addr, data, callback = None):
+ (ip, port) = addr
+
+ def sendlines(self, addr, seq, callback = None):
+ (ip, port) = addr
+
+ def start_recv(self, callback):
+
+ @ffi.callback("uv_alloc_cb")
+ def on_stream_alloc(handle, suggested_size):
+ self.read_buffer = Buffer(length = suggested_size)
+ return self.read_buffer.as_struct()
+
+ @ffi.callback("uv_udp_recv_cb")
+ def on_udp_read(udp_handle, nread, buf, addr, flags):
+ # struct sockaddr* addr
+ data = buf.base[:nread]
+ error = None
+ ip, port = None, None # TODO
+ if callback:
+ callback(udp_handle, (ip, port), data, error)
+
+ r = C.uv_udp_recv_start(self.udp_handle, on_stream_alloc, on_udp_read)
+ if r != 0:
+ raise RuntimeError()
+
+
+ def stop_recv(self):
+ r = C.uv_udp_recv_stop(self.stream_handle)
+ if r != 0:
+ raise Exception()
+
+ def set_membership(self, multicast_address, membership, interface):
+ raise NotImplementedError()
+ #r = C.uv_udp_set_membership(self.udp_handle, const char* multicast_addr, const char* interface_addr, uv_membership membership);
+
+ def set_multicast_ttl(self, ttl):
+ raise NotImplementedError()
+
+ def set_multicast_loop(self, enable):
+ raise NotImplementedError()
+
+ def set_broadcast(self, enable):
+ raise NotImplementedError()
+
+ def set_ttl(self, ttl):
+ raise NotImplementedError()
+
+
View
62 pyuv/watcher.py
@@ -0,0 +1,62 @@
+#
+# python-uv
+#
+# Unless otherwise noted, the files in python-uv are under the following MIT license:
+#
+# Copyright (c) 2013, Alvaro Saurin
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+
+from pyuv.ffi import C, ffi
+
+class Watcher(object):
+
+ __slots__ = []
+
+ @property
+ def handle(self):
+ raise NotImplementedError('must be implemented by subclasses')
+
+ def close(self, callback = None):
+
+ @ffi.callback('uv_close_cb')
+ def on_closed():
+ if callback:
+ callback()
+
+ C.uv_close(self.handle, on_closed)
+
+ @property
+ def active(self):
+ return bool(C.uv_is_active(self.handle))
+
+ @property
+ def closed(self):
+ return bool(C.uv_is_closing(self.handle))
+
+
+ def ref(self):
+ C.uv_ref(self.handle)
+
+ def unref(self):
+ C.uv_unref(self.handle)
+
+
View
52 setup.py
@@ -1,20 +1,44 @@
# coding=utf8
+import platform
+
from distutils.core import setup, Extension
-from setup_libuv import libuv_build_ext, libuv_sdist
__version__ = "0.10.0.dev"
-setup(name = "pyuv",
- version = __version__,
- author = "Saúl Ibarra Corretgé",
- author_email = "saghul@gmail.com",
- url = "http://github.com/saghul/pyuv",
- description = "Python interface for libuv",
+if platform.python_implementation() == 'PyPy':
+ from setup_libuv import get_cffi_extension
+ args = {
+ 'ext_package': 'pyuv.ffi',
+ 'ext_modules': get_cffi_extension(),
+ 'zip_safe': False
+ }
+else:
+ from setup_libuv import libuv_build_ext, libuv_sdist, LIBUV_REVISION
+ args = {
+ 'cmdclass': {
+ 'build_ext': libuv_build_ext,
+ 'sdist': libuv_sdist
+ },
+ 'ext_modules': [
+ Extension('pyuv',
+ sources = ['src/pyuv.c'],
+ define_macros = [('MODULE_VERSION', __version__),
+ ('LIBUV_REVISION', LIBUV_REVISION)]
+ )]
+
+ }
+
+setup(name = "pyuv",
+ version = __version__,
+ author = "Saúl Ibarra Corretgé",
+ author_email = "saghul@gmail.com",
+ url = "http://github.com/saghul/pyuv",
+ description = "Python interface for libuv",
long_description = open("README.rst").read(),
- platforms = ["POSIX", "Microsoft Windows"],
- classifiers = [
+ platforms = ["POSIX", "Microsoft Windows"],
+ classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
@@ -30,12 +54,6 @@
"Programming Language :: Python :: 3.2"
"Programming Language :: Python :: 3.3"
],
- cmdclass = {'build_ext': libuv_build_ext,
- 'sdist' : libuv_sdist},
- ext_modules = [Extension('pyuv',
- sources = ['src/pyuv.c'],
- define_macros=[('MODULE_VERSION', __version__),
- ('LIBUV_REVISION', libuv_build_ext.libuv_revision)]
- )]
- )
+ **args
+)
View
181 setup_libuv.py
@@ -13,6 +13,16 @@
from distutils.errors import DistutilsError
+
+LIBUV_DIR = os.path.join('deps', 'libuv')
+LIBUV_REPO = 'https://github.com/joyent/libuv.git'
+LIBUV_BRANCH = 'master'
+LIBUV_REVISION = '0ad46bd'
+LIBUV_PATCHES = []
+
+
+
+
def makedirs(path):
try:
os.makedirs(path)
@@ -28,7 +38,7 @@ def rmtree(path):
if e.errno != errno.ENOENT:
raise
-def exec_process(cmdline, silent=True, input=None, **kwargs):
+def exec_process(cmdline, silent = True, input = None, **kwargs):
"""Execute a subprocess and returns the returncode, stdout buffer and stderr buffer.
Optionally prints stdout and stderr while running."""
try:
@@ -87,12 +97,73 @@ def _set_python_executable(env):
'installation location.')
+
+def _libuv_artifact(win32_msvc):
+ if win32_msvc:
+ return os.path.join(LIBUV_DIR, 'Release', 'lib', 'libuv.lib')
+ else:
+ return os.path.join(LIBUV_DIR, 'libuv.a')
+
+def _patch_libuv():
+ if LIBUV_PATCHES:
+ log.info('Patching libuv...')
+ for patch_file in LIBUV_PATCHES:
+ exec_process(['patch', '--forward', '-d', LIBUV_DIR, '-p0', '-i', os.path.abspath(patch_file)])
+
+def _download_libuv():
+ log.info('Downloading libuv...')
+ makedirs(LIBUV_DIR)
+ exec_process(['git', 'clone', '-b', LIBUV_BRANCH, LIBUV_REPO, LIBUV_DIR])
+ exec_process(['git', 'checkout', LIBUV_REVISION], cwd = LIBUV_DIR)
+
+
+def _get_libuv(win32_msvc, clean_compile = False, force_fetch = False):
+
+ #self.debug_mode = bool(self.debug) or hasattr(sys, 'gettotalrefcount')
+
+ def _build_libuv():
+ cflags = '-fPIC'
+ env = os.environ.copy()
+ env['CFLAGS'] = ' '.join(x for x in (cflags, env.get('CFLAGS', None)) if x)
+ log.info('Building libuv...')
+ if win32_msvc:
+ if sys.version_info < (3, 3):
+ env.pop('VS100COMNTOOLS', None)
+ _set_python_executable(env)
+ libuv_arch = {'32bit': 'x86', '64bit': 'x64'}[platform.architecture()[0]]
+ exec_process(['cmd.exe', '/C', 'vcbuild.bat', libuv_arch, 'release'], cwd = LIBUV_DIR, env = env, shell = True)
+ else:
+ exec_process(['make', 'libuv.a'], cwd = LIBUV_DIR, env=env)
+
+ if force_fetch:
+ rmtree('deps')
+
+ if not os.path.exists(LIBUV_DIR):
+ try:
+ _download_libuv()
+ except BaseException:
+ rmtree('deps')
+ raise
+ _patch_libuv()
+ _build_libuv()
+ else:
+ if clean_compile:
+ if win32_msvc:
+ exec_process(['cmd.exe', '/C', 'vcbuild.bat', 'clean'], cwd = LIBUV_DIR, shell = True)
+ rmtree(os.path.join(LIBUV_DIR, 'Release'))
+ else:
+ exec_process(['make', 'clean'], cwd = LIBUV_DIR)
+
+ if not os.path.exists(_libuv_artifact(win32_msvc)):
+ log.info('libuv needs to be compiled.')
+ _build_libuv()
+ else:
+ log.info('No need to build libuv.')
+
+
+
+
class libuv_build_ext(build_ext):
- libuv_dir = os.path.join('deps', 'libuv')
- libuv_repo = 'https://github.com/joyent/libuv.git'
- libuv_branch = 'master'
- libuv_revision = '0ad46bd'
- libuv_patches = []
user_options = build_ext.user_options
user_options.extend([
@@ -112,19 +183,19 @@ def build_extensions(self):
# Dirty hack to avoid linking with more than one C runtime when using MinGW
# Note that this hack forces the compilation to use the old MSVCT
self.compiler.dll_libraries = [lib for lib in self.compiler.dll_libraries if not lib.startswith('msvcr')]
+
self.force = self.libuv_force_fetch or self.libuv_clean_compile
- if self.compiler.compiler_type == 'msvc':
- self.libuv_lib = os.path.join(self.libuv_dir, 'Release', 'lib', 'libuv.lib')
- else:
- self.libuv_lib = os.path.join(self.libuv_dir, 'libuv.a')
- self.get_libuv()
+ win32_msvc = self.compiler.compiler_type=='msvc'
+
+ _get_libuv(win32_msvc, self.libuv_clean_compile, self.libuv_force_fetch)
+
# Set compiler options
if self.compiler.compiler_type == 'mingw32':
- self.compiler.add_library_dir(self.libuv_dir)
+ self.compiler.add_library_dir(LIBUV_DIR)
self.compiler.add_library('uv')
else:
- self.extensions[0].extra_objects = [self.libuv_lib]
- self.compiler.add_include_dir(os.path.join(self.libuv_dir, 'include'))
+ self.extensions[0].extra_objects = [_libuv_artifact(win32_msvc)]
+ self.compiler.add_include_dir(os.path.join(LIBUV_DIR, 'include'))
if sys.platform.startswith('linux'):
self.compiler.add_library('rt')
elif sys.platform == 'darwin':
@@ -138,73 +209,31 @@ def build_extensions(self):
self.compiler.add_library('ws2_32')
build_ext.build_extensions(self)
- def get_libuv(self):
- #self.debug_mode = bool(self.debug) or hasattr(sys, 'gettotalrefcount')
- win32_msvc = self.compiler.compiler_type=='msvc'
- def download_libuv():
- log.info('Downloading libuv...')
- makedirs(self.libuv_dir)
- exec_process(['git', 'clone', '-b', self.libuv_branch, self.libuv_repo, self.libuv_dir])
- exec_process(['git', 'checkout', self.libuv_revision], cwd=self.libuv_dir)
- def patch_libuv():
- if self.libuv_patches:
- log.info('Patching libuv...')
- for patch_file in self.libuv_patches:
- exec_process(['patch', '--forward', '-d', self.libuv_dir, '-p0', '-i', os.path.abspath(patch_file)])
- def build_libuv():
- cflags = '-fPIC'
- env = os.environ.copy()
- env['CFLAGS'] = ' '.join(x for x in (cflags, env.get('CFLAGS', None)) if x)
- log.info('Building libuv...')
- if win32_msvc:
- if sys.version_info < (3, 3):
- env.pop('VS100COMNTOOLS', None)
- _set_python_executable(env)
- libuv_arch = {'32bit': 'x86', '64bit': 'x64'}[platform.architecture()[0]]
- exec_process(['cmd.exe', '/C', 'vcbuild.bat', libuv_arch, 'release'], cwd=self.libuv_dir, env=env, shell=True)
- else:
- exec_process(['make', 'libuv.a'], cwd=self.libuv_dir, env=env)
- if self.libuv_force_fetch:
- rmtree('deps')
- if not os.path.exists(self.libuv_dir):
- try:
- download_libuv()
- except BaseException:
- rmtree('deps')
- raise
- patch_libuv()
- build_libuv()
- else:
- if self.libuv_clean_compile:
- if win32_msvc:
- exec_process(['cmd.exe', '/C', 'vcbuild.bat', 'clean'], cwd=self.libuv_dir, shell=True)
- rmtree(os.path.join(self.libuv_dir, 'Release'))
- else:
- exec_process(['make', 'clean'], cwd=self.libuv_dir)
- if not os.path.exists(self.libuv_lib):
- log.info('libuv needs to be compiled.')
- build_libuv()
- else:
- log.info('No need to build libuv.')
+
+
+def get_cffi_extension():
+
+ win32_msvc = False ## TODO: detect if we are using MSVC
+ _get_libuv(win32_msvc, False, False)
+
+ ## just set the CFFI-uv extension
+ from pyuv.ffi import ffi
+ try:
+ return [ffi.verifier.get_extension()]
+ except AttributeError:
+ return []
+
class libuv_sdist(sdist):
- libuv_dir = os.path.join('deps', 'libuv')
- libuv_repo = libuv_build_ext.libuv_repo
- libuv_branch = libuv_build_ext.libuv_branch
- libuv_revision = libuv_build_ext.libuv_revision
- libuv_patches = libuv_build_ext.libuv_patches
def initialize_options(self):
sdist.initialize_options(self)
rmtree('deps')
- makedirs(self.libuv_dir)
- log.info('Downloading libuv...')
- exec_process(['git', 'clone', '-b', self.libuv_branch, self.libuv_repo, self.libuv_dir])
- exec_process(['git', 'checkout', self.libuv_revision], cwd=self.libuv_dir)
- if self.libuv_patches:
- log.info('Patching libuv...')
- for patch_file in self.libuv_patches:
- exec_process(['patch', '--forward', '-d', self.libuv_dir, '-p0', '-i', os.path.abspath(patch_file)])
- rmtree(os.path.join(self.libuv_dir, '.git'))
+
+ _download_libuv()
+ _patch_libuv()
+ rmtree(os.path.join(LIBUV_DIR, '.git'))
+
+
Please sign in to comment.
Something went wrong with that request. Please try again.