Exemplo n.º 1
0
def get_course_uuid_for_course(course_run_key):
    """
    Retrieve the Course UUID for a given course key

    Arguments:
        course_run_key (CourseKey): A Key for a Course run that will be pulled apart to get just the information
        required for a Course (e.g. org+course)

    Returns:
        UUID: Course UUID and None if it was not retrieved.
    """
    user, catalog_integration = check_catalog_integration_and_get_user(
        error_message_field='Course UUID')
    if user:
        api_client = get_catalog_api_client(user)
        base_api_url = get_catalog_api_base_url()

        run_cache_key = f"{catalog_integration.CACHE_KEY}.course_run.{course_run_key}"

        course_run_data = get_api_data(
            catalog_integration,
            'course_runs',
            resource_id=str(course_run_key),
            api_client=api_client,
            base_api_url=base_api_url,
            cache_key=run_cache_key
            if catalog_integration.is_cache_enabled else None,
            long_term_cache=True,
            many=False,
        )

        course_key_str = course_run_data.get('course', None)

        if course_key_str:
            run_cache_key = f"{catalog_integration.CACHE_KEY}.course.{course_key_str}"

            data = get_api_data(
                catalog_integration,
                'courses',
                resource_id=course_key_str,
                api_client=api_client,
                base_api_url=base_api_url,
                cache_key=run_cache_key
                if catalog_integration.is_cache_enabled else None,
                long_term_cache=True,
                many=False,
            )
            uuid_str = data.get('uuid', None)
            if uuid_str:
                return uuid.UUID(uuid_str)
    return None
Exemplo n.º 2
0
def get_program_types(name=None):
    """Retrieve program types from the catalog service.

    Keyword Arguments:
        name (string): Name identifying a specific program type.

    Returns:
        list of dict, representing program types.
        dict, if a specific program type is requested.
    """
    user, catalog_integration = check_catalog_integration_and_get_user(
        error_message_field='Program types')
    if user:
        cache_key = f'{catalog_integration.CACHE_KEY}.program_types'

        data = get_api_data(catalog_integration,
                            "program_types",
                            api_client=get_catalog_api_client(user),
                            base_api_url=get_catalog_api_base_url(),
                            cache_key=cache_key
                            if catalog_integration.is_cache_enabled else None)

        # Filter by name if a name was provided
        if name:
            data = next(program_type for program_type in data
                        if program_type['name'] == name)

        return data
    else:
        return []
Exemplo n.º 3
0
    def test_get_specific_resource(self):
        """
        Verify that a specific resource can be retrieved.
        """
        catalog_integration = self.create_catalog_integration()
        api = get_catalog_api_client(self.user)

        resource_id = 1
        url = urljoin(f"{self.base_api_url}/", f"programs/{resource_id}/")

        expected_resource = {'key': 'value'}

        self._mock_catalog_api([
            httpretty.Response(body=json.dumps(expected_resource),
                               content_type='application/json')
        ],
                               url=url)

        actual_resource = get_api_data(catalog_integration,
                                       'programs',
                                       api_client=api,
                                       base_api_url=self.base_api_url,
                                       resource_id=resource_id)
        assert actual_resource == expected_resource

        self._assert_num_requests(1)
Exemplo n.º 4
0
    def test_get_paginated_data_do_not_traverse_pagination(self):
        """
        Verify that pagination is not traversed if traverse_pagination=False is passed as argument.
        """
        catalog_integration = self.create_catalog_integration()
        api = get_catalog_api_client(self.user)

        url = urljoin(f"{self.base_api_url}/", "/programs/?page={}")
        responses = [
            {
                'next': url.format(2),
                'results': ['some'],
            },
            {
                'next': url.format(None),
                'results': ['test'],
            },
        ]
        expected_response = responses[0]

        self._mock_catalog_api([
            httpretty.Response(body=json.dumps(body),
                               content_type='application/json')
            for body in responses
        ])

        actual_collection = get_api_data(catalog_integration,
                                         'programs',
                                         api_client=api,
                                         base_api_url=self.base_api_url,
                                         traverse_pagination=False)
        assert actual_collection == expected_response
        self._assert_num_requests(1)
