From 0f294d9a93f16089203a0bac6d2ca1f94c13d0cc Mon Sep 17 00:00:00 2001 From: "J. Ungermann" Date: Thu, 29 Aug 2024 10:24:17 +0200 Subject: [PATCH] Revert "Merge stable to develop (#2482)" (#2490) This reverts commit 2c89c795684500fc846d131c2e273ccfab4a2a6a. --- .github/workflows/testing-all-oses.yml | 4 +- CHANGES.rst | 10 -- docs/conf.py | 2 +- docs/environment.yml | 2 +- docs/mss_theme/css/mss.css | 4 - docs/samples/automation/retriever.py | 3 +- docs/tutorial.rst | 2 +- docs/tutorials/tutorial_hexagoncontrol.rst | 2 +- .../tutorial_introduction_topview.rst | 2 +- docs/tutorials/tutorial_kml.rst | 4 +- docs/tutorials/tutorial_mscolab.rst | 2 +- docs/tutorials/tutorial_msui_views.rst | 2 +- .../tutorial_performance_settings.rst | 2 +- docs/tutorials/tutorial_remotesensing.rst | 2 +- docs/tutorials/tutorial_satellitetrack.rst | 2 +- docs/tutorials/tutorial_waypoints.rst | 2 +- localbuild/meta.yaml | 2 +- mslib/mscolab/chat_manager.py | 8 +- mslib/mscolab/file_manager.py | 33 ++--- mslib/mscolab/models.py | 38 +++--- mslib/msui/flighttrack.py | 8 +- mslib/msui/mscolab.py | 8 +- mslib/static/docs/help.md | 2 +- mslib/static/docs/installation.md | 10 +- mslib/utils/verify_waypoint_data.py | 53 -------- mslib/version.py | 2 +- requirements.d/development.txt | 1 + tests/_test_mscolab/test_chat_manager.py | 9 +- tests/_test_mscolab/test_files.py | 52 ++------ tests/_test_mscolab/test_files_api.py | 21 ++-- tests/_test_mscolab/test_models.py | 6 +- tests/_test_mscolab/test_server.py | 64 +++------- .../_test_utils/test_verify_waypoint_data.py | 119 ------------------ tests/utils.py | 51 -------- 34 files changed, 106 insertions(+), 428 deletions(-) delete mode 100644 mslib/utils/verify_waypoint_data.py delete mode 100644 tests/_test_utils/test_verify_waypoint_data.py diff --git a/.github/workflows/testing-all-oses.yml b/.github/workflows/testing-all-oses.yml index 58df9ccdb..86fb996fc 100644 --- a/.github/workflows/testing-all-oses.yml +++ b/.github/workflows/testing-all-oses.yml @@ -48,4 +48,6 @@ jobs: # I have no idea yet on why this happens and how to fix it. # Even a module level skip is not enough, they need to be completely ignored. # TODO: fix those tests and drop the ignores - run: micromamba run -n ci env QT_QPA_PLATFORM=offscreen pytest -v -n logical --durations=20 --cov=mslib tests + run: micromamba run -n ci env QT_QPA_PLATFORM=offscreen pytest -v -n logical --durations=20 --cov=mslib + --ignore=tests/_test_msui/test_sideview.py --ignore=tests/_test_msui/test_topview.py --ignore=tests/_test_msui/test_wms_control.py + tests diff --git a/CHANGES.rst b/CHANGES.rst index b1aef8422..a92d20429 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,16 +1,6 @@ Changelog ========= -Version 9.2.0 -~~~~~~~~~~~~~ - -Bug fix release and minor enhancements: -We added a verification for xml data and changed the startup of the SocketsManager. - -All changes: -https://github.com/Open-MSS/MSS/milestone/106?closed=1 - - Version 9.1.0 ~~~~~~~~~~~~~ diff --git a/docs/conf.py b/docs/conf.py index 80e5e185d..bbd933540 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -226,7 +226,7 @@ def get_tutorial_images(): html_style = 'css/mss.css' else: htmls_static_path = ['_static'] - html_css_files = ['css/mss.css'] + html_css_files = ['mss.css'] html_context = { 'display_github': False, # Add 'Edit on Bitbucket' link instead of 'View page source' 'last_updated': True, diff --git a/docs/environment.yml b/docs/environment.yml index 2a0fbaf92..8e703ec7b 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -15,7 +15,7 @@ dependencies: - xstatic - defusedxml - sphinx_rtd_theme - - sphinxcontrib-video>=0.2.1 + - sphinxcontrib-video - sphinx - fs - netCDF4 diff --git a/docs/mss_theme/css/mss.css b/docs/mss_theme/css/mss.css index 58fa4d1b7..de441f52a 100644 --- a/docs/mss_theme/css/mss.css +++ b/docs/mss_theme/css/mss.css @@ -14,7 +14,3 @@ margin-bottom: auto; margin-left: auto; } - -video { - max-width: 100%; -} diff --git a/docs/samples/automation/retriever.py b/docs/samples/automation/retriever.py index 989faa95f..0226c9c6c 100644 --- a/docs/samples/automation/retriever.py +++ b/docs/samples/automation/retriever.py @@ -31,7 +31,6 @@ import io import os import xml -import defusedxml.minidom import requests from fs import open_fs import PIL.Image @@ -59,7 +58,7 @@ def load_from_ftml(filename): _fs = open_fs(_dirname) datasource = _fs.open(_name) try: - doc = defusedxml.minidom.parse(datasource) + doc = xml.dom.minidom.parse(datasource) except xml.parsers.expat.ExpatError as ex: raise SyntaxError(str(ex)) diff --git a/docs/tutorial.rst b/docs/tutorial.rst index 8fe213c4b..a188127e3 100644 --- a/docs/tutorial.rst +++ b/docs/tutorial.rst @@ -9,7 +9,7 @@ a `public share `_ Get familiar by some videos about the Mission Support System (MSS). - .. video:: videos/mp4/tutorial_waypoints.mp4 + .. video:: _static/mp4/tutorial_waypoints.mp4 :autoplay: :loop: :alt: This is the waypoints tutorial,i.e., whenever we are going to plan diff --git a/docs/tutorials/tutorial_hexagoncontrol.rst b/docs/tutorials/tutorial_hexagoncontrol.rst index a212a70e1..0c3dae428 100644 --- a/docs/tutorials/tutorial_hexagoncontrol.rst +++ b/docs/tutorials/tutorial_hexagoncontrol.rst @@ -3,7 +3,7 @@ Table View and Hexagon Flight Patterns For tomographic imaging, a hexagonal flight pattern can be integrated by a docking widget of Table View - .. video:: ../videos/mp4/tutorial_hexagoncontrol.mp4 + .. video:: ../_static/mp4/tutorial_hexagoncontrol.mp4 :alt: Top View windows is opened (CTRL+H). We select the "global (cyl)" for the world map. Zooming in for the required region. diff --git a/docs/tutorials/tutorial_introduction_topview.rst b/docs/tutorials/tutorial_introduction_topview.rst index b72815f05..b4edd8a1f 100644 --- a/docs/tutorials/tutorial_introduction_topview.rst +++ b/docs/tutorials/tutorial_introduction_topview.rst @@ -3,7 +3,7 @@ Top View and Selecting of Layers Selection and display of different data in the Top View with the help of the layer chooser. - .. video:: ../videos/mp4/tutorial_wms.mp4 + .. video:: ../_static/mp4/tutorial_wms.mp4 :alt: When we open the Top View (CTRL+H) of the map, the Web Map Service is already opened by default. It collects its data from the server: "open-mss dot org" that provides demodata for the meteorological or atmospheric information as layer lists. diff --git a/docs/tutorials/tutorial_kml.rst b/docs/tutorials/tutorial_kml.rst index 68a85903a..5d8c3d951 100644 --- a/docs/tutorials/tutorial_kml.rst +++ b/docs/tutorials/tutorial_kml.rst @@ -3,7 +3,7 @@ Top View and KML Data es can be displayed in the Top View. Color and line width can be adjusted. - .. video:: ../videos/mp4/tutorial_kml.mp4 + .. video:: ../_static/mp4/tutorial_kml.mp4 :alt: Open the TopView (CTRL+H) After clicking on "(select to open control)", click on KML OVERLAY. The UI will look as shown. KML files can be used to show the geographical boundary which helps in planning the WAY POINTS. @@ -23,4 +23,4 @@ es can be displayed in the Top View. Color and line width can be adjusted. Changing it for some time... Now, we change line width by changing its numerical value whose range is 0 to 10. We change it to different values to obtain different linewidths. - The top view is closed and the tutorial ends. + The top view is closed and the tutorial ends. \ No newline at end of file diff --git a/docs/tutorials/tutorial_mscolab.rst b/docs/tutorials/tutorial_mscolab.rst index 7d9cb4a92..c4164fa9c 100644 --- a/docs/tutorials/tutorial_mscolab.rst +++ b/docs/tutorials/tutorial_mscolab.rst @@ -5,7 +5,7 @@ Using the different views of the MSUI with a fictitious flight path and demo dat In comparison to the standalone mode of the MSUI an example setup of users is shown on a MSColab server and the possibilities of interactions. - .. video:: ../videos/mp4/tutorial_mscolab.mp4 + .. video:: ../_static/mp4/tutorial_mscolab.mp4 :alt: MSColab stores data in an online server, and can be used to access the data remotely as also working in a team where everyone contributes his part. It is used for collaborating with the users as a team together and working on a shared MSColab operation. diff --git a/docs/tutorials/tutorial_msui_views.rst b/docs/tutorials/tutorial_msui_views.rst index 27910e9ab..7e1ba7dcd 100644 --- a/docs/tutorials/tutorial_msui_views.rst +++ b/docs/tutorials/tutorial_msui_views.rst @@ -4,7 +4,7 @@ Introduction to MSUI Using the different views of the MSUI with a fictitious flight path and demo data. - .. video:: ../videos/mp4/tutorial_views.mp4 + .. video:: ../_static/mp4//tutorial_views.mp4 :alt: Lets look at the tutorial of the various views required for flight planning: Top View (CTRL+H), Side View (CTRL+V), Linear View (CTRL+L) and Table View (CTRL+T). At first, lets open Top View and Side View. diff --git a/docs/tutorials/tutorial_performance_settings.rst b/docs/tutorials/tutorial_performance_settings.rst index 59820e2c2..82954355a 100644 --- a/docs/tutorials/tutorial_performance_settings.rst +++ b/docs/tutorials/tutorial_performance_settings.rst @@ -3,7 +3,7 @@ Table View and Aircraft Performance Data The range-specific data of an aircraft can be taken into account in Tableview for flight planning. - .. video:: ../videos/mp4/tutorial_performancesettings.mp4 + .. video:: ../_static/mp4/tutorial_performancesettings.mp4 :alt: This is the Performance Settings dockwidget opened in the Table View (CTRL+T) of the MSS software where by putting and changing some parameters, we can evaluate the performance of the aircraft. Parameters like Flight Altitude, Aviation fuel, Aircraft weight, Maximum take off weight diff --git a/docs/tutorials/tutorial_remotesensing.rst b/docs/tutorials/tutorial_remotesensing.rst index 65d1dbf4e..e1a1d1253 100644 --- a/docs/tutorials/tutorial_remotesensing.rst +++ b/docs/tutorials/tutorial_remotesensing.rst @@ -4,7 +4,7 @@ Top View and Remotesensing Tools In order to be able to take into account the viewing angle and solar level for measuring instruments, the remotesensing tools are used - .. video:: ../videos/mp4/tutorial_remotesensing.mp4 + .. video:: ../_static/mp4/tutorial_remotesensing.mp4 :alt: This is the Remote Sensing Section of the Top View. It shows the position and angle of the flight from any particular object in the sky. Azimuth is the forward direction line of the flight. If we go above tHE AZIMUTH, angle is in positive, diff --git a/docs/tutorials/tutorial_satellitetrack.rst b/docs/tutorials/tutorial_satellitetrack.rst index 7c6b55550..04561d811 100644 --- a/docs/tutorials/tutorial_satellitetrack.rst +++ b/docs/tutorials/tutorial_satellitetrack.rst @@ -4,7 +4,7 @@ Top View and Satellite Overflight To combine a flight path with a satellite overflight, the remotesensing widget is used. - .. video:: ../videos/mp4/tutorial_satellitetrack.mp4 + .. video:: ../_static/mp4/tutorial_satellitetrack.mp4 :alt: This is Satellite Tracking Prediction System that can be used to check the accuracy of the path travelled by a Satellite by the help of data collected from different space agencies and planning a flight accordingly. diff --git a/docs/tutorials/tutorial_waypoints.rst b/docs/tutorials/tutorial_waypoints.rst index 87938a01c..e43d21f3d 100644 --- a/docs/tutorials/tutorial_waypoints.rst +++ b/docs/tutorials/tutorial_waypoints.rst @@ -3,7 +3,7 @@ Top View Drawing Waypoints Waypoints for a flight path are defined, shifted and deleted. - .. video:: ../videos/mp4/tutorial_waypoints.mp4 + .. video:: ../_static/mp4/tutorial_waypoints.mp4 :alt: This is the waypoints tutorial,i.e., whenever we are going to plan a flight track, we have to place the waypoints in some places and, form a flight path. diff --git a/localbuild/meta.yaml b/localbuild/meta.yaml index 9e2b52fdc..3088dfce2 100644 --- a/localbuild/meta.yaml +++ b/localbuild/meta.yaml @@ -77,7 +77,7 @@ requirements: - metpy - pycountry - websocket-client - - libtiff + - libtiff <4.5.0 - flask-wtf - email_validator - keyring diff --git a/mslib/mscolab/chat_manager.py b/mslib/mscolab/chat_manager.py index 0d0c92bdb..e1d35624e 100644 --- a/mslib/mscolab/chat_manager.py +++ b/mslib/mscolab/chat_manager.py @@ -38,16 +38,16 @@ class ChatManager: def __init__(self): pass - def add_message(self, user, text, op_id, message_type=MessageType.TEXT, reply_id=None): + def add_message(self, user, text, operation_name, message_type=MessageType.TEXT, reply_id=None): """ - user: User object, one which emits the message text: message to be emitted to operation and saved to db - op_id: operation id to which message is emitted, + operation_name: operation-name(op_id) to which message is emitted, + user: User object, one which emits the message message_type: Enum of type MessageType. values: TEXT, SYSTEM_MESSAGE, IMAGE, DOCUMENT """ if reply_id == -1: reply_id = None - message = Message(op_id, user.id, text, message_type, reply_id) + message = Message(operation_name, user.id, text, message_type, reply_id) db.session.add(message) db.session.commit() return message diff --git a/mslib/mscolab/file_manager.py b/mslib/mscolab/file_manager.py index 9db717a44..5b41d3a50 100644 --- a/mslib/mscolab/file_manager.py +++ b/mslib/mscolab/file_manager.py @@ -36,7 +36,6 @@ import mimetypes from werkzeug.utils import secure_filename from sqlalchemy.exc import IntegrityError -from mslib.utils.verify_waypoint_data import verify_waypoint_data from mslib.mscolab.models import db, Operation, Permission, User, Change, Message from mslib.mscolab.conf import mscolab_settings @@ -59,19 +58,9 @@ def _get_operation_lock(self, op_id): def create_operation(self, path, description, user, last_used=None, content=None, category="default", active=True): """ - Creates a new operation in the mscolab system. - - :param path: The path of the operation. - :param description: The description of the operation. - :param user: The user object creating the operation. - :param last_used: The last used datetime of the operation. Default is None. - :param content: The content of the operation. Default is None. - :param category: The category of the operation. Default is 'default'. - :param active: The activity status of the operation. Default is True. - :return: True if the operation is created successfully, False otherwise. + path: path to the operation + description: description of the operation """ - if content is not None and not verify_waypoint_data(content): - return False # set codes on these later if path.find("/") != -1 or path.find("\\") != -1 or (" " in path): logging.debug("malicious request: %s", user) @@ -350,14 +339,14 @@ def update_operation(self, op_id, attribute, value, user): if value.find("/") != -1 or value.find("\\") != -1 or (" " in value): logging.debug("malicious request: %s", user) return False - with fs.open_fs(self.data_dir) as data: - if data.exists(value): - return False - # will be move when operations are introduced - # make a directory, else movedir - data.makedir(value) - data.movedir(operation.path, value) - # when renamed to a Group operation + data = fs.open_fs(self.data_dir) + if data.exists(value): + return False + # will be move when operations are introduced + # make a directory, else movedir + data.makedir(value) + data.movedir(operation.path, value) + # when renamed to a Group operation if value.endswith(mscolab_settings.GROUP_POSTFIX): # getting the category category = value.split(mscolab_settings.GROUP_POSTFIX)[0] @@ -405,8 +394,6 @@ def save_file(self, op_id, content, user, comment=""): content: content of the file to be saved # ToDo save change in schema """ - if not verify_waypoint_data(content): - return False # ToDo use comment operation = Operation.query.filter_by(id=op_id).first() if not operation: diff --git a/mslib/mscolab/models.py b/mslib/mscolab/models.py index 742583fb7..abac5406c 100644 --- a/mslib/mscolab/models.py +++ b/mslib/mscolab/models.py @@ -67,14 +67,14 @@ class User(db.Model): def __init__(self, emailid, username, password, profile_image_path=None, confirmed=False, confirmed_on=None, authentication_backend='local'): - self.username = str(username) - self.emailid = str(emailid) + self.username = username + self.emailid = emailid self.hash_password(password) self.profile_image_path = profile_image_path self.registered_on = datetime.datetime.now(tz=datetime.timezone.utc) - self.confirmed = bool(confirmed) + self.confirmed = confirmed self.confirmed_on = confirmed_on - self.authentication_backend = str(authentication_backend) + self.authentication_backend = authentication_backend def __repr__(self): return f'' @@ -137,9 +137,9 @@ def __init__(self, u_id, op_id, access_level): op_id: process-id access_level: the type of authorization to the operation """ - self.u_id = int(u_id) - self.op_id = int(op_id) - self.access_level = str(access_level) + self.u_id = u_id + self.op_id = op_id + self.access_level = access_level def __repr__(self): return f'' @@ -161,10 +161,10 @@ def __init__(self, path, description, last_used=None, category="default", active description: small description of operation category: name of category """ - self.path = str(path) - self.description = str(description) - self.category = str(category) - self.active = bool(active) + self.path = path + self.description = description + self.category = category + self.active = active if self.last_used is None: self.last_used = datetime.datetime.now(tz=datetime.timezone.utc) else: @@ -190,9 +190,9 @@ class Message(db.Model): replies = db.relationship('Message', cascade='all,delete,delete-orphan', single_parent=True) def __init__(self, op_id, u_id, text, message_type=MessageType.TEXT, reply_id=None): - self.op_id = int(op_id) - self.u_id = int(u_id) - self.text = str(text) + self.op_id = op_id + self.u_id = u_id + self.text = text self.message_type = message_type self.reply_id = reply_id @@ -213,8 +213,8 @@ class Change(db.Model): user = db.relationship('User') def __init__(self, op_id, u_id, commit_hash, version_name=None, comment=None): - self.op_id = int(op_id) - self.u_id = int(u_id) - self.commit_hash = str(commit_hash) - self.version_name = str(version_name) - self.comment = str(comment) + self.op_id = op_id + self.u_id = u_id + self.commit_hash = commit_hash + self.version_name = version_name + self.comment = comment diff --git a/mslib/msui/flighttrack.py b/mslib/msui/flighttrack.py index cc6d51467..1d3ad2b15 100644 --- a/mslib/msui/flighttrack.py +++ b/mslib/msui/flighttrack.py @@ -48,7 +48,6 @@ from mslib.utils.units import units from mslib.utils.coordinate import find_location, path_points, get_distance from mslib.utils import thermolib -from mslib.utils.verify_waypoint_data import verify_waypoint_data from mslib.utils.config import config_loader, save_settings_qsettings, load_settings_qsettings from mslib.utils.config import MSUIDefaultConfig as mss_default from mslib.utils.qt import variant_to_string, variant_to_float @@ -650,11 +649,8 @@ def load_from_ftml(self, filename): def load_from_xml_data(self, xml_content, name="Flight track"): self.name = name - if verify_waypoint_data(xml_content): - _waypoints_list = load_from_xml_data(xml_content, name) - self.replace_waypoints(_waypoints_list) - else: - raise SyntaxError(f"Invalid flight track filename: {name}") + _waypoints_list = load_from_xml_data(xml_content, name) + self.replace_waypoints(_waypoints_list) def get_filename(self): return self.filename diff --git a/mslib/msui/mscolab.py b/mslib/msui/mscolab.py index a0655a56e..a1ee04642 100644 --- a/mslib/msui/mscolab.py +++ b/mslib/msui/mscolab.py @@ -61,7 +61,6 @@ from mslib.utils.auth import get_password_from_keyring, save_password_to_keyring from mslib.utils.verify_user_token import verify_user_token -from mslib.utils.verify_waypoint_data import verify_waypoint_data from mslib.utils.qt import get_open_filename, get_save_filename, dropEvent, dragEnterEvent, show_popup from mslib.msui.qt5 import ui_mscolab_help_dialog as msc_help_dialog from mslib.msui.qt5 import ui_add_operation_dialog as add_operation_ui @@ -2048,12 +2047,10 @@ def handle_import_msc(self, file_path, extension, function, pickertype): return dir_path, file_name = fs.path.split(file_path) file_name = fs.path.basename(file_path) + name, file_ext = fs.path.splitext(file_name) if function is None: with open_fs(dir_path) as file_dir: xml_content = file_dir.readtext(file_name) - if not verify_waypoint_data(xml_content): - show_popup(self.ui, "Import Failed", f"The file - {file_name}, does not contain valid XML") - return try: model = ft.WaypointsTableModel(xml_content=xml_content) except SyntaxError: @@ -2065,9 +2062,6 @@ def handle_import_msc(self, file_path, extension, function, pickertype): model = ft.WaypointsTableModel(waypoints=new_waypoints) xml_doc = self.waypoints_model.get_xml_doc() xml_content = xml_doc.toprettyxml(indent=" ", newl="\n") - if not verify_waypoint_data(xml_content): - show_popup(self.ui, "Import Failed", f"The file - {file_name}, was not imported!", 0) - return self.waypoints_model.dataChanged.disconnect(self.handle_waypoints_changed) self.waypoints_model = model self.handle_waypoints_changed() diff --git a/mslib/static/docs/help.md b/mslib/static/docs/help.md index c0a2c0777..5ea50caa7 100644 --- a/mslib/static/docs/help.md +++ b/mslib/static/docs/help.md @@ -8,7 +8,7 @@ software that simplifies the process for planning a scientific flight. # Drawing waypoints in the MSUI Topview The example shows defining of waypoints for a flight path, moved and deleted. -![Waypoint Tutorial](https://mss.readthedocs.io/en/stable/_images/tutorial_waypoints.mp4) +![Waypoint Tutorial](https://mss.readthedocs.io/en/stable/_static/mp4/tutorial_waypoints.mp4) Further tutorials about the Mission Support System Software on: diff --git a/mslib/static/docs/installation.md b/mslib/static/docs/installation.md index b31e57473..8c8051e33 100644 --- a/mslib/static/docs/installation.md +++ b/mslib/static/docs/installation.md @@ -7,7 +7,7 @@ The Mission Support System (MSS) including a Web Map Service a Collaboration Ser [conda-forge](https://anaconda.org/conda-forge/mss) package. -We strongly recommend to start from [Miniforge3](https://github.com/conda-forge/miniforge?tab=readme-ov-file#miniforge3) +We strongly recommend to start from [Mambaforge](https://mamba.readthedocs.io/en/latest/installation.html) a community project of the conda-forge community. You can install it either automatically with the help of a script or manually. @@ -31,8 +31,8 @@ You can install it either automatically with the help of a script or manually. ### Manually -As **Beginner** start with an installation of Miniforge3 -Get [Miniforge3](https://github.com/conda-forge/miniforge?tab=readme-ov-file#miniforge3) for your Operation System +As **Beginner** start with an installation of Mambaforge +Get [mambaforge](https://github.com/conda-forge/miniforge#mambaforge) for your Operation System You must install mss into a new environment to ensure the most recent @@ -65,10 +65,10 @@ user for the apache2 wsgi script. We suggest to create a mss user. - login as mss user - create a *src* directory in /home/mss - cd src -- get [Miniforge3](https://github.com/conda-forge/miniforge?tab=readme-ov-file#miniforge3) +- get [mambaforge](https://github.com/conda-forge/miniforge#mambaforge) - set execute bit on install script - execute script, enable environment in .bashrc -- start your shell again (new login) +- login again or export PATH="/home/mss/mambaforge/bin:\$PATH" - python --version should tell Python 3.X.X - mamba create -n mssenv - mamba activate mssenv diff --git a/mslib/utils/verify_waypoint_data.py b/mslib/utils/verify_waypoint_data.py deleted file mode 100644 index 455912bfe..000000000 --- a/mslib/utils/verify_waypoint_data.py +++ /dev/null @@ -1,53 +0,0 @@ -# -*- coding: utf-8 -*- -""" - - mslib.utils.verify_waypoint_data - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - basic checks for xml waypoint data. - - This file is part of MSS. - - :copyright: Copyright 2024 Reimar Bauer - :license: APACHE-2.0, see LICENSE for details. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" - - -import defusedxml.minidom -import xml.parsers.expat - - -def verify_waypoint_data(xml_content): - try: - doc = defusedxml.minidom.parseString(xml_content) - except xml.parsers.expat.ExpatError: - return False - - ft_el = doc.getElementsByTagName("FlightTrack")[0] - waypoints = ft_el.getElementsByTagName("Waypoint") - if (len(waypoints)) < 2: - return False - - for wp_el in ft_el.getElementsByTagName("Waypoint"): - try: - wp_el.getAttribute("location") - float(wp_el.getAttribute("lat")) - float(wp_el.getAttribute("lon")) - float(wp_el.getAttribute("flightlevel")) - wp_el.getElementsByTagName("Comments")[0] - except ValueError: - return False - - return True diff --git a/mslib/version.py b/mslib/version.py index 9181d64ab..a179012a9 100644 --- a/mslib/version.py +++ b/mslib/version.py @@ -24,4 +24,4 @@ See the License for the specific language governing permissions and limitations under the License. """ -__version__ = u'9.2.0' +__version__ = u'9.1.0' diff --git a/requirements.d/development.txt b/requirements.d/development.txt index d6403b27c..232063ce6 100644 --- a/requirements.d/development.txt +++ b/requirements.d/development.txt @@ -20,3 +20,4 @@ eventlet>0.30.2 dnspython>=2.0.0, <2.3.0 gsl==2.7.0 boa +xmlschema<2.5.0 diff --git a/tests/_test_mscolab/test_chat_manager.py b/tests/_test_mscolab/test_chat_manager.py index 0405f04b8..4cc1691c4 100644 --- a/tests/_test_mscolab/test_chat_manager.py +++ b/tests/_test_mscolab/test_chat_manager.py @@ -27,7 +27,7 @@ import pytest from mslib.mscolab.models import Message, MessageType -from mslib.mscolab.seed import add_user, get_user, add_operation, add_user_to_operation, get_operation +from mslib.mscolab.seed import add_user, get_user, add_operation, add_user_to_operation class Test_Chat_Manager: @@ -42,21 +42,20 @@ def setup(self, mscolab_app, mscolab_managers): assert add_operation(self.operation_name, "test europe") assert add_user_to_operation(path=self.operation_name, emailid=self.userdata[0]) self.user = get_user(self.userdata[0]) - self.operation = get_operation(self.operation_name) with self.app.app_context(): yield def test_add_message(self): with self.app.test_client(): message = self.cm.add_message(self.user, 'some message', - self.operation.id, message_type=MessageType.TEXT, + self.operation_name, message_type=MessageType.TEXT, reply_id=None) assert message.text == 'some message' def test_edit_messages(self): with self.app.test_client(): message = self.cm.add_message(self.user, 'some test message', - self.operation.id, message_type=MessageType.TEXT, + self.operation_name, message_type=MessageType.TEXT, reply_id=None) new_message_text = "Wonderland" self.cm.edit_message(message.id, new_message_text) @@ -66,7 +65,7 @@ def test_edit_messages(self): def test_delete_messages(self): with self.app.test_client(): message = self.cm.add_message(self.user, 'some test example message', - self.operation.id, message_type=MessageType.TEXT, + self.operation_name, message_type=MessageType.TEXT, reply_id=None) assert 'some test example message' in message.text self.cm.delete_message(message.id) diff --git a/tests/_test_mscolab/test_files.py b/tests/_test_mscolab/test_files.py index 35f0da5d2..1710ec9d5 100644 --- a/tests/_test_mscolab/test_files.py +++ b/tests/_test_mscolab/test_files.py @@ -32,7 +32,6 @@ from mslib.mscolab.models import User, Operation, Permission, Change, Message from mslib.mscolab.seed import add_user, get_user from mslib.mscolab.utils import get_recent_op_id -from tests.utils import XML_CONTENT1, XML_CONTENT2, XML_CONTENT3 class Test_Files: @@ -95,54 +94,25 @@ def test_is_creator(self): def test_file_save(self): with self.app.test_client(): flight_path, operation = self._create_operation(flight_path="operation77") - assert self.fm.save_file(operation.id, XML_CONTENT1, self.user) - assert self.fm.get_file(operation.id, self.user) == XML_CONTENT1 - assert self.fm.save_file(operation.id, XML_CONTENT2, self.user) - assert self.fm.get_file(operation.id, self.user) == XML_CONTENT2 + assert self.fm.save_file(operation.id, "beta", self.user) + assert self.fm.get_file(operation.id, self.user) == "beta" + assert self.fm.save_file(operation.id, "gamma", self.user) + assert self.fm.get_file(operation.id, self.user) == "gamma" # check if change is saved properly changes = self.fm.get_all_changes(operation.id, self.user) assert len(changes) == 2 - def test_cant_save(self): - with self.app.test_client(): - flight_path, operation = self._create_operation(flight_path="operation911") - assert self.fm.save_file(operation.id, "text", self.user) is False - incomplete = """ - - - """ - assert self.fm.save_file(operation.id, incomplete, self.user) is False - incomplete = """ - - - - - - - - - - """ - assert self.fm.save_file(operation.id, incomplete, self.user) is False - - def test_stub_data(self): - with self.app.test_client(): - flight_path, operation = self._create_operation(flight_path="operationstub") - content = self.fm.get_file(operation.id, self.user) - assert flight_path == "operationstub" - assert content == mscolab_settings.STUB_CODE - def test_undo(self): with self.app.test_client(): - flight_path, operation = self._create_operation(flight_path="operation7", content=XML_CONTENT1) - assert self.fm.save_file(operation.id, XML_CONTENT2, self.user) - assert self.fm.save_file(operation.id, XML_CONTENT3, self.user) + flight_path, operation = self._create_operation(flight_path="operation7", content="alpha") + assert self.fm.save_file(operation.id, "beta", self.user) + assert self.fm.save_file(operation.id, "gamma", self.user) changes = Change.query.filter_by(op_id=operation.id).all() assert changes is not None assert changes[0].id == 1 assert self.fm.undo_changes(changes[0].id, self.user) is True assert len(self.fm.get_all_changes(operation.id, self.user)) == 3 - assert XML_CONTENT2 == self.fm.get_file(operation.id, self.user) + assert "beta" in self.fm.get_file(operation.id, self.user) def test_get_operation(self): with self.app.test_client(): @@ -186,7 +156,8 @@ def test_delete_operation(self): assert len(messages) == 0 def _example_data(self): - self.content1 = """ + self.content1 = """\ + new flight track (1) @@ -207,7 +178,8 @@ def _example_data(self): """ - self.content2 = """ + self.content2 = """\ + new flight track (1) diff --git a/tests/_test_mscolab/test_files_api.py b/tests/_test_mscolab/test_files_api.py index 14e4b871e..43dcb4864 100644 --- a/tests/_test_mscolab/test_files_api.py +++ b/tests/_test_mscolab/test_files_api.py @@ -29,7 +29,6 @@ from mslib.mscolab.models import Operation from mslib.mscolab.seed import add_user, get_user -from tests.utils import XML_CONTENT1, XML_CONTENT2, XML_CONTENT3 class Test_Files: @@ -171,8 +170,8 @@ def test_delete_operation(self): def test_get_all_changes(self): with self.app.test_client(): flight_path, operation = self._create_operation(flight_path="V11") - assert self.fm.save_file(operation.id, XML_CONTENT1, self.user) - assert self.fm.save_file(operation.id, XML_CONTENT2, self.user) + assert self.fm.save_file(operation.id, "content1", self.user) + assert self.fm.save_file(operation.id, "content2", self.user) all_changes = self.fm.get_all_changes(operation.id, self.user) # the newest change is on index 0, because it has a recent created_at time assert len(all_changes) == 2 @@ -182,20 +181,20 @@ def test_get_all_changes(self): def test_get_change_content(self): with self.app.test_client(): - flight_path, operation = self._create_operation(flight_path="V12", content=XML_CONTENT3) - assert self.fm.save_file(operation.id, XML_CONTENT1, self.user) - assert self.fm.save_file(operation.id, XML_CONTENT2, self.user) - assert self.fm.save_file(operation.id, XML_CONTENT3, self.user) + flight_path, operation = self._create_operation(flight_path="V12", content='initial') + assert self.fm.save_file(operation.id, "content1", self.user) + assert self.fm.save_file(operation.id, "content2", self.user) + assert self.fm.save_file(operation.id, "content3", self.user) all_changes = self.fm.get_all_changes(operation.id, self.user) previous_change = self.fm.get_change_content(all_changes[2]["id"], self.user) - assert previous_change == XML_CONTENT1 + assert previous_change == "content1" previous_change = self.fm.get_change_content(all_changes[1]["id"], self.user) - assert previous_change == XML_CONTENT2 + assert previous_change == "content2" def test_set_version_name(self): with self.app.test_client(): - flight_path, operation = self._create_operation(flight_path="V13", content=XML_CONTENT3) - assert self.fm.save_file(operation.id, XML_CONTENT1, self.user) + flight_path, operation = self._create_operation(flight_path="V13", content='initial') + assert self.fm.save_file(operation.id, "content1", self.user) all_changes = self.fm.get_all_changes(operation.id, self.user) ch_id = all_changes[-1]["id"] self.fm.set_version_name(ch_id, operation.id, self.user.id, "berlin") diff --git a/tests/_test_mscolab/test_models.py b/tests/_test_mscolab/test_models.py index bf38a4894..8b0a2140f 100644 --- a/tests/_test_mscolab/test_models.py +++ b/tests/_test_mscolab/test_models.py @@ -30,7 +30,7 @@ from zoneinfo import ZoneInfo from mslib.mscolab.server import register_user -from mslib.mscolab.models import AwareDateTime, User, Permission, Operation, Message, MessageType, Change +from mslib.mscolab.models import AwareDateTime, User, Permission, Operation, Message, Change def test_aware_datetime_conversion(): @@ -90,12 +90,12 @@ def test_operation_repr(): def test_message_creation(): - message = Message(1, 1, "Hello, this is a test message", MessageType.TEXT, None) + message = Message(1, 1, "Hello, this is a test message", "TEXT", None) assert message.op_id == 1 assert message.u_id == 1 assert message.text == "Hello, this is a test message" - assert message.message_type == MessageType.TEXT + assert message.message_type == "TEXT" assert message.reply_id is None diff --git a/tests/_test_mscolab/test_server.py b/tests/_test_mscolab/test_server.py index f7085e450..9ffb47a0c 100644 --- a/tests/_test_mscolab/test_server.py +++ b/tests/_test_mscolab/test_server.py @@ -33,14 +33,12 @@ from mslib.mscolab.server import check_login, register_user from mslib.mscolab.file_manager import FileManager from mslib.mscolab.seed import add_user, get_user -from tests.utils import XML_CONTENT1, XML_CONTENT2 class Test_Server: @pytest.fixture(autouse=True) - def setup(self, mscolab_app, mscolab_managers): + def setup(self, mscolab_app): self.app = mscolab_app - self.sockio, _, self.fm = mscolab_managers self.userdata = 'UV10@uv10', 'UV10', 'uv10' with self.app.app_context(): yield @@ -196,17 +194,6 @@ def test_create_operation(self): assert operation.active is False assert token is not None - def test_dont_create_operation(self): - content = """ - - - -""" - assert add_user(self.userdata[0], self.userdata[1], self.userdata[2]) - with self.app.test_client() as test_client: - operation, token = self._create_operation(test_client, self.userdata, content=content) - assert operation is None - def test_get_operation_by_id(self): assert add_user(self.userdata[0], self.userdata[1], self.userdata[2]) with self.app.test_client() as test_client: @@ -245,16 +232,8 @@ def test_get_all_changes(self): assert add_user(self.userdata[0], self.userdata[1], self.userdata[2]) with self.app.test_client() as test_client: operation, token = self._create_operation(test_client, self.userdata) - self._save_content(operation, self.userdata) - sio = self.sockio.test_client(self.app) - # ToDo implement storing comment - sio.emit('file-save', { - "op_id": operation.id, - "token": token, - "content": XML_CONTENT2, - "comment": "XML_CONTENT2"}) - sio.emit('disconnect') - + fm, user = self._save_content(operation, self.userdata) + fm.save_file(operation.id, "content2", user) # the newest change is on index 0, because it has a recent created_at time response = test_client.get('/get_all_changes', data={"token": token, "op_id": operation.id}) @@ -270,35 +249,22 @@ def test_get_change_content(self): assert add_user(self.userdata[0], self.userdata[1], self.userdata[2]) with self.app.test_client() as test_client: operation, token = self._create_operation(test_client, self.userdata) - user = self._save_content(operation, self.userdata) - sio = self.sockio.test_client(self.app) - # ToDo implement storing comment - sio.emit('file-save', { - "op_id": operation.id, - "token": token, - "content": XML_CONTENT2, - "comment": "XML_CONTENT2"}) - sio.emit('disconnect') - all_changes = self.fm.get_all_changes(operation.id, user) + fm, user = self._save_content(operation, self.userdata) + fm.save_file(operation.id, "content2", user) + all_changes = fm.get_all_changes(operation.id, user) response = test_client.get('/get_change_content', data={"token": token, "ch_id": all_changes[1]["id"]}) assert response.status_code == 200 data = json.loads(response.data.decode('utf-8')) - assert data == {'content': XML_CONTENT1} + assert data == {'content': 'content1'} def test_set_version_name(self): assert add_user(self.userdata[0], self.userdata[1], self.userdata[2]) with self.app.test_client() as test_client: operation, token = self._create_operation(test_client, self.userdata) - user = self._save_content(operation, self.userdata) - sio = self.sockio.test_client(self.app) - sio.emit('file-save', { - "op_id": operation.id, - "token": token, - "content": XML_CONTENT2, - "comment": "XML_CONTENT2"}) - sio.emit("disconnect") - all_changes = self.fm.get_all_changes(operation.id, user) + fm, user = self._save_content(operation, self.userdata) + fm.save_file(operation.id, "content2", user) + all_changes = fm.get_all_changes(operation.id, user) ch_id = all_changes[1]["id"] version_name = "THIS" response = test_client.post('/set_version_name', data={"token": token, @@ -414,8 +380,7 @@ def test_import_permissions(self): # creator is not listed assert data["success"] is True - def _create_operation(self, test_client, userdata=None, path="firstflight", description="simple test", active=True, - content=None): + def _create_operation(self, test_client, userdata=None, path="firstflight", description="simple test", active=True): if userdata is None: userdata = self.userdata response = test_client.post('/token', data={"email": userdata[0], "password": userdata[2]}) @@ -424,9 +389,9 @@ def _create_operation(self, test_client, userdata=None, path="firstflight", desc response = test_client.post('/create_operation', data={"token": token, "path": path, "description": description, - "content": content, "active": str(active)}) assert response.status_code == 200 + assert response.data.decode('utf-8') == "True" operation = Operation.query.filter_by(path=path).first() return operation, token @@ -444,5 +409,6 @@ def _save_content(self, operation, userdata=None): if userdata is None: userdata = self.userdata user = get_user(userdata[0]) - self.fm.save_file(operation.id, XML_CONTENT1, user) - return user + fm = FileManager(self.app.config["MSCOLAB_DATA_DIR"]) + fm.save_file(operation.id, "content1", user) + return fm, user diff --git a/tests/_test_utils/test_verify_waypoint_data.py b/tests/_test_utils/test_verify_waypoint_data.py deleted file mode 100644 index c87d802e5..000000000 --- a/tests/_test_utils/test_verify_waypoint_data.py +++ /dev/null @@ -1,119 +0,0 @@ -# -*- coding: utf-8 -*- -""" - - tests._test_utils.test_verify_xml_waypoint - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This tests for valid xml data of waypoint data. - - This file is part of MSS. - - :copyright: Copyright 2024 Reimar Bauer - :license: APACHE-2.0, see LICENSE for details. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" -import pytest - -from mslib.utils.verify_waypoint_data import verify_waypoint_data - - -flight_track_with_waypoints = """ - - - - - - - - - - - - - - - - """ - -flight_track_with_waypoints_and_broken_by_linebreak = """ - - - - - - - - - - - - - - - - - """ - -flight_track_empty = """ - - - - """ - -flight_track_incomplete = """ - - - - - - - - - - - - - - - - """ - -flight_track_with_typo = """ - - - - - - - - - - - - - """ # typo is "233.0"" - -cases = [ - (flight_track_with_waypoints, True), - (flight_track_with_waypoints_and_broken_by_linebreak, False), - (flight_track_empty, False), - (flight_track_incomplete, False), - (flight_track_with_typo, False), -] - - -@pytest.mark.parametrize("xml_content, verification_result", cases) -def test_verify_xml_waypoint(xml_content, verification_result): - """Test xml verification.""" - assert verify_waypoint_data(xml_content) is verification_result diff --git a/tests/utils.py b/tests/utils.py index b7a47b7e9..7e0083f5d 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -34,57 +34,6 @@ from tests.constants import MSUI_CONFIG_PATH -XML_CONTENT1 = """ - - - - - - - - - - - - - - - - """ - - -XML_CONTENT2 = """ - - - - - - - - - - """ - - -XML_CONTENT3 = """ - - - - - - - - - - - - - - - - """ - - def callback_ok_image(status, response_headers): assert status == "200 OK" assert response_headers[0] == ('Content-type', 'image/png')