def __delitem__(self, key): entity = self.new_entity() entity.SetKey(key) request = http.HTTPRequest(str(entity.GetLocation()), 'DELETE') self.client.ProcessRequest(request) if request.status == 204: # success, nothing to read back return else: self.RaiseError(request)
def LoadService(self, serviceRoot): """Configures this client to use the service at *serviceRoot* *serviceRoot* is a string or :py:class:`pyslet.rfc2396.URI` instance.""" if isinstance(serviceRoot, uri.URI): self.serviceRoot = serviceRoot else: self.serviceRoot = uri.URIFactory.URI(serviceRoot) request = http.HTTPRequest(str(self.serviceRoot)) request.SetHeader('Accept', 'application/atomsvc+xml') self.ProcessRequest(request) if request.status != 200: raise UnexpectedHTTPResponse( "%i %s" % (request.status, request.response.reason)) doc = core.Document(baseURI=self.serviceRoot) doc.Read(request.resBody) if isinstance(doc.root, app.Service): self.service = doc.root self.serviceRoot = uri.URIFactory.URI(doc.root.ResolveBase()) self.feeds = {} self.model = None for w in self.service.Workspace: for f in w.Collection: url = f.GetFeedURL() if f.Title: self.feeds[f.Title.GetValue()] = url else: raise InvalidServiceDocument(str(serviceRoot)) self.pathPrefix = self.serviceRoot.absPath if self.pathPrefix[-1] == u"/": self.pathPrefix = self.pathPrefix[:-1] metadata = uri.URIFactory.Resolve(serviceRoot, '$metadata') doc = edmx.Document(baseURI=metadata, reqManager=self) defaultContainer = None try: doc.Read() if isinstance(doc.root, edmx.Edmx): self.model = doc.root for s in self.model.DataServices.Schema: for container in s.EntityContainer: if container.IsDefaultEntityContainer(): prefix = "" defaultContainer = container else: prefix = container.name + "." for es in container.EntitySet: fTitle = prefix + es.name if fTitle in self.feeds: if self.feeds[fTitle] == es.GetLocation(): self.feeds[fTitle] = es else: raise DataFormatError(str(metadata)) except xml.XMLError, e: # Failed to read the metadata document, there may not be one of course raise DataFormatError(str(e))
def GetStreamGenerator(self): """A generator function that yields blocks (strings) of data from the entity's media stream.""" streamURL = str(self.GetLocation()) + "/$value" request = http.HTTPRequest(str(streamURL), 'GET') request.SetHeader('Accept', '*/*') self.client.ProcessRequest(request) if request.status == 404: return elif request.status != 200: raise UnexpectedHTTPResponse( "%i %s" % (request.status, request.response.reason)) yield request.resBody
def GetStreamSize(self): """Returns the size of the entity's media stream in bytes by issuing a HEAD request.""" streamURL = str(self.GetLocation()) + "/$value" request = http.HTTPRequest(str(streamURL), 'HEAD') request.SetHeader('Accept', '*/*') self.client.ProcessRequest(request) if request.status == 404: return None elif request.status != 200: raise UnexpectedHTTPResponse( "%i %s" % (request.status, request.response.reason)) return request.response.GetContentLength()
def entity_generator(self): feedURL = self.baseURI sysQueryOptions = {} if self.filter is not None: sysQueryOptions[ core.SystemQueryOption.filter] = unicode(self.filter) if self.expand is not None: sysQueryOptions[ core.SystemQueryOption.expand] = core.FormatExpand(self.expand) if self.select is not None: sysQueryOptions[ core.SystemQueryOption.select] = core.FormatSelect(self.select) if self.orderby is not None: sysQueryOptions[ core.SystemQueryOption.orderby] = core.CommonExpression.OrderByToString( self.orderby) if sysQueryOptions: feedURL = uri.URIFactory.URI( str(feedURL) + "?" + core.ODataURI.FormatSysQueryOptions(sysQueryOptions)) while True: request = http.HTTPRequest(str(feedURL)) request.SetHeader('Accept', 'application/atom+xml') self.client.ProcessRequest(request) if request.status != 200: raise UnexpectedHTTPResponse( "%i %s" % (request.status, request.response.reason)) doc = core.Document(baseURI=feedURL) doc.Read(request.resBody) if isinstance(doc.root, atom.Feed): if len(doc.root.Entry): for e in doc.root.Entry: entity = core.Entity(self.entity_set) entity.exists = True e.GetValue(entity) yield entity else: break else: raise core.InvalidFeedDocument(str(feedURL)) feedURL = None for link in doc.root.Link: if link.rel == "next": feedURL = link.ResolveURI(link.href) break if feedURL is None: break
def __getitem__(self, key): if self.isCollection: return super(NavigationCollection, self).__getitem__(key) else: # The baseURI points to a single entity already, we must not add # the key entityURL = str(self.baseURI) sysQueryOptions = {} if self.filter is not None: sysQueryOptions[ core.SystemQueryOption.filter] = unicode(self.filter) if self.expand is not None: sysQueryOptions[ core.SystemQueryOption.expand] = core.FormatExpand( self.expand) if self.select is not None: sysQueryOptions[ core.SystemQueryOption.select] = core.FormatSelect( self.select) if sysQueryOptions: entityURL = uri.URIFactory.URI( entityURL + "?" + core.ODataURI.FormatSysQueryOptions(sysQueryOptions)) request = http.HTTPRequest(str(entityURL)) request.SetHeader('Accept', 'application/atom+xml;type=entry') self.client.ProcessRequest(request) if request.status == 404: raise KeyError(key) elif request.status != 200: raise UnexpectedHTTPResponse( "%i %s" % (request.status, request.response.reason)) doc = core.Document(baseURI=entityURL) doc.Read(request.resBody) if isinstance(doc.root, atom.Entry): entity = core.Entity(self.entity_set) entity.exists = True doc.root.GetValue(entity) if entity.Key() == key: return entity else: raise KeyError(key) elif isinstance(doc.root, core.Error): raise KeyError(key) else: raise core.InvalidEntryDocument(str(entityURL))
def runWeatherLoader(container=None): """Starts a thread that monitors the DTG website for new values""" if container is None: doc = LoadMetadata() container = MakeContainer(doc) client = http.HTTPRequestManager() weatherData = container['DataPoints'] DTG = "http://www.cl.cam.ac.uk/research/dtg/weather/daily-text.cgi?%s" with weatherData.OpenCollection() as collection: collection.set_orderby( core.CommonExpression.OrderByFromString('TimePoint desc')) sleepInterval = 60 collection.set_page(1) lastPoint = list(collection.iterpage()) if lastPoint: lastPoint = lastPoint[0]['TimePoint'].value else: lastPoint = iso.TimePoint.FromString("19950630T000000Z") nextDay = lastPoint.date while True: today = iso.TimePoint.FromNowUTC().date if nextDay < today: # Load in nextDay logging.info("Requesting data for %s", str(nextDay)) century, year, month, day = nextDay.GetCalendarDay() request = http.HTTPRequest(DTG % str(nextDay)) client.ProcessRequest(request) if request.status == 200: # process this file and move on to the next day f = StringIO.StringIO(request.resBody) LoadDataFromFile(weatherData, f, century * 100 + year, month, day) nextDay = nextDay.Offset(days=1) if sleepInterval > 10: sleepInterval = sleepInterval // 2 else: # back off and try again sleepInterval = sleepInterval * 2 else: # back off and try again sleepInterval = sleepInterval * 2 client.IdleCleanup(0) if sleepInterval > 86400: sleepInterval = 86400 time.sleep(sleepInterval)
def InsertEntity(self, entity): if entity.exists: raise edm.EntityExists(str(entity.GetLocation())) doc = core.Document(root=core.Entry(None, entity)) data = str(doc) request = http.HTTPRequest(str(self.baseURI), 'POST', reqBody=data) request.SetContentType( http.MediaType.FromString(core.ODATA_RELATED_ENTRY_TYPE)) self.client.ProcessRequest(request) if request.status == 201: # success, read the entity back from the response doc = core.Document() doc.Read(request.resBody) entity.exists = True doc.root.GetValue(entity) # so which bindings got handled? Assume all of them for k, dv in entity.NavigationItems(): dv.bindings = [] else: self.RaiseError(request)
def replace(self, entity): if not entity.exists: raise edm.NonExistentEntity(str(entity.GetLocation())) if self.isCollection: # inherit the implementation super(NavigationCollection, self).replace(entity) else: if not isinstance(entity, edm.Entity) or entity.entity_set is not self.entity_set: raise TypeError doc = core.Document(root=core.URI) doc.root.SetValue(str(entity.GetLocation())) data = str(doc) request = http.HTTPRequest(str(self.linksURI), 'PUT', reqBody=data) request.SetContentType( http.MediaType.FromString('application/xml')) self.client.ProcessRequest(request) if request.status == 204: return else: self.RaiseError(request)
def __len__(self): # use $count feedURL = self.baseURI sysQueryOptions = {} if self.filter is not None: sysQueryOptions[core.SystemQueryOption.filter] = unicode( self.filter) if sysQueryOptions: feedURL = uri.URIFactory.URI( str(feedURL) + "/$count?" + core.ODataURI.FormatSysQueryOptions(sysQueryOptions)) else: feedURL = uri.URIFactory.URI(str(feedURL) + "/$count") request = http.HTTPRequest(str(feedURL)) request.SetHeader('Accept', 'text/plain') self.client.ProcessRequest(request) if request.status == 200: return int(request.resBody) else: raise UnexpectedHTTPResponse( "%i %s" % (request.status, request.response.reason))
def iterpage(self, setNextPage=False): feedURL = self.baseURI sysQueryOptions = {} if self.filter is not None: sysQueryOptions[core.SystemQueryOption.filter] = unicode( self.filter) if self.expand is not None: sysQueryOptions[core.SystemQueryOption.expand] = core.FormatExpand( self.expand) if self.select is not None: sysQueryOptions[core.SystemQueryOption.select] = core.FormatSelect( self.select) if self.orderby is not None: sysQueryOptions[core.SystemQueryOption. orderby] = core.CommonExpression.OrderByToString( self.orderby) if self.top is not None: sysQueryOptions[core.SystemQueryOption.top] = unicode(self.top) if self.skip is not None: sysQueryOptions[core.SystemQueryOption.skip] = unicode(self.skip) if self.skiptoken is not None: sysQueryOptions[core.SystemQueryOption.skiptoken] = self.skiptoken if sysQueryOptions: feedURL = uri.URIFactory.URI( str(feedURL) + "?" + core.ODataURI.FormatSysQueryOptions(sysQueryOptions)) request = http.HTTPRequest(str(feedURL)) request.SetHeader('Accept', 'application/atom+xml') self.client.ProcessRequest(request) if request.status != 200: raise UnexpectedHTTPResponse( "%i %s" % (request.status, request.response.reason)) doc = core.Document(baseURI=feedURL) doc.Read(request.resBody) if isinstance(doc.root, atom.Feed): if len(doc.root.Entry): for e in doc.root.Entry: entity = core.Entity(self.entitySet) entity.exists = True e.GetValue(entity) yield entity feedURL = self.nextSkiptoken = None for link in doc.root.Link: if link.rel == "next": feedURL = link.ResolveURI(link.href) break if feedURL is not None: # extract the skiptoken from this link feedURL = core.ODataURI(feedURL, self.client.pathPrefix) self.nextSkiptoken = feedURL.sysQueryOptions.get( core.SystemQueryOption.skiptoken, None) if setNextPage: if self.nextSkiptoken is not None: self.skiptoken = self.nextSkiptoken self.skip = None elif self.skip is not None: self.skip += len(doc.root.Entry) else: self.skip = len(doc.root.Entry) else: raise core.InvalidFeedDocument(str(feedURL))
def LoadService(self, serviceRoot): """Configures this client to use the service at *serviceRoot* *serviceRoot* is a string or :py:class:`pyslet.rfc2396.URI` instance.""" if isinstance(serviceRoot, uri.URI): self.serviceRoot = serviceRoot else: self.serviceRoot = uri.URIFactory.URI(serviceRoot) request = http.HTTPRequest(str(self.serviceRoot)) request.SetHeader('Accept', 'application/atomsvc+xml') self.ProcessRequest(request) if request.status != 200: raise UnexpectedHTTPResponse( "%i %s" % (request.status, request.response.reason)) doc = core.Document(baseURI=self.serviceRoot) doc.Read(request.resBody) if isinstance(doc.root, app.Service): self.service = doc.root self.serviceRoot = uri.URIFactory.URI(doc.root.ResolveBase()) self.feeds = {} self.model = None for w in self.service.Workspace: for f in w.Collection: url = f.GetFeedURL() if f.Title: self.feeds[f.Title.GetValue()] = url else: raise InvalidServiceDocument(str(serviceRoot)) self.pathPrefix = self.serviceRoot.absPath if self.pathPrefix[-1] == u"/": self.pathPrefix = self.pathPrefix[:-1] metadata = uri.URIFactory.Resolve(serviceRoot, '$metadata') doc = edmx.Document(baseURI=metadata, reqManager=self) defaultContainer = None try: doc.Read() if isinstance(doc.root, edmx.Edmx): self.model = doc.root for s in self.model.DataServices.Schema: for container in s.EntityContainer: if container.IsDefaultEntityContainer(): prefix = "" defaultContainer = container else: prefix = container.name + "." for es in container.EntitySet: fTitle = prefix + es.name if fTitle in self.feeds: if self.feeds[fTitle] == es.GetLocation(): self.feeds[fTitle] = es else: raise DataFormatError(str(metadata)) except xml.XMLError as e: # Failed to read the metadata document, there may not be one of # course raise DataFormatError(str(e)) # Missing feeds are pruned from the list, perhaps the service advertises them # but if we don't have a model of them we can't use of them for f in self.feeds.keys(): if isinstance(self.feeds[f], uri.URI): logging.info( "Can't find metadata definition of feed: %s", str( self.feeds[f])) del self.feeds[f] else: # Bind our EntityCollection class entity_set = self.feeds[f] entity_set.Bind(EntityCollection, client=self) for np in entity_set.entityType.NavigationProperty: entity_set.BindNavigation( np.name, NavigationCollection, client=self) logging.debug( "Registering feed: %s", str(self.feeds[f].GetLocation()))