| Index: client/libs/logdog/streamname.py
|
| diff --git a/client/libs/logdog/streamname.py b/client/libs/logdog/streamname.py
|
| index 8aaffb830b84db23fd0fdc31f93bec56ee7087cf..5cd3b3144ef3ea38815fff2629d771bbd3a88ad6 100644
|
| --- a/client/libs/logdog/streamname.py
|
| +++ b/client/libs/logdog/streamname.py
|
| @@ -2,9 +2,12 @@
|
| # Use of this source code is governed under the Apache License, Version 2.0
|
| # that can be found in the LICENSE file.
|
|
|
| +import collections
|
| import re
|
| import string
|
| import types
|
| +import urllib
|
| +import urlparse
|
|
|
| _ALNUM_CHARS = string.ascii_letters + string.digits
|
| _SEGMENT_RE_BASE = r'[a-zA-Z0-9][a-zA-Z0-9:_\-.]*'
|
| @@ -105,3 +108,81 @@ def _is_valid_stream_char(ch, first=False):
|
|
|
| # Check additional middle-name characters:
|
| return ch in ':_-./'
|
| +
|
| +
|
| +class StreamPath(collections.namedtuple('_StreamPath', ('prefix', 'name'))):
|
| + """StreamPath is a full stream path.
|
| +
|
| + This consists of both a stream prefix and a stream name.
|
| +
|
| + When constructed with parse or make, the stream path must be completely valid.
|
| + However, invalid stream paths may be constructed by manually instantiation.
|
| + This can be useful for wildcard query values (e.g., "prefix='foo/*/bar/**'").
|
| + """
|
| +
|
| + @classmethod
|
| + def make(cls, prefix, name):
|
| + """Returns (StreamPath): The validated StreamPath instance.
|
| +
|
| + Args:
|
| + prefix (str): the prefix component
|
| + name (str): the name component
|
| +
|
| + Raises:
|
| + ValueError: If path is not a full, valid stream path string.
|
| + """
|
| + inst = cls(prefix=prefix, name=name)
|
| + inst.validate()
|
| + return inst
|
| +
|
| + @classmethod
|
| + def parse(cls, path):
|
| + """Returns (StreamPath): The parsed StreamPath instance.
|
| +
|
| + Args:
|
| + path (str): the full stream path to parse.
|
| +
|
| + Raises:
|
| + ValueError: If path is not a full, valid stream path string.
|
| + """
|
| + parts = path.split('/+/', 1)
|
| + if len(parts) != 2:
|
| + raise ValueError('Not a full stream path: [%s]' % (path,))
|
| + return cls.make(*parts)
|
| +
|
| + def validate(self):
|
| + """Raises: ValueError if this is not a valid stream name."""
|
| + try:
|
| + validate_stream_name(self.prefix)
|
| + except ValueError as e:
|
| + raise ValueError('Invalid prefix component [%s]: %s' % (
|
| + self.prefix, e.message,))
|
| +
|
| + try:
|
| + validate_stream_name(self.name)
|
| + except ValueError as e:
|
| + raise ValueError('Invalid name component [%s]: %s' % (
|
| + self.name, e.message,))
|
| +
|
| + def __str__(self):
|
| + return '%s/+/%s' % (self.prefix, self.name)
|
| +
|
| +
|
| +def get_logdog_viewer_url(host, project, *stream_paths):
|
| + """Returns (str): The LogDog viewer URL for the named stream(s).
|
| +
|
| + Args:
|
| + host (str): The name of the Coordiantor host.
|
| + project (str): The project name.
|
| + stream_paths: A set of StreamPath instances for the stream paths to
|
| + generate the URL for.
|
| + """
|
| + return urlparse.urlunparse((
|
| + 'https', # Scheme
|
| + host, # netloc
|
| + 'v/', # path
|
| + '', # params
|
| + '&'.join(('s=%s' % (urllib.quote('%s/%s' % (project, path), safe=''))
|
| + for path in stream_paths)), # query
|
| + '', # fragment
|
| + ))
|
|
|