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)
Esempio n. 10
0
    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)
Esempio n. 12
0
        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)