def test_update_service_areas(self): # This Library has no ServiceAreas associated with it. library = self._library() country1 = self._place(abbreviated_name="C1", type=Place.NATION) country2 = self._place(abbreviated_name="C2", type=Place.NATION) everywhere = AuthenticationDocument.COVERAGE_EVERYWHERE doc_dict = dict(service_area=everywhere, focus_area={ country1.abbreviated_name: everywhere, country2.abbreviated_name: everywhere }) doc = AuthenticationDocument.from_dict(self._db, doc_dict) problem = doc.update_service_areas(library) self._db.commit() eq_(None, problem) # Now this Library has three associated ServiceAreas. [a1, a2, a3] = sorted([(x.type, x.place.abbreviated_name) for x in library.service_areas]) everywhere_place = Place.everywhere(self._db) # Anyone is eligible for access. eq_(('eligibility', everywhere_place.abbreviated_name), a1) # But people in two particular countries are the focus. eq_(('focus', country1.abbreviated_name), a2) eq_(('focus', country2.abbreviated_name), a3) # Remove one of the countries from the focus, add a new one, # and try again. country3 = self._place(abbreviated_name="C3", type=Place.NATION) doc_dict = dict(service_area=everywhere, focus_area={ country1.abbreviated_name: everywhere, country3.abbreviated_name: everywhere }) doc = AuthenticationDocument.from_dict(self._db, doc_dict) doc.update_service_areas(library) self._db.commit() # The ServiceArea for country #2 has been removed. assert a2 not in library.service_areas assert not any(a.place == country2 for a in library.service_areas) [a1, a2, a3] = sorted([(x.type, x.place.abbreviated_name) for x in library.service_areas]) eq_(('eligibility', everywhere_place.abbreviated_name), a1) eq_(('focus', country1.abbreviated_name), a2) eq_(('focus', country3.abbreviated_name), a3)
def test_known_place_becomes_servicearea(self): """Test the helper method in a successful case.""" library = self._library() # We identified two places, with no ambiguous or unknown # places. p1 = self._place() p2 = self._place() valid = [p1, p2] ambiguous = [] unknown = [] areas = [] # This will use those places to create new ServiceAreas, # which will be gathered in the 'areas' array. problem = AuthenticationDocument._update_service_areas( library, [valid, unknown, ambiguous], ServiceArea.FOCUS, areas) eq_(None, problem) [a1, a2] = sorted(library.service_areas, key=lambda x: x.place_id) eq_(p1, a1.place) eq_(ServiceArea.FOCUS, a1.type) eq_(p2, a2.place) eq_(ServiceArea.FOCUS, a2.type) # The ServiceArea IDs were added to the `ids` list. eq_(set([a1, a2]), set(areas))
class CoverageController(BaseController): """Converts coverage area descriptions to GeoJSON documents so they can be visualized. """ def geojson_response(self, document): if isinstance(document, dict): document = json.dumps(document) headers = {"Content-Type": "application/geo+json"} return Response(document, 200, headers=headers) def lookup(self): coverage = flask.request.args.get('coverage') try: coverage = json.loads(coverage) except ValueError, e: pass places, unknown, ambiguous = AuthenticationDocument.parse_coverage( self._db, coverage) document = Place.to_geojson(self._db, *places) # Extend the GeoJSON with extra information about parts of the # coverage document we found ambiguous or couldn't associate # with a Place. if unknown: document['unknown'] = unknown if ambiguous: document['ambiguous'] = ambiguous return self.geojson_response(document)
def update(self, value): result = AuthenticationDocument._update_collection_size( self.library, value) # If there's a problem detail document, it must be of the type # INVALID_INTEGRATION_DOCUMENT. The caller may perform additional # checks. if isinstance(result, ProblemDetail): eq_(result.uri, INVALID_INTEGRATION_DOCUMENT.uri) return result
def update(self, audiences): """Wrapper around AuthenticationDocument._update_audiences.""" result = AuthenticationDocument._update_audiences( self.library, audiences) # If there's a problem detail document, it must be of the type # INVALID_INTEGRATION_DOCUMENT. The caller may perform additional # checks. if isinstance(result, ProblemDetail): eq_(result.uri, INVALID_INTEGRATION_DOCUMENT.uri) return result
def test_update_audiences(self): # Set the library's audiences. audiences = [Audience.EDUCATIONAL_SECONDARY, Audience.RESEARCH] doc_dict = dict(audience=audiences) doc = AuthenticationDocument.from_dict(self._db, doc_dict) problem = doc.update_audiences(self.library) eq_(None, problem) eq_(set(audiences), set([x.name for x in self.library.audiences])) # Set them again to different but partially overlapping values. audiences = [ Audience.EDUCATIONAL_PRIMARY, Audience.EDUCATIONAL_SECONDARY ] problem = self.update(audiences) eq_(set(audiences), set([x.name for x in self.library.audiences]))
def test_service_area_registered_as_focus_area_if_no_focus_area(self): library = self._library() # Create an authentication document that defines service_area # but not focus_area. everywhere = AuthenticationDocument.COVERAGE_EVERYWHERE doc_dict = dict(service_area=everywhere) doc = AuthenticationDocument.from_dict(self._db, doc_dict) problem = doc.update_service_areas(library) self._db.commit() eq_(None, problem) # We have a focus area but no explicit eligibility area. This # means that the library's eligibility area and focus area are # the same. [area] = library.service_areas eq_(Place.EVERYWHERE, area.place.type) eq_(ServiceArea.FOCUS, area.type)
def test_service_area_registered_as_focus_area_if_identical_to_focus_area( self): library = self._library() # Create an authentication document that defines service_area # and focus_area as the same value. everywhere = AuthenticationDocument.COVERAGE_EVERYWHERE doc_dict = dict( service_area=everywhere, focus_area=everywhere, ) doc = AuthenticationDocument.from_dict(self._db, doc_dict) problem = doc.update_service_areas(library) self._db.commit() eq_(None, problem) # Since focus area and eligibility area are the same, only the # focus area was registered. [area] = library.service_areas eq_(Place.EVERYWHERE, area.place.type) eq_(ServiceArea.FOCUS, area.type)
def test_success(self): sizes = dict(eng=100, jpn=0) doc_dict = dict(collection_size=sizes) doc = AuthenticationDocument.from_dict(self._db, doc_dict) problem = doc.update_collection_size(self.library) eq_(None, problem) # Two CollectionSummaries have been created, for the English # collection and the (empty) Japanese collection. eq_([(u'eng', 100), (u'jpn', 0)], sorted([(x.language, x.size) for x in self.library.collections])) # Update the library with new data. self.update({"eng": "200"}) # The Japanese collection has been removed altogether, since # it was not mentioned in the input. [english] = self.library.collections eq_("eng", english.language) eq_(200, english.size) self.update(None) # Now both collections have been removed. eq_([], self.library.collections)
def register(self, library, library_stage): """Register the given Library with this registry, if possible. :param library: A Library to register or re-register. :param library_stage: The library administrator's proposed value for Library.library_stage. :return: A ProblemDetail if there's a problem. Otherwise, a 2-tuple (auth_document, new_hyperlinks). `auth_document` is an AuthenticationDocument corresponding to the library's authentication document, as found at auth_url. `new_hyperlinks` is a list of Hyperlinks that ought to be created for registration to be complete. """ hyperlinks_to_create = [] auth_url = library.authentication_url auth_response = self._make_request( auth_url, auth_url, _("No Authentication For OPDS document present at %(url)s", url=auth_url), _("Timeout retrieving auth document %(url)s", url=auth_url), _("Error retrieving auth document %(url)s", url=auth_url), ) if isinstance(auth_response, ProblemDetail): return auth_response try: auth_document = AuthenticationDocument.from_string(self._db, auth_response.content) except Exception, e: self.log.error( "Registration of %s failed: invalid auth document.", auth_url, exc_info=e ) return INVALID_INTEGRATION_DOCUMENT
def test_ambiguous_and_unknown_places_become_problemdetail(self): """Test the helper method in a case that ends in failure.""" library = self._library() # We were able to identify one valid place. valid = [self._place()] # But we also found unknown and ambiguous places. ambiguous = ["Ambiguous"] unknown = ["Unknown 1", "Unknown 2"] ids = [] problem = AuthenticationDocument._update_service_areas( library, [valid, unknown, ambiguous], ServiceArea.ELIGIBILITY, ids) # We got a ProblemDetail explaining the problem assert isinstance(problem, ProblemDetail) eq_(INVALID_INTEGRATION_DOCUMENT.uri, problem.uri) eq_( 'The following service area was unknown: ["Unknown 1", "Unknown 2"]. The following service area was ambiguous: ["Ambiguous"].', problem.detail) # No IDs were added to the list. eq_([], ids)
service_area = parsed.service_area focus_area = parsed.focus_area # If the areas make sense as JSON, parse them. Otherwise a # string will be interpreted as a single place name. try: service_area = json.loads(service_area) except (ValueError, TypeError), e: pass try: focus_area = json.loads(focus_area) except (ValueError, TypeError), e: pass service_area, focus_area = AuthenticationDocument.parse_service_and_focus_area( self._db, service_area, focus_area, place_class ) for (valid, unknown, ambiguous) in [service_area, focus_area]: if unknown: raise ValueError("Unknown places: %r" % unknown.items()) if ambiguous: raise ValueError("Ambiguous places: %r" % unknown.items()) AuthenticationDocument.set_service_areas( library, service_area, focus_area ) self._db.commit() self.report(library) def report(self, library): logging.info("Service areas for %s:", library.name)