Пример #1
0
    def get_class_xsd(self, io, cls):
        """ Returns the XSD for a mapped class. """
        attrs = {}
        attrs['xmlns:gml'] = 'http://www.opengis.net/gml'
        attrs['xmlns:xsd'] = 'http://www.w3.org/2001/XMLSchema'
        tb = TreeBuilder()
        with tag(tb, 'xsd:schema', attrs) as tb:
            with tag(tb, 'xsd:complexType', {'name': cls.__name__}) as tb:
                with tag(tb, 'xsd:complexContent') as tb:
                    with tag(tb, 'xsd:extension',
                             {'base': 'gml:AbstractFeatureType'}) as tb:
                        with tag(tb, 'xsd:sequence') as tb:
                            self.add_class_properties_xsd(tb, cls)

        ElementTree(tb.close()).write(io, encoding='utf-8')
        return io
Пример #2
0
    def get_class_xsd(self, io, cls):
        """ Returns the XSD for a mapped class. """
        attrs = {}
        attrs['xmlns:gml'] = 'http://www.opengis.net/gml'
        attrs['xmlns:xsd'] = 'http://www.w3.org/2001/XMLSchema'
        tb = TreeBuilder()
        with tag(tb, 'xsd:schema', attrs) as tb:
            with tag(tb, 'xsd:complexType', {'name': cls.__name__}) as tb:
                with tag(tb, 'xsd:complexContent') as tb:
                    with tag(tb, 'xsd:extension',
                             {'base': 'gml:AbstractFeatureType'}) as tb:
                        with tag(tb, 'xsd:sequence') as tb:
                            self.add_class_properties_xsd(tb, cls)

        ElementTree(tb.close()).write(io, encoding='utf-8')
        return io
Пример #3
0
def gpx_tag():
    attrs = {
        'creator':
        'http://code.google.com/p/flytecfs',
        'version':
        '1.1',
        'xmlns':
        'http://www.topografix.com/GPX/1/1',
        'xmlns:xsi':
        'http://www.w3.org/2001/XMLSchema-instance',
        'xsi:schemaLocation':
        'http://www.topografix.com/GPX/1/1 '
        'http://www.topografix.com/GPX/1/1/gpx.xsd',
    }
    with tag(TreeBuilder(), 'gpx', attrs) as tb:
        yield tb
Пример #4
0
class XMLGenerator(object):

    def __init__(self, out, encoding='utf-8'):

        self.out = out
        self.encoding = encoding
        self.builder = TreeBuilder()

    def getOutputStream(self):
        return self.out

    def getEncoding(self):
        return self.encoding

    def write(self, data):
        self.builder.data(data)

    def startDocument(self):
        self.out.write('<?xml version="1.0" encoding="%s"?>' %(self.encoding))

    def endDocument(self):

        root = self.builder.close()
        ElementTree(root).write(self.out, self.encoding)
        self.out.flush()

    def startElement(self, tag, attrs):

        self.builder.start(tag, attrs)

    def endElement(self, tag):

        self.builder.end(tag)
    
    def characters(self, data):

        if data:
            self.builder.data(data)
Пример #5
0
def main(argv):
    parser = OptionParser(description='olc2002 to GPX converter')
    parser.add_option('-l', '--league', metavar='STRING')
    parser.add_option('-o', '--output', metavar='FILENAME')
    parser.add_option('--debug', action='store_true')
    parser.set_defaults(debug=False)
    parser.set_defaults(league='OLC')
    options, args = parser.parse_args(argv)
    #
    routes = []
    date = None
    for line in fileinput.input(args[1:]):
        line = line.rstrip()
        m = DEBUG_DATE_RE.match(line)
        if m:
            day, mon, year = map(int, m.groups())
            date = datetime.date(year + 2000, mon, day)
            continue
        m = OUT_TYPE_RE.match(line)
        if m:
            name = PRETTY_NAME[m.group(1)]
            circuit = m.group(1) in CIRCUITS
            route = Route(name, options.league, None, None, None, circuit, [])
            routes.append(route)
            last_time = None
            continue
        m = OUT_FLIGHT_KM_RE.match(line)
        if m:
            route.distance = float(m.group(1))
            continue
        m = OUT_FLIGHT_POINTS_RE.match(line)
        if m:
            route.score = float(m.group(1))
            route.multiplier = route.score / route.distance
            continue
        m = OUT_P_RE.match(line)
        if m:
            name = 'TP%d' % len(route.tps) if route.tps else 'Start'
            lat = int(m.group(5)) + float(m.group(6)) / 60.0
            if m.group(4) == 'S':
                lat = -lat
            lon = int(m.group(8)) + float(m.group(9)) / 60.0
            if m.group(7) == 'W':
                lon = -lon
            time = datetime.time(*map(int, m.group(1, 2, 3)))
            if not last_time is None and time < last_time:
                date += datetime.timedelta(1)
            dt = datetime.datetime.combine(date, time)
            coord = Coord(lat, lon, 0, dt)
            tp = Turnpoint(name, coord)
            route.tps.append(tp)
            last_time = time
            continue
        if options.debug:
            logging.warning(line)
    for route in routes:
        route.tps[-1].name = 'Finish'
    xc = XC(routes)
    with gpx_tag(TreeBuilder()) as tb:
        element = xc.build_tree(tb).close()
    output = open(options.output, 'w') if options.output else sys.stdout
    output.write('<?xml version="1.0" encoding="UTF-8"?>')
    ElementTree(element).write(output)
