[CalendarServer-changes] [14351] twext/trunk/twext/python

source_changes at macosforge.org source_changes at macosforge.org
Thu Jan 29 12:21:25 PST 2015


Revision: 14351
          http://trac.calendarserver.org//changeset/14351
Author:   sagen at apple.com
Date:     2015-01-29 12:21:25 -0800 (Thu, 29 Jan 2015)
Log Message:
-----------
OMG launchd API is down to a single function

Modified Paths:
--------------
    twext/trunk/twext/python/launchd.py
    twext/trunk/twext/python/test/test_launchd.py

Modified: twext/trunk/twext/python/launchd.py
===================================================================
--- twext/trunk/twext/python/launchd.py	2015-01-28 04:11:47 UTC (rev 14350)
+++ twext/trunk/twext/python/launchd.py	2015-01-29 20:21:25 UTC (rev 14351)
@@ -16,20 +16,7 @@
 ##
 
 """
-Bindings for launchd check-in API.
-
- at see: U{SampleD.c
-    <http://developer.apple.com/library/mac/#samplecode/SampleD/>}
-
- at var ffi: a L{cffi.FFI} instance wrapping the functions exposed by C{launch.h}.
-
- at var lib: a L{cffi} "U{dynamic library object
-    <http://cffi.readthedocs.org/en/release-0.6/#the-verification-step>}"
-    wrapping the functions exposed by C{launch.h}.
-
- at var constants: Select C{LAUNCH_*} constants from C{launch.h}, exposed as plain
-    Python values.  Note that this is not a complete wrapping, but as the
-    header file suggests, these APIs are only for use during check-in.
+Binding for launchd socket hand-off API.
 """
 
 from __future__ import print_function
@@ -40,61 +27,7 @@
 
 ffi.cdef(
     """
-    static char const* const LAUNCH_KEY_CHECKIN;
-    static char const* const LAUNCH_JOBKEY_LABEL;
-    static char const* const LAUNCH_JOBKEY_SOCKETS;
-
-    typedef enum {
-        LAUNCH_DATA_DICTIONARY = 1,
-        LAUNCH_DATA_ARRAY,
-        LAUNCH_DATA_FD,
-        LAUNCH_DATA_INTEGER,
-        LAUNCH_DATA_REAL,
-        LAUNCH_DATA_BOOL,
-        LAUNCH_DATA_STRING,
-        LAUNCH_DATA_OPAQUE,
-        LAUNCH_DATA_ERRNO,
-        LAUNCH_DATA_MACHPORT,
-    } launch_data_type_t;
-
-    typedef struct _launch_data *launch_data_t;
-
-    bool launch_data_dict_insert(
-        launch_data_t, const launch_data_t, const char *
-    );
-
-    launch_data_t launch_data_alloc(launch_data_type_t);
-    launch_data_t launch_data_new_string(const char *);
-    launch_data_t launch_data_new_integer(long long);
-    launch_data_t launch_data_new_fd(int);
-    launch_data_t launch_data_new_bool(bool);
-    launch_data_t launch_data_new_real(double);
-    launch_data_t launch_msg(const launch_data_t);
-
-    launch_data_type_t launch_data_get_type(const launch_data_t);
-
-    launch_data_t launch_data_dict_lookup(const launch_data_t, const char *);
-    size_t launch_data_dict_get_count(const launch_data_t);
-    long long launch_data_get_integer(const launch_data_t);
-    void launch_data_dict_iterate(
-        const launch_data_t, void (*)(
-            const launch_data_t, const char *, void *
-        ),
-        void *
-    );
-
-    int launch_data_get_fd(const launch_data_t);
-    bool launch_data_get_bool(const launch_data_t);
-    const char * launch_data_get_string(const launch_data_t);
-    double launch_data_get_real(const launch_data_t);
-
-    size_t launch_data_array_get_count(const launch_data_t);
-    launch_data_t launch_data_array_get_index(const launch_data_t, size_t);
-    bool launch_data_array_set_index(
-        launch_data_t, const launch_data_t, size_t
-    );
-
-    void launch_data_free(launch_data_t);
+    int launch_activate_socket(const char *name, int **fds, size_t *cnt);
     """
 )
 
@@ -109,201 +42,18 @@
     raise ImportError(ve)
 
 
