<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[14351] twext/trunk/twext/python</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/14351">14351</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2015-01-29 12:21:25 -0800 (Thu, 29 Jan 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>OMG launchd API is down to a single function</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#twexttrunktwextpythonlaunchdpy">twext/trunk/twext/python/launchd.py</a></li>
<li><a href="#twexttrunktwextpythontesttest_launchdpy">twext/trunk/twext/python/test/test_launchd.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="twexttrunktwextpythonlaunchdpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/python/launchd.py (14350 => 14351)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -16,20 +16,7 @@
</span><span class="cx"> ##
</span><span class="cx">
</span><span class="cx"> """
</span><del>-Bindings for launchd check-in API.
-
-@see: U{SampleD.c
- <http://developer.apple.com/library/mac/#samplecode/SampleD/>}
-
-@var ffi: a L{cffi.FFI} instance wrapping the functions exposed by C{launch.h}.
-
-@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}.
-
-@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.
</del><ins>+Binding for launchd socket hand-off API.
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> from __future__ import print_function
</span><span class="lines">@@ -40,61 +27,7 @@
</span><span class="cx">
</span><span class="cx"> ffi.cdef(
</span><span class="cx"> """
</span><del>- 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);
</del><ins>+ int launch_activate_socket(const char *name, int **fds, size_t *cnt);
</ins><span class="cx"> """
</span><span class="cx"> )
</span><span class="cx">
</span><span class="lines">@@ -109,201 +42,18 @@
</span><span class="cx"> raise ImportError(ve)
</span><span class="cx">
</span><span class="cx">
</span><ins>+def launchActivateSocket(name):
+ fdList = []
</ins><span class="cx">
</span><del>-class _LaunchArray(object):
- def __init__(self, launchdata):
- self.launchdata = launchdata
</del><ins>+ 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
</ins><span class="cx">
</span><span class="cx">
</span><del>- 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])
-
-
-
</del><span class="cx"> __all__ = [
</span><del>- 'checkin',
- 'lib',
- 'ffi',
- 'plainPython',
</del><ins>+ 'launchActivateSocket',
</ins><span class="cx"> ]
</span></span></pre></div>
<a id="twexttrunktwextpythontesttest_launchdpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/python/test/test_launchd.py (14350 => 14351)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -42,10 +42,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> try:
</span><del>- from twext.python.launchd import (
- lib, ffi, _LaunchDictionary, _LaunchArray, _managed, constants,
- plainPython, checkin, _launchify, getLaunchDSocketFDs
- )
</del><ins>+ from twext.python.launchd import launchActivateSocket
</ins><span class="cx"> except ImportError:
</span><span class="cx"> skip = "LaunchD not available."
</span><span class="cx"> else:
</span><span class="lines">@@ -55,235 +52,6 @@
</span><span class="cx"> from twisted.python.filepath import FilePath
</span><span class="cx">
</span><span class="cx">
</span><del>-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)
-
-
-
</del><span class="cx"> class CheckInTests(TestCase):
</span><span class="cx"> """
</span><span class="cx"> Integration tests making sure that actual checkin with launchd results in
</span><span class="lines">@@ -348,36 +116,12 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> @staticmethod
</span><del>- 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
</del><span class="cx"> def job_getFDs():
</span><span class="cx"> """
</span><span class="cx"> Check-in via the high-level C{getLaunchDSocketFDs} API, that just gives
</span><span class="cx"> us listening FDs.
</span><span class="cx"> """
</span><del>- sys.stdout.write(json.dumps(getLaunchDSocketFDs()))
</del><ins>+ sys.stdout.write(json.dumps(launchActivateSocket("Awesome")))
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_getFDs(self):
</span><span class="lines">@@ -388,10 +132,7 @@
</span><span class="cx"> """
</span><span class="cx"> sockets = json.loads(self.stdout.getContent())
</span><span class="cx"> self.assertEquals(len(sockets), 1)
</span><del>- self.assertEqual(['Awesome'], sockets.keys())
- awesomeSocket = sockets['Awesome']
- self.assertEqual(len(awesomeSocket), 1)
- self.assertIsInstance(awesomeSocket[0], int)
</del><ins>+ self.assertIsInstance(sockets[0], int)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def tearDown(self):
</span></span></pre>
</div>
</div>
</body>
</html>