Пример #6
0
def main(argv):
    parser = OptionParser(usage='Usage: %prog [options] filename.igc',
                          description='IGC to task converter')
    parser.add_option('-o',
                      '--output',
                      metavar='FILENAME',
                      help='set output filename')
    parser.add_option('-n', '--name', metavar='NAME', help='set task name')
    parser.add_option('-z',
                      '--tz-offset',
                      metavar='HOURS',
                      type='int',
                      help='set timezone offset')
    parser.add_option('--start', metavar='NAME', help='set start turnpoint')
    parser.add_option('--start-count',
                      metavar='NUMBER',
                      type='int',
                      help='set start count')
    parser.add_option('--start-radius',
                      metavar='RADIUS',
                      type='int',
                      help='set start radius in meters')
    parser.add_option('--start-time', metavar='TIME', help='set start time')
    parser.add_option('--ess',
                      metavar='NAME',
                      help='set end of speed section turnpoint')
    parser.add_option('--ess-count',
                      metavar='NUMBER',
                      type='int',
                      help='set end of speed section count')
    parser.add_option('--ess-radius',
                      metavar='RADIUS',
                      type='int',
                      help='set end of speed section radius in meters')
    parser.add_option('--goal', metavar='NAME', help='set goal turnpoint')
    parser.add_option('--goal-count',
                      metavar='NUMBER',
                      type='int',
                      help='set goal count')
    parser.add_option('--goal-radius',
                      metavar='RADIUS',
                      type='int',
                      help='set start radius in meters')
    parser.set_defaults(tz_offset=0)
    parser.set_defaults(start_count=0)
    parser.set_defaults(ess_count=0)
    parser.set_defaults(goal_count=0)
    #
    options, args = parser.parse_args(argv)
    if len(args) < 2:
        parser.error('no IGC file specified')
    if len(args) > 2:
        parser.error('excess arguments on command line: %s' % repr(args[2:]))
    #
    igc = IGC(open(args[1]))
    if not igc.c:
        parser.error('%s does not contain a task' % repr(argv[1]))
    tps = []
    for c in igc.c:
        if c.name == 'TAKEOFF' or c.name == 'LANDING':
            continue
        m = re.match(r'([A-Z][0-9]{2})([0-9]{3})', c.name)
        if m:
            name = m.group(1)
            ele = 10 * int(m.group(2))
        else:
            name = c.name
            ele = 0
        coord = Coord(c.lat, c.lon, ele)
        tp = Turnpoint(name, coord)
        tps.append(tp)
    task = Task(options.name, tps)
    #
    if options.start:
        start = find_nth(lambda tp: tp.name == options.start, task.tps,
                         options.start_count)
        if not start:
            parser.error('start turnpoint %s not found' % repr(options.start))
    else:
        start = task.tps[1]
    if options.start_radius:
        start.radius = int(options.start_radius)
    if options.start_time:
        m = re.match(r'(\d+):(\d\d)\Z', options.start_time)
        if not m:
            parser.error('invalid start time %s' % repr(options.start_time))
        hour, minute = map(int, m.group(1, 2))
        start.coord.dt = igc.b[0].dt.replace(hour=hour,
                                             minute=minute,
                                             second=0) \
                         - timedelta(seconds=3600 * options.tz_offset)
    #
    if options.ess:
        ess = find_nth(lambda tp: tp.name == options.ess, task.tps,
                       options.ess_count)
        if not ess:
            parser.error('end of speed section turnpoint %s not found' %
                         repr(options.ess))
    else:
        ess = task.tps[-2]
    if options.ess_radius:
        ess.radius = int(options.ess_radius)
    #
    if options.goal:
        goal = find_nth(lambda tp: tp.name == options.goal, task.tps,
                        options.goal_count)
        if not goal:
            parser.error('goal turnpoint %s not found' % repr(options.goal))
    else:
        goal = task.tps[-1]
    if options.goal_radius:
        goal.radius = int(options.goal_radius)
    #
    with gpx_tag(TreeBuilder()) as tb:
        element = task.build_tree(tb).close()
    output = open(options.output, 'w') if options.output else sys.stdout
    output.write('<?xml version="1.0" encoding="utf-8"?>\n')
    pretty_write(output, element)
