Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ threaded
:target: https://pypi.python.org/pypi/threaded
.. image:: https://img.shields.io/github/license/python-useful-helpers/threaded.svg
:target: https://raw.githubusercontent.com/python-useful-helpers/threaded/master/LICENSE
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/ambv/black

threaded is a set of decorators, which wrap functions in:

Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ requires = [
"setuptools >= 21.0.0,!=24.0.0,!=34.0.0,!=34.0.1,!=34.0.2,!=34.0.3,!=34.1.0,!=34.1.1,!=34.2.0,!=34.3.0,!=34.3.1,!=34.3.2,!=36.2.0", # PSF/ZPL
"wheel",
]

[tool.black]
line-length = 120
safe = true
12 changes: 11 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,23 @@ exclude =
__init__.py,
docs
ignore =
E203
# whitespace before ':'
show-pep8 = True
show-source = True
count = True
max-line-length = 120

[pydocstyle]
ignore = D401, D203, D213
ignore =
D401,
D202,
D203,
D213
# First line should be in imperative mood; try rephrasing
# No blank lines allowed after function docstring
# 1 blank line required before class docstring
# Multi-line docstring summary should start at the second line

[aliases]
test=pytest
Expand Down
161 changes: 63 additions & 98 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,61 +23,59 @@
import sys

try:
# noinspection PyPackageRequirements
from Cython.Build import cythonize

# noinspection PyPackageRequirements
import gevent
except ImportError:
gevent = cythonize = None

import setuptools

with open(
os.path.join(
os.path.dirname(__file__),
'threaded', '__init__.py'
)
) as f:
with open(os.path.join(os.path.dirname(__file__), "threaded", "__init__.py")) as f:
source = f.read()

with open('requirements.txt') as f:
with open("requirements.txt") as f:
required = f.read().splitlines()

with open('README.rst',) as f:
with open("README.rst") as f:
long_description = f.read()


def _extension(modpath):
"""Make setuptools.Extension."""
return setuptools.Extension(modpath, [modpath.replace('.', '/') + '.py'])
return setuptools.Extension(modpath, [modpath.replace(".", "/") + ".py"])


requires_optimization = [
_extension('threaded._class_decorator'),
_extension('threaded._base_threaded'),
_extension('threaded._asynciotask'),
_extension('threaded._threaded'),
_extension('threaded._threadpooled'),
_extension('threaded._gthreadpooled'),
_extension("threaded._class_decorator"),
_extension("threaded._base_threaded"),
_extension("threaded._asynciotask"),
_extension("threaded._threaded"),
_extension("threaded._threadpooled"),
_extension("threaded._gthreadpooled"),
]

if 'win32' != sys.platform:
requires_optimization.append(
_extension('threaded.__init__')
)
if "win32" != sys.platform:
requires_optimization.append(_extension("threaded.__init__"))

ext_modules = cythonize(
requires_optimization,
compiler_directives=dict(
always_allow_keywords=True,
binding=True,
embedsignature=True,
overflowcheck=True,
language_level=3,
# noinspection PyCallingNonCallable
ext_modules = (
cythonize(
requires_optimization,
compiler_directives=dict(
always_allow_keywords=True, binding=True, embedsignature=True, overflowcheck=True, language_level=3
),
)
) if cythonize is not None else []
if cythonize is not None
else []
)


class BuildFailed(Exception):
"""For install clear scripts."""

pass


Expand All @@ -91,10 +89,10 @@ def run(self):

# Copy __init__.py back to repair package.
build_dir = os.path.abspath(self.build_lib)
root_dir = os.path.abspath(os.path.join(__file__, '..'))
root_dir = os.path.abspath(os.path.join(__file__, ".."))
target_dir = build_dir if not self.inplace else root_dir

src_file = os.path.join('threaded', '__init__.py')
src_file = os.path.join("threaded", "__init__.py")

src = os.path.join(root_dir, src_file)
dst = os.path.join(target_dir, src_file)
Expand All @@ -103,7 +101,7 @@ def run(self):
shutil.copyfile(src, dst)
except (
distutils.errors.DistutilsPlatformError,
getattr(globals()['__builtins__'], 'FileNotFoundError', OSError)
getattr(globals()["__builtins__"], "FileNotFoundError", OSError),
):
raise BuildFailed()

Expand All @@ -115,7 +113,7 @@ def build_extension(self, ext):
distutils.errors.CCompilerError,
distutils.errors.DistutilsExecError,
distutils.errors.DistutilsPlatformError,
ValueError
ValueError,
):
raise BuildFailed()

