def _rel_abs(self, url): if not hasattr(url, 'relative_to'): cat_url = self.catalog_url if '://' in url: abs_url = URL(url, cat_url) else: abs_url = URL(URL(url, cat_url).absolute, cat_url) rel_url = abs_url.relative_to(cat_url) else: abs_url = url.absolute rel_url = url.relative_to(self.catalog_url) return rel_url, abs_url
def __init__(__this__, session, **members): if 'self' in members: if not isinstance(members['self'], URL): members['self'] = URL(members['self'], "") if 'index' in members: members['index'] = Index(session, members['self'], **members['index']) super(Catalog, __this__).__init__(session, **members)
def __init__(__this__, session, **members): members.setdefault("body", {}) if 'self' in members: if not isinstance(members['self'], URL): members['self'] = URL(members['self'], "") members['body'] = Tuple(session, members['self'], **members['body']) super(Entity, __this__).__init__(session, **members)
def __init__(self, session, catalog_url, **members): self.session = session self.catalog_url = catalog_url catalog_url_absolute, frag = urllib.parse.urldefrag(catalog_url.absolute) # Normalized keys stores a dictionary of shortest relative URLs # obtained via URL.relative_to that maps to the arbitrary URL relative # or absolute that the client submitted. We can use this to always # key the tuples by relative URL regardless of what kind of URL the # user asks to fetch an item by. normalized_keys = {} for entity_url, tup in six.iteritems(members): url = entity_url if not hasattr(url, "relative_to"): # Faster than isinstance(url, URL) url = URL(url, catalog_url_absolute) members[url] = Tuple(session, url, **tup) if tup is not None else None normalized_keys[url.relative_to(catalog_url)] = url self.normalized_keys = normalized_keys elements.JSONObject.__init__(self, **members)
def test_normalized_key_on_None(self): base_url = URL('http://host.name/base/url/', None) session = mock.MagicMock() rel_url = '../folder/item/' abs_url = URL(rel_url, base_url).absolute rel_index = Index(session, base_url, **{ rel_url: None }) abs_index = Index(session, base_url, **{ abs_url: None }) abs_on_rel = rel_index[abs_url] rel_on_abs = abs_index[rel_url] self.assertEqual(abs_on_rel, rel_on_abs) self.assertEqual(abs_on_rel, None) self.assertEqual(rel_on_abs, None) self.assertEqual(list(rel_index.normalized_keys.keys()), [rel_url]) self.assertEqual(list(abs_index.normalized_keys.keys()), [rel_url])
def test_relative_access(self): base_url = URL('http://host.name/base/url/', None) session = mock.MagicMock() rel_url = '../folder/item/' abs_url = URL(rel_url, base_url).absolute tup = {'id': 1} # Some arbitrary value rel_index = Index(session, base_url, **{ rel_url: tup }) abs_index = Index(session, base_url, **{ abs_url: tup }) abs_on_rel = rel_index[abs_url] rel_on_abs = abs_index[rel_url] self.assertEqual(abs_on_rel, rel_on_abs) self.assertEqual(abs_on_rel, tup) self.assertEqual(rel_on_abs, tup)
def __init__(self, session, catalog_url, **members): self.session = session self.catalog_url = catalog_url catalog_url_absolute, frag = urllib.parse.urldefrag(catalog_url.absolute) # Normalized keys stores a dictionary of shortest relative URLs # obtained via URL.relative_to that maps to the arbitrary URL relative # or absolute that the client submitted. We can use this to always # key the tuples by relative URL regardless of what kind of URL the # user asks to fetch an item by. normalized_keys = {} for entity_url, tup in six.iteritems(members): if tup is not None: url = entity_url if not hasattr(url, "relative_to"): # Faster than isinstance(url, URL) url = URL(url, catalog_url_absolute) members[url] = Tuple(session, url, **tup) normalized_keys[url.relative_to(catalog_url)] = url self.normalized_keys = normalized_keys elements.JSONObject.__init__(self, **members)
def _wait_for_progress(self, entity, r, progress_tracker): entity['self'] = URL(r.headers['Location'], '') if r.status_code == 202: try: progress_url = r.payload['value'] # noqa except Exception: # Not a progress API just return the incomplete entity. # User will refresh it. pass else: # We have a progress_url, wait for completion entity.wait_progress(r, progress_tracker) return entity
def __init__(self, session, catalog_url, **members): self.session = session self.catalog_url = catalog_url catalog_url_absolute, frag = urllib.parse.urldefrag( catalog_url.absolute) for entity_url, tup in six.iteritems(members): if tup is not None: url = entity_url if not hasattr( url, "relative_to"): # Faster than isinstance(url, URL) url = URL(url, catalog_url_absolute) members[entity_url] = Tuple(session, url, **tup) elements.JSONObject.__init__(self, **members)
def create(self, entity=None, progress_tracker=None): """POST the given Entity to this catalog to create a new resource. The 'entity' arg may be a complete shoji.Entity, in which case its .json will be POST'ed to this Catalog, or it may be a plain dict of attributes, in which case it will first be wrapped in an Entity. This latter case is more common simply for the fact that it results in cleaner calling code; compare: foo_catalog.create(pycrunch.shoji.Entity(my.session, bar=qux)) versus: foo_catalog.create({"bar": qux}) The `progress_tracker` argument allows overriding progress tracking configuration provided by session. See ``Entity.wait_progress`` for details. An entity is returned. """ if entity is None: entity = Entity(self.session) elif isinstance(entity, dict) and not isinstance(entity, elements.Document): entity = Entity(self.session, **entity) response = self.post(data=entity.json) if response.history: # Coming from a redirect seeother = [r for r in response.history if r.status_code == 303] if seeother: # We got a See Other response, this means the resource # was not created because an equivalent one is already available. entity['self'] = URL(seeother[-1].headers['Location'], '') return entity return self._wait_for_progress(entity, response, progress_tracker)
def test_catalog_follow_entity(self): base_url = URL('http://host.name/catalog/', None) ent_1_url = urljoin(base_url, '01/') ent_2_url = urljoin(base_url, '02/') ent_3_url = urljoin(base_url, '03/') ent_4_url = urljoin(base_url, '04/') entities = { ent_1_url: { 'full_entity': True, 'name': 'Ent 01' }, ent_2_url: { 'full_entity': True, 'name': 'Ent 02' }, ent_3_url: { 'full_entity': True, 'name': 'Ent 03' }, ent_4_url: { 'full_entity': True, 'name': 'Ent 04' } } fetches = [] def _get(ent_url, *args, **kwargs): fetches.append((ent_url, args, kwargs)) resp = mock.Mock(payload=entities[ent_url]) return resp session = mock.MagicMock() session.get = _get payload = { 'element': 'shoji:catalog', 'self': base_url, # This index has mixed urls as kes 'index': { './01/': { 'name': '01' }, ent_2_url: { 'name': '02' } } } index = Index(session, base_url, **payload['index']) # Continue growing the index using other ways, __setitem__ and .update index['03/'] = { # This has another way of being valid relative 'name': '03' } index.update({ '../catalog/04/': { # Yet way of being valid relative 'name': '04' } }) self.assertTrue(index[ent_1_url].entity['full_entity']) self.assertEqual(index[ent_1_url].entity['name'], 'Ent 01') self.assertTrue(index['01/'].entity['full_entity']) self.assertEqual(index['01/'].entity['name'], 'Ent 01') self.assertTrue(index['./01/'].entity['full_entity']) self.assertEqual(index['./01/'].entity['name'], 'Ent 01') self.assertTrue(index['../catalog/01/'].entity['full_entity']) self.assertEqual(index['../catalog/01/'].entity['name'], 'Ent 01') self.assertTrue(index[ent_2_url].entity['full_entity']) self.assertEqual(index[ent_2_url].entity['name'], 'Ent 02') self.assertTrue(index['02/'].entity['full_entity']) self.assertEqual(index['02/'].entity['name'], 'Ent 02') self.assertTrue(index['./02/'].entity['full_entity']) self.assertEqual(index['./02/'].entity['name'], 'Ent 02') self.assertTrue(index['../catalog/02/'].entity['full_entity']) self.assertEqual(index['../catalog/02/'].entity['name'], 'Ent 02') self.assertTrue(index[ent_3_url].entity['full_entity']) self.assertEqual(index[ent_3_url].entity['name'], 'Ent 03') self.assertTrue(index['03/'].entity['full_entity']) self.assertEqual(index['03/'].entity['name'], 'Ent 03') self.assertTrue(index['./03/'].entity['full_entity']) self.assertEqual(index['./03/'].entity['name'], 'Ent 03') self.assertTrue(index['../catalog/03/'].entity['full_entity']) self.assertEqual(index['../catalog/03/'].entity['name'], 'Ent 03') self.assertTrue(index[ent_4_url].entity['full_entity']) self.assertEqual(index[ent_4_url].entity['name'], 'Ent 04') self.assertTrue(index['04/'].entity['full_entity']) self.assertEqual(index['04/'].entity['name'], 'Ent 04') self.assertTrue(index['./04/'].entity['full_entity']) self.assertEqual(index['./04/'].entity['name'], 'Ent 04') self.assertTrue(index['../catalog/04/'].entity['full_entity']) self.assertEqual(index['../catalog/04/'].entity['name'], 'Ent 04') self.assertEqual(fetches, [ (ent_1_url, (), {}), (ent_2_url, (), {}), (ent_3_url, (), {}), (ent_4_url, (), {}), ])
def __init__(__this__, session, **members): if 'self' in members and not isinstance(members['self'], URL): members['self'] = URL(members['self'], "") super(Order, __this__).__init__(session, **members)
def wait_progress(self, r, progress_tracker=None): self['self'] = URL(r.headers['Location'], '') wait_progress(r, self.session, progress_tracker, entity=self) return self