Пример #7
0
    def do_rss(self, repo_data, latest):
        """
        Write the RSS feed.
        
        @param repo_data: the dict containing repository data
        @type  repo_data: dict
        @param latest:    the list of tuples returned by get_latest_packages
        @type  latest:    list
        
        @rtype: void
        """
        self.say('Generating rss feed...')
        etb = TreeBuilder()
        out = os.path.join(self.outdir, RSSFILE)
        etb.start('rss', {'version': '2.0'})
        etb.start('channel')
        etb.start('title')
        etb.data(repo_data['title'])
        etb.end('title')
        etb.start('link')
        etb.data('%s/repoview/%s' % (self.opts.url, RSSFILE))
        etb.end('link')
        etb.start('description')
        etb.data('Latest packages for %s' % repo_data['title'])
        etb.end('description')
        etb.start('lastBuildDate')
        etb.data(time.strftime(ISOFORMAT))
        etb.end('lastBuildDate')
        etb.start('generator')
        etb.data('Repoview-%s' % repo_data['my_version'])
        etb.end('generator')

        rss_tpt = os.path.join(self.opts.templatedir, RSSKID)
        rss_kid = Template(file=rss_tpt)
        rss_kid.assume_encoding = "utf-8"
        rss_kid.repo_data = repo_data
        rss_kid.url = self.opts.url

        for row in latest:
            pkg_data = self.get_package_data(row[0])

            rpm = pkg_data['rpms'][0]
            (epoch, version, release, arch, built) = rpm[:5]
            etb.start('item')
            etb.start('guid')
            etb.data('%s/repoview/%s+%s:%s-%s.%s' %
                     (self.opts.url, pkg_data['filename'], epoch, version,
                      release, arch))
            etb.end('guid')
            etb.start('link')
            etb.data('%s/repoview/%s' % (self.opts.url, pkg_data['filename']))
            etb.end('link')
            etb.start('pubDate')
            etb.data(time.strftime(ISOFORMAT, time.gmtime(int(built))))
            etb.end('pubDate')
            etb.start('title')
            etb.data('Update: %s-%s-%s' % (pkg_data['name'], version, release))
            etb.end('title')
            rss_kid.pkg_data = pkg_data
            description = rss_kid.serialize()
            etb.start('description')
            etb.data(description.decode('utf-8'))
            etb.end('description')
            etb.end('item')

        etb.end('channel')
        etb.end('rss')
        rss = etb.close()

        etree = ElementTree(rss)
        out = os.path.join(self.outdir, RSSFILE)
        etree.write(out, 'utf-8')
        self.say('done\n')