Exemplo n.º 5
0
def get_course_run_details(course_run_key, fields):
    """
    Retrieve information about the course run with the given id

    Arguments:
        course_run_key: key for the course_run about which we are retrieving information

    Returns:
        dict with language, start date, end date, and max_effort details about specified course run
    """
    course_run_details = {}
    user, catalog_integration = check_catalog_integration_and_get_user(
        error_message_field=f'Data for course_run {course_run_key}')
    if user:
        cache_key = f'{catalog_integration.CACHE_KEY}.course_runs'

        course_run_details = get_api_data(
            catalog_integration,
            'course_runs',
            api_client=get_catalog_api_client(user),
            base_api_url=get_catalog_api_base_url(),
            resource_id=course_run_key,
            cache_key=cache_key,
            many=False,
            traverse_pagination=False,
            fields=fields)
    return course_run_details
Exemplo n.º 6
0
    def test_get_unpaginated_data(self):
        """
        Verify that unpaginated data can be retrieved.
        """
        catalog_integration = self.create_catalog_integration()
        api = get_catalog_api_client(self.user)

        expected_collection = ['some', 'test', 'data']
        data = {
            'next': None,
            'results': expected_collection,
        }

        self._mock_catalog_api([
            httpretty.Response(body=json.dumps(data),
                               content_type='application/json')
        ])

        with mock.patch('requests.Session') as mock_init:
            actual_collection = get_api_data(catalog_integration,
                                             'programs',
                                             api_client=api,
                                             base_api_url=self.base_api_url)

            # Verify that the helper function didn't initialize its own client.
            assert not mock_init.called
            assert actual_collection == expected_collection

        # Verify the API was actually hit (not the cache)
        self._assert_num_requests(1)
Exemplo n.º 7
0
    def test_get_paginated_data(self):
        """
        Verify that paginated data can be retrieved.
        """
        catalog_integration = self.create_catalog_integration()
        api = get_catalog_api_client(self.user)

        expected_collection = ['some', 'test', 'data']
        url = urljoin(f"{self.base_api_url}/", "/programs/?page={}")

        responses = []
        for page, record in enumerate(expected_collection, start=1):
            data = {
                'next':
                url.format(page +
                           1) if page < len(expected_collection) else None,
                'results': [record],
            }

            body = json.dumps(data)
            responses.append(
                httpretty.Response(body=body, content_type='application/json'))

        self._mock_catalog_api(responses)

        actual_collection = get_api_data(catalog_integration,
                                         'programs',
                                         api_client=api,
                                         base_api_url=self.base_api_url)
        assert actual_collection == expected_collection

        self._assert_num_requests(len(expected_collection))
Exemplo n.º 8
0
    def test_get_specific_resource_with_falsey_id(self):
        """
        Check the call with falsey resource_id.

        Verify that a specific resource can be retrieved, and pagination parsing is
        not attempted, if the ID passed is falsey (e.g., 0). The expected resource contains
        a "results" key, as a paginatable item would have, so if the function looks for falsey
        values in the resource_id field, rather than specifically None, the function will
        return the value of that "results" key.
        """
        catalog_integration = self.create_catalog_integration()
        api = get_catalog_api_client(self.user)

        resource_id = 0
        url = urljoin(f"{self.base_api_url}/", f"programs/{resource_id}/")

        expected_resource = {'key': 'value', 'results': []}

        self._mock_catalog_api([
            httpretty.Response(body=json.dumps(expected_resource),
                               content_type='application/json')
        ],
                               url=url)

        actual_resource = get_api_data(catalog_integration,
                                       'programs',
                                       api_client=api,
                                       base_api_url=self.base_api_url,
                                       resource_id=resource_id)
        assert actual_resource == expected_resource

        self._assert_num_requests(1)
Exemplo n.º 9
0
    def test_get_specific_fields_from_cache_response(self):
        """
        Verify that resource response is cached and get required fields from cached response.
        """
        catalog_integration = self.create_catalog_integration(cache_ttl=5)
        api = get_catalog_api_client(self.user)

        response = {'lang': 'en', 'weeks_to_complete': '5'}

        resource_id = 'course-v1:testX+testABC+1T2019'
        url = urljoin(f"{self.base_api_url}/", f"course_runs/{resource_id}/")

        expected_resource_for_lang = {'lang': 'en'}
        expected_resource_for_weeks_to_complete = {'weeks_to_complete': '5'}

        self._mock_catalog_api([
            httpretty.Response(body=json.dumps(response),
                               content_type='application/json')
        ],
                               url=url)

        cache_key = CatalogIntegration.current().CACHE_KEY

        # get response and set the cache.
        actual_resource_for_lang = get_api_data(catalog_integration,
                                                'course_runs',
                                                resource_id=resource_id,
                                                api_client=api,
                                                base_api_url=self.base_api_url,
                                                cache_key=cache_key,
                                                fields=['lang'])
        assert actual_resource_for_lang == expected_resource_for_lang

        # Hit the cache
        actual_resource = get_api_data(catalog_integration,
                                       'course_runs',
                                       api_client=api,
                                       base_api_url=self.base_api_url,
                                       resource_id=resource_id,
                                       cache_key=cache_key,
                                       fields=['weeks_to_complete'])

        assert actual_resource == expected_resource_for_weeks_to_complete

        # Verify that only one requests were made, not three.
        self._assert_num_requests(1)
