diff --git a/TUTORIAL.mkd b/TUTORIAL.mkd index e160198..b5586d3 100644 --- a/TUTORIAL.mkd +++ b/TUTORIAL.mkd @@ -447,8 +447,9 @@ extension. [PyYAML]: http://pyyaml.org/ [libyaml]: http://pyyaml.org/wiki/LibYAML -If, for whatever reason, you cannot use PyYAML, you can still use beanstalkc -and just leave the YAML responses unparsed. To do that, pass `parse_yaml=False` +If, for whatever reason, you cannot use PyYAML, you can still use beanstalkc. +beanstalkc includes a limited parser which may suit your needs, or you can +just leave the YAML responses unparsed. To do that, pass `parse_yaml=False` when creating the `Connection`: >>> beanstalk = beanstalkc.Connection(host='localhost', @@ -482,3 +483,8 @@ Alternatively, you can also pass a function to be used as YAML parser: >>> beanstalk.close() This should come in handy if PyYAML simply does not fit your needs. + +The output of the builtin parser is mostly identical to PyYAML for the +data returned by beanstalkd. The known difference is that all non-integer +values are left as strings. This affects a limited set of keys in the +stats() response. diff --git a/beanstalkc.py b/beanstalkc.py index 511f514..725828b 100755 --- a/beanstalkc.py +++ b/beanstalkc.py @@ -50,8 +50,7 @@ def __init__(self, host=DEFAULT_HOST, port=DEFAULT_PORT, parse_yaml=True, try: parse_yaml = __import__('yaml').load except ImportError: - logging.error('Failed to load PyYAML, will not parse YAML') - parse_yaml = False + parse_yaml = self.__yparse self._connect_timeout = connect_timeout self._parse_yaml = parse_yaml or (lambda x: x) self.host = host @@ -251,6 +250,23 @@ def stats_job(self, jid): ['OK'], ['NOT_FOUND']) + @staticmethod + def __yparse(stats): + "best efforts yaml parser, sufficient for tube stats" + try: + t = stats[4:].rstrip().split('\n') + if t and t[0][:2] != '- ': + # We need to make the second argument an int if possible. + # The weird order (not ...) is to ensure '0' gets converted + # to int + return dict((y[0], not y[1].isdigit() and y[1] or int(y[1])) + for y in (x.split(': ', 1) for x in t)) + else: + return [x[2:] for x in t] + except: + return stats + + class Job(object): def __init__(self, conn, jid, body, reserved=True):