Chromium Code Reviews| Index: client/libs/logdog/streamname.py |
| diff --git a/client/libs/logdog/streamname.py b/client/libs/logdog/streamname.py |
| index 8aaffb830b84db23fd0fdc31f93bec56ee7087cf..63d4c7da26979479fbf7735916a5b9d37d11a083 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,82 @@ 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. |
| + |
|
jbudorick
2016/10/27 13:24:06
nit: missing Args
dnj
2016/10/27 22:42:45
Done.
|
| + 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 urlquote(self): |
| + return urllib.quote(str(self), safe='') |
| + |
| + |
| +def get_logdog_viewer_url(host, *stream_paths): |
| + """Returns (str): The LogDog viewer URL for the named stream(s). |
| + |
| + Args: |
| + host (str): The name of the Coordiantor host. |
| + stream_paths: A set of StreamPath instances for the stream paths to |
| + generate the URL for. |
| + """ |
| + if len(stream_paths) == 0: |
| + raise ValueError('At least one stream name must be supplied.') |
| + |
| + return urlparse.urlunparse(( |
| + 'https', # Scheme |
| + host, # netloc |
| + 'v/', # path |
| + '', # params |
| + '&'.join(('s=%s' % (path.urlquote(),) for path in stream_paths)), # query |
| + '', # fragment |
| + )) |