Exemplo n.º 10
0
    def test_api_config_disabled(self, mock_warning):
        """
        Verify that no data is retrieved if the provided config model is disabled.
        """
        catalog_integration = self.create_catalog_integration(enabled=False)

        actual = get_api_data(catalog_integration,
                              'programs',
                              api_client=None,
                              base_api_url=self.base_api_url)

        assert mock_warning.called
        assert actual == []
Exemplo n.º 11
0
    def test_api_config_disabled_with_id_and_not_collection(
            self, mock_warning):
        """
        Verify that no data is retrieved if the provided config model is disabled.
        """
        catalog_integration = self.create_catalog_integration(enabled=False)

        actual = get_api_data(catalog_integration,
                              'programs',
                              api_client=None,
                              base_api_url=self.base_api_url,
                              resource_id=100,
                              many=False)

        assert mock_warning.called
        assert actual == {}
Exemplo n.º 12
0
def get_credentials(user, program_uuid=None, credential_type=None):
    """
    Given a user, get credentials earned from the credentials service.

    Arguments:
        user (User): The user to authenticate as when requesting credentials.

    Keyword Arguments:
        program_uuid (str): UUID of the program whose credential to retrieve.
        credential_type (str): Which type of credentials to return (course-run or program)

    Returns:
        list of dict, representing credentials returned by the Credentials
        service.
    """
    credential_configuration = CredentialsApiConfig.current()

    querystring = {
        'username': user.username,
        'status': 'awarded',
        'only_visible': 'True'
    }

    if program_uuid:
        querystring['program_uuid'] = program_uuid

    if credential_type:
        querystring['type'] = credential_type

    # Bypass caching for staff users, who may be generating credentials and
    # want to see them displayed immediately.
    use_cache = credential_configuration.is_cache_enabled and not user.is_staff
    cache_key = f'{credential_configuration.CACHE_KEY}.{user.username}' if use_cache else None
    if cache_key and program_uuid:
        cache_key = f'{cache_key}.{program_uuid}'

    api_client = get_credentials_api_client(user)
    base_api_url = get_credentials_api_base_url()

    return get_api_data(credential_configuration,
                        'credentials',
                        api_client=api_client,
                        base_api_url=base_api_url,
                        querystring=querystring,
                        cache_key=cache_key)
Exemplo n.º 13
0
def get_owners_for_course(course_uuid):  # lint-amnesty, pylint: disable=missing-function-docstring
    user, catalog_integration = check_catalog_integration_and_get_user(
        error_message_field='Owners')
    if user:
        cache_key = f"{catalog_integration.CACHE_KEY}.course.{course_uuid}.course_runs"

        data = get_api_data(catalog_integration,
                            'courses',
                            resource_id=course_uuid,
                            api_client=get_catalog_api_client(user),
                            base_api_url=get_catalog_api_base_url(),
                            cache_key=cache_key
                            if catalog_integration.is_cache_enabled else None,
                            long_term_cache=True,
                            many=False)
        return data.get('owners', [])

    return []
Exemplo n.º 14
0
    def test_data_retrieval_failure(self, mock_exception):
        """
        Verify that an exception is logged when data can't be retrieved.
        """
        catalog_integration = self.create_catalog_integration()
        api = get_catalog_api_client(self.user)

        self._mock_catalog_api([
            httpretty.Response(body='clunk',
                               content_type='application/json',
                               status_code=500)
        ])

        actual = get_api_data(catalog_integration,
                              'programs',
                              api_client=api,
                              base_api_url=self.base_api_url)

        assert mock_exception.called
        assert actual == []