+def launchActivateSocket(name):
+    fdList = []
 
-class _LaunchArray(object):
-    def __init__(self, launchdata):
-        self.launchdata = launchdata
+    fds = ffi.new('int **')
+    count = ffi.new('size_t *')
+    result = lib.launch_activate_socket(name, fds, count)
+    if result == 0:
+        for i in xrange(count[0]):
+            fdList.append(fds[0][i])
+    return fdList
 
 
-    def __len__(self):
-        return lib.launch_data_array_get_count(self.launchdata)
-
-
-    def __getitem__(self, index):
-        if index >= len(self):
-            raise IndexError(index)
-        return _launchify(
-            lib.launch_data_array_get_index(self.launchdata, index)
-        )
-
-
-
-class _LaunchDictionary(object):
-    def __init__(self, launchdata):
-        self.launchdata = launchdata
-
-
-    def keys(self):
-        """
-        Return keys in the dictionary.
-        """
-        keys = []
-
-        @ffi.callback("void (*)(const launch_data_t, const char *, void *)")
-        def icb(v, k, n):
-            keys.append(ffi.string(k))
-
-        lib.launch_data_dict_iterate(self.launchdata, icb, ffi.NULL)
-        return keys
-
-
-    def values(self):
-        """
-        Return values in the dictionary.
-        """
-        values = []
-
-        @ffi.callback("void (*)(const launch_data_t, const char *, void *)")
-        def icb(v, k, n):
-            values.append(_launchify(v))
-
-        lib.launch_data_dict_iterate(self.launchdata, icb, ffi.NULL)
-        return values
-
-
-    def items(self):
-        """
-        Return items in the dictionary.
-        """
-        values = []
-
-        @ffi.callback("void (*)(const launch_data_t, const char *, void *)")
-        def icb(v, k, n):
-            values.append((ffi.string(k), _launchify(v)))
-
-        lib.launch_data_dict_iterate(self.launchdata, icb, ffi.NULL)
-        return values
-
-
-    def __getitem__(self, key):
-        launchvalue = lib.launch_data_dict_lookup(self.launchdata, key)
-        try:
-            return _launchify(launchvalue)
-        except LaunchErrno:
-            raise KeyError(key)
-
-
-    def __len__(self):
-        return lib.launch_data_dict_get_count(self.launchdata)
-
-
-
-def plainPython(x):
-    """
-    Convert a launchd python-like data structure into regular Python
-    dictionaries and lists.
-    """
-    if isinstance(x, _LaunchDictionary):
-        result = {}
-        for k, v in x.items():
-            result[k] = plainPython(v)
-        return result
-    elif isinstance(x, _LaunchArray):
-        return map(plainPython, x)
-    else:
-        return x
-
-
-
-class LaunchErrno(Exception):
-    """
-    Error from launchd.
-    """
-
-
-
-def _launchify(launchvalue):
-    """
-    Convert a ctypes value wrapping a C{_launch_data} structure into the
-    relevant Python object (integer, bytes, L{_LaunchDictionary},
-    L{_LaunchArray}).
-    """
-    if launchvalue == ffi.NULL:
-        return None
-    dtype = lib.launch_data_get_type(launchvalue)
-
-    if dtype == lib.LAUNCH_DATA_DICTIONARY:
-        return _LaunchDictionary(launchvalue)
-    elif dtype == lib.LAUNCH_DATA_ARRAY:
-        return _LaunchArray(launchvalue)
-    elif dtype == lib.LAUNCH_DATA_FD:
-        return lib.launch_data_get_fd(launchvalue)
-    elif dtype == lib.LAUNCH_DATA_INTEGER:
-        return lib.launch_data_get_integer(launchvalue)
-    elif dtype == lib.LAUNCH_DATA_REAL:
-        return lib.launch_data_get_real(launchvalue)
-    elif dtype == lib.LAUNCH_DATA_BOOL:
-        return lib.launch_data_get_bool(launchvalue)
-    elif dtype == lib.LAUNCH_DATA_STRING:
-        cvalue = lib.launch_data_get_string(launchvalue)
-        if cvalue == ffi.NULL:
-            return None
-        return ffi.string(cvalue)
-    elif dtype == lib.LAUNCH_DATA_OPAQUE:
-        return launchvalue
-    elif dtype == lib.LAUNCH_DATA_ERRNO:
-        raise LaunchErrno(launchvalue)
-    elif dtype == lib.LAUNCH_DATA_MACHPORT:
-        return lib.launch_data_get_machport(launchvalue)
-    else:
-        raise TypeError("Unknown Launch Data Type", dtype)
-
-
-
-def checkin():
-    """
-    Perform a launchd checkin, returning a Pythonic wrapped data structure
-    representing the retrieved check-in plist.
-
-    @return: a C{dict}-like object.
-    """
-    lkey = lib.launch_data_new_string(lib.LAUNCH_KEY_CHECKIN)
-    msgr = lib.launch_msg(lkey)
-    return _launchify(msgr)
-
-
-
-def _managed(obj):
-    """
-    Automatically free an object that was allocated with a launch_data_*
-    function, or raise L{MemoryError} if it's C{NULL}.
-    """
-    if obj == ffi.NULL:
-        raise MemoryError()
-    else:
-        return ffi.gc(obj, lib.launch_data_free)
-
-
-
-class _Strings(object):
-    """
-    Expose constants as Python-readable values rather than wrapped ctypes
-    pointers.
-    """
-    def __getattribute__(self, name):
-        value = getattr(lib, name)
-        if isinstance(value, int):
-            return value
-        if ffi.typeof(value) != ffi.typeof("char *"):
-            raise AttributeError("no such constant", name)
-        return ffi.string(value)
-
-constants = _Strings()
-
-
-
-def getLaunchDSocketFDs():
-    """
-    Perform checkin via L{checkin} and return just a dictionary mapping the
-    sockets to file descriptors.
-    """
-    return plainPython(checkin()[constants.LAUNCH_JOBKEY_SOCKETS])
-
-
-
 __all__ = [
-    'checkin',
-    'lib',
-    'ffi',
-    'plainPython',
+    'launchActivateSocket',
 ]

