~ubuntu-branches/ubuntu/vivid/simplestreams/vivid-updates

« back to all changes in this revision

Viewing changes to bin/sstream-query

  • Committer: Package Import Robot
  • Author(s): Scott Moser
  • Date: 2013-06-28 16:23:11 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20130628162311-zit9qzwvhsexcarl
Tags: 0.1.0~bzr266-0ubuntu1
* New upstream snapshot.
  * include sstream-query, improved sstream-sync
  * supports python3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python3
 
2
#
 
3
# client showing use of command_hook_mirror
 
4
 
 
5
from simplestreams import mirrors
 
6
from simplestreams import log
 
7
from simplestreams import util
 
8
 
 
9
import argparse
 
10
import os
 
11
import re
 
12
import sys
 
13
import yaml
 
14
 
 
15
 
 
16
def warn(msg):
 
17
    sys.stderr.write("WARN: %s" % msg)
 
18
 
 
19
 
 
20
class ItemFilter(object):
 
21
    def __init__(self, content, noneval=""):
 
22
        rparsefmt="(\w+)[ ]*([!]{0,1}[=~])[ ]*(.*)[ ]*$"
 
23
        parsed = re.match(rparsefmt, content)
 
24
 
 
25
        if not parsed:
 
26
            raise ValueError("Unable to parse expression %s" % content)
 
27
 
 
28
        (key, op, val) = parsed.groups()
 
29
 
 
30
        if op in ("!=", "="):
 
31
            self._matches = val.__eq__
 
32
        elif op in ("!~", "~"):
 
33
            self._matches = re.compile(val).search
 
34
        else:
 
35
            raise ValueError("Bad parsing of %s" % content)
 
36
 
 
37
        self.negator = (op[0] != "!")
 
38
        self.op = op
 
39
        self.key = key
 
40
        self.value = val
 
41
        self.content = content
 
42
        self.noneval = noneval
 
43
 
 
44
 
 
45
    def __str__(self):
 
46
        return "%s %s %s [none=%s]" % (self.key, self.op,
 
47
                                       self.value, self.noneval)
 
48
 
 
49
    def __repr__(self):
 
50
        return self.__str__()
 
51
 
 
52
    def matches(self, item):
 
53
        val = str(item.get(self.key, self.noneval))
 
54
        return (self.negator == bool(self._matches(val)))
 
55
 
 
56
 
 
57
def get_filters(filters, noneval=""):
 
58
    flist = []
 
59
    for f in filters:
 
60
        flist.append(ItemFilter(f, noneval=noneval))
 
61
    return flist
 
62
 
 
63
 
 
64
class FilterMirror(mirrors.BasicMirrorWriter):
 
65
    def __init__(self, config=None):
 
66
        super(FilterMirror, self).__init__(config=config)
 
67
        if config is None:
 
68
            config = {}
 
69
        self.config = config
 
70
        self.filters = config.get('filters', [])
 
71
        outfmt = config.get('output_format')
 
72
        if not outfmt:
 
73
            outfmt = "%s"
 
74
        self.output_format = outfmt
 
75
            
 
76
 
 
77
    def load_products(self, path=None, content_id=None):
 
78
        return {'content_id': content_id, 'products': {}}
 
79
 
 
80
    def filter_item(self, data, src, target, pedigree):
 
81
        # src and target are top level products:1.0
 
82
        # data is src['products'][ped[0]]['versions'][ped[1]]['items'][ped[2]]
 
83
        data = util.products_exdata(src, pedigree)
 
84
        for f in self.filters:
 
85
            if not f.matches(data):
 
86
                return False
 
87
        return True
 
88
 
 
89
    def insert_item(self, data, src, target, pedigree, contentsource):
 
90
        # src and target are top level products:1.0
 
91
        # data is src['products'][ped[0]]['versions'][ped[1]]['items'][ped[2]]
 
92
        # contentsource is a ContentSource if 'path' exists in data or None
 
93
        data = util.products_exdata(src, pedigree)
 
94
        if 'path' in data:
 
95
            data.update({'item_url': contentsource.url})
 
96
 
 
97
        try:
 
98
            print(self.output_format % (data))
 
99
        except KeyError as e:
 
100
            sys.stderr.write("output format failed. Missing %s\n" % e.args)
 
101
            sys.stderr.write("item: %s\n" % data)
 
102
 
 
103
 
 
104
def main():
 
105
    parser = argparse.ArgumentParser()
 
106
 
 
107
    parser.add_argument('--max', type=int, default=None, dest='max_items',
 
108
                        help='store at most MAX items in the target')
 
109
 
 
110
    parser.add_argument('--path', default=None,
 
111
                        help='sync from index or products file in mirror')
 
112
 
 
113
    parser.add_argument('--output-format', '-o', action='store', default=None)
 
114
    parser.add_argument('--verbose', '-v', action='count', default=0)
 
115
    parser.add_argument('--log-file', default=sys.stderr,
 
116
                        type=argparse.FileType('w'))
 
117
 
 
118
    parser.add_argument('mirror_url')
 
119
    parser.add_argument('filters', nargs='*', default=[])
 
120
 
 
121
    cmdargs = parser.parse_args()
 
122
 
 
123
    (mirror_url, path) = util.path_from_mirror_url(cmdargs.mirror_url,
 
124
                                                   cmdargs.path)
 
125
 
 
126
    level = (log.ERROR, log.INFO, log.DEBUG)[min(cmdargs.verbose, 2)]
 
127
    log.basicConfig(stream=cmdargs.log_file, level=level)
 
128
 
 
129
    smirror = mirrors.UrlMirrorReader(mirror_url)
 
130
 
 
131
    filters = get_filters(cmdargs.filters)
 
132
    cfg = {'max_items': cmdargs.max_items,
 
133
           'filters': filters,
 
134
           'output_format': cmdargs.output_format}
 
135
 
 
136
    tmirror = FilterMirror(config=cfg)
 
137
    tmirror.sync(smirror.reader, path)
 
138
 
 
139
if __name__ == '__main__':
 
140
    main()
 
141
 
 
142
# vi: ts=4 expandtab syntax=python