Пример #8
0
    def _get_sync(self, view, iq, args):

        try:
            if 'toRepoId' in args and UUID(args['toRepoId']) != self._repoId:
                raise RepositoryMismatchError, args['toRepoId']

            view.refresh(None, None, False)

            repoId = UUID(args['fromRepoId'])
            name = args['name']
            version = int(args.get('version', '0'))
            uuid = args.get('uuid')
            if uuid is not None:
                uuid = UUID(uuid)

            collection, name, uuid = self.findCollection(view, name, uuid)
            share = self.findShare(view, collection, repoId, iq['from'])

            iq = client.IQ(self.client.xmlstream, "result")
            query = iq.addElement(("jabber:x:chandler", "query"))
            sync = query.addElement('sync')
            sync['name'] = name

            changes = self.computeChanges(view, version, collection, share)
            keys = set()
            compressed = len(changes) > 16

            if compressed:
                builder = TreeBuilder()
                dom = formats.ElementTreeDOM()
                data = dom.openElement(builder, 'data')
            else:
                dom = DomishDOM()
                data = dom.openElement(sync, 'data')

            for key, (_changes, status) in changes.iteritems():
                if key not in keys:
                    if status & CItem.DELETED:
                        dom.openElement(data,
                                        'item',
                                        uuid=key.str64(),
                                        status='deleted')
                    else:
                        attrs = {'uuid': key.str64()}
                        if key in collection:
                            attrs['status'] = 'member'
                        item = dom.openElement(data, 'item', **attrs)
                        share.format.exportProcess(dom, key, item, changes,
                                                   keys)
                    dom.closeElement(data, 'item')
                elif key in collection:
                    dom.openElement(data,
                                    'item',
                                    uuid=key.str64(),
                                    status='member')
                    dom.closeElement(data, 'item')

            dom.closeElement(data, 'data')

            sync['fromRepoId'] = self._repoId.str64()
            sync['toRepoId'] = repoId.str64()
            sync['version'] = str(view.itsVersion)
            sync['uuid'] = collection.itsUUID.str64()

            if compressed:
                sync['compressed'] = 'true'
                out = StringIO()
                ElementTree(builder.close()).write(out, 'utf-8')
                sync.children.append(b64encode(compress(out.getvalue())))
                out.close()

        except:
            view.cancel()
            raise

        share.localVersion = view.itsVersion + 1
        share.established = True
        share.ackPending = True
        view.commit()

        return iq
Пример #9
0
 def to_element(self):
     return self.build_tree(TreeBuilder()).close()
Пример #10
0
    def _get_sync(self, view, shareId, peerId, name, op):

        try:
            view.refresh(None, None, False)

            if shareId is not None:
                share = view[shareId]
                peerId = share.conduit.peerId
                toRepoId = share.repoId
                collection = share.contents
                name = collection.displayName
                uuid = collection.itsUUID
                version = share.localVersion
            else:
                collection, name, uuid = self.findCollection(view, name, None)
                toRepoId = None
                version = 0

            replyTo = view[self.client.account].imap.replyToAddress.emailAddress
            share = self.findShare(view, collection, toRepoId, peerId)

            changes = self.computeChanges(view, version, collection, share)
            if op == 'sync' and not changes:
                share.localVersion = view.itsVersion + 1
                view.commit()
                return None

            message = MIMEMultipart()
            message['From'] = replyTo
            message['Reply-To'] = replyTo
            message['To'] = peerId
            message['Subject'] = 'Chandler sent "%s" collection' %(name)
            message['X-chandler'] = 'p2p'
            textPart = MIMEBase('text', 'plain')
            textPart.set_payload('Chandler sent "%s"' %(name))
            message.attach(textPart)
            attachment = MIMEBase('application', 'octet-stream')

            builder = TreeBuilder()
            dom = ElementTreeDOM()
            data = dom.openElement(builder, 'data')

            keys = set()
            for key, (_changes, status) in changes.iteritems():
                if key not in keys:
                    attrs = { 'uuid': key.str64() }
                    if status & CItem.DELETED:
                        attrs['status'] = 'deleted'
                        item = dom.openElement(data, 'item', **attrs)
                    else:
                        if key in collection:
                            attrs['status'] = 'member'
                        item = dom.openElement(data, 'item', **attrs)
                        share.format.exportProcess(dom, key, item,
                                                   changes, keys)
                    dom.closeElement(data, 'item')
                elif key in collection:
                    item = dom.openElement(data, 'item', uuid=key.str64(),
                                           status='member')
                    dom.closeElement(data, 'item')

            dom.closeElement(builder, 'data')
            out = StringIO()
            ElementTree(builder.close()).write(out, 'utf-8')
            data = compress(out.getvalue())
            out.close()

            message['X-chandler-p2p-name'] = name
            message['X-chandler-p2p-from'] = self._repoId.str64()
            if toRepoId is not None:
                message['X-chandler-p2p-to'] = toRepoId.str64()
            message['X-chandler-p2p-item'] = "%s-%d" %(uuid.str64(),
                                                       view.itsVersion)
            message['X-chandler-p2p-op'] = 'sync'

            attachment.set_payload(data)
            encode_base64(attachment)
            attachment.add_header('Content-Disposition', 'attachment',
                                  name=name)
            message.attach(attachment)
        except:
            view.cancel()
            raise

        share.localVersion = view.itsVersion + 1
        share.established = True
        share.ackPending = True
        view.commit()

        return message