Exemplo n.º 15
0
def get_currency_data():
    """Retrieve currency data from the catalog service.

    Returns:
        list of dict, representing program types.
        dict, if a specific program type is requested.
    """
    user, catalog_integration = check_catalog_integration_and_get_user(
        error_message_field='Currency data')
    if user:
        cache_key = f'{catalog_integration.CACHE_KEY}.currency'

        return get_api_data(catalog_integration,
                            "currency",
                            api_client=get_catalog_api_client(user),
                            base_api_url=get_catalog_api_base_url(),
                            traverse_pagination=False,
                            cache_key=cache_key
                            if catalog_integration.is_cache_enabled else None)
    else:
        return []
Exemplo n.º 16
0
def get_course_runs():
    """
    Retrieve all the course runs from the catalog service.

    Returns:
        list of dict with each record representing a course run.
    """
    course_runs = []
    user, catalog_integration = check_catalog_integration_and_get_user(
        error_message_field='Course runs')
    if user:
        querystring = {
            'page_size': catalog_integration.page_size,
            'exclude_utm': 1,
        }

        course_runs = get_api_data(catalog_integration,
                                   'course_runs',
                                   api_client=get_catalog_api_client(user),
                                   base_api_url=get_catalog_api_base_url(),
                                   querystring=querystring)

    return course_runs
Exemplo n.º 17
0
def get_user_orders(user):
    """Given a user, get the detail of all the orders from the Ecommerce service.

    Args:
        user (User): The user to authenticate as when requesting ecommerce.

    Returns:
        list of dict, representing orders returned by the Ecommerce service.
    """
    user_orders = []
    commerce_configuration = CommerceConfiguration.current()
    user_query = {'username': user.username}

    use_cache = commerce_configuration.is_cache_enabled
    cache_key = commerce_configuration.CACHE_KEY + '.' + str(user.id) if use_cache else None
    commerce_user_orders = get_api_data(
        commerce_configuration,
        'orders',
        api_client=get_ecommerce_api_client(user),
        base_api_url=get_ecommerce_api_base_url(),
        querystring=user_query,
        cache_key=cache_key
    )

    for order in commerce_user_orders:
        if order['status'].lower() == 'complete':
            date_placed = datetime.strptime(order['date_placed'], "%Y-%m-%dT%H:%M:%SZ")
            order_data = {
                'number': order['number'],
                'price': order['total_excl_tax'],
                'order_date': strftime_localized(date_placed, 'SHORT_DATE'),
                'receipt_url': EcommerceService().get_receipt_page_url(order['number']),
                'lines': order['lines'],
            }
            user_orders.append(order_data)

    return user_orders
Exemplo n.º 18
0
    def test_cache_utilization(self):
        """
        Verify that when enabled, the cache is used.
        """
        catalog_integration = self.create_catalog_integration(cache_ttl=5)
        api = get_catalog_api_client(self.user)

        expected_collection = ['some', 'test', 'data']
        data = {
            'next': None,
            'results': expected_collection,
        }

        self._mock_catalog_api([
            httpretty.Response(body=json.dumps(data),
                               content_type='application/json')
        ], )

        resource_id = 1
        url = urljoin(f"{self.base_api_url}/", f"programs/{resource_id}/")

        expected_resource = {'key': 'value'}

        self._mock_catalog_api([
            httpretty.Response(body=json.dumps(expected_resource),
                               content_type='application/json')
        ],
                               url=url)

        cache_key = CatalogIntegration.current().CACHE_KEY

        # Warm up the cache.
        get_api_data(catalog_integration,
                     'programs',
                     api_client=api,
                     base_api_url=self.base_api_url,
                     cache_key=cache_key)
        get_api_data(catalog_integration,
                     'programs',
                     api_client=api,
                     base_api_url=self.base_api_url,
                     resource_id=resource_id,
                     cache_key=cache_key)

        # Hit the cache.
        actual_collection = get_api_data(catalog_integration,
                                         'programs',
                                         api_client=api,
                                         base_api_url=self.base_api_url,
                                         cache_key=cache_key)
        assert actual_collection == expected_collection

        actual_resource = get_api_data(catalog_integration,
                                       'programs',
                                       api_client=api,
                                       base_api_url=self.base_api_url,
                                       resource_id=resource_id,
                                       cache_key=cache_key)
        assert actual_resource == expected_resource

        # Verify that only two requests were made, not four.
        self._assert_num_requests(2)