Modified: twext/trunk/twext/python/test/test_launchd.py
===================================================================
--- twext/trunk/twext/python/test/test_launchd.py	2015-01-28 04:11:47 UTC (rev 14350)
+++ twext/trunk/twext/python/test/test_launchd.py	2015-01-29 20:21:25 UTC (rev 14351)
@@ -42,10 +42,7 @@
 
 
 try:
-    from twext.python.launchd import (
-        lib, ffi, _LaunchDictionary, _LaunchArray, _managed, constants,
-        plainPython, checkin, _launchify, getLaunchDSocketFDs
-    )
+    from twext.python.launchd import launchActivateSocket
 except ImportError:
     skip = "LaunchD not available."
 else:
@@ -55,235 +52,6 @@
 from twisted.python.filepath import FilePath
 
 
-class LaunchDataStructures(TestCase):
-    """
-    Tests for L{_launchify} converting data structures from launchd's internals
-    to Python objects.
-    """
-
-    def test_fd(self):
-        """
-        Test converting a launchd FD to an integer.
-        """
-        fd = _managed(lib.launch_data_new_fd(2))
-        self.assertEquals(_launchify(fd), 2)
-
-    test_fd.todo = "Figure out why this test stopped working"
-
-
-    def test_bool(self):
-        """
-        Test converting a launchd bool to a Python bool.
-        """
-        t = _managed(lib.launch_data_new_bool(True))
-        f = _managed(lib.launch_data_new_bool(False))
-        self.assertEqual(_launchify(t), True)
-        self.assertEqual(_launchify(f), False)
-
-
-    def test_real(self):
-        """
-        Test converting a launchd real to a Python float.
-        """
-        notQuitePi = _managed(lib.launch_data_new_real(3.14158))
-        self.assertEqual(_launchify(notQuitePi), 3.14158)
-
-
-
-class DictionaryTests(TestCase):
-    """
-    Tests for L{_LaunchDictionary}
-    """
-
-    def setUp(self):
-        """
-        Assemble a test dictionary.
-        """
-        self.testDict = _managed(
-            lib.launch_data_alloc(lib.LAUNCH_DATA_DICTIONARY)
-        )
-        key1 = ffi.new("char[]", "alpha")
-        val1 = lib.launch_data_new_string("alpha-value")
-        key2 = ffi.new("char[]", "beta")
-        val2 = lib.launch_data_new_string("beta-value")
-        key3 = ffi.new("char[]", "gamma")
-        val3 = lib.launch_data_new_integer(3)
-        lib.launch_data_dict_insert(self.testDict, val1, key1)
-        lib.launch_data_dict_insert(self.testDict, val2, key2)
-        lib.launch_data_dict_insert(self.testDict, val3, key3)
-        self.assertEquals(lib.launch_data_dict_get_count(self.testDict), 3)
-
-
-    def test_len(self):
-        """
-        C{len(_LaunchDictionary())} returns the number of keys in the
-        dictionary.
-        """
-        self.assertEquals(len(_LaunchDictionary(self.testDict)), 3)
-
-
-    def test_keys(self):
-        """
-        L{_LaunchDictionary.keys} returns keys present in a C{launch_data_dict}.
-        """
-        dictionary = _LaunchDictionary(self.testDict)
-        self.assertEquals(set(dictionary.keys()),
-                          set([b"alpha", b"beta", b"gamma"]))
-
-
-    def test_values(self):
-        """
-        L{_LaunchDictionary.values} returns keys present in a
-        C{launch_data_dict}.
-        """
-        dictionary = _LaunchDictionary(self.testDict)
-        self.assertEquals(set(dictionary.values()),
-                          set([b"alpha-value", b"beta-value", 3]))
-
-
-    def test_items(self):
-        """
-        L{_LaunchDictionary.items} returns all (key, value) tuples present in a
-        C{launch_data_dict}.
-        """
-        dictionary = _LaunchDictionary(self.testDict)
-        self.assertEquals(set(dictionary.items()),
-                          set([(b"alpha", b"alpha-value"),
-                               (b"beta", b"beta-value"), (b"gamma", 3)]))
-
-
-    def test_plainPython(self):
-        """
-        L{plainPython} will convert a L{_LaunchDictionary} into a Python
-        dictionary.
-        """
-        self.assertEquals(
-            {b"alpha": b"alpha-value", b"beta": b"beta-value", b"gamma": 3},
-            plainPython(_LaunchDictionary(self.testDict))
-        )
-
-
-    def test_plainPythonNested(self):
-        """
-        L{plainPython} will convert a L{_LaunchDictionary} containing another
-        L{_LaunchDictionary} into a nested Python dictionary.
-        """
-        otherDict = lib.launch_data_alloc(lib.LAUNCH_DATA_DICTIONARY)
-        lib.launch_data_dict_insert(otherDict,
-                                    lib.launch_data_new_string("bar"), "foo")
-        lib.launch_data_dict_insert(self.testDict, otherDict, "delta")
-        self.assertEquals(
-            {b"alpha": b"alpha-value", b"beta": b"beta-value",
-             b"gamma": 3, b"delta": {b"foo": b"bar"}},
-            plainPython(_LaunchDictionary(self.testDict))
-        )
-
-
-
-class ArrayTests(TestCase):
-    """
-    Tests for L{_LaunchArray}
-    """
-
-    def setUp(self):
-        """
-        Assemble a test array.
-        """
-        self.testArray = ffi.gc(
-            lib.launch_data_alloc(lib.LAUNCH_DATA_ARRAY),
-            lib.launch_data_free
-        )
-
-        lib.launch_data_array_set_index(
-            self.testArray, lib.launch_data_new_string("test-string-1"), 0
-        )
-        lib.launch_data_array_set_index(
-            self.testArray, lib.launch_data_new_string("another string."), 1
-        )
-        lib.launch_data_array_set_index(
-            self.testArray, lib.launch_data_new_integer(4321), 2
-        )
-
-
-    def test_length(self):
-        """
-        C{len(_LaunchArray(...))} returns the number of elements in the array.
-        """
-        self.assertEquals(len(_LaunchArray(self.testArray)), 3)
-
-
-    def test_indexing(self):
-        """
-        C{_LaunchArray(...)[n]} returns the n'th element in the array.
-        """
-        array = _LaunchArray(self.testArray)
-        self.assertEquals(array[0], b"test-string-1")
-        self.assertEquals(array[1], b"another string.")
-        self.assertEquals(array[2], 4321)
-
-
-    def test_indexTooBig(self):
-        """
-        C{_LaunchArray(...)[n]}, where C{n} is greater than the length of the
-        array, raises an L{IndexError}.
-        """
-        array = _LaunchArray(self.testArray)
-        self.assertRaises(IndexError, lambda: array[3])
-
-
-    def test_iterating(self):
-        """
-        Iterating over a C{_LaunchArray} returns each item in sequence.
-        """
-        array = _LaunchArray(self.testArray)
-        i = iter(array)
-        self.assertEquals(i.next(), b"test-string-1")
-        self.assertEquals(i.next(), b"another string.")
-        self.assertEquals(i.next(), 4321)
-        self.assertRaises(StopIteration, i.next)
-
-
-    def test_plainPython(self):
-        """
-        L{plainPython} converts a L{_LaunchArray} into a Python list.
-        """
-        array = _LaunchArray(self.testArray)
-        self.assertEquals(plainPython(array),
-                          [b"test-string-1", b"another string.", 4321])
-
-
-    def test_plainPythonNested(self):
-        """
-        L{plainPython} converts a L{_LaunchArray} containing another
-        L{_LaunchArray} into a Python list.
-        """
-        sub = lib.launch_data_alloc(lib.LAUNCH_DATA_ARRAY)
-        lib.launch_data_array_set_index(sub, lib.launch_data_new_integer(7), 0)
-        lib.launch_data_array_set_index(self.testArray, sub, 3)
-        array = _LaunchArray(self.testArray)
-        self.assertEqual(plainPython(array), [b"test-string-1",
-                                              b"another string.", 4321, [7]])
-
-
-
-class SimpleStringConstants(TestCase):
-    """
-    Tests for bytestring-constants wrapping.
-    """
-
-    def test_constant(self):
-        """
-        C{launchd.constants.LAUNCH_*} will return a bytes object corresponding
-        to a constant.
-        """
-        self.assertEqual(constants.LAUNCH_JOBKEY_SOCKETS,
-                         b"Sockets")
-        self.assertRaises(AttributeError, getattr, constants,
-                          "launch_data_alloc")
-        self.assertEquals(constants.LAUNCH_DATA_ARRAY, 2)
-
-
-
 class CheckInTests(TestCase):
     """
     Integration tests making sure that actual checkin with launchd results in
@@ -348,36 +116,12 @@
 
 
     @staticmethod
-    def job_checkin():
-        """
-        Check in in the subprocess.
-        """
-        sys.stdout.write(json.dumps(plainPython(checkin())))
-
-
-    def test_checkin(self):
-        """
-        L{checkin} performs launchd checkin and returns a launchd data
-        structure.
-        """
-        d = json.loads(self.stdout.getContent())
-        self.assertEqual(d[constants.LAUNCH_JOBKEY_LABEL], self.launchLabel)
-        self.assertIsInstance(d, dict)
-        sockets = d[constants.LAUNCH_JOBKEY_SOCKETS]
-        self.assertEquals(len(sockets), 1)
-        self.assertEqual(['Awesome'], sockets.keys())
-        awesomeSocket = sockets['Awesome']
-        self.assertEqual(len(awesomeSocket), 1)
-        self.assertIsInstance(awesomeSocket[0], int)
-
-
-    @staticmethod
     def job_getFDs():
         """
         Check-in via the high-level C{getLaunchDSocketFDs} API, that just gives
         us listening FDs.
         """
-        sys.stdout.write(json.dumps(getLaunchDSocketFDs()))
+        sys.stdout.write(json.dumps(launchActivateSocket("Awesome")))
 
 
     def test_getFDs(self):
@@ -388,10 +132,7 @@
         """
         sockets = json.loads(self.stdout.getContent())
         self.assertEquals(len(sockets), 1)
-        self.assertEqual(['Awesome'], sockets.keys())
-        awesomeSocket = sockets['Awesome']
-        self.assertEqual(len(awesomeSocket), 1)
-        self.assertIsInstance(awesomeSocket[0], int)
+        self.assertIsInstance(sockets[0], int)
 
 
     def tearDown(self):
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20150129/6fabec55/attachment-0001.html>


More information about the calendarserver-changes mailing list