diff options
author | Aleksey Lim <alsroot@sugarlabs.org> | 2013-03-15 17:14:56 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@sugarlabs.org> | 2013-03-15 18:13:51 (GMT) |
commit | 46b931c08946581486224c07ff2f49a0910a05d4 (patch) | |
tree | 0bef0bf990fab0e99592cadbe7f842e1e3b46095 | |
parent | c0fe0c6b16959aae8c94dba045e0d7f80ea8a350 (diff) |
Polish design, move master related stuff from Context to node.master
-rw-r--r-- | sugar_network/client/clones.py | 2 | ||||
-rw-r--r-- | sugar_network/client/spec.py | 3 | ||||
-rw-r--r-- | sugar_network/db/document.py | 1 | ||||
-rw-r--r-- | sugar_network/db/volume.py | 5 | ||||
-rw-r--r-- | sugar_network/node/commands.py | 25 | ||||
-rw-r--r-- | sugar_network/node/master.py | 75 | ||||
-rw-r--r-- | sugar_network/node/slave.py | 2 | ||||
-rw-r--r-- | sugar_network/resources/context.py | 54 | ||||
-rw-r--r-- | tests/units/node/__main__.py | 1 | ||||
-rwxr-xr-x | tests/units/node/master.py | 210 | ||||
-rwxr-xr-x | tests/units/resources/context.py | 194 |
11 files changed, 291 insertions, 281 deletions
diff --git a/sugar_network/client/clones.py b/sugar_network/client/clones.py index eb1943a..aedeb0f 100644 --- a/sugar_network/client/clones.py +++ b/sugar_network/client/clones.py @@ -134,7 +134,7 @@ class _Inotify(Inotify): exception(_logger, 'Cannot read %r spec', clone_path) return - context = spec['Activity', 'implement'] + context = spec['implement'] context_path = _context_path(context, hashed_path) _ensure_path(context_path) diff --git a/sugar_network/client/spec.py b/sugar_network/client/spec.py index 544935e..ccbc787 100644 --- a/sugar_network/client/spec.py +++ b/sugar_network/client/spec.py @@ -29,6 +29,7 @@ _POLICY_URL = 'http://wiki.sugarlabs.org/go/Sugar_Network/Policy' _FIELDS = { # name: (required, typecast) + 'implement': (True, None), 'name': (True, None), 'summary': (True, None), 'description': (False, None), @@ -119,7 +120,7 @@ class Spec(object): return self._config.get(section, key) def __repr__(self): - return '<Spec %s>' % self['Activity', 'implement'] + return '<Spec %s>' % self['implement'] def _get(self, section, key): if self._config.has_option(section, key): diff --git a/sugar_network/db/document.py b/sugar_network/db/document.py index 66a1344..26f039b 100644 --- a/sugar_network/db/document.py +++ b/sugar_network/db/document.py @@ -32,6 +32,7 @@ class Document(object): def __init__(self, guid, record, cached_props=None, request=None): self.props = cached_props or {} self.guid = guid + self.is_new = bool(guid) self._record = record self.request = request diff --git a/sugar_network/db/volume.py b/sugar_network/db/volume.py index 30eed62..0bbbeb8 100644 --- a/sugar_network/db/volume.py +++ b/sugar_network/db/volume.py @@ -228,6 +228,9 @@ class VolumeCommands(CommandsProcessor): def before_update(self, request, props): props['mtime'] = int(time.time()) + def after_post(self, doc): + pass + @contextmanager def _post(self, request, access): enforce(isinstance(request.content, dict), 'Invalid value') @@ -284,6 +287,8 @@ class VolumeCommands(CommandsProcessor): directory.set_blob(doc.guid, name, value, mime_type=request.content_type) + self.after_post(doc) + def _preget(self, request): metadata = self.volume[request['document']].metadata reply = request.setdefault('reply', []) diff --git a/sugar_network/node/commands.py b/sugar_network/node/commands.py index e43af1d..d964ca7 100644 --- a/sugar_network/node/commands.py +++ b/sugar_network/node/commands.py @@ -14,7 +14,6 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os -import re import logging import hashlib from os.path import exists, join @@ -26,18 +25,16 @@ from sugar_network.toolkit import router, util, coroutine, exception, enforce _MAX_STATS_LENGTH = 100 -_GUID_RE = re.compile('[a-zA-Z0-9_+-.]+$') _logger = logging.getLogger('node.commands') class NodeCommands(db.VolumeCommands, Commands): - def __init__(self, is_master, guid, volume): + def __init__(self, guid, volume): db.VolumeCommands.__init__(self, volume) Commands.__init__(self) - self._is_master = is_master self._guid = guid self._stats = None @@ -51,10 +48,6 @@ class NodeCommands(db.VolumeCommands, Commands): def guid(self): return self._guid - @property - def is_master(self): - return self._is_master - @router.route('GET', '/packages') def packages(self, request, response): response.content_type = 'application/json' @@ -86,10 +79,7 @@ class NodeCommands(db.VolumeCommands, Commands): documents = {} for name, directory in self.volume.items(): documents[name] = {'mtime': directory.mtime} - return {'guid': self._guid, - 'master': self._is_master, - 'documents': documents, - } + return {'guid': self._guid, 'documents': documents} @db.volume_command(method='GET', cmd='stats', mime_type='application/json', arguments={ @@ -278,17 +268,8 @@ class NodeCommands(db.VolumeCommands, Commands): return cmd def before_create(self, request, props): - document = request['document'] - if document == 'user': + if request['document'] == 'user': props['guid'], props['pubkey'] = _load_pubkey(props['pubkey']) - - if self._is_master and props.get('implement'): - implement = props['implement'][0] - enforce(not self.volume[document].exists(implement), - 'Document already exists') - enforce(_GUID_RE.match(implement) is not None, 'Malformed GUID') - props['guid'] = implement - db.VolumeCommands.before_create(self, request, props) @db.directory_command_pre(method='GET') diff --git a/sugar_network/node/master.py b/sugar_network/node/master.py index 460e798..acb1199 100644 --- a/sugar_network/node/master.py +++ b/sugar_network/node/master.py @@ -13,28 +13,29 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import re +import time import json import base64 import logging -from urlparse import urlsplit from Cookie import SimpleCookie from os.path import join -from sugar_network import db, client, node -from sugar_network.node import sync, stats_user, files, volume, downloads +from sugar_network import db, node +from sugar_network.node import sync, stats_user, files, volume, downloads, obs from sugar_network.node.commands import NodeCommands -from sugar_network.toolkit import cachedir, util, enforce +from sugar_network.toolkit import cachedir, coroutine, util, enforce +_GUID_RE = re.compile('[a-zA-Z0-9_+-.]+$') + _logger = logging.getLogger('node.master') class MasterCommands(NodeCommands): - def __init__(self, volume_, guid=None): - if not guid: - guid = urlsplit(client.api_url.value).netloc - NodeCommands.__init__(self, True, guid, volume_) + def __init__(self, guid, volume_): + NodeCommands.__init__(self, guid, volume_) self._pulls = { 'pull': lambda **kwargs: @@ -128,6 +129,28 @@ class MasterCommands(NodeCommands): cookie.store(response) return reply + def before_create(self, request, props): + implement = props.get('implement') + if implement: + implement = implement[0] + enforce(not self.volume[request['document']].exists(implement), + 'Document already exists') + enforce(_GUID_RE.match(implement) is not None, 'Malformed GUID') + props['guid'] = implement + NodeCommands.before_create(self, request, props) + + def after_post(self, doc): + if doc.metadata.name == 'context': + shift_implementations = ('dependencies' in doc.props) + if 'aliases' in doc.props: + # TODO Already launched job should be killed + coroutine.spawn(self._resolve_aliases, doc) + shift_implementations = True + if shift_implementations and not doc.is_new: + # Shift mtime to invalidate solutions + self.volume['implementation'].mtime = int(time.time()) + NodeCommands.after_post(self, doc) + def _push(self, stream): reply = [] cookie = _Cookie() @@ -160,6 +183,42 @@ class MasterCommands(NodeCommands): return reply, cookie + def _resolve_aliases(self, doc): + packages = {} + for repo in obs.get_repos(): + alias = doc['aliases'].get(repo['distributor_id']) + if not alias: + continue + package = packages[repo['name']] = {} + for kind in ('binary', 'devel'): + obs_fails = [] + for to_resolve in alias.get(kind) or []: + if not to_resolve: + continue + try: + for arch in repo['arches']: + obs.resolve(repo['name'], arch, to_resolve) + except Exception, error: + _logger.warning('Failed to resolve %r on %s', + to_resolve, repo['name']) + obs_fails.append(str(error)) + continue + package[kind] = to_resolve + break + else: + package['status'] = '; '.join(obs_fails) + break + else: + if 'binary' in package: + package['status'] = 'success' + else: + package['status'] = 'no packages to resolve' + + if packages != doc['packages']: + doc.request.call('PUT', document='context', guid=doc.guid, + content={'packages': packages}) + obs.presolve(doc['aliases']) + class _Cookie(list): diff --git a/sugar_network/node/slave.py b/sugar_network/node/slave.py index f25ccaf..aad36ed 100644 --- a/sugar_network/node/slave.py +++ b/sugar_network/node/slave.py @@ -38,7 +38,7 @@ _logger = logging.getLogger('node.slave') class SlaveCommands(NodeCommands): def __init__(self, guid, volume_): - NodeCommands.__init__(self, False, guid, volume_) + NodeCommands.__init__(self, guid, volume_) self._push_seq = util.PersistentSequence( join(volume_.root, 'push.sequence'), [1, None]) diff --git a/sugar_network/resources/context.py b/sugar_network/resources/context.py index 59a937e..433970b 100644 --- a/sugar_network/resources/context.py +++ b/sugar_network/resources/context.py @@ -13,14 +13,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import time import logging from os.path import join from sugar_network import db, resources, static from sugar_network.resources.volume import Resource -from sugar_network.node import obs -from sugar_network.toolkit import coroutine _logger = logging.getLogger('resources.context') @@ -136,63 +133,12 @@ class Context(Resource): """ return value - @dependencies.setter - def dependencies(self, value): - if self.guid is not None or value: - # Shift mtime to invalidate solutions - self.volume['implementation'].mtime = int(time.time()) - return value - @db.stored_property(typecast=dict, default={}, permissions=db.ACCESS_PUBLIC | db.ACCESS_LOCAL) def aliases(self, value): return value - @aliases.setter - def aliases(self, value): - coroutine.spawn(self._process_aliases, value) - return value - @db.stored_property(typecast=dict, default={}, permissions=db.ACCESS_PUBLIC | db.ACCESS_LOCAL | db.ACCESS_SYSTEM) def packages(self, value): return value - - def _process_aliases(self, aliases): - packages = {} - for repo in obs.get_repos(): - alias = aliases.get(repo['distributor_id']) - if not alias: - continue - package = packages[repo['name']] = {} - for kind in ('binary', 'devel'): - obs_fails = [] - for to_resolve in alias.get(kind) or []: - if not to_resolve: - continue - try: - for arch in repo['arches']: - obs.resolve(repo['name'], arch, to_resolve) - except Exception, error: - _logger.warning('Failed to resolve %r on %s', - to_resolve, repo['name']) - obs_fails.append(str(error)) - continue - package[kind] = to_resolve - break - else: - package['status'] = '; '.join(obs_fails) - break - else: - if 'binary' in package: - package['status'] = 'success' - else: - package['status'] = 'no packages to resolve' - - if packages != self['packages']: - self.request.call('PUT', document='context', guid=self.guid, - content={'packages': packages}) - # Shift mtime to invalidate solutions - self.volume['implementation'].mtime = int(time.time()) - - obs.presolve(aliases) diff --git a/tests/units/node/__main__.py b/tests/units/node/__main__.py index 684e1b7..4ab7386 100644 --- a/tests/units/node/__main__.py +++ b/tests/units/node/__main__.py @@ -5,6 +5,7 @@ from __init__ import tests from auth import * from downloads import * from files import * +from master import * from node import * from obs import * from stats_node import * diff --git a/tests/units/node/master.py b/tests/units/node/master.py new file mode 100755 index 0000000..ffdf8b0 --- /dev/null +++ b/tests/units/node/master.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python +# sugar-lint: disable + +from __init__ import tests + +from sugar_network.node import obs +from sugar_network.client import IPCClient +from sugar_network.toolkit import coroutine, enforce + + +class MasterTest(tests.Test): + + def test_Aliases(self): + self.override(obs, 'get_repos', lambda: [ + {'distributor_id': 'Gentoo', 'name': 'Gentoo-2.1', 'arches': ['x86', 'x86_64']}, + {'distributor_id': 'Debian', 'name': 'Debian-6.0', 'arches': ['x86']}, + {'distributor_id': 'Debian', 'name': 'Debian-7.0', 'arches': ['x86_64']}, + ]) + self.override(obs, 'resolve', lambda repo, arch, names: ['fake']) + self.override(obs, 'presolve', lambda *args: None) + + self.start_online_client() + ipc = IPCClient() + + guid = ipc.post(['context'], { + 'type': 'activity', + 'title': 'title', + 'summary': 'summary', + 'description': 'description', + }) + + ipc.put(['context', guid, 'aliases'], { + 'Gentoo': { + 'binary': [['pkg1.bin', 'pkg2.bin']], + 'devel': [['pkg3.devel']], + }, + 'Debian': { + 'binary': [['pkg4.bin']], + 'devel': [['pkg5.devel', 'pkg6.devel']], + }, + }) + coroutine.dispatch() + self.assertEqual({ + 'Gentoo-2.1': {'status': 'success', 'binary': ['pkg1.bin', 'pkg2.bin'], 'devel': ['pkg3.devel']}, + 'Debian-6.0': {'status': 'success', 'binary': ['pkg4.bin'], 'devel': ['pkg5.devel', 'pkg6.devel']}, + 'Debian-7.0': {'status': 'success', 'binary': ['pkg4.bin'], 'devel': ['pkg5.devel', 'pkg6.devel']}, + }, + ipc.get(['context', guid, 'packages'])) + + def test_WrongAliases(self): + self.override(obs, 'get_repos', lambda: [ + {'distributor_id': 'Gentoo', 'name': 'Gentoo-2.1', 'arches': ['x86', 'x86_64']}, + {'distributor_id': 'Debian', 'name': 'Debian-6.0', 'arches': ['x86']}, + {'distributor_id': 'Debian', 'name': 'Debian-7.0', 'arches': ['x86_64']}, + ]) + self.override(obs, 'resolve', lambda repo, arch, names: enforce(False, 'resolve failed')) + self.override(obs, 'presolve', lambda *args: None) + + self.start_online_client() + ipc = IPCClient() + + guid = ipc.post(['context'], { + 'type': 'activity', + 'title': 'title', + 'summary': 'summary', + 'description': 'description', + }) + + ipc.put(['context', guid, 'aliases'], { + 'Gentoo': { + 'binary': [['pkg1.bin', 'pkg2.bin']], + 'devel': [['pkg3.devel']], + }, + 'Debian': { + 'binary': [['pkg4.bin']], + 'devel': [['pkg5.devel', 'pkg6.devel']], + }, + }) + coroutine.dispatch() + self.assertEqual({ + 'Gentoo-2.1': {'status': 'resolve failed'}, + 'Debian-6.0': {'status': 'resolve failed'}, + 'Debian-7.0': {'status': 'resolve failed'}, + }, + ipc.get(['context', guid, 'packages'])) + + def test_MultipleAliases(self): + + def resolve(repo, arch, names): + enforce(not [i for i in names if 'fake' in i], 'resolve failed') + return ['fake'] + + self.override(obs, 'get_repos', lambda: [ + {'distributor_id': 'Gentoo', 'name': 'Gentoo-2.1', 'arches': ['x86', 'x86_64']}, + ]) + self.override(obs, 'resolve', resolve) + self.override(obs, 'presolve', lambda *args: None) + + self.start_online_client() + ipc = IPCClient() + + guid = ipc.post(['context'], { + 'type': 'activity', + 'title': 'title', + 'summary': 'summary', + 'description': 'description', + }) + + ipc.put(['context', guid, 'aliases'], { + 'Gentoo': { + 'binary': [['fake.bin'], ['proper.bin'], ['not-reach.bin']], + 'devel': [['fake.devel'], ['proper.devel'], ['not-reach.devel']], + }, + }) + coroutine.dispatch() + self.assertEqual({ + 'Gentoo-2.1': {'status': 'success', 'binary': ['proper.bin'], 'devel': ['proper.devel']}, + }, + ipc.get(['context', guid, 'packages'])) + + ipc.put(['context', guid, 'aliases'], { + 'Gentoo': { + 'binary': [['proper.bin']], + 'devel': [['fake.devel']], + }, + }) + coroutine.dispatch() + self.assertEqual({ + 'Gentoo-2.1': {'status': 'resolve failed', 'binary': ['proper.bin']}, + }, + ipc.get(['context', guid, 'packages'])) + + ipc.put(['context', guid, 'aliases'], { + 'Gentoo': { + 'binary': [['fake.bin']], + 'devel': [['proper.devel']], + }, + }) + coroutine.dispatch() + self.assertEqual({ + 'Gentoo-2.1': {'status': 'resolve failed'}, + }, + ipc.get(['context', guid, 'packages'])) + + def test_InvalidateSolutions(self): + self.override(obs, 'get_repos', lambda: [ + {'distributor_id': 'Gentoo', 'name': 'Gentoo-2.1', 'arches': ['x86_64']}, + ]) + self.override(obs, 'resolve', lambda repo, arch, names: ['fake']) + self.override(obs, 'presolve', lambda *args: None) + + self.start_online_client() + ipc = IPCClient() + + events = [] + def read_events(): + for event in ipc.subscribe(): + if event.get('document') == 'implementation': + events.append(event) + job = coroutine.spawn(read_events) + + guid = ipc.post(['context'], { + 'type': 'activity', + 'title': 'title', + 'summary': 'summary', + 'description': 'description', + }) + ipc.put(['context', guid, 'aliases'], { + 'Gentoo': { + 'binary': [['bin']], + 'devel': [['devel']], + }, + }) + coroutine.dispatch() + self.assertEqual({ + 'Gentoo-2.1': {'status': 'success', 'binary': ['bin'], 'devel': ['devel']}, + }, + ipc.get(['context', guid, 'packages'])) + print events + self.assertEqual(1, len(events)) + assert 'mtime' in events[0]['props'] + + def test_InvalidateSolutionsOnDependenciesChanges(self): + self.start_online_client() + ipc = IPCClient() + + events = [] + def read_events(): + for event in ipc.subscribe(): + if event.get('document') == 'implementation': + events.append(event) + job = coroutine.spawn(read_events) + + guid = ipc.post(['context'], { + 'type': 'activity', + 'title': 'title', + 'summary': 'summary', + 'description': 'description', + 'dependencies': [], + }) + self.assertEqual(0, len(events)) + + ipc.put(['context', guid, 'dependencies'], ['foo']) + self.assertEqual(1, len(events)) + assert 'mtime' in events[0]['props'] + del events[:] + + +if __name__ == '__main__': + tests.main() diff --git a/tests/units/resources/context.py b/tests/units/resources/context.py index 6321798..7f61a5c 100755 --- a/tests/units/resources/context.py +++ b/tests/units/resources/context.py @@ -10,200 +10,6 @@ from sugar_network.toolkit import coroutine, enforce class ContextTest(tests.Test): - def test_Aliases(self): - self.override(obs, 'get_repos', lambda: [ - {'distributor_id': 'Gentoo', 'name': 'Gentoo-2.1', 'arches': ['x86', 'x86_64']}, - {'distributor_id': 'Debian', 'name': 'Debian-6.0', 'arches': ['x86']}, - {'distributor_id': 'Debian', 'name': 'Debian-7.0', 'arches': ['x86_64']}, - ]) - self.override(obs, 'resolve', lambda repo, arch, names: ['fake']) - self.override(obs, 'presolve', lambda: None) - - self.start_offline_client() - client = IPCClient() - - guid = client.post(['context'], { - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - }) - - client.put(['context', guid, 'aliases'], { - 'Gentoo': { - 'binary': [['pkg1.bin', 'pkg2.bin']], - 'devel': [['pkg3.devel']], - }, - 'Debian': { - 'binary': [['pkg4.bin']], - 'devel': [['pkg5.devel', 'pkg6.devel']], - }, - }) - coroutine.dispatch() - self.assertEqual({ - 'Gentoo-2.1': {'status': 'success', 'binary': ['pkg1.bin', 'pkg2.bin'], 'devel': ['pkg3.devel']}, - 'Debian-6.0': {'status': 'success', 'binary': ['pkg4.bin'], 'devel': ['pkg5.devel', 'pkg6.devel']}, - 'Debian-7.0': {'status': 'success', 'binary': ['pkg4.bin'], 'devel': ['pkg5.devel', 'pkg6.devel']}, - }, - client.get(['context', guid, 'packages'])) - - def test_WrongAliases(self): - self.override(obs, 'get_repos', lambda: [ - {'distributor_id': 'Gentoo', 'name': 'Gentoo-2.1', 'arches': ['x86', 'x86_64']}, - {'distributor_id': 'Debian', 'name': 'Debian-6.0', 'arches': ['x86']}, - {'distributor_id': 'Debian', 'name': 'Debian-7.0', 'arches': ['x86_64']}, - ]) - self.override(obs, 'resolve', lambda repo, arch, names: enforce(False, 'resolve failed')) - self.override(obs, 'presolve', lambda: None) - - self.start_offline_client() - client = IPCClient() - - guid = client.post(['context'], { - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - }) - - client.put(['context', guid, 'aliases'], { - 'Gentoo': { - 'binary': [['pkg1.bin', 'pkg2.bin']], - 'devel': [['pkg3.devel']], - }, - 'Debian': { - 'binary': [['pkg4.bin']], - 'devel': [['pkg5.devel', 'pkg6.devel']], - }, - }) - coroutine.dispatch() - self.assertEqual({ - 'Gentoo-2.1': {'status': 'resolve failed'}, - 'Debian-6.0': {'status': 'resolve failed'}, - 'Debian-7.0': {'status': 'resolve failed'}, - }, - client.get(['context', guid, 'packages'])) - - def test_MultipleAliases(self): - - def resolve(repo, arch, names): - enforce(not [i for i in names if 'fake' in i], 'resolve failed') - return ['fake'] - - self.override(obs, 'get_repos', lambda: [ - {'distributor_id': 'Gentoo', 'name': 'Gentoo-2.1', 'arches': ['x86', 'x86_64']}, - ]) - self.override(obs, 'resolve', resolve) - self.override(obs, 'presolve', lambda: None) - - self.start_offline_client() - client = IPCClient() - - guid = client.post(['context'], { - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - }) - - client.put(['context', guid, 'aliases'], { - 'Gentoo': { - 'binary': [['fake.bin'], ['proper.bin'], ['not-reach.bin']], - 'devel': [['fake.devel'], ['proper.devel'], ['not-reach.devel']], - }, - }) - coroutine.dispatch() - self.assertEqual({ - 'Gentoo-2.1': {'status': 'success', 'binary': ['proper.bin'], 'devel': ['proper.devel']}, - }, - client.get(['context', guid, 'packages'])) - - client.put(['context', guid, 'aliases'], { - 'Gentoo': { - 'binary': [['proper.bin']], - 'devel': [['fake.devel']], - }, - }) - coroutine.dispatch() - self.assertEqual({ - 'Gentoo-2.1': {'status': 'resolve failed', 'binary': ['proper.bin']}, - }, - client.get(['context', guid, 'packages'])) - - client.put(['context', guid, 'aliases'], { - 'Gentoo': { - 'binary': [['fake.bin']], - 'devel': [['proper.devel']], - }, - }) - coroutine.dispatch() - self.assertEqual({ - 'Gentoo-2.1': {'status': 'resolve failed'}, - }, - client.get(['context', guid, 'packages'])) - - def test_InvalidateSolutions(self): - self.override(obs, 'get_repos', lambda: [ - {'distributor_id': 'Gentoo', 'name': 'Gentoo-2.1', 'arches': ['x86_64']}, - ]) - self.override(obs, 'resolve', lambda repo, arch, names: ['fake']) - self.override(obs, 'presolve', lambda: None) - - self.start_offline_client() - client = IPCClient() - - events = [] - def read_events(): - for event in client.subscribe(): - if event.get('document') == 'implementation': - events.append(event) - job = coroutine.spawn(read_events) - - guid = client.post(['context'], { - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - }) - client.put(['context', guid, 'aliases'], { - 'Gentoo': { - 'binary': [['bin']], - 'devel': [['devel']], - }, - }) - coroutine.dispatch() - self.assertEqual({ - 'Gentoo-2.1': {'status': 'success', 'binary': ['bin'], 'devel': ['devel']}, - }, - client.get(['context', guid, 'packages'])) - self.assertEqual(1, len(events)) - assert 'mtime' in events[0]['props'] - - def test_InvalidateSolutionsOnDependenciesChanges(self): - self.start_offline_client() - client = IPCClient() - - events = [] - def read_events(): - for event in client.subscribe(): - if event.get('document') == 'implementation': - events.append(event) - job = coroutine.spawn(read_events) - - guid = client.post(['context'], { - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - 'dependencies': [], - }) - self.assertEqual(0, len(events)) - - client.put(['context', guid, 'dependencies'], ['foo']) - self.assertEqual(1, len(events)) - assert 'mtime' in events[0]['props'] - del events[:] - def test_SetCommonLayerForPackages(self): self.start_offline_client() ipc = IPCClient() |