mirror of
https://github.com/beetbox/beets.git
synced 2026-01-12 19:24:32 +01:00
Removed unicode_literals from module util
This commit is contained in:
parent
2048a4fbcb
commit
95e940b9f2
7 changed files with 74 additions and 81 deletions
|
|
@ -15,8 +15,7 @@
|
|||
|
||||
"""Miscellaneous utility functions."""
|
||||
|
||||
from __future__ import (division, absolute_import, print_function,
|
||||
unicode_literals)
|
||||
from __future__ import (division, absolute_import, print_function)
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
|
|
@ -57,10 +56,10 @@ class HumanReadableException(Exception):
|
|||
def _gerund(self):
|
||||
"""Generate a (likely) gerund form of the English verb.
|
||||
"""
|
||||
if ' ' in self.verb:
|
||||
if u' ' in self.verb:
|
||||
return self.verb
|
||||
gerund = self.verb[:-1] if self.verb.endswith('e') else self.verb
|
||||
gerund += 'ing'
|
||||
gerund = self.verb[:-1] if self.verb.endswith(u'e') else self.verb
|
||||
gerund += u'ing'
|
||||
return gerund
|
||||
|
||||
def _reasonstr(self):
|
||||
|
|
@ -415,7 +414,7 @@ def copy(path, dest, replace=False):
|
|||
path = syspath(path)
|
||||
dest = syspath(dest)
|
||||
if not replace and os.path.exists(dest):
|
||||
raise FilesystemError('file exists', 'copy', (path, dest))
|
||||
raise FilesystemError(u'file exists', 'copy', (path, dest))
|
||||
try:
|
||||
shutil.copyfile(path, dest)
|
||||
except (OSError, IOError) as exc:
|
||||
|
|
@ -436,7 +435,7 @@ def move(path, dest, replace=False):
|
|||
path = syspath(path)
|
||||
dest = syspath(dest)
|
||||
if os.path.exists(dest) and not replace:
|
||||
raise FilesystemError('file exists', 'rename', (path, dest),
|
||||
raise FilesystemError(u'file exists', 'rename', (path, dest),
|
||||
traceback.format_exc())
|
||||
|
||||
# First, try renaming the file.
|
||||
|
|
@ -462,13 +461,13 @@ def link(path, dest, replace=False):
|
|||
path = syspath(path)
|
||||
dest = syspath(dest)
|
||||
if os.path.exists(dest) and not replace:
|
||||
raise FilesystemError('file exists', 'rename', (path, dest),
|
||||
raise FilesystemError(u'file exists', 'rename', (path, dest),
|
||||
traceback.format_exc())
|
||||
try:
|
||||
os.symlink(path, dest)
|
||||
except OSError:
|
||||
raise FilesystemError('Operating system does not support symbolic '
|
||||
'links.', 'link', (path, dest),
|
||||
raise FilesystemError(u'Operating system does not support symbolic '
|
||||
u'links.', 'link', (path, dest),
|
||||
traceback.format_exc())
|
||||
|
||||
|
||||
|
|
@ -619,7 +618,7 @@ def legalize_path(path, replacements, length, extension, fragment):
|
|||
|
||||
def str2bool(value):
|
||||
"""Returns a boolean reflecting a human-entered string."""
|
||||
return value.lower() in ('yes', '1', 'true', 't', 'y')
|
||||
return value.lower() in (u'yes', u'1', u'true', u't', u'y')
|
||||
|
||||
|
||||
def as_string(value):
|
||||
|
|
@ -643,7 +642,7 @@ def plurality(objs):
|
|||
"""
|
||||
c = Counter(objs)
|
||||
if not c:
|
||||
raise ValueError('sequence must be non-empty')
|
||||
raise ValueError(u'sequence must be non-empty')
|
||||
return c.most_common(1)[0]
|
||||
|
||||
|
||||
|
|
@ -766,7 +765,7 @@ def shlex_split(s):
|
|||
return [c.decode('utf8') for c in shlex.split(bs)]
|
||||
|
||||
else:
|
||||
raise TypeError('shlex_split called with non-string')
|
||||
raise TypeError(u'shlex_split called with non-string')
|
||||
|
||||
|
||||
def interactive_open(targets, command):
|
||||
|
|
@ -854,8 +853,8 @@ def raw_seconds_short(string):
|
|||
Raises ValueError if the conversion cannot take place due to `string` not
|
||||
being in the right format.
|
||||
"""
|
||||
match = re.match('^(\d+):([0-5]\d)$', string)
|
||||
match = re.match(r'^(\d+):([0-5]\d)$', string)
|
||||
if not match:
|
||||
raise ValueError('String not in M:SS format')
|
||||
raise ValueError(u'String not in M:SS format')
|
||||
minutes, seconds = map(int, match.groups())
|
||||
return float(minutes * 60 + seconds)
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@
|
|||
"""Abstraction layer to resize images using PIL, ImageMagick, or a
|
||||
public resizing proxy if neither is available.
|
||||
"""
|
||||
from __future__ import (division, absolute_import, print_function,
|
||||
unicode_literals)
|
||||
from __future__ import (division, absolute_import, print_function)
|
||||
|
||||
import urllib
|
||||
import subprocess
|
||||
|
|
@ -125,10 +124,10 @@ def im_getsize(path_in):
|
|||
try:
|
||||
out = util.command_output(cmd)
|
||||
except subprocess.CalledProcessError as exc:
|
||||
log.warn('ImageMagick size query failed')
|
||||
log.warn(u'ImageMagick size query failed')
|
||||
log.debug(
|
||||
'`convert` exited with (status {}) when '
|
||||
'getting size with command {}:\n{}',
|
||||
u'`convert` exited with (status {}) when '
|
||||
u'getting size with command {}:\n{}',
|
||||
exc.returncode, cmd, exc.output.strip()
|
||||
)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ asyncore.
|
|||
|
||||
Bluelet: easy concurrency without all the messy parallelism.
|
||||
"""
|
||||
from __future__ import (division, absolute_import, print_function,
|
||||
unicode_literals)
|
||||
from __future__ import (division, absolute_import, print_function)
|
||||
|
||||
import socket
|
||||
import select
|
||||
|
|
@ -555,7 +554,7 @@ def spawn(coro):
|
|||
and child coroutines run concurrently.
|
||||
"""
|
||||
if not isinstance(coro, types.GeneratorType):
|
||||
raise ValueError('%s is not a coroutine' % coro)
|
||||
raise ValueError(u'%s is not a coroutine' % coro)
|
||||
return SpawnEvent(coro)
|
||||
|
||||
|
||||
|
|
@ -565,7 +564,7 @@ def call(coro):
|
|||
returns a value using end(), then this event returns that value.
|
||||
"""
|
||||
if not isinstance(coro, types.GeneratorType):
|
||||
raise ValueError('%s is not a coroutine' % coro)
|
||||
raise ValueError(u'%s is not a coroutine' % coro)
|
||||
return DelegationEvent(coro)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@
|
|||
|
||||
"""Worry-free YAML configuration files.
|
||||
"""
|
||||
from __future__ import (unicode_literals, absolute_import, print_function,
|
||||
division)
|
||||
from __future__ import (absolute_import, print_function, division)
|
||||
|
||||
import platform
|
||||
import os
|
||||
|
|
@ -101,17 +100,17 @@ class ConfigReadError(ConfigError):
|
|||
self.filename = filename
|
||||
self.reason = reason
|
||||
|
||||
message = 'file {0} could not be read'.format(filename)
|
||||
message = u'file {0} could not be read'.format(filename)
|
||||
if isinstance(reason, yaml.scanner.ScannerError) and \
|
||||
reason.problem == YAML_TAB_PROBLEM:
|
||||
# Special-case error message for tab indentation in YAML markup.
|
||||
message += ': found tab character at line {0}, column {1}'.format(
|
||||
message += u': found tab character at line {0}, column {1}'.format(
|
||||
reason.problem_mark.line + 1,
|
||||
reason.problem_mark.column + 1,
|
||||
)
|
||||
elif reason:
|
||||
# Generic error message uses exception's message.
|
||||
message += ': {0}'.format(reason)
|
||||
message += u': {0}'.format(reason)
|
||||
|
||||
super(ConfigReadError, self).__init__(message)
|
||||
|
||||
|
|
@ -125,7 +124,7 @@ class ConfigSource(dict):
|
|||
def __init__(self, value, filename=None, default=False):
|
||||
super(ConfigSource, self).__init__(value)
|
||||
if filename is not None and not isinstance(filename, BASESTRING):
|
||||
raise TypeError('filename must be a string or None')
|
||||
raise TypeError(u'filename must be a string or None')
|
||||
self.filename = filename
|
||||
self.default = default
|
||||
|
||||
|
|
@ -147,7 +146,7 @@ class ConfigSource(dict):
|
|||
elif isinstance(value, dict):
|
||||
return ConfigSource(value)
|
||||
else:
|
||||
raise TypeError('source value must be a dict')
|
||||
raise TypeError(u'source value must be a dict')
|
||||
|
||||
|
||||
class ConfigView(object):
|
||||
|
|
@ -182,7 +181,7 @@ class ConfigView(object):
|
|||
try:
|
||||
return iter_first(pairs)
|
||||
except ValueError:
|
||||
raise NotFoundError("{0} not found".format(self.name))
|
||||
raise NotFoundError(u"{0} not found".format(self.name))
|
||||
|
||||
def exists(self):
|
||||
"""Determine whether the view has a setting in any source.
|
||||
|
|
@ -213,7 +212,7 @@ class ConfigView(object):
|
|||
raise NotImplementedError
|
||||
|
||||
def __repr__(self):
|
||||
return '<{}: {}>'.format(self.__class__.__name__, self.name)
|
||||
return u'<{}: {}>'.format(self.__class__.__name__, self.name)
|
||||
|
||||
def __iter__(self):
|
||||
"""Iterate over the keys of a dictionary view or the *subviews*
|
||||
|
|
@ -230,7 +229,7 @@ class ConfigView(object):
|
|||
collection = self.get()
|
||||
if not isinstance(collection, (list, tuple)):
|
||||
raise ConfigTypeError(
|
||||
'{0} must be a dictionary or a list, not {1}'.format(
|
||||
u'{0} must be a dictionary or a list, not {1}'.format(
|
||||
self.name, type(collection).__name__
|
||||
)
|
||||
)
|
||||
|
|
@ -308,7 +307,7 @@ class ConfigView(object):
|
|||
cur_keys = dic.keys()
|
||||
except AttributeError:
|
||||
raise ConfigTypeError(
|
||||
'{0} must be a dict, not {1}'.format(
|
||||
u'{0} must be a dict, not {1}'.format(
|
||||
self.name, type(dic).__name__
|
||||
)
|
||||
)
|
||||
|
|
@ -349,7 +348,7 @@ class ConfigView(object):
|
|||
it = iter(collection)
|
||||
except TypeError:
|
||||
raise ConfigTypeError(
|
||||
'{0} must be an iterable, not {1}'.format(
|
||||
u'{0} must be an iterable, not {1}'.format(
|
||||
self.name, type(collection).__name__
|
||||
)
|
||||
)
|
||||
|
|
@ -489,7 +488,7 @@ class Subview(ConfigView):
|
|||
if not isinstance(self.key, int):
|
||||
self.name += '.'
|
||||
if isinstance(self.key, int):
|
||||
self.name += '#{0}'.format(self.key)
|
||||
self.name += u'#{0}'.format(self.key)
|
||||
elif isinstance(self.key, BASESTRING):
|
||||
if isinstance(self.key, bytes):
|
||||
self.name += self.key.decode('utf8')
|
||||
|
|
@ -511,7 +510,7 @@ class Subview(ConfigView):
|
|||
except TypeError:
|
||||
# Not subscriptable.
|
||||
raise ConfigTypeError(
|
||||
"{0} must be a collection, not {1}".format(
|
||||
u"{0} must be a collection, not {1}".format(
|
||||
self.parent.name, type(collection).__name__
|
||||
)
|
||||
)
|
||||
|
|
@ -621,7 +620,7 @@ class Loader(yaml.SafeLoader):
|
|||
else:
|
||||
raise yaml.constructor.ConstructorError(
|
||||
None, None,
|
||||
'expected a mapping node, but found %s' % node.id,
|
||||
u'expected a mapping node, but found %s' % node.id,
|
||||
node.start_mark
|
||||
)
|
||||
|
||||
|
|
@ -632,7 +631,7 @@ class Loader(yaml.SafeLoader):
|
|||
hash(key)
|
||||
except TypeError as exc:
|
||||
raise yaml.constructor.ConstructorError(
|
||||
'while constructing a mapping',
|
||||
u'while constructing a mapping',
|
||||
node.start_mark, 'found unacceptable key (%s)' % exc,
|
||||
key_node.start_mark
|
||||
)
|
||||
|
|
@ -710,9 +709,9 @@ class Dumper(yaml.SafeDumper):
|
|||
"""Represent bool as 'yes' or 'no' instead of 'true' or 'false'.
|
||||
"""
|
||||
if data:
|
||||
value = 'yes'
|
||||
value = u'yes'
|
||||
else:
|
||||
value = 'no'
|
||||
value = u'no'
|
||||
return self.represent_scalar('tag:yaml.org,2002:bool', value)
|
||||
|
||||
def represent_none(self, data):
|
||||
|
|
@ -837,7 +836,7 @@ class Configuration(RootView):
|
|||
appdir = os.environ[self._env_var]
|
||||
appdir = os.path.abspath(os.path.expanduser(appdir))
|
||||
if os.path.isfile(appdir):
|
||||
raise ConfigError('{0} must be a directory'.format(
|
||||
raise ConfigError(u'{0} must be a directory'.format(
|
||||
self._env_var
|
||||
))
|
||||
|
||||
|
|
@ -990,7 +989,7 @@ class Template(object):
|
|||
return self.convert(value, view)
|
||||
elif self.default is REQUIRED:
|
||||
# Missing required value. This is an error.
|
||||
raise NotFoundError("{0} not found".format(view.name))
|
||||
raise NotFoundError(u"{0} not found".format(view.name))
|
||||
else:
|
||||
# Missing value, but not required.
|
||||
return self.default
|
||||
|
|
@ -1015,11 +1014,11 @@ class Template(object):
|
|||
"""
|
||||
exc_class = ConfigTypeError if type_error else ConfigValueError
|
||||
raise exc_class(
|
||||
'{0}: {1}'.format(view.name, message)
|
||||
u'{0}: {1}'.format(view.name, message)
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return '{0}({1})'.format(
|
||||
return u'{0}({1})'.format(
|
||||
type(self).__name__,
|
||||
'' if self.default is REQUIRED else repr(self.default),
|
||||
)
|
||||
|
|
@ -1036,7 +1035,7 @@ class Integer(Template):
|
|||
elif isinstance(value, float):
|
||||
return int(value)
|
||||
else:
|
||||
self.fail('must be a number', view, True)
|
||||
self.fail(u'must be a number', view, True)
|
||||
|
||||
|
||||
class Number(Template):
|
||||
|
|
@ -1049,7 +1048,7 @@ class Number(Template):
|
|||
return value
|
||||
else:
|
||||
self.fail(
|
||||
'must be numeric, not {0}'.format(type(value).__name__),
|
||||
u'must be numeric, not {0}'.format(type(value).__name__),
|
||||
view,
|
||||
True
|
||||
)
|
||||
|
|
@ -1111,12 +1110,12 @@ class String(Template):
|
|||
if isinstance(value, BASESTRING):
|
||||
if self.pattern and not self.regex.match(value):
|
||||
self.fail(
|
||||
"must match the pattern {0}".format(self.pattern),
|
||||
u"must match the pattern {0}".format(self.pattern),
|
||||
view
|
||||
)
|
||||
return value
|
||||
else:
|
||||
self.fail('must be a string', view, True)
|
||||
self.fail(u'must be a string', view, True)
|
||||
|
||||
|
||||
class Choice(Template):
|
||||
|
|
@ -1137,7 +1136,7 @@ class Choice(Template):
|
|||
"""
|
||||
if value not in self.choices:
|
||||
self.fail(
|
||||
'must be one of {0}, not {1}'.format(
|
||||
u'must be one of {0}, not {1}'.format(
|
||||
repr(list(self.choices)), repr(value)
|
||||
),
|
||||
view
|
||||
|
|
@ -1206,7 +1205,7 @@ class OneOf(Template):
|
|||
raise ConfigTemplateError(exc)
|
||||
|
||||
self.fail(
|
||||
'must be one of {0}, not {1}'.format(
|
||||
u'must be one of {0}, not {1}'.format(
|
||||
repr(self.allowed), repr(value)
|
||||
),
|
||||
view
|
||||
|
|
@ -1242,7 +1241,7 @@ class StrSeq(Template):
|
|||
try:
|
||||
value = list(value)
|
||||
except TypeError:
|
||||
self.fail('must be a whitespace-separated string or a list',
|
||||
self.fail(u'must be a whitespace-separated string or a list',
|
||||
view, True)
|
||||
|
||||
def convert(x):
|
||||
|
|
@ -1251,7 +1250,7 @@ class StrSeq(Template):
|
|||
elif isinstance(x, bytes):
|
||||
return x.decode('utf8', 'ignore')
|
||||
else:
|
||||
self.fail('must be a list of strings', view, True)
|
||||
self.fail(u'must be a list of strings', view, True)
|
||||
return list(map(convert, value))
|
||||
|
||||
|
||||
|
|
@ -1301,19 +1300,19 @@ class Filename(Template):
|
|||
if not isinstance(template, (collections.Mapping, MappingTemplate)):
|
||||
# disallow config.get(Filename(relative_to='foo'))
|
||||
raise ConfigTemplateError(
|
||||
'relative_to may only be used when getting multiple values.'
|
||||
u'relative_to may only be used when getting multiple values.'
|
||||
)
|
||||
|
||||
elif self.relative_to == view.key:
|
||||
raise ConfigTemplateError(
|
||||
'{0} is relative to itself'.format(view.name)
|
||||
u'{0} is relative to itself'.format(view.name)
|
||||
)
|
||||
|
||||
elif self.relative_to not in view.parent.keys():
|
||||
# self.relative_to is not in the config
|
||||
self.fail(
|
||||
(
|
||||
'needs sibling value "{0}" to expand relative path'
|
||||
u'needs sibling value "{0}" to expand relative path'
|
||||
).format(self.relative_to),
|
||||
view
|
||||
)
|
||||
|
|
@ -1335,12 +1334,12 @@ class Filename(Template):
|
|||
if next_relative in template.subtemplates:
|
||||
# we encountered this config key previously
|
||||
raise ConfigTemplateError((
|
||||
'{0} and {1} are recursively relative'
|
||||
u'{0} and {1} are recursively relative'
|
||||
).format(view.name, self.relative_to))
|
||||
else:
|
||||
raise ConfigTemplateError((
|
||||
'missing template for {0}, needed to expand {1}\'s' +
|
||||
'relative path'
|
||||
u'missing template for {0}, needed to expand {1}\'s' +
|
||||
u'relative path'
|
||||
).format(self.relative_to, view.name))
|
||||
|
||||
next_template.subtemplates[next_relative] = rel_to_template
|
||||
|
|
@ -1352,7 +1351,7 @@ class Filename(Template):
|
|||
path, source = view.first()
|
||||
if not isinstance(path, BASESTRING):
|
||||
self.fail(
|
||||
'must be a filename, not {0}'.format(type(path).__name__),
|
||||
u'must be a filename, not {0}'.format(type(path).__name__),
|
||||
view,
|
||||
True
|
||||
)
|
||||
|
|
@ -1390,7 +1389,7 @@ class TypeTemplate(Template):
|
|||
def convert(self, value, view):
|
||||
if not isinstance(value, self.typ):
|
||||
self.fail(
|
||||
'must be a {0}, not {1}'.format(
|
||||
u'must be a {0}, not {1}'.format(
|
||||
self.typ.__name__,
|
||||
type(value).__name__,
|
||||
),
|
||||
|
|
@ -1444,4 +1443,4 @@ def as_template(value):
|
|||
elif isinstance(value, type):
|
||||
return TypeTemplate(value)
|
||||
else:
|
||||
raise ValueError('cannot convert to template: {0!r}'.format(value))
|
||||
raise ValueError(u'cannot convert to template: {0!r}'.format(value))
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@
|
|||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
|
||||
from __future__ import (division, absolute_import, print_function,
|
||||
unicode_literals)
|
||||
from __future__ import (division, absolute_import, print_function)
|
||||
|
||||
from enum import Enum
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@ This is sort of like a tiny, horrible degeneration of a real templating
|
|||
engine like Jinja2 or Mustache.
|
||||
"""
|
||||
|
||||
from __future__ import (division, absolute_import, print_function,
|
||||
unicode_literals)
|
||||
from __future__ import (division, absolute_import, print_function)
|
||||
|
||||
import re
|
||||
import ast
|
||||
|
|
@ -79,7 +78,7 @@ def ex_literal(val):
|
|||
return ast.Name(bytes(val), ast.Load())
|
||||
elif isinstance(val, basestring):
|
||||
return ast.Str(val)
|
||||
raise TypeError('no literal for {0}'.format(type(val)))
|
||||
raise TypeError(u'no literal for {0}'.format(type(val)))
|
||||
|
||||
|
||||
def ex_varassign(name, expr):
|
||||
|
|
@ -571,4 +570,4 @@ if __name__ == b'__main__':
|
|||
'from __main__ import _tmpl, _vars, _funcs',
|
||||
number=10000)
|
||||
print(comp_time)
|
||||
print('Speedup:', interp_time / comp_time)
|
||||
print(u'Speedup:', interp_time / comp_time)
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@ To do so, pass an iterable of coroutines to the Pipeline constructor
|
|||
in place of any single coroutine.
|
||||
"""
|
||||
|
||||
from __future__ import (division, absolute_import, print_function,
|
||||
unicode_literals)
|
||||
from __future__ import (division, absolute_import, print_function)
|
||||
|
||||
import Queue
|
||||
from threading import Thread, Lock
|
||||
|
|
@ -362,7 +361,7 @@ class Pipeline(object):
|
|||
be at least two stages.
|
||||
"""
|
||||
if len(stages) < 2:
|
||||
raise ValueError('pipeline must have at least two stages')
|
||||
raise ValueError(u'pipeline must have at least two stages')
|
||||
self.stages = []
|
||||
for stage in stages:
|
||||
if isinstance(stage, (list, tuple)):
|
||||
|
|
@ -467,14 +466,14 @@ if __name__ == b'__main__':
|
|||
# in parallel.
|
||||
def produce():
|
||||
for i in range(5):
|
||||
print('generating %i' % i)
|
||||
print(u'generating %i' % i)
|
||||
time.sleep(1)
|
||||
yield i
|
||||
|
||||
def work():
|
||||
num = yield
|
||||
while True:
|
||||
print('processing %i' % num)
|
||||
print(u'processing %i' % num)
|
||||
time.sleep(2)
|
||||
num = yield num * 2
|
||||
|
||||
|
|
@ -482,7 +481,7 @@ if __name__ == b'__main__':
|
|||
while True:
|
||||
num = yield
|
||||
time.sleep(1)
|
||||
print('received %i' % num)
|
||||
print(u'received %i' % num)
|
||||
|
||||
ts_start = time.time()
|
||||
Pipeline([produce(), work(), consume()]).run_sequential()
|
||||
|
|
@ -491,22 +490,22 @@ if __name__ == b'__main__':
|
|||
ts_par = time.time()
|
||||
Pipeline([produce(), (work(), work()), consume()]).run_parallel()
|
||||
ts_end = time.time()
|
||||
print('Sequential time:', ts_seq - ts_start)
|
||||
print('Parallel time:', ts_par - ts_seq)
|
||||
print('Multiply-parallel time:', ts_end - ts_par)
|
||||
print(u'Sequential time:', ts_seq - ts_start)
|
||||
print(u'Parallel time:', ts_par - ts_seq)
|
||||
print(u'Multiply-parallel time:', ts_end - ts_par)
|
||||
print()
|
||||
|
||||
# Test a pipeline that raises an exception.
|
||||
def exc_produce():
|
||||
for i in range(10):
|
||||
print('generating %i' % i)
|
||||
print(u'generating %i' % i)
|
||||
time.sleep(1)
|
||||
yield i
|
||||
|
||||
def exc_work():
|
||||
num = yield
|
||||
while True:
|
||||
print('processing %i' % num)
|
||||
print(u'processing %i' % num)
|
||||
time.sleep(3)
|
||||
if num == 3:
|
||||
raise Exception()
|
||||
|
|
@ -515,6 +514,6 @@ if __name__ == b'__main__':
|
|||
def exc_consume():
|
||||
while True:
|
||||
num = yield
|
||||
print('received %i' % num)
|
||||
print(u'received %i' % num)
|
||||
|
||||
Pipeline([exc_produce(), exc_work(), exc_consume()]).run_parallel(1)
|
||||
|
|
|
|||
Loading…
Reference in a new issue