Updated dependencies.

Also changed the base Docker image from Centos to Rocky Linux.
master
Pacman Ghost 2 years ago
parent 4288125a7a
commit aeb3eaf5c8
  1. 3
      .pylintrc
  2. 15
      Dockerfile
  3. 19
      conftest.py
  4. 8
      requirements-dev.txt
  5. 10
      requirements.txt
  6. 6
      vasl_templates/webapp/scenarios.py
  7. 4
      vasl_templates/webapp/snippets.py
  8. 4
      vasl_templates/webapp/tests/test_template_packs.py
  9. 7
      vasl_templates/webapp/tests/utils.py
  10. 4
      vasl_templates/webapp/vo_notes.py
  11. 22
      vasl_templates/webapp/webdriver.py

@ -148,7 +148,8 @@ disable=print-statement,
import-outside-toplevel, import-outside-toplevel,
isinstance-second-argument-not-valid-type, isinstance-second-argument-not-valid-type,
consider-using-f-string, consider-using-f-string,
consider-using-max-builtin consider-using-max-builtin,
use-implicit-booleaness-not-comparison
# Enable the message, report, category or checker with the given id(s). You can # Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option # either give multiple identifier separated by comma (,) or put this option

@ -1,7 +1,7 @@
# NOTE: Use the run-container.sh script to build and launch this container. # NOTE: Use the run-container.sh script to build and launch this container.
# NOTE: Multi-stage builds require Docker >= 17.05. # NOTE: Multi-stage builds require Docker >= 17.05.
FROM centos:8 AS base FROM rockylinux:8 AS base
# update packages and install requirements # update packages and install requirements
RUN dnf -y upgrade-minimal && \ RUN dnf -y upgrade-minimal && \
@ -16,14 +16,14 @@ RUN url="https://download.java.net/java/GA/jdk15.0.1/51f4f36ad4ef43e39d0dfdbaf65
# install Firefox # install Firefox
RUN dnf install -y wget bzip2 xorg-x11-server-Xvfb gtk3 dbus-glib && \ RUN dnf install -y wget bzip2 xorg-x11-server-Xvfb gtk3 dbus-glib && \
wget -qO- "https://download.mozilla.org/?product=firefox-latest-ssl&os=linux64&lang=en-US" \ wget -qO- "https://ftp.mozilla.org/pub/firefox/releases/94.0.2/linux-x86_64/en-US/firefox-94.0.2.tar.bz2" \
| tar -C /usr/local/ -jx && \ | tar -C /usr/local/ -jx && \
ln -s /usr/local/firefox/firefox /usr/bin/firefox && \ ln -s /usr/local/firefox/firefox /usr/bin/firefox && \
echo "exclude=firefox" >>/etc/dnf/dnf.conf echo "exclude=firefox" >>/etc/dnf/dnf.conf
# install geckodriver # install geckodriver
RUN url=$( curl -s https://api.github.com/repos/mozilla/geckodriver/releases/latest | grep -Poh 'https.*linux64\.tar\.gz(?!\.)' ) && \ RUN curl -sL "https://github.com/mozilla/geckodriver/releases/download/v0.30.0/geckodriver-v0.30.0-linux64.tar.gz" \
curl -sL "$url" | tar -C /usr/bin/ -xz | tar -C /usr/bin/ -xz
# clean up # clean up
RUN dnf clean all RUN dnf clean all
@ -73,6 +73,13 @@ COPY docker/config/ ./vasl_templates/webapp/config/
RUN useradd --create-home app RUN useradd --create-home app
USER app USER app
# FUDGE! We need this to stop spurious warning messages:
# Fork support is only compatible with the epoll1 and poll polling strategies
# Setting the verbosity to ERROR should suppress these, but doesn't :-/
# https://github.com/grpc/grpc/issues/17253
# https://github.com/grpc/grpc/blob/master/doc/environment_variables.md
ENV GRPC_VERBOSITY=NONE
# run the application # run the application
EXPOSE 5010 EXPOSE 5010
COPY docker/run.sh ./ COPY docker/run.sh ./

@ -1,11 +1,9 @@
""" pytest support functions. """ """ pytest support functions. """
import os
import threading import threading
import json import json
import re import re
import logging import logging
import tempfile
import urllib.request import urllib.request
from urllib.error import URLError from urllib.error import URLError
import pytest import pytest
@ -147,7 +145,8 @@ def _make_webapp():
def is_ready(): def is_ready():
"""Try to connect to the webapp server.""" """Try to connect to the webapp server."""
try: try:
with urllib.request.urlopen( app.url_for("ping") ) as resp: url = app.url_for( "ping" )
with urllib.request.urlopen( url ) as resp:
assert resp.read().startswith( b"pong: " ) assert resp.read().startswith( b"pong: " )
return True return True
except URLError: except URLError:
@ -200,24 +199,12 @@ def webdriver( request ):
if driver == "firefox": if driver == "firefox":
options = wb.FirefoxOptions() options = wb.FirefoxOptions()
options.headless = _pytest_options.headless options.headless = _pytest_options.headless
driver = wb.Firefox( driver = wb.Firefox( options=options )
options = options,
service_log_path = os.path.join( tempfile.gettempdir(), "geckodriver.log" )
)
elif driver == "chrome": elif driver == "chrome":
options = wb.ChromeOptions() options = wb.ChromeOptions()
options.headless = _pytest_options.headless options.headless = _pytest_options.headless
options.add_argument( "--disable-gpu" ) options.add_argument( "--disable-gpu" )
driver = wb.Chrome( options=options ) driver = wb.Chrome( options=options )
elif driver == "ie":
# NOTE: IE11 requires a registry key to be set:
# https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver#required-configuration
options = wb.IeOptions()
if _pytest_options.headless:
raise RuntimeError( "IE WebDriver cannot be run headless." )
options.IntroduceInstabilityByIgnoringProtectedModeSettings = True
options.EnsureCleanSession = True
driver = wb.Ie( ie_options=options )
else: else:
raise RuntimeError( "Unknown webdriver: {}".format( driver ) ) raise RuntimeError( "Unknown webdriver: {}".format( driver ) )

@ -1,7 +1,7 @@
pytest==6.2.5 pytest==6.2.5
grpcio-tools==1.41.0 grpcio-tools==1.44.0
tabulate==0.8.9 tabulate==0.8.9
lxml==4.6.3 lxml==4.8.0
pylint==2.11.1 pylint==2.12.2
pytest-pylint==0.18.0 pytest-pylint==0.18.0
pyinstaller==4.5.1 pyinstaller==4.9

@ -1,8 +1,8 @@
# python 3.8.7 # python 3.8.7
flask==2.0.1 flask==2.0.3
pyyaml==5.4.1 pyyaml==6.0
pillow==8.3.2 pillow==9.0.1
selenium==3.141.0 selenium==4.1.0
waitress==2.0.0 waitress==2.0.0
click==8.0.1 click==8.0.4

@ -563,8 +563,10 @@ def on_successful_asa_upload( scenario_id ):
# download the specified scenario # download the specified scenario
url = app.config["ASA_GET_SCENARIO_URL"].replace( "{ID}", scenario_id ) url = app.config["ASA_GET_SCENARIO_URL"].replace( "{ID}", scenario_id )
try: try:
with urllib.request.urlopen( url ) as fp: with urllib.request.urlopen( url ) as resp:
new_scenario = json.loads( fp.read().decode( "utf-8" ) ) new_scenario = json.loads(
resp.read().decode( "utf-8" )
)
except Exception as ex: #pylint: disable=broad-except except Exception as ex: #pylint: disable=broad-except
msg = str( getattr(ex,"reason",None) or ex ) msg = str( getattr(ex,"reason",None) or ex )
return jsonify( { "status": "error", "message": msg } ) return jsonify( { "status": "error", "message": msg } )

@ -204,8 +204,8 @@ def get_flag( nat ):
fname = globvars.template_pack.get( "nationalities", {} ).get( nat, {} ).get( "flag" ) fname = globvars.template_pack.get( "nationalities", {} ).get( nat, {} ).get( "flag" )
if fname: if fname:
if fname.startswith( ("http://","https://") ): if fname.startswith( ("http://","https://") ):
with urllib.request.urlopen( fname ) as fp: with urllib.request.urlopen( fname ) as resp:
return _get_small_image( fp, key, height ) return _get_small_image( resp, key, height )
else: else:
with open( fname, "rb" ) as fp: with open( fname, "rb" ) as fp:
return _get_small_image( fp, key, height ) return _get_small_image( fp, key, height )

@ -6,6 +6,8 @@ import base64
import re import re
import random import random
from selenium.webdriver.common.by import By
from vasl_templates.webapp.utils import TempFile from vasl_templates.webapp.utils import TempFile
from vasl_templates.webapp.tests.test_vehicles_ordnance import add_vo from vasl_templates.webapp.tests.test_vehicles_ordnance import add_vo
from vasl_templates.webapp.tests.utils import \ from vasl_templates.webapp.tests.utils import \
@ -199,7 +201,7 @@ def test_missing_templates( webapp, webdriver ):
disabled = webdriver.execute_script( "return $(arguments[0]).button('option','disabled')", btn ) disabled = webdriver.execute_script( "return $(arguments[0]).button('option','disabled')", btn )
assert expected == disabled assert expected == disabled
# check that snippet control groups have been enabled/disabled correctly # check that snippet control groups have been enabled/disabled correctly
parent = btn.find_element_by_xpath( ".." ) parent = btn.find_element( By.XPATH, ".." )
parent_classes = get_css_classes( parent ) parent_classes = get_css_classes( parent )
if is_snippet_control: if is_snippet_control:
assert "snippet-control" in parent_classes assert "snippet-control" in parent_classes

@ -13,6 +13,7 @@ import lxml.html
from selenium.webdriver.support.ui import Select from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException, WebDriverException from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException, WebDriverException
import vasl_templates.webapp.tests import vasl_templates.webapp.tests
@ -157,7 +158,7 @@ def select_tab_for_elem( elem ):
def get_tab_for_elem( elem ): def get_tab_for_elem( elem ):
"""Identify the tab that contains the specified element.""" """Identify the tab that contains the specified element."""
while elem.tag_name not in ("html","body"): while elem.tag_name not in ("html","body"):
elem = elem.find_element_by_xpath( ".." ) elem = elem.find_element( By.XPATH, ".." )
if elem.tag_name == "div": if elem.tag_name == "div":
div_id = elem.get_attribute( "id" ) div_id = elem.get_attribute( "id" )
if div_id.startswith( "tabs-" ): if div_id.startswith( "tabs-" ):
@ -431,14 +432,14 @@ def find_child( sel, parent=None ):
"""Find a single child element.""" """Find a single child element."""
try: try:
# NOTE: I tried caching these results, but it didn't help the tests run any faster :-( # NOTE: I tried caching these results, but it didn't help the tests run any faster :-(
return (parent if parent else _webdriver).find_element_by_css_selector( sel ) return (parent if parent else _webdriver).find_element( By.CSS_SELECTOR, sel )
except NoSuchElementException: except NoSuchElementException:
return None return None
def find_children( sel, parent=None ): def find_children( sel, parent=None ):
"""Find child elements.""" """Find child elements."""
try: try:
return (parent if parent else _webdriver).find_elements_by_css_selector( sel ) return (parent if parent else _webdriver).find_elements( By.CSS_SELECTOR, sel )
except NoSuchElementException: except NoSuchElementException:
return None return None

@ -438,8 +438,8 @@ def load_asl_rulebook2_vo_note_targets( msg_store ):
with open( base_url, "r", encoding="utf-8" ) as fp: with open( base_url, "r", encoding="utf-8" ) as fp:
_asl_rulebook2_targets = json.load( fp ) _asl_rulebook2_targets = json.load( fp )
else: else:
with urllib.request.urlopen( base_url + "/vo-note-targets" ) as fp: with urllib.request.urlopen( base_url + "/vo-note-targets" ) as resp:
_asl_rulebook2_targets = json.load( fp ) _asl_rulebook2_targets = json.load( resp )
except Exception as ex: #pylint: disable=broad-except except Exception as ex: #pylint: disable=broad-except
msg = str( getattr(ex,"reason",None) or ex ) msg = str( getattr(ex,"reason",None) or ex )
msg_store.warning( "Couldn't get the ASL Rulebook2 Chapter H targets: {}".format( msg ) ) msg_store.warning( "Couldn't get the ASL Rulebook2 Chapter H targets: {}".format( msg ) )

@ -67,7 +67,9 @@ class WebDriver:
# create the webdriver # create the webdriver
_logger.debug( "- Launching webdriver process: %s", webdriver_path ) _logger.debug( "- Launching webdriver process: %s", webdriver_path )
kwargs = { "executable_path": webdriver_path } log_fname = app.config.get( "WEBDRIVER_LOG",
os.path.join( tempfile.gettempdir(), "webdriver.log" )
)
if "chromedriver" in webdriver_path: if "chromedriver" in webdriver_path:
options = webdriver.ChromeOptions() options = webdriver.ChromeOptions()
options.headless = True options.headless = True
@ -78,17 +80,21 @@ class WebDriver:
chrome_path = app.config.get( "CHROME_PATH" ) chrome_path = app.config.get( "CHROME_PATH" )
if chrome_path: if chrome_path:
options.binary_location = chrome_path options.binary_location = chrome_path
kwargs["options"] = options service = webdriver.chrome.service.Service(
self.driver = webdriver.Chrome( **kwargs ) webdriver_path, log_path=log_fname
)
self.driver = webdriver.Chrome(
options=options, service=service
)
elif "geckodriver" in webdriver_path: elif "geckodriver" in webdriver_path:
options = webdriver.FirefoxOptions() options = webdriver.FirefoxOptions()
options.headless = True options.headless = True
kwargs["options"] = options service = webdriver.firefox.service.Service(
kwargs["service_log_path"] = app.config.get( "GECKODRIVER_LOG", webdriver_path, log_path=log_fname
os.path.join( tempfile.gettempdir(), "geckodriver.log" ) )
self.driver = webdriver.Firefox(
options=options, proxy=None, service=service
) )
kwargs["proxy"] = None
self.driver = webdriver.Firefox( **kwargs )
else: else:
raise SimpleError( "Can't identify webdriver: {}".format( webdriver_path ) ) raise SimpleError( "Can't identify webdriver: {}".format( webdriver_path ) )
_logger.debug( "- Started OK." ) _logger.debug( "- Started OK." )

Loading…
Cancel
Save