From 858c9a6f6c38674ffe137c88284569e89fce2269 Mon Sep 17 00:00:00 2001 From: salman2013 Date: Tue, 9 Jan 2024 13:19:37 +0500 Subject: [PATCH 1/3] chore: remove bok-choy usage --- conftest.py | 7 +- docs/conf.py | 2 - ecommerce/extensions/api/tests/test_utils.py | 4 +- .../extensions/api/v2/views/enterprise.py | 6 +- ecommerce/extensions/api/v2/views/orders.py | 2 +- .../extensions/dashboard/orders/tests.py | 2 +- .../dashboard/refunds/tests/browser.py | 605 ++++++++++++++++++ .../dashboard/refunds/tests/promise.py | 183 ++++++ .../refunds/tests/test_acceptance.py | 2 +- .../extensions/iap/api/v1/tests/test_views.py | 2 +- .../tests/test_batch_update_mobile_seats.py | 2 +- .../extensions/payment/processors/stripe.py | 2 + requirements/base.txt | 216 ++++--- requirements/common_constraints.txt | 9 - requirements/dev.txt | 280 ++++---- requirements/docs.txt | 29 +- requirements/e2e.txt | 64 +- requirements/pip.txt | 6 +- requirements/pip_tools.txt | 19 +- requirements/production.txt | 218 ++++--- requirements/test.in | 1 - requirements/test.txt | 267 ++++---- requirements/tox.txt | 7 +- 23 files changed, 1375 insertions(+), 560 deletions(-) create mode 100644 ecommerce/extensions/dashboard/refunds/tests/browser.py create mode 100644 ecommerce/extensions/dashboard/refunds/tests/promise.py diff --git a/conftest.py b/conftest.py index e39df9a848f..c08e9d6491f 100644 --- a/conftest.py +++ b/conftest.py @@ -6,16 +6,15 @@ from ecommerce.core.constants import ( COUPON_PRODUCT_CLASS_NAME, COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME, + DONATIONS_FROM_CHECKOUT_TESTS_PRODUCT_TYPE_NAME, ENROLLMENT_CODE_PRODUCT_CLASS_NAME, + ENTERPRISE_COUPON_ADMIN_ROLE, + ORDER_MANAGER_ROLE, SEAT_PRODUCT_CLASS_NAME ) from ecommerce.extensions.basket.constants import EMAIL_OPT_IN_ATTRIBUTE, PURCHASER_BEHALF_ATTRIBUTE from ecommerce.extensions.catalogue.utils import create_subcategories from ecommerce.extensions.checkout.signals import BUNDLE -from ecommerce.core.constants import ORDER_MANAGER_ROLE -from ecommerce.core.constants import DONATIONS_FROM_CHECKOUT_TESTS_PRODUCT_TYPE_NAME -from ecommerce.core.constants import ENTERPRISE_COUPON_ADMIN_ROLE - COUPON_CATEGORY_NAME = 'Coupons' diff --git a/docs/conf.py b/docs/conf.py index 27c41a249d0..99faba6090b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,8 +16,6 @@ import os from datetime import datetime - - # on_rtd is whether we are on readthedocs.org on_rtd = os.environ.get('READTHEDOCS', None) == 'True' diff --git a/ecommerce/extensions/api/tests/test_utils.py b/ecommerce/extensions/api/tests/test_utils.py index cc81c0293d1..3a7f96ecbb8 100644 --- a/ecommerce/extensions/api/tests/test_utils.py +++ b/ecommerce/extensions/api/tests/test_utils.py @@ -28,7 +28,7 @@ def test_send_mail_to_mobile_team_with_no_email_specified(self): email_sender = 'ecommerce.extensions.communication.utils.Dispatcher.dispatch_direct_messages' msg_t = "Couldn't mail mobile team for change in {}. No email was specified for mobile team in configurations" msg = msg_t.format(self.course.name) - with LogCapture(logger_name) as utils_logger,\ + with LogCapture(logger_name) as utils_logger, \ mock.patch(email_sender) as mock_send_email: send_mail_to_mobile_team_for_change_in_course(self.course, self.course.seat_products.all()) @@ -47,7 +47,7 @@ def test_send_mail_to_mobile_team(self): iap_configs = IAPProcessorConfiguration.get_solo() iap_configs.mobile_team_email = self.mock_mobile_team_mail iap_configs.save() - with LogCapture(logger_name) as utils_logger,\ + with LogCapture(logger_name) as utils_logger, \ mock.patch(email_sender) as mock_send_email: send_mail_to_mobile_team_for_change_in_course(self.course, self.course.seat_products.all()) diff --git a/ecommerce/extensions/api/v2/views/enterprise.py b/ecommerce/extensions/api/v2/views/enterprise.py index f71f2fe6dd8..8f23c7b71c8 100644 --- a/ecommerce/extensions/api/v2/views/enterprise.py +++ b/ecommerce/extensions/api/v2/views/enterprise.py @@ -811,7 +811,7 @@ def assign(self, request, pk): # pylint: disable=unused-argument all_uploaded_un_uploaded_files = request.data.pop('template_files', []) self._validate_email_fields(subject, greeting, closing) files_with_url = [ - {'file_name': file['name'], 'url':file['url']} + {'file_name': file['name'], 'url': file['url']} for file in all_uploaded_un_uploaded_files if 'url' in file ] @@ -916,7 +916,7 @@ def revoke(self, request, pk): # pylint: disable=unused-argument self._validate_assignments_data(request.data.get('assignments')) files_with_url = [ - {'file_name': file['name'], 'url':file['url']} + {'file_name': file['name'], 'url': file['url']} for file in all_uploaded_un_uploaded_files if 'url' in file ] @@ -1006,7 +1006,7 @@ def remind(self, request, pk): # pylint: disable=unused-argument ) files_with_url = [ - {'file_name': file['name'], 'url':file['url']} + {'file_name': file['name'], 'url': file['url']} for file in all_uploaded_un_uploaded_files if 'url' in file ] diff --git a/ecommerce/extensions/api/v2/views/orders.py b/ecommerce/extensions/api/v2/views/orders.py index 6f7c60fcd8c..2182293476d 100644 --- a/ecommerce/extensions/api/v2/views/orders.py +++ b/ecommerce/extensions/api/v2/views/orders.py @@ -439,7 +439,7 @@ def _get_enrollment_data(self, enrollment): if discount_percentage is not None: if not isinstance(discount_percentage, float) or (discount_percentage < 0.0 or discount_percentage > 100.0): raise ValidationError('Discount percentage should be a float from 0 to 100.') - return lms_user_id, learner_username, learner_email, course_run_key, mode, discount_percentage,\ + return lms_user_id, learner_username, learner_email, course_run_key, mode, discount_percentage, \ sales_force_id, salesforce_opportunity_line_item def _get_learner_user(self, lms_user_id, learner_username, learner_email): diff --git a/ecommerce/extensions/dashboard/orders/tests.py b/ecommerce/extensions/dashboard/orders/tests.py index cfd96bcc429..6e2b3e48218 100644 --- a/ecommerce/extensions/dashboard/orders/tests.py +++ b/ecommerce/extensions/dashboard/orders/tests.py @@ -4,7 +4,6 @@ from unittest import SkipTest, skipIf import pytest -from bok_choy.browser import browser from django.contrib.messages import constants as MSG from django.test import override_settings from django.urls import reverse @@ -13,6 +12,7 @@ from selenium.webdriver.support.wait import WebDriverWait from ecommerce.extensions.dashboard.orders.views import queryset_orders_for_user +from ecommerce.extensions.dashboard.refunds.tests.browser import browser from ecommerce.extensions.dashboard.tests import DashboardViewTestMixin from ecommerce.extensions.fulfillment.signals import SHIPPING_EVENT_NAME from ecommerce.extensions.fulfillment.status import LINE, ORDER diff --git a/ecommerce/extensions/dashboard/refunds/tests/browser.py b/ecommerce/extensions/dashboard/refunds/tests/browser.py new file mode 100644 index 00000000000..e0012c9f0c1 --- /dev/null +++ b/ecommerce/extensions/dashboard/refunds/tests/browser.py @@ -0,0 +1,605 @@ +""" +Use environment variables to configure Selenium remote WebDriver. +For use with SauceLabs (via SauceConnect) or local browsers. +""" + +import errno +import logging +import os +from json import dumps +from shutil import copyfile + +try: + from needle.driver import NeedleChrome as Chrome + from needle.driver import NeedleFirefox as Firefox + from needle.driver import NeedleIe as Ie + from needle.driver import NeedleOpera as Opera + from needle.driver import NeedlePhantomJS as PhantomJS + from needle.driver import NeedleSafari as Safari +except ImportError: + from selenium.webdriver import Chrome, Firefox, Ie, Opera, PhantomJS, Safari + +from selenium import webdriver +from selenium.common.exceptions import WebDriverException +from selenium.webdriver.chrome.options import Options as ChromeOptions +from selenium.webdriver.firefox.firefox_binary import FirefoxBinary +from selenium.webdriver.firefox.options import Options as FirefoxOptions + +from ecommerce.extensions.dashboard.refunds.tests.promise import Promise + +LOGGER = logging.getLogger(__name__) + +REMOTE_ENV_VARS = [ + 'SELENIUM_BROWSER', + 'SELENIUM_HOST', + 'SELENIUM_PORT', +] + +SAUCE_ENV_VARS = REMOTE_ENV_VARS + [ + 'SELENIUM_VERSION', + 'SELENIUM_PLATFORM', + 'SAUCE_USER_NAME', + 'SAUCE_API_KEY', +] + + +OPTIONAL_ENV_VARS = [ + 'JOB_NAME', + 'BUILD_NUMBER', + 'SELENIUM_INSECURE_CERTS', +] + + +BROWSERS = { + 'chrome': Chrome, + 'firefox': Firefox, + 'internet explorer': Ie, + 'opera': Opera, + 'phantomjs': PhantomJS, + 'safari': Safari, +} + +FIREFOX_PROFILE_ENV_VAR = 'FIREFOX_PROFILE_PATH' + +# A list of functions accepting one FirefoxProfile argument +FIREFOX_PROFILE_CUSTOMIZERS = [] + + +class BrowserConfigError(Exception): + + """ + Misconfiguration error in the environment variables. + """ + + +def save_source(driver, name): + """ + Save the rendered HTML of the browser. + + The location of the source can be configured + by the environment variable `SAVED_SOURCE_DIR`. If not set, + this defaults to the current working directory. + + Args: + driver (selenium.webdriver): The Selenium-controlled browser. + name (str): A name to use in the output file name. + Note that ".html" is appended automatically + + Returns: + None + """ + source = driver.page_source + saved_source_dir = os.environ.get('SAVED_SOURCE_DIR') + if not saved_source_dir: + LOGGER.warning('The SAVED_SOURCE_DIR environment variable was not set; not saving page source') + return + file_name = os.path.join(saved_source_dir, + f'{name}.html') + + try: + if not os.path.exists(saved_source_dir): + os.makedirs(saved_source_dir) + with open(file_name, 'wb') as output_file: + output_file.write(source.encode('utf-8')) + except Exception: # pylint: disable=broad-except + msg = f"Could not save the browser page source to {file_name}." + LOGGER.warning(msg) + + +def save_screenshot(driver, name): + """ + Save a screenshot of the browser. + + The location of the screenshot can be configured + by the environment variable `SCREENSHOT_DIR`. If not set, + this defaults to the current working directory. + + Args: + driver (selenium.webdriver): The Selenium-controlled browser. + name (str): A name for the screenshot, which will be used in the output file name. + + Returns: + None + """ + if hasattr(driver, 'save_screenshot'): + screenshot_dir = os.environ.get('SCREENSHOT_DIR') + if not screenshot_dir: + LOGGER.warning('The SCREENSHOT_DIR environment variable was not set; not saving a screenshot') + return + if not os.path.exists(screenshot_dir): + os.makedirs(screenshot_dir) + image_name = os.path.join(screenshot_dir, name + '.png') + driver.save_screenshot(image_name) + + else: + msg = f"Browser does not support screenshots. Could not save screenshot '{name}'" + LOGGER.warning(msg) + + +def save_driver_logs(driver, prefix): + """ + Save the selenium driver logs. + + The location of the driver log files can be configured + by the environment variable `SELENIUM_DRIVER_LOG_DIR`. If not set, + this defaults to the current working directory. + + Args: + driver (selenium.webdriver): The Selenium-controlled browser. + prefix (str): A prefix which will be used in the output file names for the logs. + + Returns: + None + """ + browser_name = os.environ.get('SELENIUM_BROWSER', 'firefox') + log_dir = os.environ.get('SELENIUM_DRIVER_LOG_DIR') + if not log_dir: + LOGGER.warning('The SELENIUM_DRIVER_LOG_DIR environment variable was not set; not saving logs') + return + if not os.path.exists(log_dir): + os.makedirs(log_dir) + if browser_name == 'firefox': + # Firefox doesn't yet provide logs to Selenium, but does log to a separate file + # https://github.com/mozilla/geckodriver/issues/284 + # https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/TraceLogs.html + log_path = os.path.join(os.getcwd(), 'geckodriver.log') + if os.path.exists(log_path): + dest_path = os.path.join(log_dir, f'{prefix}_geckodriver.log') + copyfile(log_path, dest_path) + return + + log_types = driver.log_types + for log_type in log_types: + try: + log = driver.get_log(log_type) + file_name = os.path.join( + log_dir, f'{prefix}_{log_type}.log' + ) + with open(file_name, 'w', encoding="utf8") as output_file: + for line in log: + output_file.write("{}{}".format(dumps(line), '\n')) + except: # pylint: disable=bare-except + msg = ( + f"Could not save browser log of type '{log_type}'. It may be that the browser does not support it." + ) + + LOGGER.warning(msg, exc_info=True) + + +def browser(tags=None, proxy=None, other_caps=None): + """ + Interpret environment variables to configure Selenium. + Performs validation, logging, and sensible defaults. + + There are three cases: + + 1. Local browsers: If the proper environment variables are not all set for the second case, + then we use a local browser. + + * The environment variable `SELENIUM_BROWSER` can be set to specify which local browser to use. The default is \ + Firefox. + * Additionally, if a proxy instance is passed and the browser choice is either Chrome or Firefox, then the \ + browser will be initialized with the proxy server set. + * The environment variable `SELENIUM_FIREFOX_PATH` can be used for specifying a path to the Firefox binary. \ + Default behavior is to use the system location. + * The environment variable `FIREFOX_PROFILE_PATH` can be used for specifying a path to the Firefox profile. \ + Default behavior is to use a barebones default profile with a few useful preferences set. + + 2. Remote browser (not SauceLabs): Set all of the following environment variables, but not all of + the ones needed for SauceLabs: + + * SELENIUM_BROWSER + * SELENIUM_HOST + * SELENIUM_PORT + + 3. SauceLabs: Set all of the following environment variables: + + * SELENIUM_BROWSER + * SELENIUM_VERSION + * SELENIUM_PLATFORM + * SELENIUM_HOST + * SELENIUM_PORT + * SAUCE_USER_NAME + * SAUCE_API_KEY + + **NOTE:** these are the environment variables set by the SauceLabs + Jenkins plugin. + + Optionally provide Jenkins info, used to identify jobs to Sauce: + + * JOB_NAME + * BUILD_NUMBER + + `tags` is a list of string tags to apply to the SauceLabs + job. If not using SauceLabs, these will be ignored. + + Keyword Args: + tags (list of str): Tags to apply to the SauceLabs job. If not using SauceLabs, these will be ignored. + proxy: A proxy instance. + other_caps (dict of str): Additional desired capabilities to provide to remote WebDriver instances. Note + that these values will be overwritten by environment variables described above. This is only used for + remote driver instances, where such info is usually used by services for additional configuration and + metadata. + + Returns: + selenium.webdriver: The configured browser object used to drive tests + + Raises: + BrowserConfigError: The environment variables are not correctly specified. + """ + + browser_name = os.environ.get('SELENIUM_BROWSER', 'firefox') + + def browser_check_func(): + """ Instantiate the browser and return the browser instance """ + # See https://openedx.atlassian.net/browse/TE-701 + try: + # Get the class and kwargs required to instantiate the browser based on + # whether we are using a local or remote one. + if _use_remote_browser(SAUCE_ENV_VARS): + browser_class, browser_args, browser_kwargs = _remote_browser_class( + SAUCE_ENV_VARS, tags) + elif _use_remote_browser(REMOTE_ENV_VARS): + browser_class, browser_args, browser_kwargs = _remote_browser_class( + REMOTE_ENV_VARS, tags) + else: + browser_class, browser_args, browser_kwargs = _local_browser_class( + browser_name) + + # If we are using a proxy, we need extra kwargs passed on intantiation. + if proxy: + browser_kwargs = _proxy_kwargs(browser_name, proxy, browser_kwargs) + + # Load in user given desired caps but override with derived caps from above. This is to retain existing + # behavior. Only for remote drivers, where various testing services use this info for configuration. + if browser_class == webdriver.Remote: + desired_caps = other_caps or {} + desired_caps.update(browser_kwargs.get('desired_capabilities', {})) + browser_kwargs['desired_capabilities'] = desired_caps + + return True, browser_class(*browser_args, **browser_kwargs) + + except (OSError, WebDriverException) as err: + msg = str(err) + LOGGER.debug('Failed to instantiate browser: %s', msg) + return False, None + + browser_instance = Promise( + # There are cases where selenium takes 30s to return with a failure, so in order to try 3 + # times, we set a long timeout. If there is a hang on the first try, the timeout will + # be enforced. + browser_check_func, "Browser is instantiated successfully.", try_limit=3, timeout=95).fulfill() + + return browser_instance + + +def add_profile_customizer(func): + """Add a new function that modifies the preferences of the firefox profile object it receives as an argument""" + FIREFOX_PROFILE_CUSTOMIZERS.append(func) + + +def clear_profile_customizers(): + """Remove any previously-configured functions for customizing the firefox profile""" + FIREFOX_PROFILE_CUSTOMIZERS[:] = [] + + +def _firefox_profile(): + """Configure the Firefox profile, respecting FIREFOX_PROFILE_PATH if set""" + profile_dir = os.environ.get(FIREFOX_PROFILE_ENV_VAR) + + if profile_dir: + LOGGER.info("Using firefox profile: %s", profile_dir) + try: + firefox_profile = webdriver.FirefoxProfile(profile_dir) + except OSError as err: + if err.errno == errno.ENOENT: + raise BrowserConfigError( + f"Firefox profile directory {FIREFOX_PROFILE_ENV_VAR}={profile_dir} does not exist" + ) from err + if err.errno == errno.EACCES: + raise BrowserConfigError( + f"Firefox profile directory {FIREFOX_PROFILE_ENV_VAR}={profile_dir} has incorrect permissions. " + f"It must be readable and executable." + ) from err + # Some other OSError: + raise BrowserConfigError( + f"Problem with firefox profile directory {FIREFOX_PROFILE_ENV_VAR}={profile_dir}: {str(err)}" + ) from err + else: + LOGGER.info("Using default firefox profile") + firefox_profile = webdriver.FirefoxProfile() + + # Bypasses the security prompt displayed by the browser when it attempts to + # access a media device (e.g., a webcam) + firefox_profile.set_preference('media.navigator.permission.disabled', True) + + # Disable the initial url fetch to 'learn more' from mozilla (so you don't have to + # be online to run bok-choy on firefox) + firefox_profile.set_preference('browser.startup.homepage', 'about:blank') + firefox_profile.set_preference('startup.homepage_welcome_url', 'about:blank') + firefox_profile.set_preference('startup.homepage_welcome_url.additional', 'about:blank') + + # Disable fetching an updated version of firefox + firefox_profile.set_preference('app.update.enabled', False) + + # Disable plugin checking + firefox_profile.set_preference('plugins.hide_infobar_for_outdated_plugin', True) + + # Disable health reporter + firefox_profile.set_preference('datareporting.healthreport.service.enabled', False) + + # Disable all data upload (Telemetry and FHR) + firefox_profile.set_preference('datareporting.policy.dataSubmissionEnabled', False) + + # Disable crash reporter + firefox_profile.set_preference('toolkit.crashreporter.enabled', False) + + # Disable the JSON Viewer + firefox_profile.set_preference('devtools.jsonview.enabled', False) + + # Grant OS focus to the launched browser so focus-related tests function correctly + firefox_profile.set_preference('focusmanager.testmode', True) + for function in FIREFOX_PROFILE_CUSTOMIZERS: + function(firefox_profile) + return firefox_profile + + +def _local_browser_class(browser_name): + """ + Returns class, kwargs, and args needed to instantiate the local browser. + """ + + # Log name of local browser + LOGGER.info("Using local browser: %s [Default is firefox]", browser_name) + + # Get class of local browser based on name + browser_class = BROWSERS.get(browser_name) + headless = os.environ.get('BOKCHOY_HEADLESS', 'false').lower() == 'true' + if browser_class is None: + raise BrowserConfigError( + f"Invalid browser name {browser_name}. Options are: {', '.join(list(BROWSERS.keys()))}" + ) + + if browser_name == 'firefox': + # Remove geckodriver log data from previous test cases + log_path = os.path.join(os.getcwd(), 'geckodriver.log') + if os.path.exists(log_path): + os.remove(log_path) + + firefox_options = FirefoxOptions() + firefox_options.log.level = 'trace' + if headless: + firefox_options.headless = True + browser_args = [] + browser_kwargs = { + 'firefox_profile': _firefox_profile(), + 'options': firefox_options, + } + + firefox_path = os.environ.get('SELENIUM_FIREFOX_PATH') + firefox_log = os.environ.get('SELENIUM_FIREFOX_LOG') + if firefox_path and firefox_log: + browser_kwargs.update({ + 'firefox_binary': FirefoxBinary( + firefox_path=firefox_path, log_file=firefox_log) + }) + elif firefox_path: + browser_kwargs.update({ + 'firefox_binary': FirefoxBinary(firefox_path=firefox_path) + }) + elif firefox_log: + browser_kwargs.update({ + 'firefox_binary': FirefoxBinary(log_file=firefox_log) + }) + + elif browser_name == 'chrome': + chrome_options = ChromeOptions() + if headless: + chrome_options.headless = True + + # Emulate webcam and microphone for testing purposes + chrome_options.add_argument('--use-fake-device-for-media-stream') + + # Bypasses the security prompt displayed by the browser when it attempts to + # access a media device (e.g., a webcam) + chrome_options.add_argument('--use-fake-ui-for-media-stream') + browser_args = [] + browser_kwargs = { + 'options': chrome_options, + } + else: + browser_args, browser_kwargs = [], {} + return browser_class, browser_args, browser_kwargs + + +def _remote_browser_class(env_vars, tags=None): + """ + Returns class, kwargs, and args needed to instantiate the remote browser. + """ + if tags is None: + tags = [] + + # Interpret the environment variables, raising an exception if they're + # invalid + envs = _required_envs(env_vars) + envs.update(_optional_envs()) + + # Turn the environment variables into a dictionary of desired capabilities + caps = _capabilities_dict(envs, tags) + + if 'accessKey' in caps: + LOGGER.info("Using SauceLabs: %s %s %s", caps['platform'], caps['browserName'], caps['version']) + else: + LOGGER.info("Using Remote Browser: %s", caps['browserName']) + + # Create and return a new Browser + # We assume that the WebDriver end-point is running locally (e.g. using + # SauceConnect) + url = f"http://{envs['SELENIUM_HOST']}:{envs['SELENIUM_PORT']}/wd/hub" + + browser_args = [] + browser_kwargs = { + 'command_executor': url, + 'desired_capabilities': caps, + } + if caps['browserName'] == 'firefox': + browser_kwargs['browser_profile'] = _firefox_profile() + + return webdriver.Remote, browser_args, browser_kwargs + + +def _proxy_kwargs(browser_name, proxy, browser_kwargs={}): # pylint: disable=dangerous-default-value + """ + Determines the kwargs needed to set up a proxy based on the + browser type. + + Returns: a dictionary of arguments needed to pass when + instantiating the WebDriver instance. + """ + + proxy_dict = { + "httpProxy": proxy.proxy, + "proxyType": 'manual', + } + + if browser_name == 'firefox' and 'desired_capabilities' not in browser_kwargs: + # This one works for firefox locally + wd_proxy = webdriver.common.proxy.Proxy(proxy_dict) + browser_kwargs['proxy'] = wd_proxy + else: + # This one works with chrome, both locally and remote + # This one works with firefox remote, but not locally + if 'desired_capabilities' not in browser_kwargs: + browser_kwargs['desired_capabilities'] = {} + + browser_kwargs['desired_capabilities']['proxy'] = proxy_dict + + return browser_kwargs + + +def _use_remote_browser(required_vars): + """ + Returns a boolean indicating whether we should use a remote + browser. This means the user has made an attempt to set + environment variables indicating they want to connect to SauceLabs + or a remote browser. + """ + return all( + key in os.environ + for key in required_vars + ) + + +def _required_envs(env_vars): + """ + Parse environment variables for required values, + raising a `BrowserConfig` error if they are not found. + + Returns a `dict` of environment variables. + """ + envs = { + key: os.environ.get(key) + for key in env_vars + } + + # Check for missing keys + missing = [key for key, val in list(envs.items()) if val is None] + if missing: + msg = ( + "These environment variables must be set: " + ", ".join(missing) + ) + raise BrowserConfigError(msg) + + # Check that we support this browser + if envs['SELENIUM_BROWSER'] not in BROWSERS: + msg = f"Unsuppported browser: {envs['SELENIUM_BROWSER']}" + raise BrowserConfigError(msg) + + return envs + + +def _optional_envs(): + """ + Parse environment variables for optional values, + raising a `BrowserConfig` error if they are insufficiently specified. + + Returns a `dict` of environment variables. + """ + envs = { + key: os.environ.get(key) + for key in OPTIONAL_ENV_VARS + if key in os.environ + } + + # If we're using Jenkins, check that we have all the required info + if 'JOB_NAME' in envs and 'BUILD_NUMBER' not in envs: + raise BrowserConfigError("Missing BUILD_NUMBER environment var") + + if 'BUILD_NUMBER' in envs and 'JOB_NAME' not in envs: + raise BrowserConfigError("Missing JOB_NAME environment var") + + return envs + + +def _capabilities_dict(envs, tags): + """ + Convert the dictionary of environment variables to + a dictionary of desired capabilities to send to the + Remote WebDriver. + + `tags` is a list of string tags to apply to the SauceLabs job. + """ + capabilities = { + 'browserName': envs['SELENIUM_BROWSER'], + 'acceptInsecureCerts': bool(envs.get('SELENIUM_INSECURE_CERTS', False)), + 'video-upload-on-pass': False, + 'sauce-advisor': False, + 'capture-html': True, + 'record-screenshots': True, + 'max-duration': 600, + 'public': 'public restricted', + 'tags': tags, + } + + # Add SauceLabs specific environment vars if they are set. + if _use_remote_browser(SAUCE_ENV_VARS): + sauce_capabilities = { + 'platform': envs['SELENIUM_PLATFORM'], + 'version': envs['SELENIUM_VERSION'], + 'username': envs['SAUCE_USER_NAME'], + 'accessKey': envs['SAUCE_API_KEY'], + } + + capabilities.update(sauce_capabilities) + + # Optional: Add in Jenkins-specific environment variables + # to link Sauce output with the Jenkins job + if 'JOB_NAME' in envs: + jenkins_vars = { + 'build': envs['BUILD_NUMBER'], + 'name': envs['JOB_NAME'], + } + + capabilities.update(jenkins_vars) + + return capabilities diff --git a/ecommerce/extensions/dashboard/refunds/tests/promise.py b/ecommerce/extensions/dashboard/refunds/tests/promise.py new file mode 100644 index 00000000000..ca3a89e45a5 --- /dev/null +++ b/ecommerce/extensions/dashboard/refunds/tests/promise.py @@ -0,0 +1,183 @@ +""" +Variation on the "promise" design pattern. +Promises make it easier to handle asynchronous operations correctly. +""" + +import logging +import time + +LOGGER = logging.getLogger(__name__) + + +class BrokenPromise(Exception): + """ + The promise was not satisfied within the time constraints. + """ + + def __init__(self, promise): + """ + Configure the broken promise error. + + Args: + promise (Promise): The promise that was not satisfied. + """ + super().__init__() + self._promise = promise + + def __str__(self): + return f"Promise not satisfied: {self._promise}" + + +class Promise: + """ + Check that an asynchronous action completed, blocking until it does + or timeout / try limits are reached. + """ + + # pylint: disable=too-many-arguments + def __init__(self, check_func, description, try_limit=None, try_interval=0.5, timeout=30): + """ + Configure the `Promise`. + + The `Promise` will poll `check_func()` until either: + * The promise is satisfied + * The promise runs out of tries (checks more than `try_limit` times) + * The promise runs out of time (takes longer than `timeout` seconds) + + If the try_limit or timeout is reached without success, then the promise is "broken" and + an exception will be raised. + + Note that if you specify a try_limit but not a timeout, the default timeout is still used. + This is to prevent an inadvertent infinite loop. If you want to make sure that the + try_limit expires first (and thus that many attempts will be made), then you should also + pass in a larger value for timeout. + + `description` is a string that will be included in the exception to make debugging easier. + + Example: + + .. code:: python + + # Dummy check function that indicates the promise is always satisfied + check_func = lambda: (True, "Hello world!") + + # Check up to 5 times if the operation has completed + result = Promise(check_func, "Operation has completed", try_limit=5).fulfill() + + Args: + check_func (callable): A function that accepts no arguments and returns a `(is_satisfied, result)` tuple, + where `is_satisfied` is a boolean indiating whether the promise was satisfied, and `result` + is a value to return from the fulfilled `Promise`. + + description (str): Description of the `Promise`, used in log messages. + + Keyword Args: + try_limit (int or None): Number of attempts to make to satisfy the `Promise`. + Can be `None` to disable the limit. + try_interval (float): Number of seconds to wait between attempts. + timeout (float): Maximum number of seconds to wait for the `Promise` to be satisfied before timing out. + + Returns: + Promise + """ + self._check_func = check_func + self._description = description + self._try_limit = try_limit + self._try_interval = try_interval + self._timeout = timeout + self._num_tries = 0 + + def fulfill(self): + """ + Evaluate the promise and return the result. + + Returns: + The result of the `Promise` (second return value from the `check_func`) + + Raises: + BrokenPromise: the `Promise` was not satisfied within the time or attempt limits. + """ + is_fulfilled, result = self._check_fulfilled() + + if is_fulfilled: + return result + raise BrokenPromise(self) + + def __str__(self): + return str(self._description) + + def _check_fulfilled(self): + """ + Return tuple `(is_fulfilled, result)` where + `is_fulfilled` is a boolean indicating whether the promise has been fulfilled + and `result` is the value to pass to the `with` block. + """ + is_fulfilled = False + result = None + start_time = time.time() + + # Check whether the promise has been fulfilled until we run out of time or attempts + while self._has_time_left(start_time) and self._has_more_tries(): + + # Keep track of how many attempts we've made so far + self._num_tries += 1 + + is_fulfilled, result = self._check_func() + + # If the promise is satisfied, then continue execution + if is_fulfilled: + break + + # Delay between checks + time.sleep(self._try_interval) + + return is_fulfilled, result + + def _has_time_left(self, start_time): + """ + Return True if the elapsed time is less than the timeout. + """ + return time.time() - start_time < self._timeout + + def _has_more_tries(self): + """ + Return True if the promise has additional tries. + If `_try_limit` is `None`, always return True. + """ + if self._try_limit is None: + return True + return self._num_tries < self._try_limit + + +class EmptyPromise(Promise): # pylint: disable=too-few-public-methods + """ + A promise that has no result value. + """ + + def __init__(self, check_func, description, **kwargs): + """ + Configure the promise. + + Unlike a regular `Promise`, the `check_func()` does NOT return a tuple + with a result value. That's why the promise is "empty" -- you don't get anything back. + + Example usage: + + .. code:: python + + # This will block until `is_done` returns `True` or we reach the timeout limit. + EmptyPromise(lambda: is_done('test'), "Test operation is done").fulfill() + + Args: + check_func (callable): Function that accepts no arguments and + returns a boolean indicating whether the promise is fulfilled. + description (str): Description of the Promise, used in log messages. + + Returns: + EmptyPromise + """ + def full_check_func(): + check_result = check_func() + return check_result, None + + super().__init__(full_check_func, description, **kwargs) diff --git a/ecommerce/extensions/dashboard/refunds/tests/test_acceptance.py b/ecommerce/extensions/dashboard/refunds/tests/test_acceptance.py index 2ab8af7487a..9d079b00295 100644 --- a/ecommerce/extensions/dashboard/refunds/tests/test_acceptance.py +++ b/ecommerce/extensions/dashboard/refunds/tests/test_acceptance.py @@ -5,12 +5,12 @@ import ddt import pytest -from bok_choy.browser import browser from django.urls import reverse from oscar.core.loading import get_model from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.support.wait import WebDriverWait +from ecommerce.extensions.dashboard.refunds.tests.browser import browser from ecommerce.extensions.refund.status import REFUND from ecommerce.extensions.refund.tests.mixins import RefundTestMixin from ecommerce.tests.factories import UserFactory diff --git a/ecommerce/extensions/iap/api/v1/tests/test_views.py b/ecommerce/extensions/iap/api/v1/tests/test_views.py index 16ce322faa0..eafd2ff15a0 100644 --- a/ecommerce/extensions/iap/api/v1/tests/test_views.py +++ b/ecommerce/extensions/iap/api/v1/tests/test_views.py @@ -996,7 +996,7 @@ def test_non_refund_notification(self): View should ignore non refund notifications """ - with mock.patch.object(asn2, 'parse') as mock_ios_response_parse,\ + with mock.patch.object(asn2, 'parse') as mock_ios_response_parse, \ LogCapture(self.logger_name) as logger: non_refund_payload = self.mock_processor_response.copy() diff --git a/ecommerce/extensions/iap/management/commands/tests/test_batch_update_mobile_seats.py b/ecommerce/extensions/iap/management/commands/tests/test_batch_update_mobile_seats.py index 27916935e70..8275b93474b 100644 --- a/ecommerce/extensions/iap/management/commands/tests/test_batch_update_mobile_seats.py +++ b/ecommerce/extensions/iap/management/commands/tests/test_batch_update_mobile_seats.py @@ -229,7 +229,7 @@ def test_send_mail_to_mobile_team(self, mock_publish_to_lms, mock_course_run, mo 'html': None, } - with LogCapture(logger_name) as logger,\ + with LogCapture(logger_name) as logger, \ patch(email_sender) as mock_send_email: call_command(self.command) logger.check_present( diff --git a/ecommerce/extensions/payment/processors/stripe.py b/ecommerce/extensions/payment/processors/stripe.py index ae62818ecf5..d210d73200a 100644 --- a/ecommerce/extensions/payment/processors/stripe.py +++ b/ecommerce/extensions/payment/processors/stripe.py @@ -185,6 +185,7 @@ def handle_processor_response(self, response, basket=None): raise # proceed only if payment went through + # pylint: disable=E1136 assert confirm_api_response['status'] == "succeeded" self.record_processor_response(confirm_api_response, transaction_id=payment_intent_id, basket=basket) @@ -197,6 +198,7 @@ def handle_processor_response(self, response, basket=None): total = basket.total_incl_tax currency = basket.currency + # pylint: disable=E1136 card_object = confirm_api_response['charges']['data'][0]['payment_method_details']['card'] card_number = card_object['last4'] card_type = STRIPE_CARD_TYPE_MAP.get(card_object['brand']) diff --git a/requirements/base.txt b/requirements/base.txt index 34202bcc91c..e5e16190fc9 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -4,7 +4,7 @@ # # make upgrade # -aiohttp==3.8.4 +aiohttp==3.9.1 # via inapppy aiosignal==1.3.1 # via aiohttp @@ -15,73 +15,74 @@ analytics-python==1.4.post1 app-store-notifications-v2-validator==0.0.7 # via -r requirements/base.in asgiref==3.7.2 - # via django + # via + # django + # django-cors-headers asn1crypto==1.5.1 # via cybersource-rest-client-python -async-timeout==4.0.2 +async-timeout==4.0.3 # via # aiohttp # redis -attrs==23.1.0 +attrs==23.2.0 # via # aiohttp # jsonschema + # referencing # zeep -babel==2.12.1 +babel==2.14.0 # via django-oscar backoff==1.10.0 # via analytics-python -bcrypt==4.0.1 +bcrypt==4.1.2 # via # cybersource-rest-client-python # paramiko billiard==3.6.4.0 # via celery -bleach==6.0.0 +bleach==6.1.0 # via -r requirements/base.in -boto3==1.26.155 +boto3==1.34.17 # via -r requirements/base.in -botocore==1.29.155 +botocore==1.34.17 # via # boto3 # s3transfer -cachetools==5.3.1 +cachetools==5.3.2 # via google-auth celery==4.4.7 # via # -c requirements/constraints.txt # edx-ecommerce-worker -certifi==2023.5.7 +certifi==2023.11.17 # via # cybersource-rest-client-python # requests -cffi==1.15.1 +cffi==1.16.0 # via # app-store-notifications-v2-validator # cryptography # cybersource-rest-client-python # pynacl -chardet==5.1.0 +chardet==5.2.0 # via cybersource-rest-client-python -charset-normalizer==3.1.0 - # via - # aiohttp - # requests -click==8.1.3 +charset-normalizer==3.3.2 + # via requests +click==8.1.7 # via edx-django-utils -configparser==5.3.0 +configparser==6.0.0 # via cybersource-rest-client-python coreapi==2.3.3 # via -r requirements/base.in coreschema==0.0.4 # via coreapi -coverage==7.2.7 +coverage==7.4.0 # via cybersource-rest-client-python crispy-bootstrap3==2022.1 # via -r requirements/base.in crypto==1.4.1 # via cybersource-rest-client-python -cryptography==41.0.1 +cryptography==41.0.7 # via # app-store-notifications-v2-validator # cybersource-rest-client-python @@ -91,19 +92,19 @@ cryptography==41.0.1 # social-auth-core cssselect==1.2.0 # via premailer -cssutils==2.7.1 +cssutils==2.9.0 # via premailer cybersource-rest-client-python==0.0.21 # via # -c requirements/constraints.txt # -r requirements/base.in -datetime==5.1 +datetime==5.4 # via cybersource-rest-client-python -defusedxml==0.7.1 +defusedxml==0.8.0rc2 # via # python3-openid # social-auth-core -django==3.2.20 +django==3.2.23 # via # -c requirements/common_constraints.txt # -r requirements/base.in @@ -123,6 +124,7 @@ django==3.2.20 # django-solo # django-tables2 # django-treebeard + # django-waffle # djangorestframework # drf-jwt # drf-yasg @@ -136,15 +138,15 @@ django==3.2.20 # jsonfield2 # social-auth-app-django # xss-utils -django-appconf==1.0.5 +django-appconf==1.0.6 # via django-compressor -django-compressor==4.3.1 +django-compressor==4.4 # via # -r requirements/base.in # django-libsass -django-config-models==2.3.0 +django-config-models==2.5.1 # via -r requirements/base.in -django-cors-headers==4.1.0 +django-cors-headers==4.3.1 # via -r requirements/base.in django-crispy-forms==2.0 # via @@ -158,7 +160,7 @@ django-extensions==3.2.3 # via -r requirements/base.in django-extra-views==0.13.0 # via django-oscar -django-filter==23.2 +django-filter==23.5 # via -r requirements/base.in django-haystack==3.2.1 # via django-oscar @@ -184,12 +186,12 @@ django-threadlocals==0.10 # via -r requirements/base.in django-treebeard==4.4 # via django-oscar -django-waffle==3.0.0 +django-waffle==4.1.0 # via # -r requirements/base.in # edx-django-utils # edx-drf-extensions -django-widget-tweaks==1.4.12 +django-widget-tweaks==1.5.0 # via django-oscar djangorestframework==3.14.0 # via @@ -201,7 +203,7 @@ djangorestframework==3.14.0 # drf-jwt # drf-yasg # edx-drf-extensions -djangorestframework-csv==2.1.1 +djangorestframework-csv==3.0.2 # via -r requirements/base.in djangorestframework-datatables==0.7.0 # via -r requirements/base.in @@ -209,36 +211,36 @@ drf-extensions==0.7.1 # via -r requirements/base.in drf-jwt==1.19.2 # via edx-drf-extensions -drf-yasg==1.21.6 +drf-yasg==1.21.7 # via -r requirements/base.in -edx-auth-backends==4.1.0 +edx-auth-backends==4.2.0 # via -r requirements/base.in -edx-braze-client==0.1.6 +edx-braze-client==0.1.8 # via edx-ecommerce-worker -edx-django-release-util==1.2.0 +edx-django-release-util==1.3.0 # via -r requirements/base.in -edx-django-sites-extensions==4.0.0 +edx-django-sites-extensions==4.0.2 # via -r requirements/base.in -edx-django-utils==5.5.0 +edx-django-utils==5.9.0 # via # -r requirements/base.in # django-config-models # edx-drf-extensions # edx-rest-api-client # getsmarter-api-clients -edx-drf-extensions==9.0.0 +edx-drf-extensions==9.1.2 # via # -r requirements/base.in # edx-rbac edx-ecommerce-worker==3.3.4 # via -r requirements/base.in -edx-opaque-keys==2.3.0 +edx-opaque-keys==2.5.1 # via # -r requirements/base.in # edx-drf-extensions -edx-rbac==1.7.0 +edx-rbac==1.8.0 # via -r requirements/base.in -edx-rest-api-client==5.5.2 +edx-rest-api-client==5.6.1 # via # -r requirements/base.in # edx-ecommerce-worker @@ -250,34 +252,32 @@ extras==1.0.0 # python-subunit factory-boy==3.1.0 # via django-oscar -faker==18.10.1 +faker==22.2.0 # via factory-boy fixtures==4.1.0 - # via - # cybersource-rest-client-python - # testtools -frozenlist==1.3.3 + # via cybersource-rest-client-python +frozenlist==1.4.1 # via # aiohttp # aiosignal funcsigs==1.0.2 # via cybersource-rest-client-python -getsmarter-api-clients==0.6.0 +getsmarter-api-clients==0.6.1 # via -r requirements/base.in -google-api-core==2.11.1 +google-api-core==2.15.0 # via google-api-python-client google-api-python-client==2.31.0 # via # -r requirements/base.in # inapppy -google-auth==2.20.0 +google-auth==2.26.2 # via # google-api-core # google-api-python-client # google-auth-httplib2 -google-auth-httplib2==0.1.0 +google-auth-httplib2==0.2.0 # via google-api-python-client -googleapis-common-protos==1.59.1 +googleapis-common-protos==1.62.0 # via google-api-core httplib2==0.20.2 # via @@ -291,19 +291,23 @@ idna==2.7 # cybersource-rest-client-python # requests # yarl -importlib-resources==5.12.0 - # via jsonschema +importlib-resources==6.1.1 + # via + # jsonschema + # jsonschema-specifications inapppy==2.5.2 # via -r requirements/base.in inflection==0.5.1 # via drf-yasg ipaddress==1.0.23 # via cybersource-rest-client-python +iso8601==2.1.0 + # via python-subunit isodate==0.6.1 # via zeep itypes==1.2.0 # via coreapi -jinja2==3.1.2 +jinja2==3.1.3 # via coreschema jmespath==1.0.1 # via @@ -313,8 +317,10 @@ jsonfield==3.1.0 # via -r requirements/base.in jsonfield2==4.0.0.post0 # via -r requirements/base.in -jsonschema==4.17.3 +jsonschema==4.20.0 # via cybersource-rest-client-python +jsonschema-specifications==2023.12.1 + # via jsonschema kombu==4.6.11 # via celery libsass==0.9.2 @@ -327,7 +333,7 @@ linecache2==1.0.0 # traceback2 logger==1.4 # via cybersource-rest-client-python -lxml==4.9.2 +lxml==5.1.0 # via # premailer # zeep @@ -349,7 +355,7 @@ naked==0.1.32 # cybersource-rest-client-python ndg-httpsclient==0.5.1 # via -r requirements/base.in -newrelic==9.1.0 +newrelic==9.5.0 # via # -r requirements/base.in # edx-django-utils @@ -364,39 +370,38 @@ oauthlib==3.2.2 # social-auth-core openedx-atlas==0.5.0 # via -r requirements/base.in -packaging==23.1 +packaging==23.2 # via drf-yasg -paramiko==3.2.0 +paramiko==3.4.0 # via cybersource-rest-client-python path-py==7.2 # via -r requirements/base.in -paypalrestsdk==1.13.1 +paypalrestsdk==1.13.3 # via -r requirements/base.in -pbr==5.11.1 +pbr==6.0.0 # via # cybersource-rest-client-python # fixtures # stevedore - # testtools -phonenumbers==8.13.14 +phonenumbers==8.13.27 # via django-oscar -pillow==9.5.0 +pillow==10.2.0 # via django-oscar pkgutil-resolve-name==1.3.10 # via jsonschema -platformdirs==3.6.0 +platformdirs==4.1.0 # via zeep premailer==2.9.2 # via -r requirements/base.in -protobuf==4.23.3 +protobuf==4.25.2 # via # google-api-core # googleapis-common-protos -psutil==5.9.5 +psutil==5.9.7 # via edx-django-utils purl==1.6 # via django-oscar -pyasn1==0.5.0 +pyasn1==0.5.1 # via # cybersource-rest-client-python # ndg-httpsclient @@ -415,13 +420,13 @@ pycparser==2.21 # app-store-notifications-v2-validator # cffi # cybersource-rest-client-python -pycryptodome==3.18.0 +pycryptodome==3.20.0 # via cybersource-rest-client-python -pycryptodomex==3.18.0 +pycryptodomex==3.20.0 # via cybersource-rest-client-python -pygments==2.15.1 +pygments==2.17.2 # via -r requirements/base.in -pyjwt[crypto]==2.7.0 +pyjwt[crypto]==2.8.0 # via # app-store-notifications-v2-validator # cybersource-rest-client-python @@ -437,18 +442,16 @@ pynacl==1.5.0 # cybersource-rest-client-python # edx-django-utils # paramiko -pyopenssl==23.2.0 +pyopenssl==23.3.0 # via # app-store-notifications-v2-validator # cybersource-rest-client-python # ndg-httpsclient # paypalrestsdk -pyparsing==3.1.0 +pyparsing==3.1.1 # via httplib2 pypi==2.1 # via cybersource-rest-client-python -pyrsistent==0.19.3 - # via jsonschema python-dateutil==2.8.2 # via # -r requirements/base.in @@ -457,7 +460,7 @@ python-dateutil==2.8.2 # faker python-mimeparse==1.6.0 # via cybersource-rest-client-python -python-subunit==1.4.2 +python-subunit==1.4.4 # via cybersource-rest-client-python python-toolbox==1.0.11 # via cybersource-rest-client-python @@ -465,7 +468,7 @@ python3-openid==3.2.0 # via # -r requirements/base.in # social-auth-core -pytz==2023.3 +pytz==2023.3.post1 # via # -r requirements/base.in # babel @@ -478,7 +481,7 @@ pytz==2023.3 # drf-yasg # getsmarter-api-clients # zeep -pyyaml==6.0 +pyyaml==6.0.1 # via # cybersource-rest-client-python # drf-yasg @@ -486,8 +489,12 @@ pyyaml==6.0 # naked rcssmin==1.1.1 # via django-compressor -redis==4.5.5 +redis==5.0.1 # via edx-ecommerce-worker +referencing==0.32.1 + # via + # jsonschema + # jsonschema-specifications requests==2.31.0 # via # -r requirements/base.in @@ -517,6 +524,10 @@ requests-toolbelt==1.0.0 # via zeep rjsmin==1.2.1 # via django-compressor +rpds-py==0.16.2 + # via + # jsonschema + # referencing rsa==4.9 # via # cybersource-rest-client-python @@ -525,7 +536,7 @@ rsa==4.9 # oauth2client rules==3.3 # via -r requirements/base.in -s3transfer==0.6.1 +s3transfer==0.10.0 # via boto3 semantic-version==2.10.0 # via edx-drf-extensions @@ -533,7 +544,7 @@ shellescape==3.8.1 # via # crypto # cybersource-rest-client-python -simplejson==3.19.1 +simplejson==3.19.2 # via -r requirements/base.in six==1.16.0 # via @@ -541,13 +552,10 @@ six==1.16.0 # bleach # cybersource-rest-client-python # django-extra-views - # djangorestframework-csv # edx-auth-backends # edx-django-release-util # edx-ecommerce-worker # edx-rbac - # google-auth - # google-auth-httplib2 # isodate # libsass # oauth2client @@ -559,13 +567,14 @@ slumber==0.7.1 # via edx-rest-api-client social-auth-app-django==5.2.0 # via + # -c requirements/constraints.txt # -r requirements/base.in # edx-auth-backends -social-auth-core==4.4.2 +social-auth-core==4.5.1 # via # edx-auth-backends # social-auth-app-django -sorl-thumbnail==12.9.0 +sorl-thumbnail==12.10.0 # via -r requirements/base.in sqlparse==0.4.4 # via django @@ -573,9 +582,9 @@ stevedore==5.1.0 # via # edx-django-utils # edx-opaque-keys -stripe==5.4.0 +stripe==7.11.0 # via -r requirements/base.in -testtools==2.6.0 +testtools==2.7.1 # via # cybersource-rest-client-python # python-subunit @@ -583,23 +592,24 @@ traceback2==1.4.0 # via cybersource-rest-client-python typing==3.7.4.3 # via cybersource-rest-client-python -typing-extensions==4.6.3 - # via asgiref -unicodecsv==0.14.1 +typing-extensions==4.9.0 # via - # -r requirements/base.in - # djangorestframework-csv + # asgiref + # edx-opaque-keys + # faker + # stripe +unicodecsv==0.14.1 + # via -r requirements/base.in uritemplate==4.1.1 # via # coreapi # drf-yasg # google-api-python-client -urllib3==1.26.16 +urllib3==1.26.18 # via # -c requirements/constraints.txt # botocore # cybersource-rest-client-python - # google-auth # requests vine==1.3.0 # via @@ -607,19 +617,19 @@ vine==1.3.0 # celery webencodings==0.5.1 # via bleach -wheel==0.40.0 +wheel==0.42.0 # via cybersource-rest-client-python x509==0.1 # via cybersource-rest-client-python -xss-utils==0.4.0 +xss-utils==0.5.0 # via -r requirements/base.in -yarl==1.9.2 +yarl==1.9.4 # via aiohttp zeep==4.2.1 # via -r requirements/base.in -zipp==3.15.0 +zipp==3.17.0 # via importlib-resources -zope-interface==6.0 +zope-interface==6.1 # via # cybersource-rest-client-python # datetime diff --git a/requirements/common_constraints.txt b/requirements/common_constraints.txt index 7e39123ff04..15aafb293da 100644 --- a/requirements/common_constraints.txt +++ b/requirements/common_constraints.txt @@ -21,12 +21,3 @@ elasticsearch<7.14.0 # django-simple-history>3.0.0 adds indexing and causes a lot of migrations to be affected django-simple-history==3.0.0 - -# tox>4.0.0 isn't yet compatible with many tox plugins, causing CI failures in almost all repos. -# Details can be found in this discussion: https://github.com/tox-dev/tox/discussions/1810 -tox<4.0.0 - -# edx-sphinx-theme is not compatible with latest Sphinx==6.0.0 version -# Pinning Sphinx version unless the compatibility issue gets resolved -# For details, see issue https://github.com/openedx/edx-sphinx-theme/issues/197 -sphinx<6.0.0 diff --git a/requirements/dev.txt b/requirements/dev.txt index 800a57b69e9..a8a34406f51 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -8,7 +8,7 @@ accessible-pygments==0.0.4 # via # -r requirements/docs.txt # pydata-sphinx-theme -aiohttp==3.8.4 +aiohttp==3.9.1 # via # -r requirements/test.txt # inapppy @@ -32,6 +32,7 @@ asgiref==3.7.2 # via # -r requirements/test.txt # django + # django-cors-headers asn1crypto==1.5.1 # via # -r requirements/test.txt @@ -40,18 +41,19 @@ astroid==2.9.3 # via # -r requirements/test.txt # pylint -async-timeout==4.0.2 +async-timeout==4.0.3 # via # -r requirements/test.txt # aiohttp # redis -attrs==23.1.0 +attrs==23.2.0 # via # -r requirements/test.txt # aiohttp # jsonschema + # referencing # zeep -babel==2.12.1 +babel==2.14.0 # via # -r requirements/docs.txt # -r requirements/test.txt @@ -62,7 +64,7 @@ backoff==1.10.0 # via # -r requirements/test.txt # analytics-python -bcrypt==4.0.1 +bcrypt==4.1.2 # via # -r requirements/test.txt # cybersource-rest-client-python @@ -77,18 +79,16 @@ billiard==3.6.4.0 # via # -r requirements/test.txt # celery -bleach==6.0.0 - # via -r requirements/test.txt -bok-choy==2.0.2 +bleach==6.1.0 # via -r requirements/test.txt -boto3==1.26.155 +boto3==1.34.17 # via -r requirements/test.txt -botocore==1.29.155 +botocore==1.34.17 # via # -r requirements/test.txt # boto3 # s3transfer -cachetools==5.3.1 +cachetools==5.3.2 # via # -r requirements/test.txt # google-auth @@ -96,35 +96,34 @@ celery==4.4.7 # via # -r requirements/test.txt # edx-ecommerce-worker -certifi==2023.5.7 +certifi==2023.11.17 # via # -r requirements/docs.txt # -r requirements/test.txt # cybersource-rest-client-python # requests -cffi==1.15.1 +cffi==1.16.0 # via # -r requirements/test.txt # app-store-notifications-v2-validator # cryptography # cybersource-rest-client-python # pynacl -chardet==5.1.0 +chardet==5.2.0 # via # -r requirements/test.txt # cybersource-rest-client-python # diff-cover -charset-normalizer==3.1.0 +charset-normalizer==3.3.2 # via # -r requirements/docs.txt # -r requirements/test.txt - # aiohttp # requests -click==8.1.3 +click==8.1.7 # via # -r requirements/test.txt # edx-django-utils -configparser==5.3.0 +configparser==6.0.0 # via # -r requirements/test.txt # cybersource-rest-client-python @@ -134,9 +133,10 @@ coreschema==0.0.4 # via # -r requirements/test.txt # coreapi -coverage[toml]==7.2.7 +coverage[toml]==7.4.0 # via # -r requirements/test.txt + # coverage # cybersource-rest-client-python # pytest-cov crispy-bootstrap3==2022.1 @@ -145,7 +145,7 @@ crypto==1.4.1 # via # -r requirements/test.txt # cybersource-rest-client-python -cryptography==41.0.1 +cryptography==41.0.7 # via # -r requirements/test.txt # app-store-notifications-v2-validator @@ -158,26 +158,26 @@ cssselect==1.2.0 # via # -r requirements/test.txt # premailer -cssutils==2.7.1 +cssutils==2.9.0 # via # -r requirements/test.txt # premailer cybersource-rest-client-python==0.0.21 # via -r requirements/test.txt -datetime==5.1 +datetime==5.4 # via # -r requirements/test.txt # cybersource-rest-client-python -ddt==1.6.0 +ddt==1.7.1 # via -r requirements/test.txt -defusedxml==0.7.1 +defusedxml==0.8.0rc2 # via # -r requirements/test.txt # python3-openid # social-auth-core -diff-cover==7.6.0 +diff-cover==8.0.2 # via -r requirements/test.txt -django==3.2.20 +django==3.2.23 # via # -r requirements/test.txt # crispy-bootstrap3 @@ -197,6 +197,7 @@ django==3.2.20 # django-solo # django-tables2 # django-treebeard + # django-waffle # djangorestframework # drf-jwt # drf-yasg @@ -211,17 +212,17 @@ django==3.2.20 # jsonfield2 # social-auth-app-django # xss-utils -django-appconf==1.0.5 +django-appconf==1.0.6 # via # -r requirements/test.txt # django-compressor -django-compressor==4.3.1 +django-compressor==4.4 # via # -r requirements/test.txt # django-libsass -django-config-models==2.3.0 +django-config-models==2.5.1 # via -r requirements/test.txt -django-cors-headers==4.1.0 +django-cors-headers==4.3.1 # via -r requirements/test.txt django-crispy-forms==2.0 # via @@ -232,7 +233,7 @@ django-crum==0.7.9 # -r requirements/test.txt # edx-django-utils # edx-rbac -django-debug-toolbar==4.1.0 +django-debug-toolbar==4.2.0 # via -r requirements/dev.in django-extensions==3.2.3 # via -r requirements/test.txt @@ -240,7 +241,7 @@ django-extra-views==0.13.0 # via # -r requirements/test.txt # django-oscar -django-filter==23.2 +django-filter==23.5 # via -r requirements/test.txt django-haystack==3.2.1 # via @@ -272,14 +273,14 @@ django-treebeard==4.4 # via # -r requirements/test.txt # django-oscar -django-waffle==3.0.0 +django-waffle==4.1.0 # via # -r requirements/test.txt # edx-django-utils # edx-drf-extensions -django-webtest==1.9.10 +django-webtest==1.9.11 # via -r requirements/test.txt -django-widget-tweaks==1.4.12 +django-widget-tweaks==1.5.0 # via # -r requirements/test.txt # django-oscar @@ -293,7 +294,7 @@ djangorestframework==3.14.0 # drf-jwt # drf-yasg # edx-drf-extensions -djangorestframework-csv==2.1.1 +djangorestframework-csv==3.0.2 # via -r requirements/test.txt djangorestframework-datatables==0.7.0 # via -r requirements/test.txt @@ -308,26 +309,26 @@ drf-jwt==1.19.2 # via # -r requirements/test.txt # edx-drf-extensions -drf-yasg==1.21.6 +drf-yasg==1.21.7 # via -r requirements/test.txt -edx-auth-backends==4.1.0 +edx-auth-backends==4.2.0 # via -r requirements/test.txt -edx-braze-client==0.1.6 +edx-braze-client==0.1.8 # via # -r requirements/test.txt # edx-ecommerce-worker -edx-django-release-util==1.2.0 +edx-django-release-util==1.3.0 # via -r requirements/test.txt -edx-django-sites-extensions==4.0.0 +edx-django-sites-extensions==4.0.2 # via -r requirements/test.txt -edx-django-utils==5.5.0 +edx-django-utils==5.9.0 # via # -r requirements/test.txt # django-config-models # edx-drf-extensions # edx-rest-api-client # getsmarter-api-clients -edx-drf-extensions==9.0.0 +edx-drf-extensions==9.1.2 # via # -r requirements/test.txt # edx-rbac @@ -335,13 +336,13 @@ edx-ecommerce-worker==3.3.4 # via -r requirements/test.txt edx-i18n-tools==1.3.0 # via -r requirements/test.txt -edx-opaque-keys==2.3.0 +edx-opaque-keys==2.5.1 # via # -r requirements/test.txt # edx-drf-extensions -edx-rbac==1.7.0 +edx-rbac==1.8.0 # via -r requirements/test.txt -edx-rest-api-client==5.5.2 +edx-rest-api-client==5.6.1 # via # -r requirements/test.txt # edx-ecommerce-worker @@ -349,7 +350,7 @@ enum34==1.1.10 # via # -r requirements/test.txt # cybersource-rest-client-python -exceptiongroup==1.1.1 +exceptiongroup==1.2.0 # via # -r requirements/test.txt # pytest @@ -362,11 +363,11 @@ factory-boy==3.1.0 # via # -r requirements/test.txt # django-oscar -faker==18.10.1 +faker==22.2.0 # via # -r requirements/test.txt # factory-boy -filelock==3.12.2 +filelock==3.13.1 # via # -r requirements/test.txt # tox @@ -374,10 +375,9 @@ fixtures==4.1.0 # via # -r requirements/test.txt # cybersource-rest-client-python - # testtools -freezegun==1.2.2 +freezegun==1.4.0 # via -r requirements/test.txt -frozenlist==1.3.3 +frozenlist==1.4.1 # via # -r requirements/test.txt # aiohttp @@ -390,13 +390,13 @@ future==0.18.3 # via # -r requirements/test.txt # pyjwkest -getsmarter-api-clients==0.6.0 +getsmarter-api-clients==0.6.1 # via -r requirements/test.txt -gitdb==4.0.10 +gitdb==4.0.11 # via gitpython -gitpython==3.1.31 +gitpython==3.1.41 # via transifex-client -google-api-core==2.11.1 +google-api-core==2.15.0 # via # -r requirements/test.txt # google-api-python-client @@ -404,17 +404,17 @@ google-api-python-client==2.31.0 # via # -r requirements/test.txt # inapppy -google-auth==2.20.0 +google-auth==2.26.2 # via # -r requirements/test.txt # google-api-core # google-api-python-client # google-auth-httplib2 -google-auth-httplib2==0.1.0 +google-auth-httplib2==0.2.0 # via # -r requirements/test.txt # google-api-python-client -googleapis-common-protos==1.59.1 +googleapis-common-protos==1.62.0 # via # -r requirements/test.txt # google-api-core @@ -435,16 +435,17 @@ imagesize==1.4.1 # via # -r requirements/docs.txt # sphinx -importlib-metadata==6.7.0 +importlib-metadata==7.0.1 # via # -r requirements/docs.txt # -r requirements/test.txt # pytest-randomly # sphinx -importlib-resources==5.12.0 +importlib-resources==6.1.1 # via # -r requirements/test.txt # jsonschema + # jsonschema-specifications inapppy==2.5.2 # via -r requirements/test.txt inflection==0.5.1 @@ -459,11 +460,15 @@ ipaddress==1.0.23 # via # -r requirements/test.txt # cybersource-rest-client-python +iso8601==2.1.0 + # via + # -r requirements/test.txt + # python-subunit isodate==0.6.1 # via # -r requirements/test.txt # zeep -isort==5.12.0 +isort==5.13.2 # via # -r requirements/test.txt # pylint @@ -471,12 +476,13 @@ itypes==1.2.0 # via # -r requirements/test.txt # coreapi -jinja2==3.1.2 +jinja2==3.1.3 # via # -r requirements/docs.txt # -r requirements/test.txt # coreschema # diff-cover + # pytest-html # sphinx jmespath==1.0.1 # via @@ -487,19 +493,19 @@ jsonfield==3.1.0 # via -r requirements/test.txt jsonfield2==4.0.0.post0 # via -r requirements/test.txt -jsonschema==4.17.3 +jsonschema==4.20.0 # via # -r requirements/test.txt # cybersource-rest-client-python -kombu==4.6.11 +jsonschema-specifications==2023.12.1 # via # -r requirements/test.txt - # celery -lazy==1.5 + # jsonschema +kombu==4.6.11 # via # -r requirements/test.txt - # bok-choy -lazy-object-proxy==1.9.0 + # celery +lazy-object-proxy==1.10.0 # via # -r requirements/test.txt # astroid @@ -516,9 +522,10 @@ logger==1.4 # via # -r requirements/test.txt # cybersource-rest-client-python -lxml==4.9.2 +lxml==5.1.0 # via # -r requirements/test.txt + # edx-i18n-tools # premailer # zeep markdown==3.4.3 @@ -532,7 +539,7 @@ mccabe==0.6.1 # via # -r requirements/test.txt # pylint -mock==5.0.2 +mock==5.1.0 # via -r requirements/test.txt monotonic==1.6 # via @@ -552,7 +559,7 @@ naked==0.1.32 # cybersource-rest-client-python ndg-httpsclient==0.5.1 # via -r requirements/test.txt -newrelic==9.1.0 +newrelic==9.5.0 # via # -r requirements/test.txt # edx-django-utils @@ -571,8 +578,8 @@ oauthlib==3.2.2 # requests-oauthlib # social-auth-core openedx-atlas==0.5.0 - # via -r requirements/base.in -packaging==23.1 + # via -r requirements/test.txt +packaging==23.2 # via # -r requirements/docs.txt # -r requirements/test.txt @@ -581,30 +588,29 @@ packaging==23.1 # pytest # sphinx # tox -paramiko==3.2.0 +paramiko==3.4.0 # via # -r requirements/test.txt # cybersource-rest-client-python -path==16.6.0 +path==16.9.0 # via # -r requirements/test.txt # edx-i18n-tools path-py==7.2 # via -r requirements/test.txt -paypalrestsdk==1.13.1 +paypalrestsdk==1.13.3 # via -r requirements/test.txt -pbr==5.11.1 +pbr==6.0.0 # via # -r requirements/test.txt # cybersource-rest-client-python # fixtures # stevedore - # testtools -phonenumbers==8.13.14 +phonenumbers==8.13.27 # via # -r requirements/test.txt # django-oscar -pillow==9.5.0 +pillow==10.2.0 # via # -r requirements/test.txt # django-oscar @@ -612,7 +618,7 @@ pkgutil-resolve-name==1.3.10 # via # -r requirements/test.txt # jsonschema -platformdirs==3.6.0 +platformdirs==4.1.0 # via # -r requirements/test.txt # pylint @@ -629,12 +635,12 @@ polib==1.2.0 # edx-i18n-tools premailer==2.9.2 # via -r requirements/test.txt -protobuf==4.23.3 +protobuf==4.25.2 # via # -r requirements/test.txt # google-api-core # googleapis-common-protos -psutil==5.9.5 +psutil==5.9.7 # via # -r requirements/test.txt # edx-django-utils @@ -647,9 +653,8 @@ purl==1.6 py==1.11.0 # via # -r requirements/test.txt - # pytest-html # tox -pyasn1==0.5.0 +pyasn1==0.5.1 # via # -r requirements/test.txt # cybersource-rest-client-python @@ -663,7 +668,7 @@ pyasn1-modules==0.3.0 # -r requirements/test.txt # google-auth # oauth2client -pycodestyle==2.10.0 +pycodestyle==2.11.1 # via -r requirements/test.txt pycountry==17.1.8 # via -r requirements/test.txt @@ -673,20 +678,20 @@ pycparser==2.21 # app-store-notifications-v2-validator # cffi # cybersource-rest-client-python -pycryptodome==3.18.0 +pycryptodome==3.20.0 # via # -r requirements/test.txt # cybersource-rest-client-python -pycryptodomex==3.18.0 +pycryptodomex==3.20.0 # via # -r requirements/test.txt # cybersource-rest-client-python # pyjwkest -pydata-sphinx-theme==0.13.3 +pydata-sphinx-theme==0.14.4 # via # -r requirements/docs.txt # sphinx-book-theme -pygments==2.15.1 +pygments==2.17.2 # via # -r requirements/docs.txt # -r requirements/test.txt @@ -696,7 +701,7 @@ pygments==2.15.1 # sphinx pyjwkest==1.4.2 # via -r requirements/test.txt -pyjwt[crypto]==2.7.0 +pyjwt[crypto]==2.8.0 # via # -r requirements/test.txt # app-store-notifications-v2-validator @@ -705,6 +710,7 @@ pyjwt[crypto]==2.7.0 # edx-auth-backends # edx-drf-extensions # edx-rest-api-client + # pyjwt # social-auth-core pylint==2.12.2 # via -r requirements/test.txt @@ -718,14 +724,14 @@ pynacl==1.5.0 # cybersource-rest-client-python # edx-django-utils # paramiko -pyopenssl==23.2.0 +pyopenssl==23.3.0 # via # -r requirements/test.txt # app-store-notifications-v2-validator # cybersource-rest-client-python # ndg-httpsclient # paypalrestsdk -pyparsing==3.1.0 +pyparsing==3.1.1 # via # -r requirements/test.txt # httplib2 @@ -733,11 +739,7 @@ pypi==2.1 # via # -r requirements/test.txt # cybersource-rest-client-python -pyrsistent==0.19.3 - # via - # -r requirements/test.txt - # jsonschema -pytest==7.3.2 +pytest==7.4.4 # via # -r requirements/test.txt # pytest-base-url @@ -755,9 +757,9 @@ pytest-base-url==2.0.0 # pytest-selenium pytest-cov==4.1.0 # via -r requirements/test.txt -pytest-django==4.5.2 +pytest-django==4.7.0 # via -r requirements/test.txt -pytest-html==3.2.0 +pytest-html==4.1.1 # via # -r requirements/test.txt # pytest-selenium @@ -765,11 +767,11 @@ pytest-metadata==3.0.0 # via # -r requirements/test.txt # pytest-html -pytest-randomly==3.12.0 +pytest-randomly==3.15.0 # via -r requirements/test.txt pytest-selenium==2.0.1 # via -r requirements/test.txt -pytest-timeout==2.1.0 +pytest-timeout==2.2.0 # via -r requirements/test.txt pytest-variables==2.0.0 # via @@ -792,7 +794,7 @@ python-mimeparse==1.6.0 # cybersource-rest-client-python python-slugify==4.0.1 # via transifex-client -python-subunit==1.4.2 +python-subunit==1.4.4 # via # -r requirements/test.txt # cybersource-rest-client-python @@ -804,7 +806,7 @@ python3-openid==3.2.0 # via # -r requirements/test.txt # social-auth-core -pytz==2023.3 +pytz==2023.3.post1 # via # -r requirements/docs.txt # -r requirements/test.txt @@ -820,7 +822,7 @@ pytz==2023.3 # zeep pywatchman==1.4.1 # via -r requirements/dev.in -pyyaml==6.0 +pyyaml==6.0.1 # via # -r requirements/test.txt # cybersource-rest-client-python @@ -833,10 +835,15 @@ rcssmin==1.1.1 # via # -r requirements/test.txt # django-compressor -redis==4.5.5 +redis==5.0.1 # via # -r requirements/test.txt # edx-ecommerce-worker +referencing==0.32.1 + # via + # -r requirements/test.txt + # jsonschema + # jsonschema-specifications requests==2.31.0 # via # -r requirements/docs.txt @@ -876,12 +883,17 @@ requests-toolbelt==1.0.0 # via # -r requirements/test.txt # zeep -responses==0.23.1 +responses==0.24.1 # via -r requirements/test.txt rjsmin==1.2.1 # via # -r requirements/test.txt # django-compressor +rpds-py==0.16.2 + # via + # -r requirements/test.txt + # jsonschema + # referencing rsa==4.9 # via # -r requirements/test.txt @@ -891,14 +903,13 @@ rsa==4.9 # oauth2client rules==3.3 # via -r requirements/test.txt -s3transfer==0.6.1 +s3transfer==0.10.0 # via # -r requirements/test.txt # boto3 selenium==3.141.0 # via # -r requirements/test.txt - # bok-choy # pytest-selenium semantic-version==2.10.0 # via @@ -909,7 +920,7 @@ shellescape==3.8.1 # -r requirements/test.txt # crypto # cybersource-rest-client-python -simplejson==3.19.1 +simplejson==3.19.2 # via -r requirements/test.txt six==1.16.0 # via @@ -918,13 +929,10 @@ six==1.16.0 # bleach # cybersource-rest-client-python # django-extra-views - # djangorestframework-csv # edx-auth-backends # edx-django-release-util # edx-ecommerce-worker # edx-rbac - # google-auth - # google-auth-httplib2 # isodate # libsass # oauth2client @@ -941,7 +949,7 @@ slumber==0.7.1 # via # -r requirements/test.txt # edx-rest-api-client -smmap==5.0.0 +smmap==5.0.1 # via gitdb snowballstemmer==2.2.0 # via @@ -951,19 +959,19 @@ social-auth-app-django==5.2.0 # via # -r requirements/test.txt # edx-auth-backends -social-auth-core==4.4.2 +social-auth-core==4.5.1 # via # -r requirements/test.txt # edx-auth-backends # social-auth-app-django -sorl-thumbnail==12.9.0 +sorl-thumbnail==12.10.0 # via -r requirements/test.txt -soupsieve==2.4.1 +soupsieve==2.5 # via # -r requirements/docs.txt # -r requirements/test.txt # beautifulsoup4 -sphinx==5.3.0 +sphinx==6.2.1 # via # -r requirements/docs.txt # pydata-sphinx-theme @@ -1004,15 +1012,15 @@ stevedore==5.1.0 # -r requirements/test.txt # edx-django-utils # edx-opaque-keys -stripe==5.4.0 +stripe==7.11.0 # via -r requirements/test.txt tenacity==6.3.1 # via # -r requirements/test.txt # pytest-selenium -testfixtures==7.1.0 +testfixtures==7.2.2 # via -r requirements/test.txt -testtools==2.6.0 +testtools==2.7.1 # via # -r requirements/test.txt # cybersource-rest-client-python @@ -1033,7 +1041,7 @@ tox==3.14.6 # via # -r requirements/test.txt # tox-battery -tox-battery==0.6.1 +tox-battery==0.6.2 # via -r requirements/test.txt traceback2==1.4.0 # via @@ -1041,39 +1049,35 @@ traceback2==1.4.0 # cybersource-rest-client-python transifex-client==0.14.4 # via -r requirements/dev.in -types-pyyaml==6.0.12.10 - # via - # -r requirements/test.txt - # responses typing==3.7.4.3 # via # -r requirements/test.txt # cybersource-rest-client-python -typing-extensions==4.6.3 +typing-extensions==4.9.0 # via # -r requirements/docs.txt # -r requirements/test.txt # asgiref # astroid + # edx-opaque-keys + # faker # pydata-sphinx-theme # pylint + # stripe unicodecsv==0.14.1 - # via - # -r requirements/test.txt - # djangorestframework-csv + # via -r requirements/test.txt uritemplate==4.1.1 # via # -r requirements/test.txt # coreapi # drf-yasg # google-api-python-client -urllib3==1.26.16 +urllib3==1.26.18 # via # -r requirements/docs.txt # -r requirements/test.txt # botocore # cybersource-rest-client-python - # google-auth # requests # responses # selenium @@ -1103,7 +1107,7 @@ webtest==3.0.0 # via # -r requirements/test.txt # django-webtest -wheel==0.40.0 +wheel==0.42.0 # via # -r requirements/test.txt # cybersource-rest-client-python @@ -1115,21 +1119,21 @@ x509==0.1 # via # -r requirements/test.txt # cybersource-rest-client-python -xss-utils==0.4.0 +xss-utils==0.5.0 # via -r requirements/test.txt -yarl==1.9.2 +yarl==1.9.4 # via # -r requirements/test.txt # aiohttp zeep==4.2.1 # via -r requirements/test.txt -zipp==3.15.0 +zipp==3.17.0 # via # -r requirements/docs.txt # -r requirements/test.txt # importlib-metadata # importlib-resources -zope-interface==6.0 +zope-interface==6.1 # via # -r requirements/test.txt # cybersource-rest-client-python diff --git a/requirements/docs.txt b/requirements/docs.txt index 1f2dae3e304..b23daeda5d4 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -8,15 +8,15 @@ accessible-pygments==0.0.4 # via pydata-sphinx-theme alabaster==0.7.13 # via sphinx -babel==2.12.1 +babel==2.14.0 # via # pydata-sphinx-theme # sphinx beautifulsoup4==4.12.2 # via pydata-sphinx-theme -certifi==2023.5.7 +certifi==2023.11.17 # via requests -charset-normalizer==3.1.0 +charset-normalizer==3.3.2 # via requests docutils==0.19 # via @@ -28,34 +28,33 @@ idna==2.7 # requests imagesize==1.4.1 # via sphinx -importlib-metadata==6.7.0 +importlib-metadata==7.0.1 # via sphinx -jinja2==3.1.2 +jinja2==3.1.3 # via sphinx markupsafe==2.1.3 # via jinja2 -packaging==23.1 +packaging==23.2 # via # pydata-sphinx-theme # sphinx -pydata-sphinx-theme==0.13.3 +pydata-sphinx-theme==0.14.4 # via sphinx-book-theme -pygments==2.15.1 +pygments==2.17.2 # via # accessible-pygments # pydata-sphinx-theme # sphinx -pytz==2023.3 +pytz==2023.3.post1 # via babel requests==2.31.0 # via sphinx snowballstemmer==2.2.0 # via sphinx -soupsieve==2.4.1 +soupsieve==2.5 # via beautifulsoup4 -sphinx==5.3.0 +sphinx==6.2.1 # via - # -c requirements/common_constraints.txt # -r requirements/docs.in # pydata-sphinx-theme # sphinx-book-theme @@ -73,11 +72,11 @@ sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.5 # via sphinx -typing-extensions==4.6.3 +typing-extensions==4.9.0 # via pydata-sphinx-theme -urllib3==1.26.16 +urllib3==1.26.18 # via # -c requirements/constraints.txt # requests -zipp==3.15.0 +zipp==3.17.0 # via importlib-metadata diff --git a/requirements/e2e.txt b/requirements/e2e.txt index 51f87ad3f34..13b5d623bf0 100644 --- a/requirements/e2e.txt +++ b/requirements/e2e.txt @@ -8,50 +8,46 @@ asgiref==3.7.2 # via # -c requirements/base.txt # django -certifi==2023.5.7 +certifi==2023.11.17 # via # -c requirements/base.txt # requests -cffi==1.15.1 +cffi==1.16.0 # via # -c requirements/base.txt - # cryptography # pynacl -charset-normalizer==3.1.0 +charset-normalizer==3.3.2 # via # -c requirements/base.txt # requests -click==8.1.3 +click==8.1.7 # via # -c requirements/base.txt # edx-django-utils -cryptography==41.0.1 - # via - # -c requirements/base.txt - # pyjwt -django==3.2.20 +django==3.2.23 # via # -c requirements/base.txt # -c requirements/common_constraints.txt # django-crum + # django-waffle # edx-django-utils django-crum==0.7.9 # via # -c requirements/base.txt # edx-django-utils -django-waffle==3.0.0 +django-waffle==4.1.0 # via # -c requirements/base.txt # edx-django-utils -edx-django-utils==5.5.0 +edx-django-utils==5.9.0 # via # -c requirements/base.txt # edx-rest-api-client -edx-rest-api-client==5.5.2 +edx-rest-api-client==5.6.1 # via # -c requirements/base.txt # -r requirements/e2e.in -exceptiongroup==1.1.1 +exceptiongroup==1.2.0 # via pytest future==0.18.3 # via pyjwkest @@ -60,19 +56,27 @@ idna==2.7 # -c requirements/base.txt # -c requirements/constraints.txt # requests -importlib-metadata==6.7.0 +importlib-metadata==7.0.1 # via pytest-randomly iniconfig==2.0.0 # via pytest -newrelic==9.1.0 +jinja2==3.1.3 + # via + # -c requirements/base.txt + # pytest-html +markupsafe==2.1.3 + # via + # -c requirements/base.txt + # jinja2 +newrelic==9.5.0 # via # -c requirements/base.txt # edx-django-utils -packaging==23.1 +packaging==23.2 # via # -c requirements/base.txt # pytest -pbr==5.11.1 +pbr==6.0.0 # via # -c requirements/base.txt # stevedore @@ -80,23 +84,21 @@ pluggy==0.13.1 # via # -c requirements/constraints.txt # pytest -psutil==5.9.5 +psutil==5.9.7 # via # -c requirements/base.txt # edx-django-utils -py==1.11.0 - # via pytest-html pycparser==2.21 # via # -c requirements/base.txt # cffi -pycryptodomex==3.18.0 +pycryptodomex==3.20.0 # via # -c requirements/base.txt # pyjwkest pyjwkest==1.4.2 # via -r requirements/e2e.in -pyjwt[crypto]==2.7.0 +pyjwt==2.8.0 # via # -c requirements/base.txt # edx-rest-api-client @@ -104,7 +106,7 @@ pynacl==1.5.0 # via # -c requirements/base.txt # edx-django-utils -pytest==7.3.2 +pytest==7.4.4 # via # -r requirements/e2e.in # pytest-base-url @@ -116,17 +118,17 @@ pytest==7.3.2 # pytest-variables pytest-base-url==2.0.0 # via pytest-selenium -pytest-html==3.2.0 +pytest-html==4.1.1 # via pytest-selenium pytest-metadata==3.0.0 # via pytest-html -pytest-randomly==3.12.0 +pytest-randomly==3.15.0 # via -r requirements/e2e.in pytest-selenium==2.0.1 # via # -c requirements/constraints.txt # -r requirements/e2e.in -pytest-timeout==2.1.0 +pytest-timeout==2.2.0 # via -r requirements/e2e.in pytest-variables==2.0.0 # via @@ -134,7 +136,7 @@ pytest-variables==2.0.0 # pytest-selenium python-dotenv==1.0.0 # via -r requirements/e2e.in -pytz==2023.3 +pytz==2023.3.post1 # via # -c requirements/base.txt # django @@ -172,17 +174,17 @@ tenacity==6.3.1 # via pytest-selenium tomli==2.0.1 # via pytest -typing-extensions==4.6.3 +typing-extensions==4.9.0 # via # -c requirements/base.txt # asgiref -urllib3==1.26.16 +urllib3==1.26.18 # via # -c requirements/base.txt # -c requirements/constraints.txt # requests # selenium -zipp==3.15.0 +zipp==3.17.0 # via # -c requirements/base.txt # importlib-metadata diff --git a/requirements/pip.txt b/requirements/pip.txt index fa19e6f0b1a..a4cf5307d6f 100644 --- a/requirements/pip.txt +++ b/requirements/pip.txt @@ -4,11 +4,11 @@ # # make upgrade # -wheel==0.40.0 +wheel==0.42.0 # via -r requirements/pip.in # The following packages are considered to be unsafe in a requirements file: -pip==23.1.2 +pip==23.3.2 # via -r requirements/pip.in -setuptools==68.0.0 +setuptools==69.0.3 # via -r requirements/pip.in diff --git a/requirements/pip_tools.txt b/requirements/pip_tools.txt index b6150065453..c2330a4c5b2 100644 --- a/requirements/pip_tools.txt +++ b/requirements/pip_tools.txt @@ -4,20 +4,27 @@ # # make upgrade # -build==0.10.0 +build==1.0.3 # via pip-tools -click==8.1.3 +click==8.1.7 # via pip-tools -packaging==23.1 +importlib-metadata==7.0.1 # via build -pip-tools==6.13.0 +packaging==23.2 + # via build +pip-tools==7.3.0 # via -r requirements/pip_tools.in pyproject-hooks==1.0.0 # via build tomli==2.0.1 - # via build -wheel==0.40.0 + # via + # build + # pip-tools + # pyproject-hooks +wheel==0.42.0 # via pip-tools +zipp==3.17.0 + # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # pip diff --git a/requirements/production.txt b/requirements/production.txt index db30083c2ca..007166ef1a9 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -4,7 +4,7 @@ # # make upgrade # -aiohttp==3.8.4 +aiohttp==3.9.1 # via inapppy aiosignal==1.3.1 # via aiohttp @@ -15,75 +15,76 @@ analytics-python==1.4.post1 app-store-notifications-v2-validator==0.0.7 # via -r requirements/base.in asgiref==3.7.2 - # via django + # via + # django + # django-cors-headers asn1crypto==1.5.1 # via cybersource-rest-client-python -async-timeout==4.0.2 +async-timeout==4.0.3 # via # aiohttp # redis -attrs==23.1.0 +attrs==23.2.0 # via # aiohttp # jsonschema + # referencing # zeep -babel==2.12.1 +babel==2.14.0 # via django-oscar backoff==1.10.0 # via analytics-python -bcrypt==4.0.1 +bcrypt==4.1.2 # via # cybersource-rest-client-python # paramiko billiard==3.6.4.0 # via celery -bleach==6.0.0 +bleach==6.1.0 # via -r requirements/base.in -boto3==1.26.155 +boto3==1.34.17 # via # -r requirements/base.in # django-ses -botocore==1.29.155 +botocore==1.34.17 # via # boto3 # s3transfer -cachetools==5.3.1 +cachetools==5.3.2 # via google-auth celery==4.4.7 # via # -c requirements/constraints.txt # edx-ecommerce-worker -certifi==2023.5.7 +certifi==2023.11.17 # via # cybersource-rest-client-python # requests -cffi==1.15.1 +cffi==1.16.0 # via # app-store-notifications-v2-validator # cryptography # cybersource-rest-client-python # pynacl -chardet==5.1.0 +chardet==5.2.0 # via cybersource-rest-client-python -charset-normalizer==3.1.0 - # via - # aiohttp - # requests -click==8.1.3 +charset-normalizer==3.3.2 + # via requests +click==8.1.7 # via edx-django-utils -configparser==5.3.0 +configparser==6.0.0 # via cybersource-rest-client-python coreapi==2.3.3 # via -r requirements/base.in coreschema==0.0.4 # via coreapi -coverage==7.2.7 +coverage==7.4.0 # via cybersource-rest-client-python crispy-bootstrap3==2022.1 # via -r requirements/base.in crypto==1.4.1 # via cybersource-rest-client-python -cryptography==41.0.1 +cryptography==41.0.7 # via # app-store-notifications-v2-validator # cybersource-rest-client-python @@ -93,19 +94,19 @@ cryptography==41.0.1 # social-auth-core cssselect==1.2.0 # via premailer -cssutils==2.7.1 +cssutils==2.9.0 # via premailer cybersource-rest-client-python==0.0.21 # via # -c requirements/constraints.txt # -r requirements/base.in -datetime==5.1 +datetime==5.4 # via cybersource-rest-client-python -defusedxml==0.7.1 +defusedxml==0.8.0rc2 # via # python3-openid # social-auth-core -django==3.2.20 +django==3.2.23 # via # -c requirements/common_constraints.txt # -r requirements/base.in @@ -126,6 +127,7 @@ django==3.2.20 # django-solo # django-tables2 # django-treebeard + # django-waffle # djangorestframework # drf-jwt # drf-yasg @@ -139,15 +141,15 @@ django==3.2.20 # jsonfield2 # social-auth-app-django # xss-utils -django-appconf==1.0.5 +django-appconf==1.0.6 # via django-compressor -django-compressor==4.3.1 +django-compressor==4.4 # via # -r requirements/base.in # django-libsass -django-config-models==2.3.0 +django-config-models==2.5.1 # via -r requirements/base.in -django-cors-headers==4.1.0 +django-cors-headers==4.3.1 # via -r requirements/base.in django-crispy-forms==2.0 # via @@ -161,7 +163,7 @@ django-extensions==3.2.3 # via -r requirements/base.in django-extra-views==0.13.0 # via django-oscar -django-filter==23.2 +django-filter==23.5 # via -r requirements/base.in django-haystack==3.2.1 # via django-oscar @@ -175,7 +177,7 @@ django-oscar==3.1 # -r requirements/base.in django-phonenumber-field==5.0.0 # via django-oscar -django-ses==3.5.0 +django-ses==3.5.2 # via -r requirements/production.in django-simple-history==3.0.0 # via @@ -189,12 +191,12 @@ django-threadlocals==0.10 # via -r requirements/base.in django-treebeard==4.4 # via django-oscar -django-waffle==3.0.0 +django-waffle==4.1.0 # via # -r requirements/base.in # edx-django-utils # edx-drf-extensions -django-widget-tweaks==1.4.12 +django-widget-tweaks==1.5.0 # via django-oscar djangorestframework==3.14.0 # via @@ -206,7 +208,7 @@ djangorestframework==3.14.0 # drf-jwt # drf-yasg # edx-drf-extensions -djangorestframework-csv==2.1.1 +djangorestframework-csv==3.0.2 # via -r requirements/base.in djangorestframework-datatables==0.7.0 # via -r requirements/base.in @@ -214,36 +216,36 @@ drf-extensions==0.7.1 # via -r requirements/base.in drf-jwt==1.19.2 # via edx-drf-extensions -drf-yasg==1.21.6 +drf-yasg==1.21.7 # via -r requirements/base.in -edx-auth-backends==4.1.0 +edx-auth-backends==4.2.0 # via -r requirements/base.in -edx-braze-client==0.1.6 +edx-braze-client==0.1.8 # via edx-ecommerce-worker -edx-django-release-util==1.2.0 +edx-django-release-util==1.3.0 # via -r requirements/base.in -edx-django-sites-extensions==4.0.0 +edx-django-sites-extensions==4.0.2 # via -r requirements/base.in -edx-django-utils==5.5.0 +edx-django-utils==5.9.0 # via # -r requirements/base.in # django-config-models # edx-drf-extensions # edx-rest-api-client # getsmarter-api-clients -edx-drf-extensions==9.0.0 +edx-drf-extensions==9.1.2 # via # -r requirements/base.in # edx-rbac edx-ecommerce-worker==3.3.4 # via -r requirements/base.in -edx-opaque-keys==2.3.0 +edx-opaque-keys==2.5.1 # via # -r requirements/base.in # edx-drf-extensions -edx-rbac==1.7.0 +edx-rbac==1.8.0 # via -r requirements/base.in -edx-rest-api-client==5.5.2 +edx-rest-api-client==5.6.1 # via # -r requirements/base.in # edx-ecommerce-worker @@ -255,34 +257,32 @@ extras==1.0.0 # python-subunit factory-boy==3.1.0 # via django-oscar -faker==18.10.1 +faker==22.2.0 # via factory-boy fixtures==4.1.0 - # via - # cybersource-rest-client-python - # testtools -frozenlist==1.3.3 + # via cybersource-rest-client-python +frozenlist==1.4.1 # via # aiohttp # aiosignal funcsigs==1.0.2 # via cybersource-rest-client-python -getsmarter-api-clients==0.6.0 +getsmarter-api-clients==0.6.1 # via -r requirements/base.in -google-api-core==2.11.1 +google-api-core==2.15.0 # via google-api-python-client google-api-python-client==2.31.0 # via # -r requirements/base.in # inapppy -google-auth==2.20.0 +google-auth==2.26.2 # via # google-api-core # google-api-python-client # google-auth-httplib2 -google-auth-httplib2==0.1.0 +google-auth-httplib2==0.2.0 # via google-api-python-client -googleapis-common-protos==1.59.1 +googleapis-common-protos==1.62.0 # via google-api-core gunicorn==19.7.1 # via -r requirements/production.in @@ -298,19 +298,23 @@ idna==2.7 # cybersource-rest-client-python # requests # yarl -importlib-resources==5.12.0 - # via jsonschema +importlib-resources==6.1.1 + # via + # jsonschema + # jsonschema-specifications inapppy==2.5.2 # via -r requirements/base.in inflection==0.5.1 # via drf-yasg ipaddress==1.0.23 # via cybersource-rest-client-python +iso8601==2.1.0 + # via python-subunit isodate==0.6.1 # via zeep itypes==1.2.0 # via coreapi -jinja2==3.1.2 +jinja2==3.1.3 # via coreschema jmespath==1.0.1 # via @@ -320,8 +324,10 @@ jsonfield==3.1.0 # via -r requirements/base.in jsonfield2==4.0.0.post0 # via -r requirements/base.in -jsonschema==4.17.3 +jsonschema==4.20.0 # via cybersource-rest-client-python +jsonschema-specifications==2023.12.1 + # via jsonschema kombu==4.6.11 # via celery libsass==0.9.2 @@ -334,7 +340,7 @@ linecache2==1.0.0 # traceback2 logger==1.4 # via cybersource-rest-client-python -lxml==4.9.2 +lxml==5.1.0 # via # premailer # zeep @@ -356,7 +362,7 @@ naked==0.1.32 # cybersource-rest-client-python ndg-httpsclient==0.5.1 # via -r requirements/base.in -newrelic==9.1.0 +newrelic==9.5.0 # via # -r requirements/base.in # -r requirements/production.in @@ -374,39 +380,38 @@ oauthlib==3.2.2 # social-auth-core openedx-atlas==0.5.0 # via -r requirements/base.in -packaging==23.1 +packaging==23.2 # via drf-yasg -paramiko==3.2.0 +paramiko==3.4.0 # via cybersource-rest-client-python path-py==7.2 # via -r requirements/base.in -paypalrestsdk==1.13.1 +paypalrestsdk==1.13.3 # via -r requirements/base.in -pbr==5.11.1 +pbr==6.0.0 # via # cybersource-rest-client-python # fixtures # stevedore - # testtools -phonenumbers==8.13.14 +phonenumbers==8.13.27 # via django-oscar -pillow==9.5.0 +pillow==10.2.0 # via django-oscar pkgutil-resolve-name==1.3.10 # via jsonschema -platformdirs==3.6.0 +platformdirs==4.1.0 # via zeep premailer==2.9.2 # via -r requirements/base.in -protobuf==4.23.3 +protobuf==4.25.2 # via # google-api-core # googleapis-common-protos -psutil==5.9.5 +psutil==5.9.7 # via edx-django-utils purl==1.6 # via django-oscar -pyasn1==0.5.0 +pyasn1==0.5.1 # via # cybersource-rest-client-python # ndg-httpsclient @@ -425,13 +430,13 @@ pycparser==2.21 # app-store-notifications-v2-validator # cffi # cybersource-rest-client-python -pycryptodome==3.18.0 +pycryptodome==3.20.0 # via cybersource-rest-client-python -pycryptodomex==3.18.0 +pycryptodomex==3.20.0 # via cybersource-rest-client-python -pygments==2.15.1 +pygments==2.17.2 # via -r requirements/base.in -pyjwt[crypto]==2.7.0 +pyjwt[crypto]==2.8.0 # via # app-store-notifications-v2-validator # cybersource-rest-client-python @@ -447,18 +452,16 @@ pynacl==1.5.0 # cybersource-rest-client-python # edx-django-utils # paramiko -pyopenssl==23.2.0 +pyopenssl==23.3.0 # via # app-store-notifications-v2-validator # cybersource-rest-client-python # ndg-httpsclient # paypalrestsdk -pyparsing==3.1.0 +pyparsing==3.1.1 # via httplib2 pypi==2.1 # via cybersource-rest-client-python -pyrsistent==0.19.3 - # via jsonschema python-dateutil==2.8.2 # via # -r requirements/base.in @@ -469,7 +472,7 @@ python-memcached==1.59 # via -r requirements/production.in python-mimeparse==1.6.0 # via cybersource-rest-client-python -python-subunit==1.4.2 +python-subunit==1.4.4 # via cybersource-rest-client-python python-toolbox==1.0.11 # via cybersource-rest-client-python @@ -477,7 +480,7 @@ python3-openid==3.2.0 # via # -r requirements/base.in # social-auth-core -pytz==2023.3 +pytz==2023.3.post1 # via # -r requirements/base.in # babel @@ -491,7 +494,7 @@ pytz==2023.3 # drf-yasg # getsmarter-api-clients # zeep -pyyaml==6.0 +pyyaml==6.0.1 # via # -r requirements/production.in # cybersource-rest-client-python @@ -500,10 +503,14 @@ pyyaml==6.0 # naked rcssmin==1.1.1 # via django-compressor -redis==4.5.5 +redis==5.0.1 # via # -r requirements/production.in # edx-ecommerce-worker +referencing==0.32.1 + # via + # jsonschema + # jsonschema-specifications requests==2.31.0 # via # -r requirements/base.in @@ -533,6 +540,10 @@ requests-toolbelt==1.0.0 # via zeep rjsmin==1.2.1 # via django-compressor +rpds-py==0.16.2 + # via + # jsonschema + # referencing rsa==4.9 # via # cybersource-rest-client-python @@ -541,7 +552,7 @@ rsa==4.9 # oauth2client rules==3.3 # via -r requirements/base.in -s3transfer==0.6.1 +s3transfer==0.10.0 # via boto3 semantic-version==2.10.0 # via edx-drf-extensions @@ -549,7 +560,7 @@ shellescape==3.8.1 # via # crypto # cybersource-rest-client-python -simplejson==3.19.1 +simplejson==3.19.2 # via -r requirements/base.in six==1.16.0 # via @@ -557,13 +568,10 @@ six==1.16.0 # bleach # cybersource-rest-client-python # django-extra-views - # djangorestframework-csv # edx-auth-backends # edx-django-release-util # edx-ecommerce-worker # edx-rbac - # google-auth - # google-auth-httplib2 # isodate # libsass # oauth2client @@ -576,13 +584,14 @@ slumber==0.7.1 # via edx-rest-api-client social-auth-app-django==5.2.0 # via + # -c requirements/constraints.txt # -r requirements/base.in # edx-auth-backends -social-auth-core==4.4.2 +social-auth-core==4.5.1 # via # edx-auth-backends # social-auth-app-django -sorl-thumbnail==12.9.0 +sorl-thumbnail==12.10.0 # via -r requirements/base.in sqlparse==0.4.4 # via django @@ -590,9 +599,9 @@ stevedore==5.1.0 # via # edx-django-utils # edx-opaque-keys -stripe==5.4.0 +stripe==7.11.0 # via -r requirements/base.in -testtools==2.6.0 +testtools==2.7.1 # via # cybersource-rest-client-python # python-subunit @@ -600,23 +609,24 @@ traceback2==1.4.0 # via cybersource-rest-client-python typing==3.7.4.3 # via cybersource-rest-client-python -typing-extensions==4.6.3 - # via asgiref -unicodecsv==0.14.1 +typing-extensions==4.9.0 # via - # -r requirements/base.in - # djangorestframework-csv + # asgiref + # edx-opaque-keys + # faker + # stripe +unicodecsv==0.14.1 + # via -r requirements/base.in uritemplate==4.1.1 # via # coreapi # drf-yasg # google-api-python-client -urllib3==1.26.16 +urllib3==1.26.18 # via # -c requirements/constraints.txt # botocore # cybersource-rest-client-python - # google-auth # requests vine==1.3.0 # via @@ -624,19 +634,19 @@ vine==1.3.0 # celery webencodings==0.5.1 # via bleach -wheel==0.40.0 +wheel==0.42.0 # via cybersource-rest-client-python x509==0.1 # via cybersource-rest-client-python -xss-utils==0.4.0 +xss-utils==0.5.0 # via -r requirements/base.in -yarl==1.9.2 +yarl==1.9.4 # via aiohttp zeep==4.2.1 # via -r requirements/base.in -zipp==3.15.0 +zipp==3.17.0 # via importlib-resources -zope-interface==6.0 +zope-interface==6.1 # via # cybersource-rest-client-python # datetime diff --git a/requirements/test.in b/requirements/test.in index 8215d59379b..6d36ce4b1a9 100644 --- a/requirements/test.in +++ b/requirements/test.in @@ -3,7 +3,6 @@ -r e2e.txt # required for quality -r tox.txt -bok_choy coverage ddt diff-cover diff --git a/requirements/test.txt b/requirements/test.txt index 88f23748008..f7f653387fb 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -4,7 +4,7 @@ # # make upgrade # -aiohttp==3.8.4 +aiohttp==3.9.1 # via # -r requirements/base.txt # inapppy @@ -25,24 +25,26 @@ asgiref==3.7.2 # -r requirements/base.txt # -r requirements/e2e.txt # django + # django-cors-headers asn1crypto==1.5.1 # via # -r requirements/base.txt # cybersource-rest-client-python astroid==2.9.3 # via pylint -async-timeout==4.0.2 +async-timeout==4.0.3 # via # -r requirements/base.txt # aiohttp # redis -attrs==23.1.0 +attrs==23.2.0 # via # -r requirements/base.txt # aiohttp # jsonschema + # referencing # zeep -babel==2.12.1 +babel==2.14.0 # via # -r requirements/base.txt # django-oscar @@ -50,7 +52,7 @@ backoff==1.10.0 # via # -r requirements/base.txt # analytics-python -bcrypt==4.0.1 +bcrypt==4.1.2 # via # -r requirements/base.txt # cybersource-rest-client-python @@ -61,18 +63,16 @@ billiard==3.6.4.0 # via # -r requirements/base.txt # celery -bleach==6.0.0 +bleach==6.1.0 # via -r requirements/base.txt -bok-choy==2.0.2 - # via -r requirements/test.in -boto3==1.26.155 +boto3==1.34.17 # via -r requirements/base.txt -botocore==1.29.155 +botocore==1.34.17 # via # -r requirements/base.txt # boto3 # s3transfer -cachetools==5.3.1 +cachetools==5.3.2 # via # -r requirements/base.txt # google-auth @@ -81,13 +81,13 @@ celery==4.4.7 # -c requirements/constraints.txt # -r requirements/base.txt # edx-ecommerce-worker -certifi==2023.5.7 +certifi==2023.11.17 # via # -r requirements/base.txt # -r requirements/e2e.txt # cybersource-rest-client-python # requests -cffi==1.15.1 +cffi==1.16.0 # via # -r requirements/base.txt # -r requirements/e2e.txt @@ -95,23 +95,22 @@ cffi==1.15.1 # cryptography # cybersource-rest-client-python # pynacl -chardet==5.1.0 +chardet==5.2.0 # via # -r requirements/base.txt # cybersource-rest-client-python # diff-cover -charset-normalizer==3.1.0 +charset-normalizer==3.3.2 # via # -r requirements/base.txt # -r requirements/e2e.txt - # aiohttp # requests -click==8.1.3 +click==8.1.7 # via # -r requirements/base.txt # -r requirements/e2e.txt # edx-django-utils -configparser==5.3.0 +configparser==6.0.0 # via # -r requirements/base.txt # cybersource-rest-client-python @@ -121,7 +120,7 @@ coreschema==0.0.4 # via # -r requirements/base.txt # coreapi -coverage[toml]==7.2.7 +coverage[toml]==7.4.0 # via # -r requirements/base.txt # -r requirements/test.in @@ -133,10 +132,9 @@ crypto==1.4.1 # via # -r requirements/base.txt # cybersource-rest-client-python -cryptography==41.0.1 +cryptography==41.0.7 # via # -r requirements/base.txt - # -r requirements/e2e.txt # app-store-notifications-v2-validator # cybersource-rest-client-python # paramiko @@ -147,7 +145,7 @@ cssselect==1.2.0 # via # -r requirements/base.txt # premailer -cssutils==2.7.1 +cssutils==2.9.0 # via # -r requirements/base.txt # premailer @@ -155,18 +153,18 @@ cybersource-rest-client-python==0.0.21 # via # -c requirements/constraints.txt # -r requirements/base.txt -datetime==5.1 +datetime==5.4 # via # -r requirements/base.txt # cybersource-rest-client-python -ddt==1.6.0 +ddt==1.7.1 # via -r requirements/test.in -defusedxml==0.7.1 +defusedxml==0.8.0rc2 # via # -r requirements/base.txt # python3-openid # social-auth-core -diff-cover==7.6.0 +diff-cover==8.0.2 # via -r requirements/test.in # via # -c requirements/common_constraints.txt @@ -188,6 +186,7 @@ diff-cover==7.6.0 # django-solo # django-tables2 # django-treebeard + # django-waffle # djangorestframework # drf-jwt # drf-yasg @@ -202,17 +201,17 @@ diff-cover==7.6.0 # jsonfield2 # social-auth-app-django # xss-utils -django-appconf==1.0.5 +django-appconf==1.0.6 # via # -r requirements/base.txt # django-compressor -django-compressor==4.3.1 +django-compressor==4.4 # via # -r requirements/base.txt # django-libsass -django-config-models==2.3.0 +django-config-models==2.5.1 # via -r requirements/base.txt -django-cors-headers==4.1.0 +django-cors-headers==4.3.1 # via -r requirements/base.txt django-crispy-forms==2.0 # via @@ -230,7 +229,7 @@ django-extra-views==0.13.0 # via # -r requirements/base.txt # django-oscar -django-filter==23.2 +django-filter==23.5 # via -r requirements/base.txt django-haystack==3.2.1 # via @@ -266,15 +265,15 @@ django-treebeard==4.4 # via # -r requirements/base.txt # django-oscar -django-waffle==3.0.0 +django-waffle==4.1.0 # via # -r requirements/base.txt # -r requirements/e2e.txt # edx-django-utils # edx-drf-extensions -django-webtest==1.9.10 +django-webtest==1.9.11 # via -r requirements/test.in -django-widget-tweaks==1.4.12 +django-widget-tweaks==1.5.0 # via # -r requirements/base.txt # django-oscar @@ -288,7 +287,7 @@ djangorestframework==3.14.0 # drf-jwt # drf-yasg # edx-drf-extensions -djangorestframework-csv==2.1.1 +djangorestframework-csv==3.0.2 # via -r requirements/base.txt djangorestframework-datatables==0.7.0 # via -r requirements/base.txt @@ -298,19 +297,19 @@ drf-jwt==1.19.2 # via # -r requirements/base.txt # edx-drf-extensions -drf-yasg==1.21.6 +drf-yasg==1.21.7 # via -r requirements/base.txt -edx-auth-backends==4.1.0 +edx-auth-backends==4.2.0 # via -r requirements/base.txt -edx-braze-client==0.1.6 +edx-braze-client==0.1.8 # via # -r requirements/base.txt # edx-ecommerce-worker -edx-django-release-util==1.2.0 +edx-django-release-util==1.3.0 # via -r requirements/base.txt -edx-django-sites-extensions==4.0.0 +edx-django-sites-extensions==4.0.2 # via -r requirements/base.txt -edx-django-utils==5.5.0 +edx-django-utils==5.9.0 # via # -r requirements/base.txt # -r requirements/e2e.txt @@ -318,7 +317,7 @@ edx-django-utils==5.5.0 # edx-drf-extensions # edx-rest-api-client # getsmarter-api-clients -edx-drf-extensions==9.0.0 +edx-drf-extensions==9.1.2 # via # -r requirements/base.txt # edx-rbac @@ -326,13 +325,13 @@ edx-ecommerce-worker==3.3.4 # via -r requirements/base.txt edx-i18n-tools==1.3.0 # via -r requirements/test.in -edx-opaque-keys==2.3.0 +edx-opaque-keys==2.5.1 # via # -r requirements/base.txt # edx-drf-extensions -edx-rbac==1.7.0 +edx-rbac==1.8.0 # via -r requirements/base.txt -edx-rest-api-client==5.5.2 +edx-rest-api-client==5.6.1 # via # -r requirements/base.txt # -r requirements/e2e.txt @@ -341,7 +340,7 @@ enum34==1.1.10 # via # -r requirements/base.txt # cybersource-rest-client-python -exceptiongroup==1.1.1 +exceptiongroup==1.2.0 # via # -r requirements/e2e.txt # pytest @@ -355,11 +354,11 @@ factory-boy==3.1.0 # -r requirements/base.txt # -r requirements/test.in # django-oscar -faker==18.10.1 +faker==22.2.0 # via # -r requirements/base.txt # factory-boy -filelock==3.12.2 +filelock==3.13.1 # via # -r requirements/tox.txt # tox @@ -367,10 +366,9 @@ fixtures==4.1.0 # via # -r requirements/base.txt # cybersource-rest-client-python - # testtools -freezegun==1.2.2 +freezegun==1.4.0 # via -r requirements/test.in -frozenlist==1.3.3 +frozenlist==1.4.1 # via # -r requirements/base.txt # aiohttp @@ -383,9 +381,9 @@ future==0.18.3 # via # -r requirements/e2e.txt # pyjwkest -getsmarter-api-clients==0.6.0 +getsmarter-api-clients==0.6.1 # via -r requirements/base.txt -google-api-core==2.11.1 +google-api-core==2.15.0 # via # -r requirements/base.txt # google-api-python-client @@ -393,17 +391,17 @@ google-api-python-client==2.31.0 # via # -r requirements/base.txt # inapppy -google-auth==2.20.0 +google-auth==2.26.2 # via # -r requirements/base.txt # google-api-core # google-api-python-client # google-auth-httplib2 -google-auth-httplib2==0.1.0 +google-auth-httplib2==0.2.0 # via # -r requirements/base.txt # google-api-python-client -googleapis-common-protos==1.59.1 +googleapis-common-protos==1.62.0 # via # -r requirements/base.txt # google-api-core @@ -421,14 +419,15 @@ idna==2.7 # cybersource-rest-client-python # requests # yarl -importlib-metadata==6.7.0 +importlib-metadata==7.0.1 # via # -r requirements/e2e.txt # pytest-randomly -importlib-resources==5.12.0 +importlib-resources==6.1.1 # via # -r requirements/base.txt # jsonschema + # jsonschema-specifications inapppy==2.5.2 # via -r requirements/base.txt inflection==0.5.1 @@ -443,11 +442,15 @@ ipaddress==1.0.23 # via # -r requirements/base.txt # cybersource-rest-client-python +iso8601==2.1.0 + # via + # -r requirements/base.txt + # python-subunit isodate==0.6.1 # via # -r requirements/base.txt # zeep -isort==5.12.0 +isort==5.13.2 # via # -r requirements/test.in # pylint @@ -455,11 +458,13 @@ itypes==1.2.0 # via # -r requirements/base.txt # coreapi -jinja2==3.1.2 +jinja2==3.1.3 # via # -r requirements/base.txt + # -r requirements/e2e.txt # coreschema # diff-cover + # pytest-html jmespath==1.0.1 # via # -r requirements/base.txt @@ -469,17 +474,19 @@ jsonfield==3.1.0 # via -r requirements/base.txt jsonfield2==4.0.0.post0 # via -r requirements/base.txt -jsonschema==4.17.3 +jsonschema==4.20.0 # via # -r requirements/base.txt # cybersource-rest-client-python +jsonschema-specifications==2023.12.1 + # via + # -r requirements/base.txt + # jsonschema kombu==4.6.11 # via # -r requirements/base.txt # celery -lazy==1.5 - # via bok-choy -lazy-object-proxy==1.9.0 +lazy-object-proxy==1.10.0 # via astroid libsass==0.9.2 # via @@ -494,10 +501,11 @@ logger==1.4 # via # -r requirements/base.txt # cybersource-rest-client-python -lxml==4.9.2 +lxml==5.1.0 # via # -r requirements/base.txt # -r requirements/test.in + # edx-i18n-tools # premailer # zeep markdown==3.4.3 @@ -505,12 +513,13 @@ markdown==3.4.3 markupsafe==2.1.3 # via # -r requirements/base.txt + # -r requirements/e2e.txt # jinja2 mccabe==0.6.1 # via # -c requirements/constraints.txt # pylint -mock==5.0.2 +mock==5.1.0 # via -r requirements/test.in monotonic==1.6 # via @@ -530,7 +539,7 @@ naked==0.1.32 # cybersource-rest-client-python ndg-httpsclient==0.5.1 # via -r requirements/base.txt -newrelic==9.1.0 +newrelic==9.5.0 # via # -r requirements/base.txt # -r requirements/e2e.txt @@ -550,8 +559,8 @@ oauthlib==3.2.2 # requests-oauthlib # social-auth-core openedx-atlas==0.5.0 - # via -r requirements/base.in -packaging==23.1 + # via -r requirements/base.txt +packaging==23.2 # via # -r requirements/base.txt # -r requirements/e2e.txt @@ -559,29 +568,28 @@ packaging==23.1 # drf-yasg # pytest # tox -paramiko==3.2.0 +paramiko==3.4.0 # via # -r requirements/base.txt # cybersource-rest-client-python -path==16.6.0 +path==16.9.0 # via edx-i18n-tools path-py==7.2 # via -r requirements/base.txt -paypalrestsdk==1.13.1 +paypalrestsdk==1.13.3 # via -r requirements/base.txt -pbr==5.11.1 +pbr==6.0.0 # via # -r requirements/base.txt # -r requirements/e2e.txt # cybersource-rest-client-python # fixtures # stevedore - # testtools -phonenumbers==8.13.14 +phonenumbers==8.13.27 # via # -r requirements/base.txt # django-oscar -pillow==9.5.0 +pillow==10.2.0 # via # -r requirements/base.txt # django-oscar @@ -589,7 +597,7 @@ pkgutil-resolve-name==1.3.10 # via # -r requirements/base.txt # jsonschema -platformdirs==3.6.0 +platformdirs==4.1.0 # via # -r requirements/base.txt # pylint @@ -606,12 +614,12 @@ polib==1.2.0 # via edx-i18n-tools premailer==2.9.2 # via -r requirements/base.txt -protobuf==4.23.3 +protobuf==4.25.2 # via # -r requirements/base.txt # google-api-core # googleapis-common-protos -psutil==5.9.5 +psutil==5.9.7 # via # -r requirements/base.txt # -r requirements/e2e.txt @@ -622,11 +630,9 @@ purl==1.6 # django-oscar py==1.11.0 # via - # -r requirements/e2e.txt # -r requirements/tox.txt - # pytest-html # tox -pyasn1==0.5.0 +pyasn1==0.5.1 # via # -r requirements/base.txt # cybersource-rest-client-python @@ -640,7 +646,7 @@ pyasn1-modules==0.3.0 # -r requirements/base.txt # google-auth # oauth2client -pycodestyle==2.10.0 +pycodestyle==2.11.1 # via -r requirements/test.in pycountry==17.1.8 # via -r requirements/base.txt @@ -651,23 +657,23 @@ pycparser==2.21 # app-store-notifications-v2-validator # cffi # cybersource-rest-client-python -pycryptodome==3.18.0 +pycryptodome==3.20.0 # via # -r requirements/base.txt # cybersource-rest-client-python -pycryptodomex==3.18.0 +pycryptodomex==3.20.0 # via # -r requirements/base.txt # -r requirements/e2e.txt # cybersource-rest-client-python # pyjwkest -pygments==2.15.1 +pygments==2.17.2 # via # -r requirements/base.txt # diff-cover pyjwkest==1.4.2 # via -r requirements/e2e.txt -pyjwt[crypto]==2.7.0 +pyjwt[crypto]==2.8.0 # via # -r requirements/base.txt # -r requirements/e2e.txt @@ -677,6 +683,7 @@ pyjwt[crypto]==2.7.0 # edx-auth-backends # edx-drf-extensions # edx-rest-api-client + # pyjwt # social-auth-core pylint==2.12.2 # via @@ -693,14 +700,14 @@ pynacl==1.5.0 # cybersource-rest-client-python # edx-django-utils # paramiko -pyopenssl==23.2.0 +pyopenssl==23.3.0 # via # -r requirements/base.txt # app-store-notifications-v2-validator # cybersource-rest-client-python # ndg-httpsclient # paypalrestsdk -pyparsing==3.1.0 +pyparsing==3.1.1 # via # -r requirements/base.txt # httplib2 @@ -708,11 +715,7 @@ pypi==2.1 # via # -r requirements/base.txt # cybersource-rest-client-python -pyrsistent==0.19.3 - # via - # -r requirements/base.txt - # jsonschema -pytest==7.3.2 +pytest==7.4.4 # via # -r requirements/e2e.txt # -r requirements/test.in @@ -731,9 +734,9 @@ pytest-base-url==2.0.0 # pytest-selenium pytest-cov==4.1.0 # via -r requirements/test.in -pytest-django==4.5.2 +pytest-django==4.7.0 # via -r requirements/test.in -pytest-html==3.2.0 +pytest-html==4.1.1 # via # -r requirements/e2e.txt # pytest-selenium @@ -741,13 +744,13 @@ pytest-metadata==3.0.0 # via # -r requirements/e2e.txt # pytest-html -pytest-randomly==3.12.0 +pytest-randomly==3.15.0 # via -r requirements/e2e.txt pytest-selenium==2.0.1 # via # -c requirements/constraints.txt # -r requirements/e2e.txt -pytest-timeout==2.1.0 +pytest-timeout==2.2.0 # via -r requirements/e2e.txt pytest-variables==2.0.0 # via @@ -769,7 +772,7 @@ python-mimeparse==1.6.0 # via # -r requirements/base.txt # cybersource-rest-client-python -python-subunit==1.4.2 +python-subunit==1.4.4 # via # -r requirements/base.txt # cybersource-rest-client-python @@ -781,7 +784,7 @@ python3-openid==3.2.0 # via # -r requirements/base.txt # social-auth-core -pytz==2023.3 +pytz==2023.3.post1 # via # -r requirements/base.txt # -r requirements/e2e.txt @@ -795,7 +798,7 @@ pytz==2023.3 # drf-yasg # getsmarter-api-clients # zeep -pyyaml==6.0 +pyyaml==6.0.1 # via # -r requirements/base.txt # cybersource-rest-client-python @@ -808,10 +811,15 @@ rcssmin==1.1.1 # via # -r requirements/base.txt # django-compressor -redis==4.5.5 +redis==5.0.1 # via # -r requirements/base.txt # edx-ecommerce-worker +referencing==0.32.1 + # via + # -r requirements/base.txt + # jsonschema + # jsonschema-specifications requests==2.31.0 # via # -r requirements/base.txt @@ -849,12 +857,17 @@ requests-toolbelt==1.0.0 # via # -r requirements/base.txt # zeep -responses==0.23.1 +responses==0.24.1 # via -r requirements/test.in rjsmin==1.2.1 # via # -r requirements/base.txt # django-compressor +rpds-py==0.16.2 + # via + # -r requirements/base.txt + # jsonschema + # referencing rsa==4.9 # via # -r requirements/base.txt @@ -864,7 +877,7 @@ rsa==4.9 # oauth2client rules==3.3 # via -r requirements/base.txt -s3transfer==0.6.1 +s3transfer==0.10.0 # via # -r requirements/base.txt # boto3 @@ -873,7 +886,6 @@ selenium==3.141.0 # -c requirements/constraints.txt # -r requirements/e2e.txt # -r requirements/test.in - # bok-choy # pytest-selenium semantic-version==2.10.0 # via @@ -884,7 +896,7 @@ shellescape==3.8.1 # -r requirements/base.txt # crypto # cybersource-rest-client-python -simplejson==3.19.1 +simplejson==3.19.2 # via -r requirements/base.txt six==1.16.0 # via @@ -895,13 +907,10 @@ six==1.16.0 # bleach # cybersource-rest-client-python # django-extra-views - # djangorestframework-csv # edx-auth-backends # edx-django-release-util # edx-ecommerce-worker # edx-rbac - # google-auth - # google-auth-httplib2 # isodate # libsass # oauth2client @@ -920,16 +929,17 @@ slumber==0.7.1 # edx-rest-api-client social-auth-app-django==5.2.0 # via + # -c requirements/constraints.txt # -r requirements/base.txt # edx-auth-backends -social-auth-core==4.4.2 +social-auth-core==4.5.1 # via # -r requirements/base.txt # edx-auth-backends # social-auth-app-django -sorl-thumbnail==12.9.0 +sorl-thumbnail==12.10.0 # via -r requirements/base.txt -soupsieve==2.4.1 +soupsieve==2.5 # via beautifulsoup4 sqlparse==0.4.4 # via @@ -942,15 +952,15 @@ stevedore==5.1.0 # -r requirements/e2e.txt # edx-django-utils # edx-opaque-keys -stripe==5.4.0 +stripe==7.11.0 # via -r requirements/base.txt tenacity==6.3.1 # via # -r requirements/e2e.txt # pytest-selenium -testfixtures==7.1.0 +testfixtures==7.2.2 # via -r requirements/test.in -testtools==2.6.0 +testtools==2.7.1 # via # -r requirements/base.txt # cybersource-rest-client-python @@ -967,47 +977,44 @@ tomli==2.0.1 # pytest tox==3.14.6 # via - # -c requirements/common_constraints.txt # -c requirements/constraints.txt # -r requirements/tox.txt # tox-battery -tox-battery==0.6.1 +tox-battery==0.6.2 # via -r requirements/tox.txt traceback2==1.4.0 # via # -r requirements/base.txt # cybersource-rest-client-python -types-pyyaml==6.0.12.10 - # via responses typing==3.7.4.3 # via # -r requirements/base.txt # cybersource-rest-client-python -typing-extensions==4.6.3 +typing-extensions==4.9.0 # via # -r requirements/base.txt # -r requirements/e2e.txt # asgiref # astroid + # edx-opaque-keys + # faker # pylint + # stripe unicodecsv==0.14.1 - # via - # -r requirements/base.txt - # djangorestframework-csv + # via -r requirements/base.txt uritemplate==4.1.1 # via # -r requirements/base.txt # coreapi # drf-yasg # google-api-python-client -urllib3==1.26.16 +urllib3==1.26.18 # via # -c requirements/constraints.txt # -r requirements/base.txt # -r requirements/e2e.txt # botocore # cybersource-rest-client-python - # google-auth # requests # responses # selenium @@ -1031,7 +1038,7 @@ webob==1.8.7 # via webtest webtest==3.0.0 # via django-webtest -wheel==0.40.0 +wheel==0.42.0 # via # -r requirements/base.txt # cybersource-rest-client-python @@ -1043,21 +1050,21 @@ x509==0.1 # via # -r requirements/base.txt # cybersource-rest-client-python -xss-utils==0.4.0 +xss-utils==0.5.0 # via -r requirements/base.txt -yarl==1.9.2 +yarl==1.9.4 # via # -r requirements/base.txt # aiohttp zeep==4.2.1 # via -r requirements/base.txt -zipp==3.15.0 +zipp==3.17.0 # via # -r requirements/base.txt # -r requirements/e2e.txt # importlib-metadata # importlib-resources -zope-interface==6.0 +zope-interface==6.1 # via # -r requirements/base.txt # cybersource-rest-client-python diff --git a/requirements/tox.txt b/requirements/tox.txt index 7721aa931aa..df1c7fb7fc5 100644 --- a/requirements/tox.txt +++ b/requirements/tox.txt @@ -4,9 +4,9 @@ # # make upgrade # -filelock==3.12.2 +filelock==3.13.1 # via tox -packaging==23.1 +packaging==23.2 # via tox pluggy==0.13.1 # via @@ -20,11 +20,10 @@ toml==0.10.2 # via tox tox==3.14.6 # via - # -c requirements/common_constraints.txt # -c requirements/constraints.txt # -r requirements/tox.in # tox-battery -tox-battery==0.6.1 +tox-battery==0.6.2 # via -r requirements/tox.in virtualenv==16.7.9 # via From 60e1b5c65c70ad7ed9f85dd4b8c14b9b5ad76544 Mon Sep 17 00:00:00 2001 From: salman2013 Date: Wed, 17 Jan 2024 13:04:27 +0500 Subject: [PATCH 2/3] chore: remove extra code from browser class --- .../dashboard/refunds/tests/browser.py | 124 ------------------ 1 file changed, 124 deletions(-) diff --git a/ecommerce/extensions/dashboard/refunds/tests/browser.py b/ecommerce/extensions/dashboard/refunds/tests/browser.py index e0012c9f0c1..23aac5fcc21 100644 --- a/ecommerce/extensions/dashboard/refunds/tests/browser.py +++ b/ecommerce/extensions/dashboard/refunds/tests/browser.py @@ -72,120 +72,6 @@ class BrowserConfigError(Exception): """ -def save_source(driver, name): - """ - Save the rendered HTML of the browser. - - The location of the source can be configured - by the environment variable `SAVED_SOURCE_DIR`. If not set, - this defaults to the current working directory. - - Args: - driver (selenium.webdriver): The Selenium-controlled browser. - name (str): A name to use in the output file name. - Note that ".html" is appended automatically - - Returns: - None - """ - source = driver.page_source - saved_source_dir = os.environ.get('SAVED_SOURCE_DIR') - if not saved_source_dir: - LOGGER.warning('The SAVED_SOURCE_DIR environment variable was not set; not saving page source') - return - file_name = os.path.join(saved_source_dir, - f'{name}.html') - - try: - if not os.path.exists(saved_source_dir): - os.makedirs(saved_source_dir) - with open(file_name, 'wb') as output_file: - output_file.write(source.encode('utf-8')) - except Exception: # pylint: disable=broad-except - msg = f"Could not save the browser page source to {file_name}." - LOGGER.warning(msg) - - -def save_screenshot(driver, name): - """ - Save a screenshot of the browser. - - The location of the screenshot can be configured - by the environment variable `SCREENSHOT_DIR`. If not set, - this defaults to the current working directory. - - Args: - driver (selenium.webdriver): The Selenium-controlled browser. - name (str): A name for the screenshot, which will be used in the output file name. - - Returns: - None - """ - if hasattr(driver, 'save_screenshot'): - screenshot_dir = os.environ.get('SCREENSHOT_DIR') - if not screenshot_dir: - LOGGER.warning('The SCREENSHOT_DIR environment variable was not set; not saving a screenshot') - return - if not os.path.exists(screenshot_dir): - os.makedirs(screenshot_dir) - image_name = os.path.join(screenshot_dir, name + '.png') - driver.save_screenshot(image_name) - - else: - msg = f"Browser does not support screenshots. Could not save screenshot '{name}'" - LOGGER.warning(msg) - - -def save_driver_logs(driver, prefix): - """ - Save the selenium driver logs. - - The location of the driver log files can be configured - by the environment variable `SELENIUM_DRIVER_LOG_DIR`. If not set, - this defaults to the current working directory. - - Args: - driver (selenium.webdriver): The Selenium-controlled browser. - prefix (str): A prefix which will be used in the output file names for the logs. - - Returns: - None - """ - browser_name = os.environ.get('SELENIUM_BROWSER', 'firefox') - log_dir = os.environ.get('SELENIUM_DRIVER_LOG_DIR') - if not log_dir: - LOGGER.warning('The SELENIUM_DRIVER_LOG_DIR environment variable was not set; not saving logs') - return - if not os.path.exists(log_dir): - os.makedirs(log_dir) - if browser_name == 'firefox': - # Firefox doesn't yet provide logs to Selenium, but does log to a separate file - # https://github.com/mozilla/geckodriver/issues/284 - # https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/TraceLogs.html - log_path = os.path.join(os.getcwd(), 'geckodriver.log') - if os.path.exists(log_path): - dest_path = os.path.join(log_dir, f'{prefix}_geckodriver.log') - copyfile(log_path, dest_path) - return - - log_types = driver.log_types - for log_type in log_types: - try: - log = driver.get_log(log_type) - file_name = os.path.join( - log_dir, f'{prefix}_{log_type}.log' - ) - with open(file_name, 'w', encoding="utf8") as output_file: - for line in log: - output_file.write("{}{}".format(dumps(line), '\n')) - except: # pylint: disable=bare-except - msg = ( - f"Could not save browser log of type '{log_type}'. It may be that the browser does not support it." - ) - - LOGGER.warning(msg, exc_info=True) - - def browser(tags=None, proxy=None, other_caps=None): """ Interpret environment variables to configure Selenium. @@ -293,16 +179,6 @@ def browser_check_func(): return browser_instance -def add_profile_customizer(func): - """Add a new function that modifies the preferences of the firefox profile object it receives as an argument""" - FIREFOX_PROFILE_CUSTOMIZERS.append(func) - - -def clear_profile_customizers(): - """Remove any previously-configured functions for customizing the firefox profile""" - FIREFOX_PROFILE_CUSTOMIZERS[:] = [] - - def _firefox_profile(): """Configure the Firefox profile, respecting FIREFOX_PROFILE_PATH if set""" profile_dir = os.environ.get(FIREFOX_PROFILE_ENV_VAR) From a2cb91f880812d92c17a65cf70202995f6d8cbe1 Mon Sep 17 00:00:00 2001 From: salman2013 Date: Wed, 17 Jan 2024 15:01:33 +0500 Subject: [PATCH 3/3] chore: fix failing test --- ecommerce/extensions/dashboard/refunds/tests/browser.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/ecommerce/extensions/dashboard/refunds/tests/browser.py b/ecommerce/extensions/dashboard/refunds/tests/browser.py index 23aac5fcc21..8a966bd9f6f 100644 --- a/ecommerce/extensions/dashboard/refunds/tests/browser.py +++ b/ecommerce/extensions/dashboard/refunds/tests/browser.py @@ -6,8 +6,6 @@ import errno import logging import os -from json import dumps -from shutil import copyfile try: from needle.driver import NeedleChrome as Chrome