Пример #11
0
    def __init__(self, out, encoding='utf-8'):

        self.out = out
        self.encoding = encoding
        self.builder = TreeBuilder()
Пример #12
0
 def do_rss(self, repo_data, latest):
     """
     Write the RSS feed.
     
     @param repo_data: the dict containing repository data
     @type  repo_data: dict
     @param latest:    the list of tuples returned by get_latest_packages
     @type  latest:    list
     
     @rtype: void
     """
     self.say('Generating rss feed...')
     etb = TreeBuilder()
     out = os.path.join(self.outdir, RSSFILE)
     etb.start('rss', {'version': '2.0'})
     etb.start('channel')
     etb.start('title')
     etb.data(repo_data['title'])
     etb.end('title')
     etb.start('link')
     etb.data('%s/repoview/%s' % (self.opts.url, RSSFILE))
     etb.end('link')
     etb.start('description')
     etb.data('Latest packages for %s' % repo_data['title'])
     etb.end('description')
     etb.start('lastBuildDate')
     etb.data(time.strftime(ISOFORMAT))
     etb.end('lastBuildDate')
     etb.start('generator')
     etb.data('Repoview-%s' % repo_data['my_version'])
     etb.end('generator')
     
     rss_tpt = os.path.join(self.opts.templatedir, RSSKID)
     rss_kid = Template(file=rss_tpt)
     rss_kid.assume_encoding = "utf-8"
     rss_kid.repo_data = repo_data
     rss_kid.url = self.opts.url
     
     for row in latest:
         pkg_data = self.get_package_data(row[0])
         
         rpm = pkg_data['rpms'][0]
         (epoch, version, release, arch, built) = rpm[:5]
         etb.start('item')
         etb.start('guid')
         etb.data('%s/repoview/%s+%s:%s-%s.%s' % (self.opts.url, 
                                                  pkg_data['filename'], 
                                                  epoch, version, release, 
                                                  arch))
         etb.end('guid')
         etb.start('link')
         etb.data('%s/repoview/%s' % (self.opts.url, pkg_data['filename']))
         etb.end('link')
         etb.start('pubDate')
         etb.data(time.strftime(ISOFORMAT, time.gmtime(int(built))))
         etb.end('pubDate')
         etb.start('title')
         etb.data('Update: %s-%s-%s' % (pkg_data['name'], version, release))
         etb.end('title')
         rss_kid.pkg_data = pkg_data
         description = rss_kid.serialize()
         etb.start('description')
         etb.data(description.decode('utf-8'))
         etb.end('description')
         etb.end('item')
     
     etb.end('channel')
     etb.end('rss')
     rss = etb.close()
     
     etree = ElementTree(rss)
     out = os.path.join(self.outdir, RSSFILE)
     etree.write(out, 'utf-8')
     self.say('done\n')
