Commit 77ab1491 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Apply black formatter to .py files

Summary: [Folly] Apply `black` formatter to `.py` files.

Reviewed By: zertosh

Differential Revision: D17898404

fbshipit-source-id: b597b55b646e539a288d175e0b2db8111b5b103b
parent d2c64d94
......@@ -4,7 +4,7 @@ from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
'fbcode_builder steps to build & test folly'
"fbcode_builder steps to build & test folly"
import specs.fmt as fmt
import specs.gmock as gmock
......@@ -14,29 +14,27 @@ from shell_quoting import ShellQuoted
def fbcode_builder_spec(builder):
builder.add_option(
'folly/_build:cmake_defines',
{
'BUILD_SHARED_LIBS': 'OFF',
'BUILD_TESTS': 'ON',
}
"folly/_build:cmake_defines", {"BUILD_SHARED_LIBS": "OFF", "BUILD_TESTS": "ON"}
)
return {
'depends_on': [fmt, gmock],
'steps': [
builder.fb_github_cmake_install('folly/_build'),
"depends_on": [fmt, gmock],
"steps": [
builder.fb_github_cmake_install("folly/_build"),
builder.step(
'Run folly tests', [
"Run folly tests",
[
builder.run(
ShellQuoted('ctest --output-on-failure -j {n}')
.format(n=builder.option('make_parallelism'), )
ShellQuoted("ctest --output-on-failure -j {n}").format(
n=builder.option("make_parallelism")
)
)
]
],
),
]
],
}
config = {
'github_project': 'facebook/folly',
'fbcode_builder_spec': fbcode_builder_spec,
"github_project": "facebook/folly",
"fbcode_builder_spec": fbcode_builder_spec,
}
......@@ -7,10 +7,10 @@ import re
class DiGraph(object):
'''
"""
Adapted from networkx: http://networkx.github.io/
Represents a directed graph. Edges can store (key, value) attributes.
'''
"""
def __init__(self):
# Map of node -> set of nodes
......@@ -57,36 +57,36 @@ class DiGraph(object):
return graph
def node_link_data(self):
'''
"""
Returns the graph as a dictionary in a format that can be
serialized.
'''
"""
data = {
'directed': True,
'multigraph': False,
'graph': {},
'links': [],
'nodes': [],
"directed": True,
"multigraph": False,
"graph": {},
"links": [],
"nodes": [],
}
# Do one pass to build a map of node -> position in nodes
node_to_number = {}
for node in self.adjacency_map.keys():
node_to_number[node] = len(data['nodes'])
data['nodes'].append({'id': node})
node_to_number[node] = len(data["nodes"])
data["nodes"].append({"id": node})
# Do another pass to build the link information
for node, neighbors in self.adjacency_map.items():
for neighbor in neighbors:
link = self.attributes_map[(node, neighbor)].copy()
link['source'] = node_to_number[node]
link['target'] = node_to_number[neighbor]
data['links'].append(link)
link["source"] = node_to_number[node]
link["target"] = node_to_number[neighbor]
data["links"].append(link)
return data
def strongly_connected_components(G): # noqa: C901
'''
"""
Adapted from networkx: http://networkx.github.io/
Parameters
----------
......@@ -96,7 +96,7 @@ def strongly_connected_components(G): # noqa: C901
comp : generator of sets
A generator of sets of nodes, one for each strongly connected
component of G.
'''
"""
preorder = {}
lowlink = {}
scc_found = {}
......@@ -129,9 +129,7 @@ def strongly_connected_components(G): # noqa: C901
if lowlink[v] == preorder[v]:
scc_found[v] = True
scc = {v}
while (
scc_queue and preorder[scc_queue[-1]] > preorder[v]
):
while scc_queue and preorder[scc_queue[-1]] > preorder[v]:
k = scc_queue.pop()
scc_found[k] = True
scc.add(k)
......@@ -141,7 +139,7 @@ def strongly_connected_components(G): # noqa: C901
def simple_cycles(G): # noqa: C901
'''
"""
Adapted from networkx: http://networkx.github.io/
Parameters
----------
......@@ -151,7 +149,7 @@ def simple_cycles(G): # noqa: C901
cycle_generator: generator
A generator that produces elementary cycles of the graph.
Each cycle is represented by a list of nodes along the cycle.
'''
"""
def _unblock(thisnode, blocked, B):
stack = set([thisnode])
......@@ -211,12 +209,12 @@ def simple_cycles(G): # noqa: C901
def find_cycle(graph):
'''
"""
Looks for a cycle in the graph. If found, returns the first cycle.
If nodes a1, a2, ..., an are in a cycle, then this returns:
[(a1,a2), (a2,a3), ... (an-1,an), (an, a1)]
Otherwise returns an empty list.
'''
"""
cycles = list(simple_cycles(graph))
if cycles:
nodes = cycles[0]
......@@ -232,22 +230,22 @@ def find_cycle(graph):
def get_stacktrace(thread_id):
'''
"""
Returns the stack trace for the thread id as a list of strings.
'''
gdb.execute('thread %d' % thread_id, from_tty=False, to_string=True)
output = gdb.execute('bt', from_tty=False, to_string=True)
stacktrace_lines = output.strip().split('\n')
"""
gdb.execute("thread %d" % thread_id, from_tty=False, to_string=True)
output = gdb.execute("bt", from_tty=False, to_string=True)
stacktrace_lines = output.strip().split("\n")
return stacktrace_lines
def is_thread_blocked_with_frame(
thread_id, top_line, expected_top_lines, expected_frame
):
'''
"""
Returns True if we found expected_top_line in top_line, and
we found the expected_frame in the thread's stack trace.
'''
"""
if all(expected not in top_line for expected in expected_top_lines):
return False
stacktrace_lines = get_stacktrace(thread_id)
......@@ -255,41 +253,39 @@ def is_thread_blocked_with_frame(
class MutexType(Enum):
'''Types of mutexes that we can detect deadlocks.'''
"""Types of mutexes that we can detect deadlocks."""
PTHREAD_MUTEX_T = 'pthread_mutex_t'
PTHREAD_RWLOCK_T = 'pthread_rwlock_t'
PTHREAD_MUTEX_T = "pthread_mutex_t"
PTHREAD_RWLOCK_T = "pthread_rwlock_t"
@staticmethod
def get_mutex_type(thread_id, top_line):
'''
"""
Returns the probable mutex type, based on the first line
of the thread's stack. Returns None if not found.
'''
"""
WAITLIST = [
'__lll_lock_wait',
'futex_abstimed_wait',
'futex_abstimed_wait_cancelable',
'futex_reltimed_wait',
'futex_reltimed_wait_cancelable',
'futex_wait',
'futex_wait_cancelable',
"__lll_lock_wait",
"futex_abstimed_wait",
"futex_abstimed_wait_cancelable",
"futex_reltimed_wait",
"futex_reltimed_wait_cancelable",
"futex_wait",
"futex_wait_cancelable",
]
if is_thread_blocked_with_frame(
thread_id, top_line, WAITLIST, 'pthread_mutex'
):
if is_thread_blocked_with_frame(thread_id, top_line, WAITLIST, "pthread_mutex"):
return MutexType.PTHREAD_MUTEX_T
if is_thread_blocked_with_frame(
thread_id, top_line, WAITLIST, 'pthread_rwlock'
thread_id, top_line, WAITLIST, "pthread_rwlock"
):
return MutexType.PTHREAD_RWLOCK_T
return None
@staticmethod
def get_mutex_owner_and_address_func_for_type(mutex_type):
'''
"""
Returns a function to resolve the mutex owner and address for
the given type. The returned function f has the following
signature:
......@@ -299,7 +295,7 @@ class MutexType(Enum):
or (None, None) if not found.
Returns None if there is no function for this mutex_type.
'''
"""
if mutex_type == MutexType.PTHREAD_MUTEX_T:
return get_pthread_mutex_t_owner_and_address
if mutex_type == MutexType.PTHREAD_RWLOCK_T:
......@@ -308,33 +304,37 @@ class MutexType(Enum):
def print_cycle(graph, lwp_to_thread_id, cycle):
'''Prints the threads and mutexes involved in the deadlock.'''
"""Prints the threads and mutexes involved in the deadlock."""
for (m, n) in cycle:
print(
'Thread %d (LWP %d) is waiting on %s (0x%016x) held by '
'Thread %d (LWP %d)' % (
lwp_to_thread_id[m], m,
graph.attributes(m, n)['mutex_type'].value,
graph.attributes(m, n)['mutex'], lwp_to_thread_id[n], n
"Thread %d (LWP %d) is waiting on %s (0x%016x) held by "
"Thread %d (LWP %d)"
% (
lwp_to_thread_id[m],
m,
graph.attributes(m, n)["mutex_type"].value,
graph.attributes(m, n)["mutex"],
lwp_to_thread_id[n],
n,
)
)
def get_thread_info():
'''
"""
Returns a pair of:
- map of LWP -> thread ID
- map of blocked threads LWP -> potential mutex type
'''
"""
# LWP -> thread ID
lwp_to_thread_id = {}
# LWP -> potential mutex type it is blocked on
blocked_threads = {}
output = gdb.execute('info threads', from_tty=False, to_string=True)
lines = output.strip().split('\n')[1:]
regex = re.compile(r'[\s\*]*(\d+).*Thread.*\(LWP (\d+)\).*')
output = gdb.execute("info threads", from_tty=False, to_string=True)
lines = output.strip().split("\n")[1:]
regex = re.compile(r"[\s\*]*(\d+).*Thread.*\(LWP (\d+)\).*")
for line in lines:
try:
thread_id = int(regex.match(line).group(1))
......@@ -350,50 +350,46 @@ def get_thread_info():
def get_pthread_mutex_t_owner_and_address(lwp_to_thread_id, thread_lwp):
'''
"""
Finds the thread holding the mutex that this thread is blocked on.
Returns a pair of (lwp of thread owning mutex, mutex address),
or (None, None) if not found.
'''
"""
# Go up the stack to the pthread_mutex_lock frame
gdb.execute(
'thread %d' % lwp_to_thread_id[thread_lwp],
from_tty=False,
to_string=True
"thread %d" % lwp_to_thread_id[thread_lwp], from_tty=False, to_string=True
)
gdb.execute('frame 1', from_tty=False, to_string=True)
gdb.execute("frame 1", from_tty=False, to_string=True)
# Get the owner of the mutex by inspecting the internal
# fields of the mutex.
try:
mutex_info = gdb.parse_and_eval('mutex').dereference()
mutex_owner_lwp = int(mutex_info['__data']['__owner'])
mutex_info = gdb.parse_and_eval("mutex").dereference()
mutex_owner_lwp = int(mutex_info["__data"]["__owner"])
return (mutex_owner_lwp, int(mutex_info.address))
except gdb.error:
return (None, None)
def get_pthread_rwlock_t_owner_and_address(lwp_to_thread_id, thread_lwp):
'''
"""
If the thread is waiting on a write-locked pthread_rwlock_t, this will
return the pair of:
(lwp of thread that is write-owning the mutex, mutex address)
or (None, None) if not found, or if the mutex is read-locked.
'''
"""
# Go up the stack to the pthread_rwlock_{rd|wr}lock frame
gdb.execute(
'thread %d' % lwp_to_thread_id[thread_lwp],
from_tty=False,
to_string=True
"thread %d" % lwp_to_thread_id[thread_lwp], from_tty=False, to_string=True
)
gdb.execute('frame 2', from_tty=False, to_string=True)
gdb.execute("frame 2", from_tty=False, to_string=True)
# Get the owner of the mutex by inspecting the internal
# fields of the mutex.
try:
rwlock_info = gdb.parse_and_eval('rwlock').dereference()
rwlock_data = rwlock_info['__data']
field_names = ['__cur_writer', '__writer']
rwlock_info = gdb.parse_and_eval("rwlock").dereference()
rwlock_data = rwlock_info["__data"]
field_names = ["__cur_writer", "__writer"]
fields = rwlock_data.type.fields()
field = [f for f in fields if f.name in field_names][0]
rwlock_owner_lwp = int(rwlock_data[field])
......@@ -409,13 +405,13 @@ def get_pthread_rwlock_t_owner_and_address(lwp_to_thread_id, thread_lwp):
class Deadlock(gdb.Command):
'''Detects deadlocks'''
"""Detects deadlocks"""
def __init__(self):
super(Deadlock, self).__init__('deadlock', gdb.COMMAND_NONE)
super(Deadlock, self).__init__("deadlock", gdb.COMMAND_NONE)
def invoke(self, arg, from_tty):
'''Prints the threads and mutexes in a deadlock, if it exists.'''
"""Prints the threads and mutexes in a deadlock, if it exists."""
lwp_to_thread_id, blocked_threads = get_thread_info()
# Nodes represent threads. Edge (A,B) exists if thread A
......@@ -425,8 +421,9 @@ class Deadlock(gdb.Command):
# Go through all the blocked threads and see which threads
# they are blocked on, and build the thread wait graph.
for thread_lwp, mutex_type in blocked_threads.items():
get_owner_and_address_func = \
MutexType.get_mutex_owner_and_address_func_for_type(mutex_type)
get_owner_and_address_func = MutexType.get_mutex_owner_and_address_func_for_type(
mutex_type
)
if not get_owner_and_address_func:
continue
mutex_owner_lwp, mutex_address = get_owner_and_address_func(
......@@ -437,19 +434,16 @@ class Deadlock(gdb.Command):
thread_lwp,
mutex_owner_lwp,
mutex=mutex_address,
mutex_type=mutex_type
mutex_type=mutex_type,
)
# A deadlock exists if there is a cycle in the graph.
cycle = find_cycle(graph)
if cycle:
print('Found deadlock!')
print("Found deadlock!")
print_cycle(graph, lwp_to_thread_id, cycle)
else:
print(
'No deadlock detected. '
'Do you have debug symbols installed?'
)
print("No deadlock detected. " "Do you have debug symbols installed?")
def load():
......@@ -459,8 +453,8 @@ def load():
def info():
return 'Detect deadlocks'
return "Detect deadlocks"
if __name__ == '__main__':
if __name__ == "__main__":
load()
......@@ -16,7 +16,7 @@ class FiberPrinter:
def __init__(self, val):
self.val = val
state = self.val['state_']
state = self.val["state_"]
d = gdb.types.make_enum_dict(state.type)
d = dict((v, k) for k, v in d.items())
self.state = d[int(state)]
......@@ -39,9 +39,11 @@ class FiberPrinter:
return "Unknown"
def backtrace_available(self):
return self.state != "folly::fibers::Fiber::INVALID" and \
self.state != "folly::fibers::Fiber::NOT_STARTED" and \
self.state != "folly::fibers::Fiber::RUNNING"
return (
self.state != "folly::fibers::Fiber::INVALID"
and self.state != "folly::fibers::Fiber::NOT_STARTED"
and self.state != "folly::fibers::Fiber::RUNNING"
)
def children(self):
result = collections.OrderedDict()
......@@ -58,17 +60,15 @@ class FiberPrinter:
class GetFiberXMethodWorker(gdb.xmethod.XMethodWorker):
def get_arg_types(self):
return gdb.lookup_type('int')
return gdb.lookup_type("int")
def get_result_type(self):
return gdb.lookup_type('int')
return gdb.lookup_type("int")
def __call__(self, *args):
fm = args[0]
index = int(args[1])
fiber = next(itertools.islice(fiber_manager_active_fibers(fm),
index,
None))
fiber = next(itertools.islice(fiber_manager_active_fibers(fm), index, None))
if fiber is None:
raise gdb.GdbError("Index out of range")
else:
......@@ -77,35 +77,37 @@ class GetFiberXMethodWorker(gdb.xmethod.XMethodWorker):
class GetFiberXMethodMatcher(gdb.xmethod.XMethodMatcher):
def __init__(self):
super(GetFiberXMethodMatcher, self).__init__(
"Fiber address method matcher")
super(GetFiberXMethodMatcher, self).__init__("Fiber address method matcher")
self.worker = GetFiberXMethodWorker()
def match(self, class_type, method_name):
if class_type.name == "folly::fibers::FiberManager" and \
method_name == "get_fiber":
if (
class_type.name == "folly::fibers::FiberManager"
and method_name == "get_fiber"
):
return self.worker
return None
def fiber_manager_active_fibers(fm):
all_fibers = \
fm['allFibers_']['data_']['root_plus_size_']['m_header']
fiber_hook = all_fibers['next_']
all_fibers = fm["allFibers_"]["data_"]["root_plus_size_"]["m_header"]
fiber_hook = all_fibers["next_"]
fiber_count = 0
while fiber_hook != all_fibers.address:
fiber = fiber_hook.cast(gdb.lookup_type("int64_t"))
fiber = fiber - gdb.parse_and_eval(
"(int64_t)&'folly::fibers::Fiber'::globalListHook_")
"(int64_t)&'folly::fibers::Fiber'::globalListHook_"
)
fiber = fiber.cast(
gdb.lookup_type('folly::fibers::Fiber').pointer()).dereference()
gdb.lookup_type("folly::fibers::Fiber").pointer()
).dereference()
if FiberPrinter(fiber).state != "folly::fibers::Fiber::INVALID":
yield fiber
fiber_hook = fiber_hook.dereference()['next_']
fiber_hook = fiber_hook.dereference()["next_"]
fiber_count = fiber_count + 1
......@@ -123,7 +125,7 @@ class FiberManagerPrinter:
num_items = 0
for fiber in fibers_iterator:
if num_items >= self.fiber_print_limit:
yield ('...', '...')
yield ("...", "...")
return
yield (str(fiber.address), fiber)
......@@ -141,15 +143,18 @@ class FiberManagerPrinter:
class FiberPrintLimitCommand(gdb.Command):
def __init__(self):
super(FiberPrintLimitCommand, self).__init__(
"fiber-print-limit", gdb.COMMAND_USER)
"fiber-print-limit", gdb.COMMAND_USER
)
def invoke(self, arg, from_tty):
if not arg:
print("New limit has to be passed to 'fiber_print_limit' command")
return
FiberManagerPrinter.fiber_print_limit = int(arg)
print("New fiber limit for FiberManager printer set to " +
str(FiberManagerPrinter.fiber_print_limit))
print(
"New fiber limit for FiberManager printer set to "
+ str(FiberManagerPrinter.fiber_print_limit)
)
class FrameId(object):
......@@ -197,8 +202,8 @@ class FiberUnwinder(gdb.unwinder.Unwinder):
cls.instance = FiberUnwinder()
gdb.unwinder.register_unwinder(None, cls.instance)
fiber_impl = fiber['fiberImpl_']
cls.instance.fiber_context_ptr = fiber_impl['fiberContext_']
fiber_impl = fiber["fiberImpl_"]
cls.instance.fiber_context_ptr = fiber_impl["fiberContext_"]
def __init__(self):
super(FiberUnwinder, self).__init__("Fiber unwinder")
......@@ -208,10 +213,10 @@ class FiberUnwinder(gdb.unwinder.Unwinder):
if not self.fiber_context_ptr:
return None
orig_sp = pending_frame.read_register('rsp')
orig_pc = pending_frame.read_register('rip')
orig_sp = pending_frame.read_register("rsp")
orig_pc = pending_frame.read_register("rip")
void_star_star = gdb.lookup_type('uint64_t').pointer()
void_star_star = gdb.lookup_type("uint64_t").pointer()
ptr = self.fiber_context_ptr.cast(void_star_star)
# This code may need to be adjusted to newer versions of boost::context.
......@@ -236,9 +241,9 @@ class FiberUnwinder(gdb.unwinder.Unwinder):
frame_id = FrameId(rsp, orig_pc)
unwind_info = pending_frame.create_unwind_info(frame_id)
unwind_info.add_saved_register('rbp', rbp)
unwind_info.add_saved_register('rsp', rsp)
unwind_info.add_saved_register('rip', rip)
unwind_info.add_saved_register("rbp", rbp)
unwind_info.add_saved_register("rsp", rsp)
unwind_info.add_saved_register("rip", rip)
self.fiber_context_ptr = None
......@@ -279,7 +284,8 @@ class FiberActivateCommand(gdb.Command):
class FiberDeactivateCommand(gdb.Command):
def __init__(self):
super(FiberDeactivateCommand, self).__init__(
"fiber-deactivate", gdb.COMMAND_USER)
"fiber-deactivate", gdb.COMMAND_USER
)
def invoke(self, arg, from_tty):
print(fiber_deactivate())
......@@ -302,8 +308,7 @@ class FiberXMethodMatcher(gdb.xmethod.XMethodMatcher):
self.worker = FiberXMethodWorker()
def match(self, class_type, method_name):
if class_type.name == "folly::fibers::Fiber" and \
method_name == "activate":
if class_type.name == "folly::fibers::Fiber" and method_name == "activate":
return self.worker
return None
......@@ -322,21 +327,26 @@ def get_fiber_manager_map(evb_type):
# Exception thrown if unable to find type
# Probably because of missing debug symbols
global_cache_type = gdb.lookup_type(
"folly::fibers::(anonymous namespace)::GlobalCache<" + evb_type + ">")
"folly::fibers::(anonymous namespace)::GlobalCache<" + evb_type + ">"
)
except gdb.error:
raise gdb.GdbError("Unable to find types. "
"Please make sure debug info is available for this binary.\n"
"Have you run 'fbload debuginfo_fbpkg'?")
raise gdb.GdbError(
"Unable to find types. "
"Please make sure debug info is available for this binary.\n"
"Have you run 'fbload debuginfo_fbpkg'?"
)
global_cache_instance_ptr_ptr = gdb.parse_and_eval(
"&'" + global_cache_type.name + "::instance()::ret'")
"&'" + global_cache_type.name + "::instance()::ret'"
)
global_cache_instance_ptr = global_cache_instance_ptr_ptr.cast(
global_cache_type.pointer().pointer()).dereference()
global_cache_type.pointer().pointer()
).dereference()
if global_cache_instance_ptr == 0x0:
raise gdb.GdbError("FiberManager map is empty.")
global_cache_instance = global_cache_instance_ptr.dereference()
return global_cache_instance['map_']
return global_cache_instance["map_"]
def get_fiber_manager_map_evb():
......@@ -349,9 +359,10 @@ def get_fiber_manager_map_vevb():
def build_pretty_printer():
pp = gdb.printing.RegexpCollectionPrettyPrinter("folly_fibers")
pp.add_printer('fibers::Fiber', '^folly::fibers::Fiber$', FiberPrinter)
pp.add_printer('fibers::FiberManager', '^folly::fibers::FiberManager$',
FiberManagerPrinter)
pp.add_printer("fibers::Fiber", "^folly::fibers::Fiber$", FiberPrinter)
pp.add_printer(
"fibers::FiberManager", "^folly::fibers::FiberManager$", FiberManagerPrinter
)
return pp
......
......@@ -14,11 +14,11 @@ class IOBufTests(unittest.TestCase):
self.assertEqual(len(ebuf), 0)
self.assertEqual(ebuf.chain_size(), 0)
self.assertEqual(ebuf.chain_count(), 8)
self.assertEqual(b''.join(ebuf), b'')
self.assertEqual(b'', bytes(ebuf))
self.assertEqual(b"".join(ebuf), b"")
self.assertEqual(b"", bytes(ebuf))
def test_chain(self) -> None:
control = [b'facebook', b'thrift', b'python3', b'cython']
control = [b"facebook", b"thrift", b"python3", b"cython"]
chain = make_chain([IOBuf(x) for x in control])
self.assertTrue(chain.is_chained)
self.assertTrue(chain)
......@@ -27,10 +27,10 @@ class IOBufTests(unittest.TestCase):
self.assertEqual(chain.chain_size(), sum(len(x) for x in control))
self.assertEqual(chain.chain_count(), len(control))
self.assertEqual(memoryview(chain.next), control[1]) # type: ignore
self.assertEqual(b''.join(chain), b''.join(control))
self.assertEqual(b"".join(chain), b"".join(control))
def test_cyclic_chain(self) -> None:
control = [b'aaa', b'aaaa']
control = [b"aaa", b"aaaa"]
chain = make_chain([IOBuf(x) for x in control])
self.assertTrue(chain.is_chained)
self.assertTrue(chain)
......@@ -39,7 +39,7 @@ class IOBufTests(unittest.TestCase):
self.assertEqual(chain.chain_size(), sum(len(x) for x in control))
self.assertEqual(chain.chain_count(), len(control))
self.assertEqual(memoryview(chain.next), control[1]) # type: ignore
self.assertEqual(b''.join(chain), b''.join(control))
self.assertEqual(b"".join(chain), b"".join(control))
def test_hash(self) -> None:
x = b"omg"
......@@ -61,7 +61,7 @@ class IOBufTests(unittest.TestCase):
def test_iter(self) -> None:
x = b"testtest"
xb = IOBuf(x)
self.assertEqual(b''.join(iter(xb)), x)
self.assertEqual(b"".join(iter(xb)), x)
def test_bytes(self) -> None:
x = b"omgwtfbbq"
......
......@@ -11,14 +11,17 @@ from Cython.Compiler import Options
Options.fast_fail = True
ext = Extension("folly.executor",
sources=['folly/executor.pyx'],
libraries=['folly_pic', 'glog', 'double-conversion', 'iberty'])
ext = Extension(
"folly.executor",
sources=["folly/executor.pyx"],
libraries=["folly_pic", "glog", "double-conversion", "iberty"],
)
setup(name="folly",
version='0.0.1',
packages=['folly'],
package_data={"": ['*.pxd', '*.h']},
zip_safe=False,
ext_modules=cythonize([ext],
compiler_directives={'language_level': 3, }))
setup(
name="folly",
version="0.0.1",
packages=["folly"],
package_data={"": ["*.pxd", "*.h"]},
zip_safe=False,
ext_modules=cythonize([ext], compiler_directives={"language_level": 3}),
)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment