From 90a7c5d986427e97b3f75babfa6c65fefd6f2b65 Mon Sep 17 00:00:00 2001 From: Douglas Cerna Date: Wed, 6 Sep 2023 14:32:20 -0600 Subject: [PATCH] Install Python with pyenv This changes the Dockerfile to be a multi-stage build that: * Uses Ubuntu 22.04 as the base image * Installs Python 3.9 using pyenv * Downloads Chrome and Firefox using Selenium Manager. --- .github/workflows/test.yml | 29 +- .pre-commit-config.yaml | 14 +- Dockerfile | 207 +-- Makefile | 17 + amuser/am_api_ability.py | 17 +- amuser/am_browser_ability.py | 28 +- amuser/am_browser_auth_ability.py | 7 +- amuser/am_browser_file_explorer_ability.py | 29 +- amuser/am_browser_ingest_ability.py | 40 +- amuser/am_browser_jobs_tasks_ability.py | 5 +- ...m_browser_preservation_planning_ability.py | 7 +- amuser/am_browser_ss_ability.py | 9 +- amuser/am_browser_transfer_ability.py | 9 +- amuser/am_browser_transfer_ingest_ability.py | 25 +- amuser/am_docker_ability.py | 3 +- amuser/am_localfs_ability.py | 1 - amuser/am_mets_ability.py | 19 +- amuser/am_ssh_ability.py | 3 +- amuser/amuser.py | 11 +- amuser/base.py | 3 +- amuser/constants.py | 2 +- amuser/selenium_ability.py | 15 +- amuser/urls.py | 2 - amuser/utils.py | 1 - etc/docker/seccomp/chrome.json | 1535 ----------------- features/environment.py | 21 +- features/steps/aip_encryption_steps.py | 20 +- features/steps/black_box_steps.py | 63 +- features/steps/capture_output_steps.py | 5 +- features/steps/cca_dip_steps.py | 19 +- features/steps/indexless_steps.py | 11 +- features/steps/infinite_aips.py | 5 +- features/steps/manual_normalization_steps.py | 4 +- features/steps/mediaconch_steps.py | 11 +- features/steps/mets_steps.py | 5 +- .../performance_stdout_no_write_steps.py | 15 +- features/steps/pid_binding_steps.py | 4 +- features/steps/steps.py | 10 +- features/steps/utils.py | 53 +- features/steps/uuids_for_directories_steps.py | 14 +- requirements-dev.in | 4 + requirements-dev.txt | 121 ++ requirements/base.txt => requirements.in | 6 +- requirements.txt | 51 +- requirements/test.txt | 3 - simplebrowsertest.py | 20 +- tox.ini | 1 - 47 files changed, 556 insertions(+), 1948 deletions(-) create mode 100644 Makefile delete mode 100644 etc/docker/seccomp/chrome.json create mode 100644 requirements-dev.in create mode 100644 requirements-dev.txt rename requirements/base.txt => requirements.in (50%) delete mode 100644 requirements/test.txt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ddb8e58e..7d821c6e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,22 +16,14 @@ jobs: - name: "Set up Python" uses: "actions/setup-python@v4" with: - python-version: "3.8" - - name: "Get pip cache dir" - id: "pip-cache" - run: | - echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - - name: "Cache pip packages" - uses: "actions/cache@v3" - with: - path: "${{ steps.pip-cache.outputs.dir }}" - key: "${{ runner.os }}-pip-${{ hashFiles('**/base.txt', '**/test.txt') }}" - restore-keys: | - ${{ runner.os }}-pip- + python-version: "3.9" + cache: "pip" + cache-dependency-path: | + requirements-dev.txt - name: "Install requirements" run: | python -m pip install --upgrade pip - pip install -r requirements.txt + pip install -r requirements-dev.txt - name: "Run test" run: | ./simplebrowsertest.py @@ -43,15 +35,17 @@ jobs: uses: "actions/checkout@v3" - name: "Build containers" run: | - docker build -t archivematica-acceptance-tests . + docker build -t archivematica-acceptance-tests --build-arg TARGET --build-arg PYTHON_VERSION . env: COMPOSE_DOCKER_CLI_BUILD: 1 DOCKER_BUILDKIT: 1 + TARGET: "archivematica-acceptance-tests" + PYTHON_VERSION: "3.9" - name: "Run test" run: | docker run \ --rm \ - --security-opt="seccomp=etc/docker/seccomp/chrome.json" \ + --security-opt="seccomp=unconfined" \ archivematica-acceptance-tests \ /home/artefactual/acceptance-tests/simplebrowsertest.py lint: @@ -63,7 +57,10 @@ jobs: - name: "Set up Python" uses: "actions/setup-python@v4" with: - python-version: "3.8" + python-version: "3.9" + cache: "pip" + cache-dependency-path: | + requirements-dev.txt - name: "Install tox" run: | python -m pip install --upgrade pip diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 63ebce11..6b8805c2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,12 +1,22 @@ repos: +- repo: https://github.com/asottile/pyupgrade + rev: v3.10.1 + hooks: + - id: pyupgrade + args: [--py38-plus] +- repo: https://github.com/asottile/reorder_python_imports + rev: v3.10.0 + hooks: + - id: reorder-python-imports + args: [--py38-plus] - repo: https://github.com/psf/black - rev: 22.8.0 + rev: "23.7.0" hooks: - id: black args: [--safe, --quiet] language_version: python3 - repo: https://github.com/pycqa/flake8 - rev: 5.0.4 + rev: "6.1.0" hooks: - id: flake8 language_version: python3 diff --git a/Dockerfile b/Dockerfile index e147d4db..7901f7d7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,118 +1,127 @@ -FROM ubuntu:18.04 +ARG TARGET=archivematica-acceptance-tests -RUN echo "deb http://archive.ubuntu.com/ubuntu bionic main universe\n" > /etc/apt/sources.list \ - && echo "deb http://archive.ubuntu.com/ubuntu bionic-updates main universe\n" >> /etc/apt/sources.list \ - && echo "deb http://security.ubuntu.com/ubuntu bionic-security main universe\n" >> /etc/apt/sources.list +ARG UBUNTU_VERSION=22.04 + +FROM ubuntu:${UBUNTU_VERSION} AS base + +ARG USER_ID=1000 +ARG GROUP_ID=1000 +ARG PYTHON_VERSION=3.9 +ARG PYENV_DIR=/pyenv +ARG SELENIUM_DIR=/selenium ENV DEBIAN_FRONTEND=noninteractive -ENV DEBCONF_NONINTERACTIVE_SEEN=true -RUN apt-get -qqy update \ +RUN set -ex \ + && apt-get -qqy update \ && apt-get -qqy --no-install-recommends install \ - gnupg \ - bzip2 \ ca-certificates \ - tzdata \ - sudo \ - unzip \ curl \ - wget \ git \ - build-essential \ - locales \ - openssh-client \ - p7zip-full \ - python \ - python3-pip \ - python3-setuptools \ - python3-dev \ - libxml2-dev \ - libxslt-dev \ - zlib1g-dev \ jq \ - libnss3 \ - libgbm1 \ - libdrm2 \ + locales \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/* - -# Set the locale RUN locale-gen en_US.UTF-8 ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 -ENV TZ "UTC" -RUN echo "${TZ}" > /etc/timezone \ - && dpkg-reconfigure --frontend noninteractive tzdata - -RUN groupadd --gid 333 archivematica \ - && useradd --shell /bin/bash --groups sudo,archivematica --create-home artefactual \ - && echo 'ALL ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers \ - && echo 'artefactual:secret' | chpasswd - -# -# Chrome -# - -ARG CHROME_VERSION="google-chrome-stable" -RUN CHROME_STABLE_VERSION=$(wget -qO- https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json | jq -r '.channels.Stable.version') \ - && CHROME_VERSION=$(if [ ${CHROME_VERSION:-google-chrome-stable} = "google-chrome-stable" ]; then echo $CHROME_STABLE_VERSION; else echo $CHROME_VERSION; fi) \ - && CHROME_DOWNLOAD_URL=$(wget -qO- https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json | jq -r --arg version "$CHROME_VERSION" '.versions[] | select(.version == $version) | .downloads.chrome[] | select(.platform == "linux64") | .url') \ - && echo "Using chrome version: "$CHROME_VERSION \ - && wget --no-verbose -O /tmp/chrome_linux64.zip $CHROME_DOWNLOAD_URL \ - && unzip /tmp/chrome_linux64.zip -d /opt/chrome-$CHROME_VERSION \ - && rm /tmp/chrome_linux64.zip \ - && chmod 755 /opt/chrome-$CHROME_VERSION/chrome-linux64/chrome \ - && sudo ln -fs /opt/chrome-$CHROME_VERSION/chrome-linux64/chrome /usr/bin/google-chrome - -ARG CHROME_DRIVER_VERSION="latest" -RUN CHROMEDRIVER_STABLE_VERSION=$(wget -qO- https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json | jq -r '.channels.Stable.version') \ - && CHROMEDRIVER_VERSION=$(if [ ${CHROME_DRIVER_VERSION:-latest} = "latest" ]; then echo $CHROMEDRIVER_STABLE_VERSION; else echo $CHROME_DRIVER_VERSION; fi) \ - && CHROMEDRIVER_DOWNLOAD_URL=$(wget -qO- https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json | jq -r --arg version "$CHROMEDRIVER_VERSION" '.versions[] | select(.version == $version) | .downloads.chromedriver[] | select(.platform == "linux64") | .url') \ - && echo "Using chromedriver version: "$CHROMEDRIVER_VERSION \ - && wget --no-verbose -O /tmp/chromedriver_linux64.zip $CHROMEDRIVER_DOWNLOAD_URL \ - && unzip /tmp/chromedriver_linux64.zip -d /opt/chromedriver-$CHROMEDRIVER_VERSION \ - && rm /tmp/chromedriver_linux64.zip \ - && chmod 755 /opt/chromedriver-$CHROMEDRIVER_VERSION/chromedriver-linux64/chromedriver \ - && sudo ln -fs /opt/chromedriver-$CHROMEDRIVER_VERSION/chromedriver-linux64/chromedriver /usr/bin/chromedriver - -# -# Firefox -# - -ARG FIREFOX_VERSION=94.0.2 -RUN FIREFOX_DOWNLOAD_URL=$(if [ $FIREFOX_VERSION = "latest" ] || [ $FIREFOX_VERSION = "nightly-latest" ] || [ $FIREFOX_VERSION = "devedition-latest" ]; then echo "https://download.mozilla.org/?product=firefox-$FIREFOX_VERSION-ssl&os=linux64&lang=en-US"; else echo "https://download-installer.cdn.mozilla.net/pub/firefox/releases/$FIREFOX_VERSION/linux-x86_64/en-US/firefox-$FIREFOX_VERSION.tar.bz2"; fi) \ - && apt-get update -qqy \ - && apt-get -qqy --no-install-recommends install firefox \ - && rm -rf /var/lib/apt/lists/* /var/cache/apt/* \ - && wget --no-verbose -O /tmp/firefox.tar.bz2 $FIREFOX_DOWNLOAD_URL \ - && apt-get -y purge firefox \ - && rm -rf /opt/firefox \ - && tar -C /opt -xjf /tmp/firefox.tar.bz2 \ - && rm /tmp/firefox.tar.bz2 \ - && mv /opt/firefox /opt/firefox-$FIREFOX_VERSION \ - && ln -fs /opt/firefox-$FIREFOX_VERSION/firefox /usr/bin/firefox - -ARG GECKODRIVER_VERSION=0.30.0 -RUN GK_VERSION=$(if [ ${GECKODRIVER_VERSION:-latest} = "latest" ]; then echo $(wget -qO- "https://api.github.com/repos/mozilla/geckodriver/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([0-9.]+)".*/\1/'); else echo $GECKODRIVER_VERSION; fi) \ - && echo "Using GeckoDriver version: "$GK_VERSION \ - && wget --no-verbose -O /tmp/geckodriver.tar.gz https://github.com/mozilla/geckodriver/releases/download/v$GK_VERSION/geckodriver-v$GK_VERSION-linux64.tar.gz \ - && rm -rf /opt/geckodriver \ - && tar -C /opt -zxf /tmp/geckodriver.tar.gz \ - && rm /tmp/geckodriver.tar.gz \ - && mv /opt/geckodriver /opt/geckodriver-$GK_VERSION \ - && chmod 755 /opt/geckodriver-$GK_VERSION \ - && ln -fs /opt/geckodriver-$GK_VERSION /usr/bin/geckodriver - -COPY requirements /home/artefactual/acceptance-tests/requirements/ -RUN pip3 install wheel \ - && pip3 install -r /home/artefactual/acceptance-tests/requirements/base.txt \ - && pip3 install -r /home/artefactual/acceptance-tests/requirements/test.txt -COPY . /home/artefactual/acceptance-tests +ENV PYENV_ROOT=${PYENV_DIR}/data +ENV PATH=$PYENV_ROOT/shims:$PYENV_ROOT/bin:${SELENIUM_DIR}/bin:$PATH + +# ----------------------------------------------------------------------------- + +FROM base AS browsers-builder + +ARG SELENIUM_DIR=/selenium + +RUN set -ex \ + && SELENIUM_CACHE=${SELENIUM_DIR}/cache \ + && SELENIUM_BIN=${SELENIUM_DIR}/bin \ + && mkdir -p $SELENIUM_CACHE $SELENIUM_BIN \ + && curl -o $SELENIUM_BIN/selenium-manager -L https://github.com/SeleniumHQ/selenium/raw/trunk/common/manager/linux/selenium-manager \ + && chmod +x $SELENIUM_BIN/selenium-manager \ + && CHROME_OUTPUT=$($SELENIUM_BIN/selenium-manager --cache-path $SELENIUM_CACHE --browser chrome --output JSON) \ + && FIREFOX_OUTPUT=$($SELENIUM_BIN/selenium-manager --cache-path $SELENIUM_CACHE --browser firefox --output JSON) \ + && ln -s $(echo $CHROME_OUTPUT | jq -r '.result.browser_path') $SELENIUM_BIN/google-chrome \ + && ln -s $(echo $CHROME_OUTPUT | jq -r '.result.driver_path') $SELENIUM_BIN/chromedriver \ + && ln -s $(echo $FIREFOX_OUTPUT | jq -r '.result.browser_path') $SELENIUM_BIN/firefox \ + && ln -s $(echo $FIREFOX_OUTPUT | jq -r '.result.driver_path') $SELENIUM_BIN/geckodriver + +# ----------------------------------------------------------------------------- + +FROM base AS pyenv-builder + +ARG PYTHON_VERSION=3.9 + +RUN set -ex \ + && apt-get -qqy update \ + && apt-get -qqy --no-install-recommends install \ + build-essential \ + libbz2-dev \ + libffi-dev \ + liblzma-dev \ + libncursesw5-dev \ + libreadline-dev \ + libsqlite3-dev \ + libssl-dev \ + libxml2-dev \ + libxmlsec1-dev \ + tk-dev \ + xz-utils \ + zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* /var/cache/apt/* + +RUN set -ex \ + && curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash \ + && pyenv install ${PYTHON_VERSION} \ + && pyenv global ${PYTHON_VERSION} + +COPY requirements-dev.txt requirements-dev.txt + +RUN set -ex \ + && pyenv exec python${PYTHON_VERSION} -m pip install --upgrade pip setuptools \ + && pyenv exec python${PYTHON_VERSION} -m pip install --requirement requirements-dev.txt \ + && pyenv rehash + +# ----------------------------------------------------------------------------- + +FROM base AS archivematica-acceptance-tests + +ARG USER_ID=1000 +ARG GROUP_ID=1000 + +RUN set -ex \ + && apt-get -qqy update \ + && apt-get -qqy --no-install-recommends install \ + bzip2 \ + gnupg \ + libasound2 \ + libdbus-glib-1-2 \ + libdrm2 \ + libgbm1 \ + libglib2.0-0 \ + libgtk-3-0 \ + libnss3 \ + libx11-xcb1 \ + libxcb1 \ + libxslt-dev \ + libxtst6 \ + openssh-client \ + p7zip-full \ + tzdata \ + unzip \ + && rm -rf /var/lib/apt/lists/* /var/cache/apt/* + +COPY --chown=${USER_ID}:${GROUP_ID} --from=browsers-builder --link /selenium /selenium +COPY --chown=${USER_ID}:${GROUP_ID} --from=pyenv-builder --link /pyenv /pyenv +COPY --chown=${USER_ID}:${GROUP_ID} --link . /home/artefactual/acceptance-tests + +RUN set -ex \ + && groupadd --gid ${GROUP_ID} artefactual \ + && useradd --uid ${USER_ID} --gid ${GROUP_ID} --create-home artefactual + WORKDIR /home/artefactual/acceptance-tests -RUN chown -R artefactual:artefactual /home/artefactual USER artefactual -ENV HOME /home/artefactual -ENV USER artefactual diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..a06623c6 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +.PHONY: pip-compile +pip-compile: # Compile pip requirements + pip-compile --allow-unsafe --output-file requirements.txt requirements.in + pip-compile --allow-unsafe --output-file requirements-dev.txt requirements-dev.in + +.PHONY: pip-upgrade +pip-upgrade: # Upgrade pip requirements + pip-compile --allow-unsafe --upgrade --output-file requirements.txt requirements.in + pip-compile --allow-unsafe --upgrade --output-file requirements-dev.txt requirements-dev.in + +.PHONY: pip-sync +pip-sync: # Sync virtualenv + pip-sync requirements.txt + +.PHONY: pip-sync-dev +pip-sync-dev: # Sync dev virtualenv + pip-sync requirements-dev.txt diff --git a/amuser/am_api_ability.py b/amuser/am_api_ability.py index a3053ce1..dc725b61 100644 --- a/amuser/am_api_ability.py +++ b/amuser/am_api_ability.py @@ -3,7 +3,6 @@ This module contains the ``ArchivematicaAPIAbility`` class, which represents a user's ability to use Archivematica's APIs to interact with Archivematica. """ - import logging import os import time @@ -31,8 +30,8 @@ def download_aip(self, transfer_name, sip_uuid, ss_api_key): ?username=&api_key= """ payload = {"username": self.ss_username, "api_key": ss_api_key} - url = "{}api/v2/file/{}/download/".format(self.ss_url, sip_uuid) - aip_name = "{}-{}.7z".format(transfer_name, sip_uuid) + url = f"{self.ss_url}api/v2/file/{sip_uuid}/download/" + aip_name = f"{transfer_name}-{sip_uuid}.7z" aip_path = os.path.join(self.tmp_path, aip_name) max_attempts = self.max_download_aip_attempts attempt = 0 @@ -62,9 +61,7 @@ def download_aip(self, transfer_name, sip_uuid, ss_api_key): r.status_code, r.text, ) - raise ArchivematicaAPIAbilityError( - "Unable to download AIP {}".format(sip_uuid) - ) + raise ArchivematicaAPIAbilityError(f"Unable to download AIP {sip_uuid}") def download_aip_pointer_file(self, sip_uuid, ss_api_key): """Use the AM SS API to download the completed AIP's pointer file. @@ -72,8 +69,8 @@ def download_aip_pointer_file(self, sip_uuid, ss_api_key): ?username=&api_key= """ payload = {"username": self.ss_username, "api_key": ss_api_key} - url = "{}api/v2/file/{}/pointer_file/".format(self.ss_url, sip_uuid) - pointer_file_name = "pointer.{}.xml".format(sip_uuid) + url = f"{self.ss_url}api/v2/file/{sip_uuid}/pointer_file/" + pointer_file_name = f"pointer.{sip_uuid}.xml" pointer_file_path = os.path.join(self.tmp_path, pointer_file_name) max_attempts = self.max_download_aip_attempts attempt = 0 @@ -105,7 +102,7 @@ def download_aip_pointer_file(self, sip_uuid, ss_api_key): r.text, ) raise ArchivematicaAPIAbilityError( - "Unable to download AIP {} pointer file".format(sip_uuid) + f"Unable to download AIP {sip_uuid} pointer file" ) def poll_until_aip_stored( @@ -113,7 +110,7 @@ def poll_until_aip_stored( ): max_polls = max_polls or self.max_check_aip_stored_attempts payload = {"username": self.ss_username, "api_key": ss_api_key} - url = "{}api/v2/file/{}/".format(self.ss_url, sip_uuid) + url = f"{self.ss_url}api/v2/file/{sip_uuid}/" counter = 0 while True: counter += 1 diff --git a/amuser/am_browser_ability.py b/amuser/am_browser_ability.py index c8d985f4..0a0c0b07 100644 --- a/amuser/am_browser_ability.py +++ b/amuser/am_browser_ability.py @@ -5,26 +5,24 @@ Archivematica. This class provides an interface to Selenium for opening browser windows and interacting with Archivematica's GUIs. """ - import logging import time import requests +from selenium.common.exceptions import ElementNotInteractableException +from selenium.common.exceptions import ElementNotVisibleException +from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.common.by import By -from selenium.common.exceptions import ( - ElementNotInteractableException, - ElementNotVisibleException, - NoSuchElementException, -) from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.support.ui import Select, WebDriverWait +from selenium.webdriver.support.ui import Select +from selenium.webdriver.support.ui import WebDriverWait -from . import constants as c -from . import base from . import am_browser_auth_ability as auth_abl -from . import am_browser_transfer_ingest_ability as tra_ing_abl -from . import am_browser_ss_ability as ss_abl from . import am_browser_preservation_planning_ability as pres_plan_abl +from . import am_browser_ss_ability as ss_abl +from . import am_browser_transfer_ingest_ability as tra_ing_abl +from . import base +from . import constants as c logger = logging.getLogger("amuser.browser") @@ -73,7 +71,7 @@ def assert_sip_arrange_pane_not_displayed(self): try: self.driver.find_element_by_css_selector(selector) except NoSuchElementException as exc: - assert "Unable to locate element: {}".format(selector) in str(exc) + assert f"Unable to locate element: {selector}" in str(exc) assert self.driver.find_element_by_css_selector("div#sip-container") # ========================================================================== @@ -150,9 +148,7 @@ def navigate_to_aip_in_archival_storage(self, aip_uuid): s.cookies.update({cookie["name"]: cookie["value"]}) while True: if attempt > max_attempts: - raise ArchivematicaBrowserAbilityError( - "Unable to navigate to {}".format(url) - ) + raise ArchivematicaBrowserAbilityError(f"Unable to navigate to {url}") r = s.get(url) if r.status_code == requests.codes.ok: logger.info( @@ -200,7 +196,7 @@ def initiate_reingest(self, aip_uuid, reingest_type="metadata-only"): alert_text = self.driver.find_element_by_css_selector( "div.alert-success" ).text.strip() - assert alert_text.startswith("Package {} sent to pipeline".format(aip_uuid)) + assert alert_text.startswith(f"Package {aip_uuid} sent to pipeline") assert alert_text.endswith("for re-ingest") # ========================================================================== diff --git a/amuser/am_browser_auth_ability.py b/amuser/am_browser_auth_ability.py index 730c9cc5..51a8a67f 100644 --- a/amuser/am_browser_auth_ability.py +++ b/amuser/am_browser_auth_ability.py @@ -1,11 +1,10 @@ """Archivematica Authentication Ability""" - import logging -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.common.by import By from selenium.common.exceptions import TimeoutException +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import WebDriverWait from . import selenium_ability diff --git a/amuser/am_browser_file_explorer_ability.py b/amuser/am_browser_file_explorer_ability.py index e975b1b1..d889b8ef 100644 --- a/amuser/am_browser_file_explorer_ability.py +++ b/amuser/am_browser_file_explorer_ability.py @@ -1,17 +1,14 @@ """Archivematica Browser File Explorer Ability""" - import logging import time -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.common.by import By -from selenium.common.exceptions import ( - MoveTargetOutOfBoundsException, - TimeoutException, - WebDriverException, -) +from selenium.common.exceptions import MoveTargetOutOfBoundsException +from selenium.common.exceptions import TimeoutException +from selenium.common.exceptions import WebDriverException from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import WebDriverWait from . import constants as c from . import selenium_ability @@ -89,7 +86,7 @@ def _navigate_to_transfer_directory_and_click(self, path): is_last = True folder_label_xpath = get_xpath_matches_folder_text(folder) if i == 0: - folder_label_xpath = "//{}".format(folder_label_xpath) + folder_label_xpath = f"//{folder_label_xpath}" xtrail.append(folder_label_xpath) # Now the XPath matches folder ONLY if it's in the directory it # should be, i.e., this is now an absolute XPath. @@ -123,7 +120,7 @@ def click_add_folder(self, folder_id): hover.perform() time.sleep(self.micro_wait) # seems to be necessary (! jQuery animations?) span_elem = self.driver.find_element_by_css_selector( - "div#{} span.{}".format(folder_id, c.CLASS_ADD_TRANSFER_FOLDER) + f"div#{folder_id} span.{c.CLASS_ADD_TRANSFER_FOLDER}" ) hover = ActionChains(self.driver).move_to_element(span_elem) hover.perform() @@ -160,7 +157,7 @@ def click_folder_label(self, folder_el, offset=0): ".transfer-tree-container" ) self.driver.execute_script( - "arguments[0].scrollTop = {}".format(offset), container_el + f"arguments[0].scrollTop = {offset}", container_el ) self.click_folder_label(folder_el, offset + 100) @@ -190,7 +187,7 @@ def click_folder(self, folder_label_xpath, is_file=False, offset=0): ".transfer-tree-container" ) self.driver.execute_script( - "arguments[0].scrollTop = {}".format(offset), container_el + f"arguments[0].scrollTop = {offset}", container_el ) self.click_folder(folder_label_xpath, is_file, offset + 100) @@ -211,7 +208,7 @@ def click_folder_old_browser(self, folder_id, is_file=False): if is_file: class_ = "backbone-file-explorer-directory_entry_name" folder_id = folder_id.replace(".", r"\.") - selector = "div#{} span.{}".format(folder_id, class_) + selector = f"div#{folder_id} span.{class_}" span_elem = self.driver.find_element_by_css_selector(selector) hover = ActionChains(self.driver).move_to_element(span_elem) hover.perform() @@ -223,7 +220,7 @@ def click_folder_old_browser(self, folder_id, is_file=False): return try: folder_contents_selector = ( - "div#{} + div.backbone-file-explorer-level".format(folder_id) + f"div#{folder_id} + div.backbone-file-explorer-level" ) block = WebDriverWait(self.driver, 10) block.until( @@ -267,4 +264,4 @@ def folder_label2icon_xpath(folder_label_xpath): def folder_label2children_xpath(folder_label_xpath): """Given XPATH for TS folder label, return XPATH for its children element.""" - return "{}/following-sibling::treeitem".format(folder_label_xpath) + return f"{folder_label_xpath}/following-sibling::treeitem" diff --git a/amuser/am_browser_ingest_ability.py b/amuser/am_browser_ingest_ability.py index 7c60af09..adb9fa4a 100644 --- a/amuser/am_browser_ingest_ability.py +++ b/amuser/am_browser_ingest_ability.py @@ -1,29 +1,23 @@ -# -*- coding: utf-8 -*- - """Archivematica Ingest Tab Ability""" - -import os import logging +import os import tempfile import time -from lxml import etree -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.common.by import By -from selenium.common.exceptions import ( - MoveTargetOutOfBoundsException, - NoSuchElementException, - TimeoutException, -) import tenacity - from amclient import AMClient +from lxml import etree +from selenium.common.exceptions import MoveTargetOutOfBoundsException +from selenium.common.exceptions import NoSuchElementException +from selenium.common.exceptions import TimeoutException +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import WebDriverWait from . import base from . import constants as c -from . import utils from . import selenium_ability +from . import utils class ArchivematicaBrowserMETSAbilityError(base.ArchivematicaUserError): @@ -72,9 +66,9 @@ def get_mets_via_api(self, transfer_name, sip_uuid=None, parse_xml=True): """Return METS once stored in an AIP.""" if not sip_uuid: sip_uuid = self.get_sip_uuid(transfer_name) - absolute_transfer_name = "{}-{}".format(transfer_name, sip_uuid) - mets_name = "METS.{}.xml".format(sip_uuid) - mets_path = "{}/data/{}".format(absolute_transfer_name, mets_name) + absolute_transfer_name = f"{transfer_name}-{sip_uuid}" + mets_name = f"METS.{sip_uuid}.xml" + mets_path = f"{absolute_transfer_name}/data/{mets_name}" mets_tmp_dir = tempfile.mkdtemp() mets_tmp_file = os.path.join(mets_tmp_dir, mets_name) AMClient( @@ -86,7 +80,7 @@ def get_mets_via_api(self, transfer_name, sip_uuid=None, parse_xml=True): saveas_filename=mets_tmp_file, ).extract_file() mets = "" - with open(mets_tmp_file, "r") as mets_file: + with open(mets_tmp_file) as mets_file: mets = mets_file.read() os.unlink(mets_tmp_file) if parse_xml: @@ -166,7 +160,7 @@ def _navigate_to_aip_directory_and_click(self, path): path = path[:-1] path_parts = path.split("/") if path_parts[-1].startswith("METS."): - path_parts[-1] = "METS__{}".format(path_parts[-1][5:]) + path_parts[-1] = f"METS__{path_parts[-1][5:]}" for i, folder in enumerate(path_parts): is_last = False if i == len(path_parts) - 1: @@ -185,13 +179,11 @@ def _navigate_to_aip_directory_and_click(self, path): def add_dummy_metadata(self, sip_uuid): self.navigate(self.get_ingest_url()) self.driver.find_element_by_id( - "sip-row-{}".format(sip_uuid) + f"sip-row-{sip_uuid}" ).find_element_by_css_selector("a.btn_show_metadata").click() self.navigate(self.get_metadata_add_url(sip_uuid)) for attr in self.metadata_attrs: - self.driver.find_element_by_id("id_{}".format(attr)).send_keys( - self.dummy_val - ) + self.driver.find_element_by_id(f"id_{attr}").send_keys(self.dummy_val) try: self.driver.find_element_by_css_selector("input[value=Create]").click() except NoSuchElementException: diff --git a/amuser/am_browser_jobs_tasks_ability.py b/amuser/am_browser_jobs_tasks_ability.py index 7edaeca7..c9de0ef7 100644 --- a/amuser/am_browser_jobs_tasks_ability.py +++ b/amuser/am_browser_jobs_tasks_ability.py @@ -1,5 +1,4 @@ """Archivematica Browser Jobs & Tasks Ability""" - import logging import sys import time @@ -7,8 +6,8 @@ from selenium.common.exceptions import NoSuchElementException from . import constants as c -from . import utils from . import selenium_ability +from . import utils logger = logging.getLogger("amuser.jobstasks") @@ -224,7 +223,7 @@ def process_task_header_row(row_elem, row_dict): line = line[1:] if line.endswith(")"): line = line[:-1] - attr, val = [x.strip() for x in line.split(":")] + attr, val = (x.strip() for x in line.split(":")) row_dict[attr.lower().replace(" ", "_")] = val return row_dict diff --git a/amuser/am_browser_preservation_planning_ability.py b/amuser/am_browser_preservation_planning_ability.py index 93d72627..9d969668 100644 --- a/amuser/am_browser_preservation_planning_ability.py +++ b/amuser/am_browser_preservation_planning_ability.py @@ -1,9 +1,8 @@ """Archivematica Browser Preservation Planning Ability""" - import logging -from selenium.webdriver.support.ui import Select from selenium.common.exceptions import NoSuchElementException +from selenium.webdriver.support.ui import Select from . import selenium_ability @@ -136,7 +135,7 @@ def get_policy_command(self, policy_file, policy_path): lines.append(line) lines += policy_lines elif line.strip() == "POLICY_NAME = ''": - lines.append("POLICY_NAME = '{}'".format(policy_file)) + lines.append(f"POLICY_NAME = '{policy_file}'") else: lines.append(line) return "\n".join(lines) @@ -252,4 +251,4 @@ def ensure_fpr_rule_enabled(self, purpose, format_, command_description): @staticmethod def get_policy_command_description(policy_file): - return "Check against policy {} using MediaConch".format(policy_file) + return f"Check against policy {policy_file} using MediaConch" diff --git a/amuser/am_browser_ss_ability.py b/amuser/am_browser_ss_ability.py index 100342da..bc35d73e 100644 --- a/amuser/am_browser_ss_ability.py +++ b/amuser/am_browser_ss_ability.py @@ -1,15 +1,14 @@ """Archivematica Browser Storage Service Ability""" - import logging import pprint import time -from selenium.webdriver.support.ui import Select from selenium.common.exceptions import NoSuchElementException +from selenium.webdriver.support.ui import Select -from . import utils from . import base from . import selenium_ability +from . import utils logger = logging.getLogger("amuser.ss") @@ -156,7 +155,7 @@ def create_ss_location(self, space_uuid, attributes): """ self.navigate(self.get_locations_create_url(space_uuid)) form_el = self.driver.find_element_by_css_selector( - 'form[action="/spaces/{}/location_create/"]'.format(space_uuid) + f'form[action="/spaces/{space_uuid}/location_create/"]' ) for p_el in form_el.find_elements_by_tag_name("p"): for el in p_el.find_elements_by_css_selector("*"): @@ -426,7 +425,7 @@ def disable_default_transfer_backlog(self): def create_new_gpg_key(self): """Create a new GPG key with a unique name.""" self.navigate(self.get_create_gpg_key_url()) - new_key_name = "GPGKey {}".format(utils.unixtimestamp()) + new_key_name = f"GPGKey {utils.unixtimestamp()}" new_key_email = "{}@example.com".format(new_key_name.lower().replace(" ", "")) self.driver.find_element_by_id("id_name_real").send_keys(new_key_name) self.driver.find_element_by_id("id_name_email").send_keys(new_key_email) diff --git a/amuser/am_browser_transfer_ability.py b/amuser/am_browser_transfer_ability.py index d5e76932..8f348dc7 100644 --- a/amuser/am_browser_transfer_ability.py +++ b/amuser/am_browser_transfer_ability.py @@ -1,14 +1,11 @@ """Archivematica Transfer Tab Ability""" - import logging import os import time +from selenium.common.exceptions import NoSuchElementException +from selenium.common.exceptions import StaleElementReferenceException from selenium.webdriver.support.ui import Select -from selenium.common.exceptions import ( - NoSuchElementException, - StaleElementReferenceException, -) from . import constants as c from . import selenium_ability @@ -207,7 +204,7 @@ def navigate_to_transfer_tab(self): self.login() self.driver.get(url) transfer_name_input_id = "transfer-browser-form" - self.wait_for_presence("#{}".format(transfer_name_input_id)) + self.wait_for_presence(f"#{transfer_name_input_id}") assert "Archivematica Dashboard - Transfer" in self.driver.title def enter_transfer_name(self, transfer_name): diff --git a/amuser/am_browser_transfer_ingest_ability.py b/amuser/am_browser_transfer_ingest_ability.py index 86bc96a1..6925bf89 100644 --- a/amuser/am_browser_transfer_ingest_ability.py +++ b/amuser/am_browser_transfer_ingest_ability.py @@ -1,19 +1,18 @@ """Archivematica Transfer & Ingest Tabs Ability""" - import logging import sys import time -from selenium.webdriver.support.ui import Select from selenium.common.exceptions import NoSuchElementException +from selenium.webdriver.support.ui import Select -from . import utils -from . import base -from . import selenium_ability -from . import am_browser_jobs_tasks_ability as jobs_tasks_abl from . import am_browser_file_explorer_ability as file_explorer_abl -from . import am_browser_transfer_ability as transfer_abl from . import am_browser_ingest_ability as ingest_abl +from . import am_browser_jobs_tasks_ability as jobs_tasks_abl +from . import am_browser_transfer_ability as transfer_abl +from . import base +from . import selenium_ability +from . import utils logger = logging.getLogger("amuser.transferingest") @@ -96,11 +95,11 @@ def make_choice(self, choice_text, decision_point, uuid_val, unit_type="transfer Select(select_el).select_by_index(index) else: raise ArchivematicaBrowserTransferIngestAbilityError( - 'Unable to select choice "{}"'.format(choice_text) + f'Unable to select choice "{choice_text}"' ) else: raise ArchivematicaBrowserTransferIngestAbilityError( - "Unable to find decision point {}".format(decision_point) + f"Unable to find decision point {decision_point}" ) def assert_no_option( @@ -113,7 +112,7 @@ def assert_no_option( try: self.make_choice(choice_text, decision_point, uuid_val, unit_type=unit_type) except ArchivematicaBrowserTransferIngestAbilityError as exc: - assert 'Unable to select choice "{}"'.format(choice_text) == str(exc) + assert f'Unable to select choice "{choice_text}"' == str(exc) else: raise AssertionError( 'We were able to select choice "{}" at decision point "{}" even' @@ -206,7 +205,7 @@ def get_transfer_micro_service_group_elem(self, group_name, transfer_uuid): with name ``group_name`` of the transfer with UUID ``transfer_uuid``. """ transfer_div_elem = None - transfer_dom_id = "sip-row-{}".format(transfer_uuid) + transfer_dom_id = f"sip-row-{transfer_uuid}" for elem in self.driver.find_elements_by_css_selector("div.sip"): try: elem.find_element_by_id(transfer_dom_id) @@ -217,9 +216,9 @@ def get_transfer_micro_service_group_elem(self, group_name, transfer_uuid): logger.warning("Unable to find Transfer %s.", transfer_uuid) return None if self.vn == "1.6": - expected_name = "Micro-service: {}".format(group_name) + expected_name = f"Micro-service: {group_name}" else: - expected_name = "Microservice: {}".format(group_name) + expected_name = f"Microservice: {group_name}" result = None for ms_group_elem in transfer_div_elem.find_elements_by_css_selector( "div.microservicegroup" diff --git a/amuser/am_docker_ability.py b/amuser/am_docker_ability.py index a120daa8..5fbb4baf 100644 --- a/amuser/am_docker_ability.py +++ b/amuser/am_docker_ability.py @@ -4,7 +4,6 @@ ability of an Archivematica user to use Docker to interact configure and deploy Archivematica. """ - import logging import os import shlex @@ -98,7 +97,7 @@ def _get_container_id(self, docker_container_name): raise return ( subprocess.check_output( - shlex.split("docker-compose ps -q {}".format(docker_container_name)), + shlex.split(f"docker-compose ps -q {docker_container_name}"), cwd=docker_compose_path, ) .decode("utf8") diff --git a/amuser/am_localfs_ability.py b/amuser/am_localfs_ability.py index eee646a2..66072bb8 100644 --- a/amuser/am_localfs_ability.py +++ b/amuser/am_localfs_ability.py @@ -3,7 +3,6 @@ This module contains the ``ArchivematicaLocalFSAbility`` class, which encodes the ability to transfer files when they're locally available. """ - import logging from . import base diff --git a/amuser/am_mets_ability.py b/amuser/am_mets_ability.py index a455907e..e78cbfef 100644 --- a/amuser/am_mets_ability.py +++ b/amuser/am_mets_ability.py @@ -3,7 +3,6 @@ This module contains the ``ArchivematicaMETSAbility`` class, which represents an Archivematica user's ability to interact with METS XML files. """ - import os from . import base @@ -81,7 +80,7 @@ def validate_mets_for_pids(mets_doc, accession_no=None): elif idfr_type == "hdl": assert utils.is_hdl( idfr, entity["type"], accession_no - ), "Identifier {} is not a hdl".format(idfr) + ), f"Identifier {idfr} is not a hdl" else: purls.append(idfr) assert utils.all_urls_resolve( @@ -108,15 +107,13 @@ def assert_empty_dir_documented_identified(mets_doc, empty_dir_rel_path): assert objects_div_el is not None xpath = [] for dir_ in empty_dir_rel_path.split("/"): - xpath.append("mets:div[@TYPE='Directory' and @LABEL='{}']".format(dir_)) + xpath.append(f"mets:div[@TYPE='Directory' and @LABEL='{dir_}']") xpath = "/".join(xpath) empty_dir_div_el = objects_div_el.xpath(xpath, namespaces=ns)[0] assert empty_dir_div_el is not None dmdid = empty_dir_div_el.get("DMDID") assert dmdid is not None - dmd_sec_el = mets_doc.xpath( - "mets:dmdSec[@ID='{}']".format(dmdid), namespaces=ns - )[0] + dmd_sec_el = mets_doc.xpath(f"mets:dmdSec[@ID='{dmdid}']", namespaces=ns)[0] assert dmd_sec_el is not None identifiers = [] for obj_idfr_el in dmd_sec_el.findall( @@ -148,7 +145,7 @@ def _add_entity_identifiers(entity, doc, ns): if e_id is None: return entity elif e_type == "file": - amd_sec_el = doc.xpath("mets:amdSec[@ID='{}']".format(e_id), namespaces=ns)[0] + amd_sec_el = doc.xpath(f"mets:amdSec[@ID='{e_id}']", namespaces=ns)[0] obj_idfr_els = amd_sec_el.findall( ".//mets:mdWrap/" "mets:xmlData/" @@ -164,7 +161,7 @@ def _add_entity_identifiers(entity, doc, ns): ) ) else: - dmd_sec_el = doc.xpath("mets:dmdSec[@ID='{}']".format(e_id), namespaces=ns)[0] + dmd_sec_el = doc.xpath(f"mets:dmdSec[@ID='{e_id}']", namespaces=ns)[0] for obj_idfr_el in dmd_sec_el.findall( "mets:mdWrap/mets:xmlData/premis:object/premis:objectIdentifier", ns ): @@ -212,9 +209,9 @@ def _get_mets_entities(doc, root_el=None, entities=None, path="", ns=None): for file_el in root_el.xpath("mets:div[@TYPE='Item']", namespaces=ns): file_name = file_el.get("LABEL") file_id = file_el.find("mets:fptr", ns).get("FILEID") - file_id = doc.xpath("//mets:file[@ID='{}']".format(file_id), namespaces=ns)[ - 0 - ].get("ADMID") + file_id = doc.xpath(f"//mets:file[@ID='{file_id}']", namespaces=ns)[0].get( + "ADMID" + ) entities.append( { "type": "file", diff --git a/amuser/am_ssh_ability.py b/amuser/am_ssh_ability.py index 4700bfee..a9c351ff 100644 --- a/amuser/am_ssh_ability.py +++ b/amuser/am_ssh_ability.py @@ -4,7 +4,6 @@ ability of an Archivematica user to use SSH and scp to interact with Archivematica. """ - import logging import os import shlex @@ -184,4 +183,4 @@ def assert_elasticsearch_not_installed(self): ) return None needle = "No such file or directory" - assert needle in out, 'We expected "{}" to be in "{}".'.format(needle, out) + assert needle in out, f'We expected "{needle}" to be in "{out}".' diff --git a/amuser/amuser.py b/amuser/amuser.py index 565cfb49..29cbde2a 100644 --- a/amuser/amuser.py +++ b/amuser/amuser.py @@ -3,7 +3,6 @@ This module contains the ``ArchivematicaUser`` class, which represents a user of Archivematica. """ - import logging import os import shlex @@ -13,8 +12,8 @@ from . import am_browser_ability from . import am_docker_ability from . import am_localfs_ability -from . import am_ssh_ability from . import am_mets_ability +from . import am_ssh_ability from . import base from . import constants as c @@ -62,9 +61,7 @@ def decompress_package(package_path): logger.info("7z is not installed; aborting decompression attempt") return False try: - subprocess.check_output( - ["7z", "x", package_path, "-o{}".format(c.TMP_DIR_NAME)] - ) + subprocess.check_output(["7z", "x", package_path, f"-o{c.TMP_DIR_NAME}"]) except subprocess.CalledProcessError: logger.info( "7z extraction failed. File %s is not a .7z file or it is encrypted", @@ -82,7 +79,7 @@ def decompress_aip(self, aip_path, cwd=None): devnull = open(os.devnull, "wb") aip_dir_name = get_aip_dir_name_from_archive(aip_path) aip_dir_path = os.path.join(aip_parent_dir_path, aip_dir_name) - cmd = shlex.split("7z x {} -aoa".format(aip_path)) + cmd = shlex.split(f"7z x {aip_path} -aoa") logger.info("Decompress AIP command: %s", cmd) logger.info("Decompress AIP cwd: %s", cwd) p = subprocess.Popen(cmd, cwd=cwd, stdout=devnull, stderr=subprocess.STDOUT) @@ -97,7 +94,7 @@ def decompress_aip(self, aip_path, cwd=None): def get_aip_dir_name_from_archive(aip_path): - cmd = shlex.split("7z l {}".format(aip_path)) + cmd = shlex.split(f"7z l {aip_path}") output = subprocess.check_output(cmd).decode("utf8") in_table = False paths = [] diff --git a/amuser/base.py b/amuser/base.py index bc3a273d..4fce63e0 100644 --- a/amuser/base.py +++ b/amuser/base.py @@ -1,6 +1,5 @@ """Base class for ArchivematicaUser and other related classes.""" # pylint: disable=too-many-instance-attributes - import os import re import shutil @@ -119,7 +118,7 @@ def __init__(self, **kwargs): @staticmethod def unique_name(name): - return "{}_{}".format(name, utils.unixtimestamp()) + return f"{name}_{utils.unixtimestamp()}" @property def permanent_path(self): diff --git a/amuser/constants.py b/amuser/constants.py index e773a097..1af04da6 100644 --- a/amuser/constants.py +++ b/amuser/constants.py @@ -67,7 +67,7 @@ def varvn(varname, vn): """ return globals().get( "{}_{}".format(varname, vn.replace(".", "_")), - globals().get(varname, "There is no var {}".format(varname)), + globals().get(varname, f"There is no var {varname}"), ) diff --git a/amuser/selenium_ability.py b/amuser/selenium_ability.py index 5342b0eb..9f678fab 100644 --- a/amuser/selenium_ability.py +++ b/amuser/selenium_ability.py @@ -1,19 +1,16 @@ """Selenium Ability""" - import logging import os from selenium import webdriver +from selenium.common.exceptions import StaleElementReferenceException +from selenium.common.exceptions import TimeoutException +from selenium.common.exceptions import WebDriverException +from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.common.by import By from selenium.webdriver.common.desired_capabilities import DesiredCapabilities -from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.common.by import By -from selenium.common.exceptions import ( - StaleElementReferenceException, - TimeoutException, - WebDriverException, -) -from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.support.ui import WebDriverWait from . import base diff --git a/amuser/urls.py b/amuser/urls.py index a2cd7f80..04f2b5bb 100644 --- a/amuser/urls.py +++ b/amuser/urls.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """URLS used across the AMAUAT suite plus getters to help retrieve those values consistently in tests. """ diff --git a/amuser/utils.py b/amuser/utils.py index 21330d75..e4ffe0ea 100644 --- a/amuser/utils.py +++ b/amuser/utils.py @@ -1,5 +1,4 @@ """Utilities for AM User.""" - import logging import time diff --git a/etc/docker/seccomp/chrome.json b/etc/docker/seccomp/chrome.json deleted file mode 100644 index e5b0f2d6..00000000 --- a/etc/docker/seccomp/chrome.json +++ /dev/null @@ -1,1535 +0,0 @@ -{ - "defaultAction": "SCMP_ACT_ERRNO", - "syscalls": [ - { - "name": "accept", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "accept4", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "access", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "alarm", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "arch_prctl", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "bind", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "brk", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "capget", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "capset", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "chdir", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "chmod", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "chown", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "chown32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "chroot", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "clock_getres", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "clock_gettime", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "clock_nanosleep", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "clone", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "close", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "connect", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "creat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "dup", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "dup2", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "dup3", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "epoll_create", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "epoll_create1", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "epoll_ctl", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "epoll_ctl_old", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "epoll_pwait", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "epoll_wait", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "epoll_wait_old", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "eventfd", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "eventfd2", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "execve", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "execveat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "exit", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "exit_group", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "faccessat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fadvise64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fadvise64_64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fallocate", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fanotify_init", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fanotify_mark", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fchdir", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fchmod", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fchmodat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fchown", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fchown32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fchownat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fcntl", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fcntl64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fdatasync", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fgetxattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "flistxattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "flock", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fork", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fremovexattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fsetxattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fstat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fstat64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fstatat64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fstatfs", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fstatfs64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "fsync", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "ftruncate", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "ftruncate64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "futex", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "futimesat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getcpu", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getcwd", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getdents", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getdents64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getegid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getegid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "geteuid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "geteuid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getgid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getgid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getgroups", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getgroups32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getitimer", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getpeername", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getpgid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getpgrp", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getpid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getppid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getpriority", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getrandom", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getresgid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getresgid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getresuid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getresuid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getrlimit", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "get_robust_list", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getrusage", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getsid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getsockname", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getsockopt", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "get_thread_area", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "gettid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "gettimeofday", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getuid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getuid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "getxattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "inotify_add_watch", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "inotify_init", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "inotify_init1", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "inotify_rm_watch", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "io_cancel", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "ioctl", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "io_destroy", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "io_getevents", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "ioprio_get", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "ioprio_set", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "io_setup", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "io_submit", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "kill", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "lchown", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "lchown32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "lgetxattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "link", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "linkat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "listen", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "listxattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "llistxattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "_llseek", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "lremovexattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "lseek", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "lsetxattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "lstat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "lstat64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "madvise", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "memfd_create", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mincore", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mkdir", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mkdirat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mknod", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mknodat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mlock", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mlockall", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mmap", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mmap2", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mprotect", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mq_getsetattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mq_notify", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mq_open", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mq_timedreceive", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mq_timedsend", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mq_unlink", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "mremap", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "msgctl", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "msgget", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "msgrcv", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "msgsnd", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "msync", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "munlock", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "munlockall", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "munmap", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "name_to_handle_at", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "nanosleep", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "newfstatat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "_newselect", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "open", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "open_by_handle_at", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "openat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "pause", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "pipe", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "pipe2", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "poll", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "ppoll", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "prctl", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "pread64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "preadv", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "prlimit64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "pselect6", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "pwrite64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "pwritev", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "read", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "readahead", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "readlink", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "readlinkat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "readv", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "recvfrom", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "recvmmsg", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "recvmsg", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "remap_file_pages", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "removexattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "rename", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "renameat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "renameat2", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "rmdir", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "rt_sigaction", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "rt_sigpending", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "rt_sigprocmask", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "rt_sigqueueinfo", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "rt_sigreturn", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "rt_sigsuspend", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "rt_sigtimedwait", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "rt_tgsigqueueinfo", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sched_getaffinity", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sched_getattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sched_getparam", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sched_get_priority_max", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sched_get_priority_min", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sched_getscheduler", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sched_rr_get_interval", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sched_setaffinity", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sched_setattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sched_setparam", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sched_setscheduler", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sched_yield", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "seccomp", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "select", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "semctl", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "semget", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "semop", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "semtimedop", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sendfile", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sendfile64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sendmmsg", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sendmsg", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sendto", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setdomainname", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setfsgid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setfsgid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setfsuid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setfsuid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setgid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setgid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setgroups", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setgroups32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sethostname", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setitimer", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setns", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setpgid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setpriority", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setregid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setregid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setresgid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setresgid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setresuid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setresuid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setreuid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setreuid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setrlimit", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "set_robust_list", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setsid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setsockopt", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "set_thread_area", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "set_tid_address", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setuid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setuid32", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "setxattr", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "shmat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "shmctl", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "shmdt", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "shmget", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "shutdown", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sigaltstack", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "signalfd", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "signalfd4", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "socket", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "socketpair", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "splice", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "stat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "stat64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "statfs", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "statfs64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "symlink", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "symlinkat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sync", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sync_file_range", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "syncfs", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "sysinfo", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "syslog", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "tee", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "tgkill", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "time", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "timer_create", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "timer_delete", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "timerfd_create", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "timerfd_gettime", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "timerfd_settime", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "timer_getoverrun", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "timer_gettime", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "timer_settime", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "times", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "tkill", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "truncate", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "truncate64", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "ugetrlimit", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "umask", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "uname", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "unlink", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "unlinkat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "unshare", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "utime", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "utimensat", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "utimes", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "vfork", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "vhangup", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "vmsplice", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "wait4", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "waitid", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "write", - "action": "SCMP_ACT_ALLOW", - "args": null - }, - { - "name": "writev", - "action": "SCMP_ACT_ALLOW", - "args": null - } - ] -} diff --git a/features/environment.py b/features/environment.py index b2330532..43cdddb1 100644 --- a/features/environment.py +++ b/features/environment.py @@ -1,19 +1,18 @@ import logging import os -import amuser -from amuser.constants import ( - NIHILISTIC_WAIT, - APATHETIC_WAIT, - PESSIMISTIC_WAIT, - MEDIUM_WAIT, - OPTIMISTIC_WAIT, - QUICK_WAIT, - MICRO_WAIT, - METS_NSMAP, -) import utils +import amuser +from amuser.constants import APATHETIC_WAIT +from amuser.constants import MEDIUM_WAIT +from amuser.constants import METS_NSMAP +from amuser.constants import MICRO_WAIT +from amuser.constants import NIHILISTIC_WAIT +from amuser.constants import OPTIMISTIC_WAIT +from amuser.constants import PESSIMISTIC_WAIT +from amuser.constants import QUICK_WAIT + class EnvironmentError(Exception): """Return this when there is a problem setting up the environment""" diff --git a/features/steps/aip_encryption_steps.py b/features/steps/aip_encryption_steps.py index 51e86222..44e75317 100644 --- a/features/steps/aip_encryption_steps.py +++ b/features/steps/aip_encryption_steps.py @@ -1,11 +1,13 @@ """Steps for the AIP Encryption Feature.""" - import logging import os import tarfile +from behave import given +from behave import then +from behave import use_step_matcher +from behave import when from lxml import etree -from behave import when, then, given, use_step_matcher from features.steps import utils @@ -164,7 +166,7 @@ def step_impl(context): "GnuPG Private Key": "Archivematica Storage Service GPG Key", } )["uuid"] - new_key_repr = "{} <{}>".format(new_key_name, new_key_email) + new_key_repr = f"{new_key_name} <{new_key_email}>" logger.info('Created a new GPG key "%s"', new_key_repr) context.am_user.browser.change_encrypted_space_key( standard_encr_space_uuid, new_key_repr @@ -257,17 +259,15 @@ def step_impl(context): replica = not_the_aips[0] replica_uuid = replica["uuid"] assert replica["replica_of"] == the_aip["uuid"] - expected_replica_actions = set(["Pointer File", "Download", "Request Deletion"]) - replica_actions = set([x.strip() for x in replica["actions"].split("|")]) + expected_replica_actions = {"Pointer File", "Download", "Request Deletion"} + replica_actions = {x.strip() for x in replica["actions"].split("|")} assert ( replica_actions == expected_replica_actions ), "We expected the replica actions to be {} but in fact they were {}".format( expected_replica_actions, replica_actions ) - expected_aip_actions = set( - ["Pointer File", "Download", "Request Deletion", "Re-ingest"] - ) - aip_actions = set([x.strip() for x in the_aip["actions"].split("|")]) + expected_aip_actions = {"Pointer File", "Download", "Request Deletion", "Re-ingest"} + aip_actions = {x.strip() for x in the_aip["actions"].split("|")} assert ( aip_actions == expected_aip_actions ), "We expected the AIP actions to be {} but in fact they were {}".format( @@ -571,7 +571,7 @@ def step_impl(context, reason): assert context.scenario.delete_gpg_key_msg.startswith("GPG key") assert context.scenario.delete_gpg_key_msg.endswith( "cannot be deleted because at least one package (AIP, transfer) needs it in order to be decrypted." - ), "Reason is actually {}".format(context.scenario.delete_gpg_key_msg) + ), f"Reason is actually {context.scenario.delete_gpg_key_msg}" @then("the user succeeds in deleting the GPG key") diff --git a/features/steps/black_box_steps.py b/features/steps/black_box_steps.py index e6deb51e..22d04517 100644 --- a/features/steps/black_box_steps.py +++ b/features/steps/black_box_steps.py @@ -1,18 +1,17 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- - """Steps for the black_box features. These steps use the AM APIs to initiate transfers and validate the contents of their AIPs without relying on user interface interactions. """ - -from __future__ import print_function, unicode_literals import os -from behave import given, when, then, use_step_matcher -from lxml import etree import metsrw +from behave import given +from behave import then +from behave import use_step_matcher +from behave import when +from lxml import etree from features.steps import utils @@ -315,7 +314,7 @@ def step_impl(context): file_uuid = filesec_file.attrib["ID"].split("file-")[-1] amdsec_id = filesec_file.attrib["ADMID"] amdsec = tree.find( - 'mets:amdSec[@ID="{}"]'.format(amdsec_id), namespaces=context.mets_nsmap + f'mets:amdSec[@ID="{amdsec_id}"]', namespaces=context.mets_nsmap ) object_uuid = amdsec.xpath( "mets:techMD/mets:mdWrap/mets:xmlData/premis:object/" @@ -334,7 +333,7 @@ def step_impl(context): for filesec_file in filesec_files: amdsec_id = filesec_file.attrib["ADMID"] amdsec = tree.find( - 'mets:amdSec[@ID="{}"]'.format(amdsec_id), namespaces=context.mets_nsmap + f'mets:amdSec[@ID="{amdsec_id}"]', namespaces=context.mets_nsmap ) assert amdsec is not None @@ -344,9 +343,11 @@ def step_impl(context): "user, the organization and the software as PREMIS agents" ) def step_impl(context): - expected_agent_types = set( - ["Archivematica user pk", "repository code", "preservation system"] - ) + expected_agent_types = { + "Archivematica user pk", + "repository code", + "preservation system", + } tree = etree.parse(context.current_transfer["aip_mets_location"]) premis_events = tree.findall( 'mets:amdSec/mets:digiprovMD/mets:mdWrap[@MDTYPE="PREMIS:EVENT"]/' @@ -361,14 +362,12 @@ def step_impl(context): event_agents = event.findall( "premis:linkingAgentIdentifier", namespaces=context.mets_nsmap ) - event_agent_types = set( - [ - event_agent.findtext( - "premis:linkingAgentIdentifierType", namespaces=context.mets_nsmap - ) - for event_agent in event_agents - ] - ) + event_agent_types = { + event_agent.findtext( + "premis:linkingAgentIdentifierType", namespaces=context.mets_nsmap + ) + for event_agent in event_agents + } assert event_agent_types == expected_agent_types @@ -456,7 +455,7 @@ def step_impl(context): assert original_files, format_original_files_error(context.current_transfer) for fsentry in original_files: techmds = mets.tree.findall( - 'mets:amdSec[@ID="{}"]/mets:techMD'.format(fsentry.admids[0]), + f'mets:amdSec[@ID="{fsentry.admids[0]}"]/mets:techMD', namespaces=context.mets_nsmap, ) techmds_status = sorted([techmd.attrib["STATUS"] for techmd in techmds]) @@ -781,19 +780,17 @@ def step_impl(context): def step_impl(context): mets = metsrw.METSDocument.fromfile(context.current_transfer["aip_mets_location"]) # get the UUID of each 'original' file - original_file_uuids = set( - [fsentry.file_uuid for fsentry in mets.all_files() if fsentry.use == "original"] - ) + original_file_uuids = { + fsentry.file_uuid for fsentry in mets.all_files() if fsentry.use == "original" + } assert original_file_uuids, format_original_files_error(context.current_transfer) # verify each file UUID has a matching entry in the objects directory of the DIP - dip_file_uuids = set( - [ - f[:36] - for f in os.listdir( - os.path.join(context.current_transfer["extracted_dip_dir"], "objects") - ) - ] - ) + dip_file_uuids = { + f[:36] + for f in os.listdir( + os.path.join(context.current_transfer["extracted_dip_dir"], "objects") + ) + } error = "The DIP at {} does not contain access copies for all the original files of the {} AIP".format( context.current_transfer["extracted_dip_dir"], context.current_transfer["sip_uuid"], @@ -864,7 +861,7 @@ def step_impl(context): q_name = etree.QName(child.tag) ns = q_name.namespace localname = q_name.localname - csv_field = "{}.{}".format(namespaces_by_url[ns], localname) + csv_field = f"{namespaces_by_url[ns]}.{localname}" if row.get(csv_field) != child.text.strip(): errors.append( content_error_template.format(expected_dmdsec_status[-1], csv_field) @@ -1000,7 +997,7 @@ def step_impl(context): if row_errors: errors.extend(row_errors) continue - group_ids = set([dmdsec.group_id for dmdsec in dmdsecs_by_status.values()]) + group_ids = {dmdsec.group_id for dmdsec in dmdsecs_by_status.values()} if len(group_ids) != 1: errors.append( 'Expected the {} dmdSecs for filename "{}" to have the same ' diff --git a/features/steps/capture_output_steps.py b/features/steps/capture_output_steps.py index 3a1966e2..c9766316 100644 --- a/features/steps/capture_output_steps.py +++ b/features/steps/capture_output_steps.py @@ -1,8 +1,9 @@ """Steps for the Capture Output Setting Feature.""" - import logging -from behave import when, then, given +from behave import given +from behave import then +from behave import when logger = logging.getLogger("amauat.steps.captureoutput") diff --git a/features/steps/cca_dip_steps.py b/features/steps/cca_dip_steps.py index 36efc247..80ac9907 100644 --- a/features/steps/cca_dip_steps.py +++ b/features/steps/cca_dip_steps.py @@ -1,5 +1,4 @@ """Steps for the CCA DIP Feature.""" - import csv import logging import os @@ -7,7 +6,9 @@ import time import zipfile -from behave import when, then, given +from behave import given +from behave import then +from behave import when logger = logging.getLogger("amauat.steps.ccadip") @@ -68,14 +69,14 @@ def step_impl(context): " original Transfer name appended with the AIP UUID and “_DIP”" ) def step_impl(context): - dip_name = "{}_{}_DIP".format(context.transfer_name, context.aip_uuid) + dip_name = f"{context.transfer_name}_{context.aip_uuid}_DIP" context.dip_path = os.path.join(context.output_dir, dip_name) assert os.path.exists(context.dip_path) @then("the DIP METS XML file that describes the contents of the DIP") def step_impl(context): - mets_filename = "METS.{}.xml".format(context.aip_uuid) + mets_filename = f"METS.{context.aip_uuid}.xml" context.mets_path = os.path.join(context.dip_path, mets_filename) assert os.path.exists(context.mets_path) @@ -86,9 +87,7 @@ def step_impl(context): ) def step_impl(context): objects_path = os.path.join(context.dip_path, "objects") - context.zip_path = os.path.join( - objects_path, "{}.zip".format(context.transfer_name) - ) + context.zip_path = os.path.join(objects_path, f"{context.transfer_name}.zip") assert os.path.exists(context.zip_path) @@ -117,7 +116,7 @@ def step_impl(context): # Ignore main folder, METS, submissionDocumentation and directories if ( not filename - or filename == "METS.{}.xml".format(context.aip_uuid) + or filename == f"METS.{context.aip_uuid}.xml" or filename.startswith("submissionDocumentation") or filename.endswith("/") ): @@ -143,14 +142,14 @@ def step_impl(context): "the DIP zip file includes a copy of the submissionDocumentation from the original Transfer" ) def step_impl(context): - sub_folder = "{}/submissionDocumentation/".format(context.transfer_name) + sub_folder = f"{context.transfer_name}/submissionDocumentation/" with zipfile.ZipFile(context.zip_path, "r") as zip_file: assert sub_folder in zip_file.namelist() @then("a copy of the AIP METS file generated during ingest") def step_impl(context): - mets_filename = "{}/METS.{}.xml".format(context.transfer_name, context.aip_uuid) + mets_filename = f"{context.transfer_name}/METS.{context.aip_uuid}.xml" with zipfile.ZipFile(context.zip_path, "r") as zip_file: assert mets_filename in zip_file.namelist() diff --git a/features/steps/indexless_steps.py b/features/steps/indexless_steps.py index c7eab28c..9c35af91 100644 --- a/features/steps/indexless_steps.py +++ b/features/steps/indexless_steps.py @@ -1,10 +1,11 @@ """Steps for the Indexless ("No Elasticsearch") Feature.""" - import logging import os import re -from behave import when, then, given +from behave import given +from behave import then +from behave import when from lxml import etree from features.steps import utils @@ -264,10 +265,10 @@ def step_impl(context): indexless_uuid = os.path.basename(indexless_aip_path.rstrip("/")).split("-", 1)[1] indexed_uuid = os.path.basename(indexed_aip_path.rstrip("/")).split("-", 1)[1] indexless_mets_path = os.path.join( - indexless_aip_path, "data", "METS.{}.xml".format(indexless_uuid) + indexless_aip_path, "data", f"METS.{indexless_uuid}.xml" ) indexed_mets_path = os.path.join( - indexed_aip_path, "data", "METS.{}.xml".format(indexed_uuid) + indexed_aip_path, "data", f"METS.{indexed_uuid}.xml" ) assert os.path.isfile(indexless_mets_path), "{} is not a file".format( indexless_mets_path @@ -297,7 +298,7 @@ def step_impl(context, tab_name): def step_impl(context, tab_name): tab_name = tab_name.replace(" tab", "").strip().lower() msg1 = "Elasticsearch Indexing Disabled" - msg2 = "The {} tab is non-functional".format(tab_name) + msg2 = f"The {tab_name} tab is non-functional" page_text = context.am_user.browser.driver.find_element_by_tag_name("body").text assert msg1 in page_text assert msg2 in page_text diff --git a/features/steps/infinite_aips.py b/features/steps/infinite_aips.py index ef79a3ff..7dbc554c 100644 --- a/features/steps/infinite_aips.py +++ b/features/steps/infinite_aips.py @@ -1,5 +1,4 @@ """Infinite AIPs Steps.""" - import logging import os @@ -22,9 +21,7 @@ def step_impl(context): transfer_path = context.am_user.runtime_supplied_transfer_path if not transfer_path: transfer_path = os.path.join("TestTransfers", "small") - context.execute_steps( - "When a transfer is initiated on directory {}".format(transfer_path) - ) + context.execute_steps(f"When a transfer is initiated on directory {transfer_path}") @when("the user creates the same AIP all over again") diff --git a/features/steps/manual_normalization_steps.py b/features/steps/manual_normalization_steps.py index 5fa500d3..c5ed86e3 100644 --- a/features/steps/manual_normalization_steps.py +++ b/features/steps/manual_normalization_steps.py @@ -1,8 +1,8 @@ """Steps for the Manual Normalization Feature.""" - import logging -from behave import then, given +from behave import given +from behave import then logger = logging.getLogger("amauat.steps.manualnormalization") diff --git a/features/steps/mediaconch_steps.py b/features/steps/mediaconch_steps.py index aead03d7..5d0da4f0 100644 --- a/features/steps/mediaconch_steps.py +++ b/features/steps/mediaconch_steps.py @@ -1,9 +1,10 @@ """Steps for the MediaConch-related Features.""" - import logging import os -from behave import when, then, given +from behave import given +from behave import then +from behave import when from lxml import etree from features.steps import utils @@ -211,7 +212,7 @@ def step_impl(context): for format_ in formats: context.am_user.browser.ensure_fpr_rule_enabled( "Preservation", - "Video:{}:{}".format(format_, format_), + f"Video:{format_}:{format_}", "Transcoding to mkv with ffmpeg", ) @@ -376,7 +377,7 @@ def step_impl(context, policy_file): for x in [os.path.join(aip_policy_outputs_path, y) for y in contents] if os.path.isfile(x) and os.path.splitext(x)[1] == ".xml" ] - assert file_paths, "There are no files in dir {}!".format(aip_policy_outputs_path) + assert file_paths, f"There are no files in dir {aip_policy_outputs_path}!" for fp in file_paths: with open(fp) as f: doc = etree.parse(f) @@ -406,7 +407,7 @@ def step_impl(context, policy_file): for x in [os.path.join(aip_policy_outputs_path, y) for y in contents] if os.path.isfile(x) and os.path.splitext(x)[1] == ".xml" ] - assert file_paths, "There are no files in dir {}!".format(aip_policy_outputs_path) + assert file_paths, f"There are no files in dir {aip_policy_outputs_path}!" for fp in file_paths: with open(fp) as f: doc = etree.parse(f) diff --git a/features/steps/mets_steps.py b/features/steps/mets_steps.py index 53f074ae..1ddfda38 100644 --- a/features/steps/mets_steps.py +++ b/features/steps/mets_steps.py @@ -1,5 +1,4 @@ """Steps for the METS-related functionality.""" - import json from behave import then @@ -108,8 +107,6 @@ def step_impl(context): ) assert dublincore_el for attr in context.am_user.browser.metadata_attrs: - dc_el = dublincore_el.find( - "dc:{}".format(attr), context.am_user.mets.mets_nsmap - ) + dc_el = dublincore_el.find(f"dc:{attr}", context.am_user.mets.mets_nsmap) assert dc_el is not None assert dc_el.text == context.am_user.browser.dummy_val diff --git a/features/steps/performance_stdout_no_write_steps.py b/features/steps/performance_stdout_no_write_steps.py index bbfd410e..0fcecd16 100644 --- a/features/steps/performance_stdout_no_write_steps.py +++ b/features/steps/performance_stdout_no_write_steps.py @@ -1,13 +1,14 @@ """Steps for the Performance Testing When Output Streams Not Captured Test/Feature. """ - import json import logging import os import time -from behave import when, then, given +from behave import given +from behave import then +from behave import when from lxml import etree from features.steps import utils @@ -64,7 +65,7 @@ def step_impl(context, filename): ).decode("utf8"), "tasks": context.am_user.docker.get_tasks_from_sip_uuid(sip_uuid), } - filename = "{}-{}.json".format(filename, int(time.time())) + filename = f"{filename}-{int(time.time())}.json" path = os.path.join(context.am_user.permanent_path, filename) with open(path, "w") as fout: json.dump(data, fout, indent=4) @@ -128,10 +129,10 @@ def step_impl(context, verb): path = context.scenario.performance_stats_path with open(path) as fi: stats = json.load(fi) - std_out_len_set = set([x["len_std_out"] for x in stats["tasks"]]) - std_err_len_set = set( - [x["len_std_err"] for x in stats["tasks"] if x["exitCode"].strip() == "0"] - ) + std_out_len_set = {x["len_std_out"] for x in stats["tasks"]} + std_err_len_set = { + x["len_std_err"] for x in stats["tasks"] if x["exitCode"].strip() == "0" + } if verb == "are": assert len(std_out_len_set) > 1 assert len(std_err_len_set) > 1 diff --git a/features/steps/pid_binding_steps.py b/features/steps/pid_binding_steps.py index 474ed1f9..9a1da0c4 100644 --- a/features/steps/pid_binding_steps.py +++ b/features/steps/pid_binding_steps.py @@ -1,6 +1,6 @@ """Steps for the Bind PIDs Feature.""" - -from behave import then, given +from behave import given +from behave import then from features.steps import utils diff --git a/features/steps/steps.py b/features/steps/steps.py index 01054f55..a8440860 100644 --- a/features/steps/steps.py +++ b/features/steps/steps.py @@ -1,10 +1,12 @@ """General-purpose Steps.""" - import logging import os import time -from behave import when, then, given, use_step_matcher +from behave import given +from behave import then +from behave import use_step_matcher +from behave import when from features.steps import utils @@ -106,9 +108,7 @@ def step_impl(context): @given("a transfer is initiated on directory {transfer_path}") def step_impl(context, transfer_path): - context.execute_steps( - "When a transfer is initiated on directory {}".format(transfer_path) - ) + context.execute_steps(f"When a transfer is initiated on directory {transfer_path}") @given( diff --git a/features/steps/utils.py b/features/steps/utils.py index f293d3c1..a18c9bd4 100644 --- a/features/steps/utils.py +++ b/features/steps/utils.py @@ -1,5 +1,4 @@ """Utilities for Steps files.""" - import csv import datetime import logging @@ -10,9 +9,9 @@ import time import zipfile -from amclient.amclient import AMClient import environment import tenacity +from amclient.amclient import AMClient from environment import AM_API_CONFIG_KEY from environment import SS_API_CONFIG_KEY from lxml import etree @@ -86,7 +85,7 @@ def aip_descr_to_ptr_attr(aip_description): def get_event_attr(event_type): - return "{}_event_uuid".format(event_type) + return f"{event_type}_event_uuid" def get_mets_from_scenario(context, api=False): @@ -172,7 +171,7 @@ def assert_premis_properties(event, context, properties): elif relation == "regex": assert re.search( value, desc_el.text.strip() - ), "{} does not contain regex {}".format(desc_el.text.strip(), value) + ), f"{desc_el.text.strip()} does not contain regex {value}" def initiate_transfer(context, transfer_path, accession_no=None, transfer_type=None): @@ -243,7 +242,7 @@ def remove_common_prefix(seq): strings. """ try: - prefixes = set([x[0] for x in seq]) + prefixes = {x[0] for x in seq} except IndexError: return seq if len(prefixes) == 1: @@ -338,7 +337,7 @@ def call_api_endpoint( endpoint, endpoint_args=[], warning_message=None, error_message=None, max_attempts=3 ): if warning_message is None: - warning_message = "Got invalid response from {}. Retrying".format(endpoint) + warning_message = f"Got invalid response from {endpoint}. Retrying" if error_message is None: error_message = ( "Could not get a valid response from {}" @@ -423,7 +422,7 @@ def start_transfer( ): """Start a transfer using the create_package endpoint and return its uuid""" if transfer_name is None: - transfer_name = "amauat-transfer_{}".format(int(time.time())) + transfer_name = f"amauat-transfer_{int(time.time())}" am = configure_am_client(api_clients_config[AM_API_CONFIG_KEY]) am.transfer_source = return_default_ts_location(api_clients_config) am.transfer_directory = transfer_path @@ -517,7 +516,7 @@ def check_unit_status(api_clients_config, unit_uuid, unit="transfer"): am.transfer_uuid = unit_uuid am.sip_uuid = unit_uuid return call_api_endpoint( - endpoint=getattr(am, "get_{}_status".format(unit)), + endpoint=getattr(am, f"get_{unit}_status"), warning_message="Cannot check unit status", error_message="Cannot check unit status", ) @@ -542,12 +541,12 @@ def get_aip_file_location(extracted_aip_dir, relative_path): def get_aip_mets_location(extracted_aip_dir, sip_uuid): - path = os.path.join("data", "METS.{}.xml".format(sip_uuid)) + path = os.path.join("data", f"METS.{sip_uuid}.xml") return get_aip_file_location(extracted_aip_dir, path) def get_dip_mets_location(extracted_dip_dir, sip_uuid): - return os.path.join(extracted_dip_dir, "METS.{}.xml".format(sip_uuid)) + return os.path.join(extracted_dip_dir, f"METS.{sip_uuid}.xml") def _automation_tools_extract_package( @@ -561,7 +560,7 @@ def _automation_tools_extract_package( :param str lookup_uuid: UUID to look for inside the extraction directory :returns: absolute path to the extracted package folder """ - command = ["7z", "x", "-bd", "-y", "-o{0}".format(tmp_dir), package_file] + command = ["7z", "x", "-bd", "-y", f"-o{tmp_dir}", package_file] try: subprocess.check_output(command, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: @@ -611,7 +610,7 @@ def get_premis_events_by_type(entry, event_type): def get_transfer_dir_from_structmap(tree, transfer_name, sip_uuid, nsmap): structmap = tree.find('mets:structMap[@TYPE="physical"]', namespaces=nsmap) return structmap.find( - 'mets:div[@LABEL="{}-{}"][@TYPE="Directory"]'.format(transfer_name, sip_uuid), + f'mets:div[@LABEL="{transfer_name}-{sip_uuid}"][@TYPE="Directory"]', namespaces=nsmap, ) @@ -670,8 +669,8 @@ def assert_structmap_item_path_exists(item, root_path, parent_path=""): def is_valid_download(path): errors = { "path": "Path returned is None", - "validate": "Cannot validate {} as file".format(path), - "size": "File {} has not downloaded correctly".format(path), + "validate": f"Cannot validate {path} as file", + "size": f"File {path} has not downloaded correctly", } assert path, errors["path"] assert os.path.isfile(path), errors["validate"] @@ -694,16 +693,16 @@ def retrieve_rights_linking_object_identifiers(tree, nsmap): "mets:amdSec/mets:rightsMD/mets:mdWrap/mets:xmlData/premis:rightsStatement/premis:linkingObjectIdentifier/premis:linkingObjectIdentifierValue", namespaces=nsmap, ) - return set([id_.text for id_ in rights_objects]) + return {id_.text for id_ in rights_objects} def get_filesec_files(tree, use=None, nsmap={}): use_query = "" # an empty use parameter will retrieve all the files in the fileSec if use: - use_query = '="{}"'.format(use) + use_query = f'="{use}"' return tree.findall( - "mets:fileSec/mets:fileGrp[@USE{}]/mets:file".format(use_query), + f"mets:fileSec/mets:fileGrp[@USE{use_query}]/mets:file", namespaces=nsmap, ) @@ -718,7 +717,7 @@ def start_sample_transfer( transfer_path = os.path.join(environment.sample_data_path, sample_transfer_path) if not browse_default_ts_location(api_clients_config, transfer_path): raise environment.EnvironmentError( - "Location {} cannot be verified".format(transfer_path) + f"Location {transfer_path} cannot be verified" ) try: start_result = start_transfer( @@ -732,7 +731,7 @@ def start_sample_transfer( result["transfer_path"] = transfer_path return result except environment.EnvironmentError as err: - assert False, "Error starting transfer: {}".format(err) + assert False, f"Error starting transfer: {err}" def wait_for_transfer(api_clients_config, transfer_uuid): @@ -830,7 +829,7 @@ def create_reingest(api_clients_config, transfer, reingest_type, processing_conf processing_config, ) except environment.EnvironmentError as err: - assert False, "Error starting reingest: {}".format(err) + assert False, f"Error starting reingest: {err}" else: return { "reingest_uuid": reingest_uuid, @@ -897,7 +896,7 @@ def assert_jobs_completed_successfully( job_link_uuid=job_link_uuid, job_microservice=job_microservice, ) - assert len(jobs), "No jobs found for unit {}".format(unit_uuid) + assert len(jobs), f"No jobs found for unit {unit_uuid}" for job in jobs: job_error = "Job '{} ({})' of unit '{}' does not have a COMPLETE status".format( job["name"], job["uuid"], unit_uuid @@ -929,7 +928,7 @@ def assert_jobs_fail( job_link_uuid=job_link_uuid, job_microservice=job_microservice, ) - assert len(jobs), "No jobs found for unit {}".format(unit_uuid) + assert len(jobs), f"No jobs found for unit {unit_uuid}" for job in jobs: job_error = "Job '{} ({})' of unit '{}' does not have a FAILED status or one of its tasks has an invalid exit code ({})".format( job["name"], job["uuid"], unit_uuid, ", ".join(map(str, valid_exit_codes)) @@ -958,12 +957,12 @@ def assert_source_md_in_bagit_mets(mets_root, mets_nsmap): assert source_md_elem, "sourceMD cannot be found, sourceMD is None" assert ( len(source_md_elem) is EXPECTED_SOURCE_MD_ELEMS - ), "sourceMD count is incorrect: {}".format(len(source_md_elem)) + ), f"sourceMD count is incorrect: {len(source_md_elem)}" md_wrap_elems = source_md_elem[0].xpath("mets:mdWrap", namespaces=mets_nsmap) # Assert the metadata type is associated with BagIt. assert md_wrap_elems md_type = md_wrap_elems[0].attrib["OTHERMDTYPE"] - assert md_type == BAGITMDTYPE, "Metadata type is incorrect: {}".format(md_type) + assert md_type == BAGITMDTYPE, f"Metadata type is incorrect: {md_type}" # Assert there is a transfer metadata snippet, and it's not empty. transfer_md = md_wrap_elems[0].xpath( "mets:xmlData/transfer_metadata", namespaces=mets_nsmap @@ -1034,7 +1033,7 @@ def get_metadata_csv_files(transfer_name, transfer_uuid, extracted_aip_dir): "objects", "metadata", "transfers", - "{}-{}".format(transfer_name, transfer_uuid), + f"{transfer_name}-{transfer_uuid}", filename, ) if not os.path.exists(csv_path): @@ -1077,7 +1076,7 @@ def get_source_metadata(transfer_name, transfer_uuid, extracted_aip_dir): "objects", "metadata", "transfers", - "{}-{}".format(transfer_name, transfer_uuid), + f"{transfer_name}-{transfer_uuid}", filename, ) if not os.path.exists(csv_path): @@ -1191,7 +1190,7 @@ def find_aip_by_transfer_metadata( # Set search term phrase browser.driver.find_elements_by_css_selector('input[title="search query"]')[ -1 - ].send_keys('"{}"'.format(search_phrase)) + ].send_keys(f'"{search_phrase}"') Select( browser.driver.find_elements_by_css_selector('select[title="field name"]')[-1] ).select_by_visible_text("Transfer metadata") diff --git a/features/steps/uuids_for_directories_steps.py b/features/steps/uuids_for_directories_steps.py index 09b178b8..e383e4c6 100644 --- a/features/steps/uuids_for_directories_steps.py +++ b/features/steps/uuids_for_directories_steps.py @@ -1,10 +1,10 @@ """Steps for the UUIDs for the Direcotries Feature.""" - import logging import os import pprint -from behave import then, given +from behave import given +from behave import then from lxml import etree from features.steps import utils @@ -30,7 +30,7 @@ def step_impl(context, dir_path): record the directory structure in ``context``. """ if dir_path.startswith("~/"): - dir_path = "/home/{}/{}".format(context.HOME, dir_path[2:]) + dir_path = f"/home/{context.HOME}/{dir_path[2:]}" dir_is_zipped = bool(os.path.splitext(dir_path)[1]) if dir_is_zipped: @@ -168,7 +168,7 @@ def step_impl(context): struct_map_el = mets.find(xpath, ns) assert ( struct_map_el is not None - ), "We expected to find a {}-type structMap but did not".format(type_) + ), f"We expected to find a {type_}-type structMap but did not" subpaths = utils.get_subpaths_from_struct_map(struct_map_el, ns) subpaths = [ p.replace("/objects", "", 1) @@ -220,9 +220,7 @@ def step_impl(context): ): continue dirname = os.path.basename(dirpath) - mets_div_el = struct_map_el.find( - './/mets:div[@LABEL="{}"]'.format(dirname), ns - ) + mets_div_el = struct_map_el.find(f'.//mets:div[@LABEL="{dirname}"]', ns) assert ( mets_div_el is not None ), "Could not find a for directory at {} in {}-type structmap".format( @@ -234,7 +232,7 @@ def step_impl(context): ): continue dmdid = mets_div_el.get("DMDID") - dmdSec_el = mets.find('.//mets:dmdSec[@ID="{}"]'.format(dmdid), ns) + dmdSec_el = mets.find(f'.//mets:dmdSec[@ID="{dmdid}"]', ns) assert ( dmdSec_el is not None ), "Could not find a for directory at {} in {}-type structmap".format( diff --git a/requirements-dev.in b/requirements-dev.in new file mode 100644 index 00000000..85b46eaf --- /dev/null +++ b/requirements-dev.in @@ -0,0 +1,4 @@ +-r requirements.txt + +pip-tools +tox diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 00000000..a7512bd6 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,121 @@ +# +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: +# +# pip-compile --allow-unsafe --output-file=requirements-dev.txt requirements-dev.in +# +amclient==1.2.3 + # via -r requirements.txt +behave==1.2.6 + # via -r requirements.txt +build==1.0.0 + # via pip-tools +cachetools==5.3.1 + # via tox +certifi==2023.7.22 + # via + # -r requirements.txt + # requests +chardet==5.2.0 + # via tox +charset-normalizer==3.2.0 + # via + # -r requirements.txt + # requests +click==8.1.7 + # via pip-tools +colorama==0.4.6 + # via tox +distlib==0.3.7 + # via virtualenv +filelock==3.12.3 + # via + # tox + # virtualenv +idna==3.4 + # via + # -r requirements.txt + # requests +importlib-metadata==6.8.0 + # via build +lxml==4.9.3 + # via + # -r requirements.txt + # metsrw +metsrw==0.4.0 + # via -r requirements.txt +packaging==23.1 + # via + # build + # pyproject-api + # tox +parse==1.19.1 + # via + # -r requirements.txt + # behave + # parse-type +parse-type==0.6.2 + # via + # -r requirements.txt + # behave +pexpect==4.8.0 + # via -r requirements.txt +pip-tools==7.3.0 + # via -r requirements-dev.in +platformdirs==3.10.0 + # via + # tox + # virtualenv +pluggy==1.3.0 + # via tox +ptyprocess==0.7.0 + # via + # -r requirements.txt + # pexpect +pyproject-api==1.6.1 + # via tox +pyproject-hooks==1.0.0 + # via build +requests==2.31.0 + # via + # -r requirements.txt + # amclient +selenium==3.141.0 + # via -r requirements.txt +six==1.16.0 + # via + # -r requirements.txt + # amclient + # behave + # parse-type +tenacity==8.2.3 + # via -r requirements.txt +tomli==2.0.1 + # via + # build + # pip-tools + # pyproject-api + # pyproject-hooks + # tox +tox==4.11.1 + # via -r requirements-dev.in +typing-extensions==4.7.1 + # via filelock +urllib3==1.26.16 + # via + # -r requirements.txt + # amclient + # requests + # selenium +virtualenv==20.24.4 + # via tox +wheel==0.41.2 + # via pip-tools +zipp==3.16.2 + # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +pip==23.2.1 + # via pip-tools +setuptools==68.1.2 + # via pip-tools diff --git a/requirements/base.txt b/requirements.in similarity index 50% rename from requirements/base.txt rename to requirements.in index ab08928f..47ead6e3 100644 --- a/requirements/base.txt +++ b/requirements.in @@ -1,8 +1,8 @@ amclient -behave>=1.0 +behave lxml metsrw pexpect -requests<3.0 +requests tenacity -selenium<4.0 +selenium<4 diff --git a/requirements.txt b/requirements.txt index 5603c377..92284597 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,50 @@ --r requirements/base.txt +# +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: +# +# pip-compile --allow-unsafe --output-file=requirements.txt requirements.in +# +amclient==1.2.3 + # via -r requirements.in +behave==1.2.6 + # via -r requirements.in +certifi==2023.7.22 + # via requests +charset-normalizer==3.2.0 + # via requests +idna==3.4 + # via requests +lxml==4.9.3 + # via + # -r requirements.in + # metsrw +metsrw==0.4.0 + # via -r requirements.in +parse==1.19.1 + # via + # behave + # parse-type +parse-type==0.6.2 + # via behave +pexpect==4.8.0 + # via -r requirements.in +ptyprocess==0.7.0 + # via pexpect +requests==2.31.0 + # via + # -r requirements.in + # amclient +selenium==3.141.0 + # via -r requirements.in +six==1.16.0 + # via + # amclient + # behave + # parse-type +tenacity==8.2.3 + # via -r requirements.in +urllib3==1.26.16 + # via + # amclient + # requests + # selenium diff --git a/requirements/test.txt b/requirements/test.txt deleted file mode 100644 index ec8732a9..00000000 --- a/requirements/test.txt +++ /dev/null @@ -1,3 +0,0 @@ --r base.txt - -tox diff --git a/simplebrowsertest.py b/simplebrowsertest.py index ca96c6ff..c03279ec 100755 --- a/simplebrowsertest.py +++ b/simplebrowsertest.py @@ -1,36 +1,28 @@ #!/usr/bin/env python3 - from selenium import webdriver from selenium.common.exceptions import WebDriverException TEST_URL = "https://www.artefactual.com" -TEST_TITLE = "Home - Artefactual" +TEST_TITLE = "Home | Artefactual" def get_chrome_driver(): options = webdriver.ChromeOptions() - options.add_argument("headless") - options.add_argument("--disable-dev-shm-usage") - options.add_argument("--no-sandbox") - options.add_argument("--whitelisted-ips") - driver = webdriver.Chrome(chrome_options=options) - driver.set_window_size(1700, 900) + options.add_argument("--headless") + driver = webdriver.Chrome(options=options) return driver def get_firefox_driver(): - fp = webdriver.FirefoxProfile() - fp.set_preference("dom.max_chrome_script_run_time", 0) - fp.set_preference("dom.max_script_run_time", 0) options = webdriver.FirefoxOptions() - options.add_argument("-headless") - driver = webdriver.Firefox(firefox_profile=fp, firefox_options=options) + options.add_argument("--headless") + driver = webdriver.Firefox(options=options) return driver def run_test(driver_getter, name): - print("{}... ".format(name), end="") + print(f"{name}... ", end="") try: driver = driver_getter() except WebDriverException as err: diff --git a/tox.ini b/tox.ini index 37643cf9..4689cd85 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,5 @@ [tox] skipsdist = True -minversion = 2.7.0 envlist = linting [testenv]