Expand Down Expand Up @@ -167,11 +165,7 @@ def get_simple_vars_from_src(src):
>>> get_simple_vars_from_src(multiple_assign)
OrderedDict([('e', 1), ('f', 1), ('g', 1)])
"""
ast_data = (
ast.Str, ast.Num,
ast.List, ast.Set, ast.Dict, ast.Tuple,
ast.Bytes, ast.NameConstant,
)
ast_data = (ast.Str, ast.Num, ast.List, ast.Set, ast.Dict, ast.Tuple, ast.Bytes, ast.NameConstant)

tree = ast.parse(src)

Expand All @@ -183,9 +177,7 @@ def get_simple_vars_from_src(src):
try:
if isinstance(node.value, ast_data):
value = ast.literal_eval(node.value)
elif isinstance( # NameConstant in python < 3.4
node.value, ast.Name
) and isinstance(
elif isinstance(node.value, ast.Name) and isinstance( # NameConstant in python < 3.4
node.value.ctx, ast.Load # Read constant
):
value = ast.literal_eval(node.value)
Expand All @@ -194,91 +186,64 @@ def get_simple_vars_from_src(src):
except ValueError:
continue
for tgt in node.targets:
if isinstance(
tgt, ast.Name
) and isinstance(
tgt.ctx, ast.Store
):
if isinstance(tgt, ast.Name) and isinstance(tgt.ctx, ast.Store):
result[tgt.id] = value
return result


variables = get_simple_vars_from_src(source)

classifiers = [
'Development Status :: 5 - Production/Stable',

'Intended Audience :: Developers',
'Topic :: Software Development :: Libraries :: Python Modules',

'License :: OSI Approved :: Apache Software License',

'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',

'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries :: Python Modules",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]

keywords = [
'pooling',
'multithreading',
'threading',
'asyncio',
'gevent',
'development',
]
keywords = ["pooling", "multithreading", "threading", "asyncio", "gevent", "development"]

setup_args = dict(
name='threaded',
author=variables['__author__'],
author_email=variables['__author_email__'],
maintainer=', '.join(
'{name} <{email}>'.format(name=name, email=email)
for name, email in variables['__maintainers__'].items()
name="threaded",
author=variables["__author__"],
author_email=variables["__author_email__"],
maintainer=", ".join(
"{name} <{email}>".format(name=name, email=email) for name, email in variables["__maintainers__"].items()
),
url=variables['__url__'],
version=variables['__version__'],
license=variables['__license__'],
description=variables['__description__'],
url=variables["__url__"],
version=variables["__version__"],
license=variables["__license__"],
description=variables["__description__"],
long_description=long_description,
classifiers=classifiers,
keywords=keywords,
python_requires='>=3.4',
python_requires=">=3.4",
# While setuptools cannot deal with pre-installed incompatible versions,
# setting a lower bound is not harmful - it makes error messages cleaner. DO
# NOT set an upper bound on setuptools, as that will lead to uninstallable
# situations as progressive releases of projects are done.
# Blacklist setuptools 34.0.0-34.3.2 due to https://github.com/pypa/setuptools/issues/951
# Blacklist setuptools 36.2.0 due to https://github.com/pypa/setuptools/issues/1086
setup_requires="setuptools >= 21.0.0,!=24.0.0,"
"!=34.0.0,!=34.0.1,!=34.0.2,!=34.0.3,!=34.1.0,!=34.1.1,!=34.2.0,!=34.3.0,!=34.3.1,!=34.3.2,"
"!=36.2.0",
extras_require={
'gevent': [
'gevent >= 1.2.2'
],
},
"!=34.0.0,!=34.0.1,!=34.0.2,!=34.0.3,!=34.1.0,!=34.1.1,!=34.2.0,!=34.3.0,!=34.3.1,!=34.3.2,"
"!=36.2.0",
extras_require={"gevent": ["gevent >= 1.2.2"]},
install_requires=required,
package_data={
'threaded': ['py.typed'],
},
package_data={"threaded": ["py.typed"]},
)
if cythonize is not None:
setup_args['ext_modules'] = ext_modules
setup_args['cmdclass'] = dict(build_ext=AllowFailRepair)
setup_args["ext_modules"] = ext_modules
setup_args["cmdclass"] = dict(build_ext=AllowFailRepair)

try:
setuptools.setup(**setup_args)
except BuildFailed:
print(
'*' * 80 + '\n'
'* Build Failed!\n'
'* Use clear scripts version.\n'
'*' * 80 + '\n'
)
del setup_args['ext_modules']
del setup_args['cmdclass']
print("*" * 80 + "\n" "* Build Failed!\n" "* Use clear scripts version.\n" "*" * 80 + "\n")
del setup_args["ext_modules"]
del setup_args["cmdclass"]
setuptools.setup(**setup_args)
2 changes: 1 addition & 1 deletion test/async_syntax/test_gevent_threadpooled_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import threaded


@unittest.skipIf(gevent is None, 'No gevent')
@unittest.skipIf(gevent is None, "No gevent")
class TestThreadPooled(unittest.TestCase):
def tearDown(self):
threaded.GThreadPooled.shutdown()
Expand Down
17 changes: 6 additions & 11 deletions test/async_syntax/test_pooled_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,34 +66,29 @@ def test_thread_pooled_loop_getter_context(self):
def loop_getter(target):
return target

@threaded.threadpooled(
loop_getter=loop_getter,
loop_getter_need_context=True
)
@threaded.threadpooled(loop_getter=loop_getter, loop_getter_need_context=True)
async def test(*args, **kwargs):
return threading.current_thread().name

pooled_name = loop.run_until_complete(
asyncio.wait_for(test(loop), 1)
)
pooled_name = loop.run_until_complete(asyncio.wait_for(test(loop), 1))
self.assertNotEqual(pooled_name, threading.current_thread().name)


class TestAsyncIOTask(unittest.TestCase):
def test_default(self):
@threaded.asynciotask
async def test():
return 'test'
return "test"

loop = asyncio.get_event_loop()
res = loop.run_until_complete(asyncio.wait_for(test(), 1))
self.assertEqual(res, 'test')
self.assertEqual(res, "test")

def test_construct(self):
@threaded.asynciotask()
async def test():
return 'test'
return "test"

loop = asyncio.get_event_loop()
res = loop.run_until_complete(asyncio.wait_for(test(), 1))
self.assertEqual(res, 'test')
self.assertEqual(res, "test")
7 changes: 2 additions & 5 deletions test/test_gevent_threadpooled.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import threaded


@unittest.skipIf(gevent is None, 'No gevent')
@unittest.skipIf(gevent is None, "No gevent")
class TestThreadPooled(unittest.TestCase):
def tearDown(self):
threaded.GThreadPooled.shutdown()
Expand All @@ -50,10 +50,7 @@ def test_thread_pooled_config(self):
thread_pooled = threaded.gthreadpooled()
thread_pooled.configure()

self.assertEqual(
thread_pooled.executor.maxsize,
(os.cpu_count() or 1) * 5
)
self.assertEqual(thread_pooled.executor.maxsize, (os.cpu_count() or 1) * 5)

thread_pooled.configure(max_workers=2)

Expand Down
5 changes: 1 addition & 4 deletions test/test_pooled.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ def test():
def test_thread_pooled_config(self):
thread_pooled = threaded.threadpooled()

self.assertEqual(
thread_pooled.executor.max_workers,
(cpu_count() or 1) * 5
)
self.assertEqual(thread_pooled.executor.max_workers, (cpu_count() or 1) * 5)

thread_pooled.configure(max_workers=2)

Expand Down
Loading