Пример #13
0
    def _get_sync(self, view, shareId, peerId, name, op):

        try:
            view.refresh(None, None, False)

            if shareId is not None:
                share = view[shareId]
                peerId = share.conduit.peerId
                toRepoId = share.repoId
                collection = share.contents
                name = collection.displayName
                uuid = collection.itsUUID
                version = share.localVersion
            else:
                collection, name, uuid = self.findCollection(view, name, None)
                toRepoId = None
                version = 0

            replyTo = view[
                self.client.account].imap.replyToAddress.emailAddress
            share = self.findShare(view, collection, toRepoId, peerId)

            changes = self.computeChanges(view, version, collection, share)
            if op == 'sync' and not changes:
                share.localVersion = view.itsVersion + 1
                view.commit()
                return None

            message = MIMEMultipart()
            message['From'] = replyTo
            message['Reply-To'] = replyTo
            message['To'] = peerId
            message['Subject'] = 'Chandler sent "%s" collection' % (name)
            message['X-chandler'] = 'p2p'
            textPart = MIMEBase('text', 'plain')
            textPart.set_payload('Chandler sent "%s"' % (name))
            message.attach(textPart)
            attachment = MIMEBase('application', 'octet-stream')

            builder = TreeBuilder()
            dom = ElementTreeDOM()
            data = dom.openElement(builder, 'data')

            keys = set()
            for key, (_changes, status) in changes.iteritems():
                if key not in keys:
                    attrs = {'uuid': key.str64()}
                    if status & CItem.DELETED:
                        attrs['status'] = 'deleted'
                        item = dom.openElement(data, 'item', **attrs)
                    else:
                        if key in collection:
                            attrs['status'] = 'member'
                        item = dom.openElement(data, 'item', **attrs)
                        share.format.exportProcess(dom, key, item, changes,
                                                   keys)
                    dom.closeElement(data, 'item')
                elif key in collection:
                    item = dom.openElement(data,
                                           'item',
                                           uuid=key.str64(),
                                           status='member')
                    dom.closeElement(data, 'item')

            dom.closeElement(builder, 'data')
            out = StringIO()
            ElementTree(builder.close()).write(out, 'utf-8')
            data = compress(out.getvalue())
            out.close()

            message['X-chandler-p2p-name'] = name
            message['X-chandler-p2p-from'] = self._repoId.str64()
            if toRepoId is not None:
                message['X-chandler-p2p-to'] = toRepoId.str64()
            message['X-chandler-p2p-item'] = "%s-%d" % (uuid.str64(),
                                                        view.itsVersion)
            message['X-chandler-p2p-op'] = 'sync'

            attachment.set_payload(data)
            encode_base64(attachment)
            attachment.add_header('Content-Disposition',
                                  'attachment',
                                  name=name)
            message.attach(attachment)
        except:
            view.cancel()
            raise

        share.localVersion = view.itsVersion + 1
        share.established = True
        share.ackPending = True
        view.commit()

        return message
Пример #14
0
    def _get_sync(self, view, iq, args):

        try:
            if 'toRepoId' in args and UUID(args['toRepoId']) != self._repoId:
                raise RepositoryMismatchError, args['toRepoId']

            view.refresh(None, None, False)

            repoId = UUID(args['fromRepoId'])
            name = args['name']
            version = int(args.get('version', '0'))
            uuid = args.get('uuid')
            if uuid is not None:
                uuid = UUID(uuid)

            collection, name, uuid = self.findCollection(view, name, uuid)
            share = self.findShare(view, collection, repoId, iq['from'])

            iq = client.IQ(self.client.xmlstream, "result")
            query = iq.addElement(("jabber:x:chandler", "query"))
            sync = query.addElement('sync')
            sync['name'] = name

            changes = self.computeChanges(view, version, collection, share)
            keys = set()
            compressed = len(changes) > 16

            if compressed:
                builder = TreeBuilder()
                dom = formats.ElementTreeDOM()
                data = dom.openElement(builder, 'data')
            else:
                dom = DomishDOM()
                data = dom.openElement(sync, 'data')

            for key, (_changes, status) in changes.iteritems():
                if key not in keys:
                    if status & CItem.DELETED:
                        dom.openElement(data, 'item', uuid=key.str64(),
                                        status='deleted')
                    else:
                        attrs = { 'uuid': key.str64() }
                        if key in collection:
                            attrs['status'] = 'member'
                        item = dom.openElement(data, 'item', **attrs)
                        share.format.exportProcess(dom, key, item,
                                                   changes, keys)
                    dom.closeElement(data, 'item')
                elif key in collection:
                    dom.openElement(data, 'item', uuid=key.str64(),
                                    status='member')
                    dom.closeElement(data, 'item')

            dom.closeElement(data, 'data')

            sync['fromRepoId'] = self._repoId.str64()
            sync['toRepoId'] = repoId.str64()
            sync['version'] = str(view.itsVersion)
            sync['uuid'] = collection.itsUUID.str64()

            if compressed:
                sync['compressed'] = 'true'
                out = StringIO()
                ElementTree(builder.close()).write(out, 'utf-8')
                sync.children.append(b64encode(compress(out.getvalue())))
                out.close()

        except:
            view.cancel()
            raise

        share.localVersion = view.itsVersion + 1
        share.established = True
        share.ackPending = True
        view.commit()

        return iq