diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 6c8e77ee5..0ab2fa5fd 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,6 +13,21 @@ on: - 'GSOC**' jobs: + codespell: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3 + uses: actions/setup-python@v5 + with: + python-version: "3.x" + - name: Lint with codespell + run: | + python -m pip install --upgrade pip + pip install codespell + git ls-files -z | xargs -0 codespell --check-filenames + flake8: runs-on: ubuntu-latest timeout-minutes: 10 @@ -26,7 +41,7 @@ jobs: run: | python -m pip install --upgrade pip pip install flake8 flake8-builtins - flake8 --count --statistics mslib tests + git ls-files -z '**.py' | xargs -0 flake8 no-crlf-in-git: runs-on: ubuntu-latest diff --git a/.github/workflows/testing-all-oses.yml b/.github/workflows/testing-all-oses.yml index 92f38804c..86fb996fc 100644 --- a/.github/workflows/testing-all-oses.yml +++ b/.github/workflows/testing-all-oses.yml @@ -43,7 +43,7 @@ jobs: # Set the cache key in a way that the cache is invalidated every week on monday cache-environment-key: environment-${{ steps.year-and-week.outputs.year-and-week }} - name: Run tests - timeout-minutes: 20 + timeout-minutes: 40 # The ignored files can somehow cause the test suite to timeout. # 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. diff --git a/CHANGES.rst b/CHANGES.rst index a4d234058..a92d20429 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,15 @@ Changelog ========= +Version 9.1.0 +~~~~~~~~~~~~~ + +Bug fix release and minor enhancements: +We have corrected spelling mistakes + +All changes: +https://github.com/Open-MSS/MSS/milestone/105?closed=1 + Version 9.0.0 ~~~~~~~~~~~~~ @@ -10,7 +19,8 @@ In this way, a user can authenticate themselves in one system and gain access to by providing proof of authentication. In our documentation in the Components section you find a detailed description. Matthias Riße refactored the test suite and optimized and accelerated our CI test runs. -All tests run in parallel now and are not retried upon failure, and most tests are also executed in a randomized order, instilling more confidence in the results. +All tests run in parallel now and are not retried upon failure, and most tests are also executed in a randomized order, +instilling more confidence in the results. Quite a bit of duplicated code was unified, mostly using pytest fixtures. Additionally, CI test runs now also happen on x86_64- and ARM-based macOS. @@ -24,7 +34,7 @@ HINT: The syntax of the server configuration of MSColab and MSWMS has changed. We removed the class definition. For MSColab we have added new configuration options related to SAML2. The change on the MSColab server also required changes on the MSUI handling the MSColab login. These changes are -not backwards compatible. Server and Client must use versions >=9.0.0. +not backwards compatible. MSColab Server and MSUI Client must use versions >=9.0.0. We introduced a MSCOLAB_auth_user_name in the users configuration which simplifies the login process. All changes: @@ -80,7 +90,7 @@ https://github.com/Open-MSS/MSS/milestone/99?closed=1 Version 8.3.0 ~~~~~~~~~~~~~ -Bug fix release and minor enhacements: +Bug fix release and minor enhancements: We improved the KML docking widget feature All changes: @@ -89,7 +99,7 @@ https://github.com/Open-MSS/MSS/milestone/98?closed=1 Version 8.2.0 ~~~~~~~~~~~~~ -Bug fix release and minor enhacements: +Bug fix release and minor enhancements: HINT: ~~~~~ @@ -148,12 +158,12 @@ Jatin Jain did UI and server improvements in his GSoC project. Users can now, compare and plot multiple flightpaths on topview. This feature can be used for flightpathes or MSColab operations. A fligthpath style width can be changed. -Timestamps are dislayed below each message in MSColab. +Timestamps are displayed below each message in MSColab. Mscolab Operations in use for more than 30 days, move to an inactive list. The initial idea for multiple flightpaths on topview stems from bkirbus. GSoC mentors were Reimar Bauer, Jörn Ungermann, Sonja Gisinger -With MSS 9.0.0 we base our installation on miniforge. This has +With MSS 8.0.0 we base our installation on miniforge. This has mamba in the base environment. Mambaforge is discouraged of September 2023. All changes: @@ -311,7 +321,7 @@ Version 6.1.0 ~~~~~~~~~~~~~ This release includes some small improvements of the usablity. -A few bug fixes, a new plugin for NAVAID waypoints is decribed and +A few bug fixes, a new plugin for NAVAID waypoints is described and mscolab gots few improvements for user creation. Wind speed plots can now be created for altitudes > 25km. @@ -474,7 +484,7 @@ HINT: ~~~~~ For using the 1-D samples along the flight path you have to add a configuration to your -mss_wms_settings.py. Similiar as to the other layers add: +mss_wms_settings.py. Similar as to the other layers add: .. code-block:: python @@ -634,7 +644,7 @@ Bug Fixes: - Error in handling project permission update in mscolab, #539 - mscolab: Selected Project highlight removed if new project is added, #533 - GUI tests fail in OSX, #531 - - developer hint seperate data from source, #529 + - developer hint separate data from source, #529 - PyVirtualDisplay Package not found for Windows OS, #527 - sync our meta.yaml with the one on conda-forge, #526 - improve "Building a development environment", #524 @@ -657,7 +667,7 @@ Bug Fixes: - make rtfd use of Non-ASCII characters, #492 - mscolab server command crashes, #491 - MSS doesn't close when "quit"ing while being connected to MSCO server, #490 - - "Checkout" of older revisions has no effect without double-clicking the revison, #485 + - "Checkout" of older revisions has no effect without double-clicking the revision, #485 - Adding unknown user to project throws exception, #483 - mcso windows cannot be closed by ctrl+w, #473 @@ -698,7 +708,7 @@ HINT ~~~~ - We deprecated and disabled the unmaintained feature trajectory and time series view. This will become removed in the next major release, #476 - - We added a new powerfull feature for collaborative editing of flight pathes. + - We added a new powerful feature for collaborative editing of flight paths. This is a new server and also a new client gui window. In a future version the client gui will replace the standard gui. @@ -771,8 +781,8 @@ New Features: - Avoid "catch-all" exception handlers, #42 Bug Fixes: - - Top View Map Appeareance options not defined with web map services, #401 - - Image dissappears after insert/delete operation in sideview mode, #399 + - Top View Map Appearance options not defined with web map services, #401 + - Image disappears after insert/delete operation in sideview mode, #399 - sideview options dialog suffix always hPa, #394 - Msui crashes on selecting Northern Hemisphere (stereo) from drop down menu under Top View section, #388 - qt widget property issue, #387 @@ -781,7 +791,7 @@ Bug Fixes: Other Changes: - clean up comments, #406 - - remove superflous pass statements, #405 + - remove superfluous pass statements, #405 - Change comments for function "flightlevel2pressure_a", #384 - Documentation about Reporting Issues, #112 @@ -822,7 +832,7 @@ Bug Fixes: - Support http://msgcpp-ogc-realtime.knmi.nl/msgrt.cgi WMS Server, #352 - Support http://geoservices.knmi.nl/cgi-bin/HARM_N25.cgi WMS server, #351 - Support NASA WMS Server "https://neo.sci.gsfc.nasa.gov/wms/wms", #348 - - wms server: return only on the getcapability request a capabilty document, #346 + - wms server: return only on the getcapability request a capability document, #346 - demodata pressure levels uses inconsistent units, #341 - waypoint labels (in sideview) not readable, #317 @@ -865,7 +875,7 @@ Version 1.7.0 ------------- New Features: - - Decrease unit depency of plotting styles, #328 + - Decrease unit dependency of plotting styles, #328 - Support basemap 1.1.0, #315, #329 - zorder of several plot elements in topview is wrong, #314 - pyfilesystem2 implemented, #313 @@ -933,7 +943,7 @@ Version 1.6.0 New Features: - disable traceback for server, #156 - - hybrid sigma coordinate whould work with float values, #203 + - hybrid sigma coordinate would work with float values, #203 - WMS data access classes difficult to set up, #210 - add mss to docker platform, 211 - loading a flighttrackfile does not set filename, #214 @@ -948,7 +958,7 @@ New Features: - Try preloading WMS servers on startup, #250 - traceback should show version info, #256 - add version info to output files, #259 - - completly remove vt_cache, #260 + - completely remove vt_cache, #260 - update layer list on get_capabilities, #268 Bug Fixes: @@ -1033,7 +1043,7 @@ Version 1.5.1 ------------- Bug Fixes: - - clicks on same position crashs waypoint insert for cyl projection, #197 + - clicks on same position crashes waypoint insert for cyl projection, #197 - existing picklefiles of py2 crash on py3 version (vice versa), #198 @@ -1051,12 +1061,12 @@ New Features: - refactored url strings, #150 - performance data used for time information on vertical plots, #151 - use a singleton for WMS capability storage, #168 - - ui files, _test folders excluded from conda build pacakages, #169 + - ui files, _test folders excluded from conda build packages, #169 - implemented virtualdisplay for linux, #172 - cache for basemap coastline and country shape data added, #173 - - consistant naming of "as" imports, #175 + - consistent naming of "as" imports, #175 - loopview enable/disabled, based on given URL, #183 - - configurable external proxy to cache on low bandwidth transfered images, #188 + - configurable external proxy to cache on low bandwidth transferred images, #188 Bug Fixes: @@ -1067,7 +1077,7 @@ Bug Fixes: Other Changes: - - line seperator of source files unified to LF, #92 + - line separator of source files unified to LF, #92 - refactored whole codebase for compatibility with python3, #176 - version number of recent conda package added to documentation, #185 - split mss_settings.json.sample into snippet parts, and further documentation #194 @@ -1131,7 +1141,7 @@ Version 1.3.3 Bug Fixes: - Inserting Waypoint outside of map in TopView crashes MSS, #149 - - Some of the additional tools don't close completly, #139 + - Some of the additional tools don't close completely, #139 Version 1.3.2 @@ -1279,7 +1289,7 @@ Bug Fixes: Other Changes: - - Namespace refactored, all modules dependend to mslib #24 + - Namespace refactored, all modules dependent to mslib #24 - Sphinx documentation introduced, #25, #26 - Documentation on http://mss.rtfd.io - Installation recipes based on conda diff --git a/README.md b/README.md index ed3e5cb59..f819688af 100644 --- a/README.md +++ b/README.md @@ -72,13 +72,17 @@ Current release info ==================== [![Conda Version](https://img.shields.io/conda/vn/conda-forge/mss.svg)](https://anaconda.org/conda-forge/mss) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.6572620.svg)](https://doi.org/10.5281/zenodo.6572620) +[![JuRSE Code Pick](https://img.shields.io/badge/JuRSE_Code_Pick-July_2024-blue)](https://www.fz-juelich.de/en/rse/jurse-community/jurse-code-of-the-month/july-2024) [![Conda Platforms](https://img.shields.io/conda/pn/conda-forge/mss.svg)](https://anaconda.org/conda-forge/mss) -[![DOCS](https://img.shields.io/badge/%F0%9F%95%AE-docs-green.svg)](http://mss.rtd.io) +[![DOCS](https://img.shields.io/badge/%F0%9F%95%AE-docs-green.svg)](https://mss.rtfd.io) [![Conda Recipe](https://img.shields.io/badge/recipe-mss-green.svg)](https://anaconda.org/conda-forge/mss) [![Conda Downloads](https://img.shields.io/conda/dn/conda-forge/mss.svg)](https://anaconda.org/conda-forge/mss) [![Coverage Status](https://coveralls.io/repos/github/Open-MSS/MSS/badge.svg?branch=develop)](https://coveralls.io/github/Open-MSS/MSS?branch=develop) + + + Publications ============ diff --git a/codespell-ignored-lines.txt b/codespell-ignored-lines.txt new file mode 100644 index 000000000..36a2dc392 --- /dev/null +++ b/codespell-ignored-lines.txt @@ -0,0 +1,2 @@ + ssl_ciphers HIGH:!aNULL:!MD5; + - moved of mslib.thirdparty.owslib to mslib.owslib and hardcoded all imports in owslib to mslib.owslib, #1 diff --git a/conftest.py b/conftest.py index e596983d7..b9bf7f543 100644 --- a/conftest.py +++ b/conftest.py @@ -28,8 +28,6 @@ import importlib.util import os import sys -import logging -import matplotlib # Disable pyc files sys.dont_write_bytecode = True @@ -85,7 +83,7 @@ def generate_initial_config(): if not constants.ROOT_FS.exists("msui/testdata"): constants.ROOT_FS.makedirs("msui/testdata") - # make a copy for mscolab test, so that we read different pathes during parallel tests. + # make a copy for mscolab test, so that we read different paths during parallel tests. sample_path = os.path.join(os.path.dirname(__file__), "tests", "data") shutil.copy(os.path.join(sample_path, "example.ftml"), constants.ROOT_DIR) @@ -188,7 +186,6 @@ def generate_initial_config(): # windows needs \\ or / but mixed is terrible. *nix needs / mscolab_fs.writetext(constants.MSCOLAB_CONFIG_FILE, config_string.replace('\\', '/')) path = fs.path.join(constants.ROOT_DIR, 'mscolab', constants.MSCOLAB_CONFIG_FILE) - parent_path = fs.path.join(constants.ROOT_DIR, 'mscolab') if not constants.SERVER_CONFIG_FS.exists(constants.MSCOLAB_AUTH_FILE): config_string = ''' @@ -211,7 +208,6 @@ def _load_module(module_name, path): sys.modules[module_name] = module spec.loader.exec_module(module) - _load_module("mswms_settings", constants.SERVER_CONFIG_FILE_PATH) _load_module("mscolab_settings", path) @@ -227,7 +223,8 @@ def _load_module(module_name, path): def reset_config(): """Reset the configuration directory used in the tests (tests.constants.ROOT_FS) after every test """ - # Ideally this would just be constants.ROOT_FS.removetree("/"), but SQLAlchemy complains if the SQLite file is deleted. + # Ideally this would just be constants.ROOT_FS.removetree("/"), but SQLAlchemy complains if the SQLite file is + # deleted. for e in constants.ROOT_FS.walk.files(exclude=["mscolab.db"]): constants.ROOT_FS.remove(e) for e in constants.ROOT_FS.walk.dirs(search="depth"): @@ -239,4 +236,4 @@ def reset_config(): # Make fixtures available everywhere -from tests.fixtures import * +from tests.fixtures import * # noqa: F401, F403 diff --git a/docs/about.rst b/docs/about.rst index cc2e542b0..8b39fa961 100644 --- a/docs/about.rst +++ b/docs/about.rst @@ -3,8 +3,8 @@ About The Mission Support System (MSS) is a software that is written by scientists in the field of atmospheric science. The purpose is to have a tool that simplifies the process for planning a scientific flight in which -parameters of the atmosphere are measured. The research aircrafts typically carry a comprehensive scientific payload -comprised of data aquisition instruments by different companies and research institutions. +parameters of the atmosphere are measured. The research aircraft typically carry a comprehensive scientific payload +comprised of data acquisition instruments by different companies and research institutions. The measurement of relevant parameters, for example the chemical composition of trace gases, temperature or aerosol particle characteristics, are needed to improve the scientific understanding of the processes in the atmosphere. This is of significant importance for the understanding for example of climate change or the diff --git a/docs/conf.py b/docs/conf.py index 1b9fec3f0..bbd933540 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -13,15 +13,16 @@ # serve to show the default. import os import sys -import logging import setuptools import subprocess import requests import zipfile import shutil +import pathlib from string import Template + def get_tutorial_images(): TUTORIAL_URL = "https://fz-juelich.sciebo.de/s/KcF29hPNRzkxN6q/download" TUTORIAL_DIR = 'videos/mp4' @@ -97,24 +98,21 @@ def get_tutorial_images(): mslib.mswms.wms.server.generate_gallery(sphinx=True, generate_code=True, all_plots=True, levels="3,4,200,300", vtimes="2012-10-18T00:00:00,2012-10-19T00:00:00") -# readthedocs has no past.builtins -try: - from past.builtins import execfile -except ImportError as ex: - logging.error("%s", ex) -execfile('../mslib/version.py') +version = {} +exec(pathlib.Path("../mslib/version.py").read_text(), version) +__version__ = version["__version__"] on_rtd = os.environ.get('READTHEDOCS') == 'True' # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +# sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -133,14 +131,14 @@ def get_tutorial_images(): source_suffix = '.rst' # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = 'MSS - Mission Support System' -copyright = \ +project_copyright = \ '2016-2024 by the MSS team, see AUTHORS, ' \ '2011-2014 Marc Rautenhaus, ' \ '2008-2014 Deutsches Zentrum fuer Luft- und Raumfahrt e.V.' @@ -178,9 +176,9 @@ def get_tutorial_images(): # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' today_fmt = '%Y-%m-%d' # List of patterns, relative to source directory, that match files and @@ -190,27 +188,27 @@ def get_tutorial_images(): # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False @@ -230,7 +228,7 @@ def get_tutorial_images(): htmls_static_path = ['_static'] html_css_files = ['mss.css'] html_context = { - 'display_github': False, # Add 'Edit on Bitbucket' link instead of 'View page source' + 'display_github': False, # Add 'Edit on Bitbucket' link instead of 'View page source' 'last_updated': True, 'commit': False, } @@ -238,17 +236,17 @@ def get_tutorial_images(): # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. # " v documentation" by default. -#html_title = u'MSS - Mission Support System v1.1' +# html_title = u'MSS - Mission Support System v1.1' # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. @@ -257,7 +255,7 @@ def get_tutorial_images(): # The name of an image file (relative to this directory) to use as a favicon of # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -269,64 +267,64 @@ def get_tutorial_images(): # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not None, a 'Last updated on:' timestamp is inserted at every page # bottom, using the given strftime format. # The empty string is equivalent to '%b %d, %Y'. -#html_last_updated_fmt = None +# html_last_updated_fmt = None # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh' -#html_search_language = 'en' +# html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # 'ja' uses this config value. # 'zh' user can custom change `jieba` dictionary path. -#html_search_options = {'type': 'default'} +# html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' +# html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. htmlhelp_basename = 'MSS-MissionSupportSystemdoc' @@ -334,46 +332,51 @@ def get_tutorial_images(): # -- Options for LaTeX output --------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', + # The paper size ('letterpaper' or 'a4paper'). + # 'papersize': 'letterpaper', -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', + # The font size ('10pt', '11pt' or '12pt'). + # 'pointsize': '10pt', -# Additional stuff for the LaTeX preamble. -#'preamble': '', + # Additional stuff for the LaTeX preamble. + # 'preamble': '', -# Latex figure (float) alignment -#'figure_align': 'htbp', + # Latex figure (float) alignment + # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'MSS-MissionSupportSystem.tex', 'MSS - Mission Support System Documentation', - u'A.Hilboll, A.Lal, C.Rolf, I.Krisch, J.-U.Grooß, J.Ungermann, M.Rautenhaus, R.Bauer, S.Padhi, T.Breuer', 'manual'), + ( + master_doc, + 'MSS-MissionSupportSystem.tex', + 'MSS - Mission Support System Documentation', + 'A.Hilboll, A.Lal, C.Rolf, I.Krisch, J.-U.Grooß, J.Ungermann, M.Rautenhaus, R.Bauer, S.Padhi, T.Breuer', + 'manual' + ), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output --------------------------------------- @@ -386,7 +389,7 @@ def get_tutorial_images(): ] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -401,14 +404,14 @@ def get_tutorial_images(): ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False suppress_warnings = ['image.nonlocal_uri'] diff --git a/docs/development.rst b/docs/development.rst index 26f4dca81..2fbd3d199 100644 --- a/docs/development.rst +++ b/docs/development.rst @@ -7,8 +7,8 @@ This chapter will get you started with MSS development. MSS is written in Python. -Once a stable release is published we do only bug fixes in stable and release regulary -new minor versions. If a fix needs a API change or it is likly more a new feature you have +Once a stable release is published we do only bug fixes in stable and release regularly +new minor versions. If a fix needs a API change or it is likely more a new feature you have to make a pull request to the develop branch. Documentation of changes is done by using our `issue tracker `_. @@ -147,7 +147,7 @@ Using predefined docker images instead of installing all requirements You can easily use our testing docker images which have all libraries pre installed. These are based on miniforge. We provide two images. In openmss/testing-stable we have mss-stable-env and in openmss/testing-develop we have mss-develop-env defined. -In the further course of the documentation we speak of the environment mssdev, this corresponds to one of these evironments. +In the further course of the documentation we speak of the environment mssdev, this corresponds to one of these environments. You can either mount your MSS workdir in the container or use the environment from the container as environment on your machine. @@ -282,7 +282,7 @@ Building the docs with Sphinx The documentation (in reStructuredText format, .rst) is in docs/. Usually building the docs also includes creating the images and pages for the gallery feature. -This can be ommitted by setting an environment variable :: +This can be omitted by setting an environment variable :: export GALLERY=False @@ -428,7 +428,7 @@ After filling the template completely click on Pull request Merging stable into develop --------------------------- -Bug fixes we have done in stable we need to merge regulary into develop too:: +Bug fixes we have done in stable we need to merge regularly into develop too:: git checkout stable git pull git@github.com:Open-MSS/MSS.git stable diff --git a/docs/index.rst b/docs/index.rst index bc31a763b..02af2912c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,7 +3,7 @@ Mission Support System's Documentation ====================================== -|Conda Version| |GitHub Issues| |Coverage Status| |DOI| |Conda Platforms| |Conda Recipe| |Conda Downloads| +|Conda Version| |DOI| |JuRSE Code Pick| |GitHub Issues| |Coverage Status| |Conda Platforms| |Conda Recipe| |Conda Downloads| .. |Conda Version| image:: https://img.shields.io/conda/vn/conda-forge/mss.svg :target: https://anaconda.org/conda-forge/mss @@ -13,6 +13,8 @@ Mission Support System's Documentation :target: https://coveralls.io/github/Open-MSS/MSS?branch=develop .. |DOI| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.6572620.svg :target: https://doi.org/10.5281/zenodo.6572620 +.. |JuRSE Code Pick| image:: https://img.shields.io/badge/JuRSE_Code_Pick-July_2024-blue + :target: https://www.fz-juelich.de/en/rse/jurse-community/jurse-code-of-the-month/july-2024 .. |Conda Platforms| image:: https://img.shields.io/conda/pn/conda-forge/mss.svg :target: https://anaconda.org/conda-forge/mss .. |Conda Recipe| image:: https://img.shields.io/badge/recipe-mss-green.svg diff --git a/docs/installation.rst b/docs/installation.rst index 539a0222b..9075d450a 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -6,7 +6,7 @@ The Mission Support System (MSS) including a Web Map Service, a Collaboration Se This channel conda-forge has builds for osx-64, linux-64, win-64 -The conda-forge `github organization `_ uses various automated continuos integration +The conda-forge `github organization `_ uses various automated continuous integration build processes. We provide an automatic installation and a manual installation. @@ -147,7 +147,7 @@ you could try the `mamba update mss` as described. .. Important:: - mamba is under development. All dependencies of MSS and MSS itselfs are under development. + mamba is under development. All dependencies of MSS and MSS itself are under development. Sometimes this update feature of mamba can't resolve from existing to new dependencies. search for MSS what you can get :: @@ -164,7 +164,7 @@ compare what you have installed :: mss 7.0.2 py310hff52083_0 conda-forge -We have reports that often an update suceeds by using the install option and the new version number, +We have reports that often an update succeeds by using the install option and the new version number, in this example $mss_version and python as second option :: (mssenv) $ mamba install mss=$mss_version python @@ -175,7 +175,7 @@ The alternative is to use a new environment and install mss. -For further details of configurating mss :ref:`msui-configuration` +For further details of configuring mss :ref:`msui-configuration` Docker Instance diff --git a/docs/mscolab.rst b/docs/mscolab.rst index 983cf2921..ec482b220 100644 --- a/docs/mscolab.rst +++ b/docs/mscolab.rst @@ -54,7 +54,7 @@ Make a text file with the following format to import many users to the mscolab d $ mscolab db --users_by_file /path/to/file -After executed you get informations to exchange with users. +After executed you get information to exchange with users. .. code-block:: text @@ -69,7 +69,7 @@ Further options can be listed by `mscolab db -h` User Groups for Operations .......................... -When you want to use same set of users for different operations using same catagory +When you want to use same set of users for different operations using same category you can do this by setting up users in a special operation. On a given category for an operation ending with GROUP_POSTFIX @@ -139,10 +139,10 @@ If you want to use nginx to proxy this gunicorn server have a look on the exampl Backup Data Base ................ -For backups you can dump by `pg_dump -d mscolab -f outpu.sql` the sqlite database +For backups you can dump by `pg_dump -d mscolab -f output.sql` the sqlite database and restore it by `psql -v ON_ERROR_STOP=1 < new_db.sql` -On a PostgreSQL db you can regulary do backups by creating a dump +On a PostgreSQL db you can regularly do backups by creating a dump by `pg_dump `_ using a cron job :: #!/bin/bash @@ -150,8 +150,12 @@ by `pg_dump `_ using a pg_dump -d mscolab -f "/home/mscolab/dump/$timestamp.sql" -Data Base Migration -................... +Data Base Migration from version 8 +.................................. + +.. important:: + This manual migration on the server side by a user is deprecated and will become removed with version 10.0.0. + With version 10.0.0, the initialization of the database will be refactored and migrations will be performed automatically when mscolab is started For an easy way to update the database scheme we implemented `flask migrate `_. @@ -162,15 +166,58 @@ You have to create based on your configuration a migration script and call that export PYTHONPATH=`pwd` cd ~/INSTANCE/wsgi flask --app mscolab.py db init - flask --app mscolab.py db migrate -m "To version 8.0.0" + flask --app mscolab.py db migrate -m "To version 9.0.0" flask --app mscolab.py db upgrade +The migration script builder does the base but the created script needs first allow nullable so that we afterwards set the default for the existing data. +Use this as an example for your script :: + + """To version 9.0.0 + + Revision ID: e62d08ce88a4 + Revises: 27a026b0daec + Create Date: 2024-06-07 16:53:43.314338 + + """ + from alembic import op + import sqlalchemy as sa + + + # revision identifiers, used by Alembic. + revision = 'e62d08ce88a4' + down_revision = '27a026b0daec' + branch_labels = None + depends_on = None + + + def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('users', schema=None) as batch_op: + batch_op.add_column(sa.Column('authentication_backend', sa.String(length=255), nullable=True)) + op.execute('UPDATE users SET authentication_backend = \'local\' WHERE authentication_backend IS NULL') + + with op.batch_alter_table('users', schema=None) as batch_op: + batch_op.alter_column('authentication_backend', existing_type=sa.String(length=255), nullable=False) + batch_op.drop_constraint('users_password_key', type_='unique') + + # ### end Alembic commands ### + + + def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('users', schema=None) as batch_op: + batch_op.create_unique_constraint('users_password_key', ['password']) + batch_op.drop_column('authentication_backend') + + # ### end Alembic commands ### + + The output looks like :: ~/INSTANCE/wsgi$ flask --app mscolab.py db upgrade INFO [alembic.runtime.migration] Context impl SQLiteImpl. INFO [alembic.runtime.migration] Will assume non-transactional DDL. - INFO [alembic.runtime.migration] Running upgrade -> b70961f58f94, To version 8.0.0 + INFO [alembic.runtime.migration] Running upgrade -> e62d08ce88a, To version 9.0.0 diff --git a/docs/mswms.rst b/docs/mswms.rst index 79b3a1eff..f77975027 100644 --- a/docs/mswms.rst +++ b/docs/mswms.rst @@ -495,7 +495,7 @@ package apache2-dev on your server. At current state we have to use pip to install mod_wsgi into the INSTANCE environment:: - # Instal `mod_wsgi` + # Install `mod_wsgi` $ pip install mod_wsgi # Find the full path to installed `mod_wsgi` @@ -505,24 +505,31 @@ At current state we have to use pip to install mod_wsgi into the INSTANCE enviro $ sudo /full/path/to/installed/mod_wsgi-express install-module +This command outputs two lines:: + + LoadModule wsgi_module "/usr/lib/apache2/modules/mod_wsgi-py310.cpython-310-x86_64-linux-gnu.so" + WSGIPythonHome "/home/mss-demo/miniforge/envs/mssenv" + +You have to add the lines into your wsgi_express.conf and wsgi_express.load + Setup a /etc/apache2/mods-available/wsgi_express.conf:: - WSGIPythonHome "/home/mss-demo/miniforge/envs/demo/" + WSGIPythonHome "/home/mss-demo/miniforge/envs/mssenv/" Setup a /etc/apache2/mods-available/wsgi_express.load:: - LoadModule wsgi_module "/usr/lib/apache2/modules/mod_wsgi-py37.cpython-37m-x86_64-linux-gnu.so" + LoadModule wsgi_module "/usr/lib/apache2/modules/mod_wsgi-py310.cpython-310-x86_64-linux-gnu.so" Enable the new module by a2enmod and reload the apache2 server Configuration of apache mod_wsgi.conf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -One posibility to setup the PYTHONPATH environment variable is by adding it to your mod_wsgi.conf. Alternativly you +One possibility to setup the PYTHONPATH environment variable is by adding it to your mod_wsgi.conf. Alternatively you could add it also to wms.wsgi. - WSGIPythonPath /home/mss/INSTANCE/config:/home/mss/miniforge/envs/instance/lib/python3.X/site-packages + WSGIPythonPath /home/mss/INSTANCE/config:/home/mss/miniforge/envs/mssenv/lib/python3.X/site-packages By this setting you override the PYTHONPATH environment variable. So you have also to add @@ -540,28 +547,41 @@ INSTANCE is a placeholder for your service name:: . ├── INSTANCE - | ├── config - │   | └── mswms_settings.py - | | └── mswms_auth.py - | ├── log - │   | └── mss_error.log - | └── wsgi - | ├── auth.wsgi - | └── wms.wsgi + │ ├── config + │ │ └── mswms_settings.py + │ │ └── mswms_auth.py + │ ├── log + │ │ └── mss_error.log + │ └── wsgi + │ ├── auth.wsgi + │ └── wms.wsgi ├── miniforge - │   ├── bin - │   ├── conda-bld - │   ├── conda-meta - │   ├── envs - | | └── instance - │   ├── etc - │   ├── include - │   ├── lib - │   ├── LICENSE.txt - │   ├── pkgs - │   ├── share - │   ├── ssl - │   └── var + │ ├── bin + │ ├── cmake + │ ├── compiler_compat + │ ├── _conda + │ ├── condabin + │ ├── conda-bld + │ ├── conda_build_config.yaml + │ ├── conda-meta + │ ├── envs + │ │ └── mssenv + │ ├── etc + │ ├── include + │ ├── lib + │ ├── libexec + │ ├── LICENSE.txt + │ ├── locks + │ ├── man + │ ├── pkgs + │ ├── sbin + │ ├── share + │ ├── shell + │ ├── ssl + │ ├── x86_64-conda_cos6-linux-gnu + │ └── x86_64-conda-linux-gnu + + @@ -616,7 +636,7 @@ Enable it with a2ensite mss.yourserver.de.conf Many Instances .............. -If you want to setup many instances we suggest to use a similiar proxy based configuration +If you want to setup many instances we suggest to use a similar proxy based configuration .. literalinclude:: samples/sites-available/mss_proxy.conf diff --git a/docs/samples/config/mscolab/setup_saml2_backend.py.sample b/docs/samples/config/mscolab/setup_saml2_backend.py.sample index 23d1cea61..d2bc963e6 100644 --- a/docs/samples/config/mscolab/setup_saml2_backend.py.sample +++ b/docs/samples/config/mscolab/setup_saml2_backend.py.sample @@ -32,7 +32,7 @@ class setup_saml2_backend: yaml_data["config"]["localhost_test_idp"]["key_file"] = \ f'{mscolab_settings.MSCOLAB_SSO_DIR}/key_mscolab.key' # set path to your mscolab key file yaml_data["config"]["localhost_test_idp"]["cert_file"] = \ - f'{mscolab_settings.MSCOLAB_SSO_DIR}/crt_mscolab.crt' # set path to your mscolab certiticate file + f'{mscolab_settings.MSCOLAB_SSO_DIR}/crt_mscolab.crt' # set path to your mscolab certificate file yaml_data["config"]["localhost_test_idp"]["metadata"]["local"][0] = \ f'{mscolab_settings.MSCOLAB_SSO_DIR}/idp.xml' # set path to your idp metadata xml file @@ -41,7 +41,7 @@ class setup_saml2_backend: if not os.path.exists(yaml_data["config"]["localhost_test_idp"]["metadata"]["local"][0]): yaml_data["config"]["localhost_test_idp"]["metadata"]["local"] = [] warnings.warn("idp.xml file does not exists !\ - Ignore this warning when you initializeing metadata.") + Ignore this warning when you initialize metadata.") localhost_test_idp = SPConfig().load(yaml_data["config"]["localhost_test_idp"]) sp_localhost_test_idp = Saml2Client(localhost_test_idp) diff --git a/docs/samples/config/msui/performance_simple.json.sample b/docs/samples/config/msui/performance_simple.json.sample index 5c20d1a70..420f8448e 100644 --- a/docs/samples/config/msui/performance_simple.json.sample +++ b/docs/samples/config/msui/performance_simple.json.sample @@ -11,5 +11,5 @@ "_comment3": "empty_weight: aircraft weight without fuel (lbs)", "_comment4": "climb/descent: weight(lbs), altitude(ft), duration(min), distance(nm), fuel(lbs)", "_comment5": "cruise: weight(lbs), altitude(ft), total air speed(nm/h), fuel flow(lbs/h)", - "_comment6": "ceiling: polynomial coeficients for relating weight (lbs) with peak flightlevel (hft). Leftmost coefficient is the intercept." + "_comment6": "ceiling: polynomial coefficients for relating weight (lbs) with peak flightlevel (hft). Leftmost coefficient is the intercept." } diff --git a/docs/samples/config/mswms/mss_chem_plots.py b/docs/samples/config/mswms/mss_chem_plots.py index e55508254..eddfcb903 100644 --- a/docs/samples/config/mswms/mss_chem_plots.py +++ b/docs/samples/config/mswms/mss_chem_plots.py @@ -128,7 +128,7 @@ def _plot_style(self): def make_msschem_hs_class( - entity, nam, vert, units, scale, add_data=None, add_contours=None, fix_styles=None, + entity, name, vert, units, scale, add_data=None, add_contours=None, fix_styles=None, add_styles=None, add_prepare=None): if add_data is None: add_data = [] @@ -143,7 +143,7 @@ class fnord(HS_MSSChemStyle): dataname = entity units = units unit_scale = scale - _title_tpl = nam + " (" + vert + ")" + _title_tpl = name + " (" + vert + ")" long_name = entity if units: _title_tpl += f"({units})" @@ -151,7 +151,7 @@ class fnord(HS_MSSChemStyle): required_datafields = [(vert, entity, None)] + add_data contours = add_contours - fnord.__name__ = nam + fnord.__name__ = name fnord.styles = list(fnord.styles) return fnord @@ -285,7 +285,7 @@ def _plot_style(self): def make_msschem_vs_class( - entity, nam, vert, units, scale, add_data=None, + entity, name, vert, units, scale, add_data=None, add_contours=None, fix_styles=None, add_styles=None, add_prepare=None): # This is CTM output, so we cannot expect any additional meteorological @@ -312,14 +312,14 @@ class fnord(VS_MSSChemStyle): dataname = entity units = units unit_scale = scale - title = nam + " (" + vert + ")" + title = name + " (" + vert + ")" long_name = entity if units: title += f"({units})" required_datafields = [(vert, entity, None)] + add_data contours = add_contours if add_contours else [] - fnord.__name__ = nam + fnord.__name__ = name fnord.styles = list(fnord.styles) if add_styles is not None: diff --git a/docs/samples/config/mswms/mswms_settings.py.chem_plots b/docs/samples/config/mswms/mswms_settings.py.chem_plots index b3c7c0d1c..f3ef0c1f2 100644 --- a/docs/samples/config/mswms/mswms_settings.py.chem_plots +++ b/docs/samples/config/mswms/mswms_settings.py.chem_plots @@ -30,7 +30,7 @@ import os import sys -# on a productions system you may want to limit the amout of tracebacks to 0 +# on a productions system you may want to limit the amount of tracebacks to 0 # sys.tracebacklimit = 0 # Configuration of Python's code search path diff --git a/docs/samples/config/mswms/mswms_settings.py.demodata b/docs/samples/config/mswms/mswms_settings.py.demodata index 4965b09b9..1068ef6de 100644 --- a/docs/samples/config/mswms/mswms_settings.py.demodata +++ b/docs/samples/config/mswms/mswms_settings.py.demodata @@ -30,7 +30,7 @@ import os import sys -# on a productions system you may want to limit the amout of tracebacks to 0 +# on a productions system you may want to limit the amount of tracebacks to 0 # sys.tracebacklimit = 0 # Configuration of Python's code search path diff --git a/docs/samples/config/mswms/mswms_settings.py.sample b/docs/samples/config/mswms/mswms_settings.py.sample index be7693aeb..e668c17be 100644 --- a/docs/samples/config/mswms/mswms_settings.py.sample +++ b/docs/samples/config/mswms/mswms_settings.py.sample @@ -29,7 +29,7 @@ import os import sys -# on a productions system you may want to limit the amout of tracebacks to 0 +# on a productions system you may want to limit the amount of tracebacks to 0 # sys.tracebacklimit = 0 # Configuration of Python's code search path diff --git a/docs/samples/plugins/navaid.rst b/docs/samples/plugins/navaid.rst index 81e8d0406..39b8b7e04 100644 --- a/docs/samples/plugins/navaid.rst +++ b/docs/samples/plugins/navaid.rst @@ -10,7 +10,7 @@ Alternative plugins could be placed into the settings directory. Details ~~~~~~~ -It may be requiered to compute the waypoints in the format WPT012034, +It may be required to compute the waypoints in the format WPT012034, where WPT is the NAVAID ID, 012 is the heading and 034 is the distance in nautical miles. This standard is used by several flight authorities. Data for the location of the NAVAID waypoints can be obtained as csv from @@ -19,7 +19,7 @@ The dataset should be named NAVAID_System.csv and placed into the subdir plugins of the config dir. For a given set of waypoints, the navaid export plugin exports an ASCII table containing a column of the so-determined waypoint names. For locations -ouside the given set of NAVAID points , e.g. over the oceans, the naming +outside the given set of NAVAID points , e.g. over the oceans, the naming convention switches to coordinate based name like xxyyNwwwzzW for latitude xx°yy'N and longitude www°zz'W. This is done if the closest NAVAID waypoint is more than 500 nm. diff --git a/docs/sso_via_saml_mscolab.rst b/docs/sso_via_saml_mscolab.rst index 95ba29fc3..19f5fabe8 100644 --- a/docs/sso_via_saml_mscolab.rst +++ b/docs/sso_via_saml_mscolab.rst @@ -322,7 +322,7 @@ Create a client specifically for SAML .. note:: When creating client ID, it should be same as the issuer ID of the MSColab server. - In here, the MSColab server used different issuer IDs for the particular idp_iedentity_name, and issued it by url bellow + In here, the MSColab server used different issuer IDs for the particular idp_iedentity_name, and issued it by url below http://127.0.0.1:8083/metadata/idp_identityname/ @@ -433,7 +433,7 @@ Create a client specifically for SAML When all sorted you need to export metadata file from the keycloak, - http://localhost:8080/auth/realms/saml-example-realm/protocol/saml/descripto + http://localhost:8080/auth/realms/saml-example-realm/protocol/saml/description Since we're going to import the file with the name as "key_cloak_v_13_idp.xml" in this example, We should store it with the same name. @@ -546,7 +546,7 @@ Configuration mss_saml2_backend.yaml file eg:- entityid: http://127.0.0.1:8083/metadata/ .. note:: - may be can be occured invalid redirect url problem, since we defined localhost in keycloak admin, and using 127.0..... be careful to set it correctly. + may be can be occurred invalid redirect url problem, since we defined localhost in keycloak admin, and using 127.0..... be careful to set it correctly. eg:- assertion_consumer_service: diff --git a/docs/tutorials/tutorial_introduction_topview.rst b/docs/tutorials/tutorial_introduction_topview.rst index cda45e8a7..b4edd8a1f 100644 --- a/docs/tutorials/tutorial_introduction_topview.rst +++ b/docs/tutorials/tutorial_introduction_topview.rst @@ -6,7 +6,7 @@ Selection and display of different data in the Top View with the help of the lay .. 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 informations as layer lists. + atmospheric information as layer lists. As we click on the "server layer" option, the layer list window opens that lists out various layers. We just have to enter the WMS url and get capabilities for those layers. So, here we find various layers: Divergence and Geopotential Height, diff --git a/docs/tutorials/tutorial_mscolab.rst b/docs/tutorials/tutorial_mscolab.rst index 3aa014f12..c4164fa9c 100644 --- a/docs/tutorials/tutorial_mscolab.rst +++ b/docs/tutorials/tutorial_mscolab.rst @@ -34,7 +34,7 @@ shown on a MSColab server and the possibilities of interactions. After selecting users, we click on Add button, which moves these users to All users with permission section to the right side of the window. For the users who have access permission to the operation, we can also change the access roles. Here for b, we have changed the permission from collaborator to admin. - We can alo delete a user with a permission by selecting user and clicking on delete button. + We can also delete a user with a permission by selecting user and clicking on delete button. Changing their access roles.... We can filter users based on their roles being Collaborator, admin or viewer. Filtering for some time.... diff --git a/docs/tutorials/tutorial_satellitetrack.rst b/docs/tutorials/tutorial_satellitetrack.rst index f36dcb2ce..04561d811 100644 --- a/docs/tutorials/tutorial_satellitetrack.rst +++ b/docs/tutorials/tutorial_satellitetrack.rst @@ -8,7 +8,7 @@ To combine a flight path with a satellite overflight, the remotesensing widget i :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. - These flights which can be refered to as the Testing flights are made to travel in + These flights which can be referred to as the Testing flights are made to travel in the direction of these Satellites by collaborating with these space agencies. Open the Top View (CTRL+H) of the MSS software. Click on “(select to open control)“ and then click “Satellite Tracks“. diff --git a/localbuild/meta.yaml b/localbuild/meta.yaml index 9e200326f..3088dfce2 100644 --- a/localbuild/meta.yaml +++ b/localbuild/meta.yaml @@ -42,7 +42,7 @@ requirements: - requests >=2.31.0 - scipy - skyfield >=1.12 - - skyfield-data >=5 + - skyfield-data >=6 - tk - owslib >=0.24 - unicodecsv @@ -115,7 +115,7 @@ about: * http://www.geosci-model-dev.net/5/55/2012/gmd-5-55-2012.pdf Software for planning research Aircraft Missions. - For discussion of the possibilites of the research flights, + For discussion of the possibilities of the research flights, the Mission Support System (MSS) was developed. This software helps to review a big amount of metereological and model data by viewing the forecasted parameters of interest along possible regions diff --git a/mslib/mscolab/conf.py b/mslib/mscolab/conf.py index 1c6b02f5c..f501e62a7 100644 --- a/mslib/mscolab/conf.py +++ b/mslib/mscolab/conf.py @@ -181,7 +181,7 @@ class setup_saml2_backend: if not os.path.exists(yaml_data["config"]["localhost_test_idp"]["metadata"]["local"][0]): yaml_data["config"]["localhost_test_idp"]["metadata"]["local"] = [] warnings.warn("idp.xml file does not exists !\ - Ignore this warning when you initializeing metadata.") + Ignore this warning when you initialize metadata.") localhost_test_idp = SPConfig().load(yaml_data["config"]["localhost_test_idp"]) localhost_test_idp.verify_ssl_cert = mscolab_settings.ENABLE_SSO_SSL_CERT_VERIFICATION diff --git a/mslib/mscolab/file_manager.py b/mslib/mscolab/file_manager.py index e1a61f979..3be1a0179 100644 --- a/mslib/mscolab/file_manager.py +++ b/mslib/mscolab/file_manager.py @@ -124,7 +124,7 @@ def list_operations(self, user, skip_archived=False): ).days > mscolab_settings.ARCHIVE_THRESHOLD: # outdated OPs get archived self.update_operation(permission.op_id, "active", False, user) - # new query to get uptodate data + # new query to get up-to-date data if skip_archived: operation = Operation.query.filter_by(id=permission.op_id, active=skip_archived).first() else: @@ -228,7 +228,7 @@ def modify_user(self, user, attribute=None, value=None, action=None): db.session.delete(user) db.session.commit() user_query = User.query.filter_by(id=user.id).first() - # on delete we return succesfull deleted + # on delete we return successful deleted if user_query is None: return True elif action == "update_idp_user": diff --git a/mslib/mscolab/mscolab.py b/mslib/mscolab/mscolab.py index a04afe940..ad6dfe46b 100644 --- a/mslib/mscolab/mscolab.py +++ b/mslib/mscolab/mscolab.py @@ -306,7 +306,7 @@ def handle_local_idp_metadata_init(repo_exists): with open(os.path.join(mscolab_settings.MSCOLAB_SSO_DIR, "idp.xml"), "w", encoding="utf-8") as output_file: subprocess.run(cmd, stdout=output_file, check=True) - logging.info("idp metadata file generated succesfully") + logging.info("idp metadata file generated successfully") return True except subprocess.CalledProcessError as error: # Delete the idp.xml file when the subprocess fails diff --git a/mslib/mscolab/server.py b/mslib/mscolab/server.py index 568e78af4..7e6651161 100644 --- a/mslib/mscolab/server.py +++ b/mslib/mscolab/server.py @@ -140,7 +140,7 @@ def check_login(emailid, password): try: user = User.query.filter_by(emailid=str(emailid)).first() except sqlalchemy.exc.OperationalError as ex: - logging.debug("Problem in the database (%ex), likly version client different", ex) + logging.debug("Problem in the database (%ex), likely version client different", ex) return False if user is not None: if mscolab_settings.MAIL_ENABLED: @@ -715,7 +715,7 @@ def reset_request(): if mscolab_settings.MAIL_ENABLED: form = ResetRequestForm() if form.validate_on_submit(): - # Check wheather user exists or not based on the db + # Check whether user exists or not based on the db user = User.query.filter_by(emailid=form.email.data).first() if user: try: diff --git a/mslib/msidp/idp.py b/mslib/msidp/idp.py index 6ffa3316e..a6f1f78de 100644 --- a/mslib/msidp/idp.py +++ b/mslib/msidp/idp.py @@ -373,11 +373,11 @@ def do(self, query, binding_in, relay_state="", encrypt_cert=None, **kwargs): identity[REPOZE_ID_EQUIVALENT] = self.user try: try: - metod = self.environ["idp.authn"] + method = self.environ["idp.authn"] except KeyError: pass else: - resp_args["authn"] = metod + resp_args["authn"] = method _resp = IdpServerSettings_.IDP.create_authn_response( identity, userid=self.user, encrypt_cert_assertion=encrypt_cert, **resp_args @@ -991,7 +991,7 @@ def metadata(environ, start_response): start_response("200 OK", [("Content-Type", "text/xml")]) return [metadata] except Exception as ex: - logger.error("An error occured while creating metadata: %s", ex.message) + logger.error("An error occurred while creating metadata: %s", ex.message) return not_found(environ, start_response) @@ -1010,7 +1010,7 @@ def staticfile(environ, start_response): start_response("200 OK", [("Content-Type", "text/xml")]) return open(path).read() except Exception as ex: - logger.error("An error occured while creating metadata: %s", ex.message) + logger.error("An error occurred while creating metadata: %s", ex.message) return not_found(environ, start_response) diff --git a/mslib/msidp/idp_uwsgi.py b/mslib/msidp/idp_uwsgi.py index 7d86b6bbf..8a6097f96 100644 --- a/mslib/msidp/idp_uwsgi.py +++ b/mslib/msidp/idp_uwsgi.py @@ -368,11 +368,11 @@ def do(self, query, binding_in, relay_state="", encrypt_cert=None): identity[REPOZE_ID_EQUIVALENT] = self.user try: try: - metod = self.environ["idp.authn"] + method = self.environ["idp.authn"] except KeyError: pass else: - resp_args["authn"] = metod + resp_args["authn"] = method _resp = IDP.create_authn_response(identity, userid=self.user, encrypt_cert=encrypt_cert, **resp_args) @@ -957,7 +957,7 @@ def metadata(environ, start_response): start_response("200 OK", [("Content-Type", "text/xml")]) return metadata except Exception as ex: - logger.error("An error occured while creating metadata:", ex.message) + logger.error("An error occurred while creating metadata:", ex.message) return not_found(environ, start_response) @@ -979,7 +979,7 @@ def staticfile(environ, start_response): start_response("200 OK", [("Content-Type", "text/xml")]) return open(path).read() except Exception as ex: - logger.error("An error occured while creating metadata: %s", str(ex)) + logger.error("An error occurred while creating metadata: %s", str(ex)) return not_found(environ, start_response) diff --git a/mslib/msui/aircrafts.py b/mslib/msui/aircrafts.py index fbd2df2fc..19e5bb6c2 100644 --- a/mslib/msui/aircrafts.py +++ b/mslib/msui/aircrafts.py @@ -4,7 +4,7 @@ mslib.msui.aircrafts ~~~~~~~~~~~~~~~~~~~~ - This module provides aircrafts definitions + This module provides aircraft definitions This file is part of MSS. diff --git a/mslib/msui/mpl_map.py b/mslib/msui/mpl_map.py index ff5d12be1..e9e0efe2c 100644 --- a/mslib/msui/mpl_map.py +++ b/mslib/msui/mpl_map.py @@ -318,7 +318,7 @@ def _draw_auto_graticule(self, font_size=None): def set_graticule_visible(self, visible=True): """ - Set the visibily of the graticule. + Set the visibility of the graticule. Removes a currently visible graticule by deleting internally stored line and text objects representing graticule lines and labels, then diff --git a/mslib/msui/mpl_pathinteractor.py b/mslib/msui/mpl_pathinteractor.py index 59fb8702a..5c6f5a6d3 100644 --- a/mslib/msui/mpl_pathinteractor.py +++ b/mslib/msui/mpl_pathinteractor.py @@ -375,7 +375,7 @@ def __init__(self, ax, mplpath=None, markerfacecolor=markerfacecolor, animated=True) - # List to accomodate waypoint labels. + # List to accommodate waypoint labels. self.wp_labels = [] self.label_waypoints = label_waypoints @@ -507,7 +507,7 @@ def redraw_path(self, wp_vertices=None, waypoints_model_data=None): x, y = self.map.gcpoints_path(lons, lats) vertices = list(zip(x, y)) - # Set the line to disply great circle points, remove existing + # Set the line to display great circle points, remove existing # waypoints scatter instance and draw a new one. This is # necessary as scatter() does not provide a set_data method. self.line.set_data(list(zip(*vertices))) diff --git a/mslib/msui/mpl_qtwidget.py b/mslib/msui/mpl_qtwidget.py index 2544c154e..7b37b186a 100644 --- a/mslib/msui/mpl_qtwidget.py +++ b/mslib/msui/mpl_qtwidget.py @@ -314,7 +314,7 @@ def draw_image(self, img): def draw_legend(self, img): """Draw the legend graphics img on the current plot. - Adds new axes to the plot that accomodate the legend. + Adds new axes to the plot that accommodate the legend. """ # If the method is called with a "None" image, the current legend # graphic should be removed (if one exists). @@ -742,9 +742,9 @@ def set_settings(self, settings, save=False): pts = (self.linearview_size_settings["plot_title_size"] if self.settings["plot_title_size"] == "default" else int(self.settings["plot_title_size"])) - als = (self.linearview_size_settings["axes_label_size"] if self.settings["axes_label_size"] == "default" - else int(self.settings["axes_label_size"])) - self.ax.tick_params(axis='both', labelsize=als) + label_size = (self.linearview_size_settings["axes_label_size"] if self.settings["axes_label_size"] == "default" + else int(self.settings["axes_label_size"])) + self.ax.tick_params(axis='both', labelsize=label_size) self.ax.set_title("Linear flight profile", fontsize=pts, horizontalalignment='left', x=0) self.ax.figure.canvas.draw() @@ -1617,7 +1617,7 @@ def draw_image(self, img): def draw_legend(self, img): """Draw the legend graphics img on the current plot. - Adds new axes to the plot that accomodate the legend. + Adds new axes to the plot that accommodate the legend. """ self.plotter.draw_legend(img) # required so that it is actually drawn... diff --git a/mslib/msui/mscolab.py b/mslib/msui/mscolab.py index 2c59ace2d..42c086035 100644 --- a/mslib/msui/mscolab.py +++ b/mslib/msui/mscolab.py @@ -456,8 +456,8 @@ def new_user_handler(self): try: error_msg = json.loads(r.text)["message"] except Exception as e: - logging.debug("Unexpected error occured %s", e) - error_msg = "Unexpected error occured. Please try again." + logging.debug("Unexpected error occurred %s", e) + error_msg = "Unexpected error occurred. Please try again." self.set_status("Error", error_msg) @@ -1710,7 +1710,8 @@ def archive_operation(self): data = { "token": self.token, "op_id": self.active_op_id, - "days": 31, + # when a user archives an operation we set the max “natural” integer in days + "days": sys.maxsize, } url = urljoin(self.mscolab_server_url, 'set_last_used') try: diff --git a/mslib/msui/performance_settings.py b/mslib/msui/performance_settings.py index 6e1c0d725..e34b141dd 100644 --- a/mslib/msui/performance_settings.py +++ b/mslib/msui/performance_settings.py @@ -30,13 +30,13 @@ from PyQt5 import QtCore, QtWidgets from mslib.utils import FatalUserError -from mslib.msui import aircrafts, constants +from mslib.msui import aircrafts as aircraft, constants from mslib.utils.qt import get_open_filename from mslib.msui.qt5 import ui_performance_dockwidget as ui_dw DEFAULT_PERFORMANCE = { - "aircraft": aircrafts.SimpleAircraft(aircrafts.AIRCRAFT_DUMMY), + "aircraft": aircraft.SimpleAircraft(aircraft.AIRCRAFT_DUMMY), "visible": False, "takeoff_weight": 0, "takeoff_time": QtCore.QDateTime.currentDateTimeUtc(), @@ -84,7 +84,7 @@ def get_settings(self): Encapsulates GUI selections in a python dictionary. :return: - Dictionary of all setting informations + Dictionary of all setting information """ settings_dict = { "aircraft": self.aircraft, @@ -109,7 +109,7 @@ def load_performance(self): try: with open(filename) as tf: performance = json.load(tf) - self.aircraft = aircrafts.SimpleAircraft(performance) + self.aircraft = aircraft.SimpleAircraft(performance) self.lbAircraftName.setText(self.aircraft.name) self.dsbTakeoffWeight.setValue(self.aircraft.takeoff_weight) if not any(hasattr(self.aircraft, _x) for _x in ("fuel", "empty_weight")): diff --git a/mslib/msui/sideview.py b/mslib/msui/sideview.py index 53ecfc3ba..05c685fbc 100644 --- a/mslib/msui/sideview.py +++ b/mslib/msui/sideview.py @@ -313,7 +313,7 @@ def setFlightTrackModel(self, model): def open_settings_dialog(self): """ - Slot to open a dialog that lets the user specifiy sideview options. + Slot to open a dialog that lets the user specify sideview options. """ settings = self.getView().get_settings() dlg = MSUI_SV_OptionsDialog(parent=self, settings=settings) diff --git a/mslib/msui/socket_control.py b/mslib/msui/socket_control.py index 7f76c0b0d..2717eafff 100644 --- a/mslib/msui/socket_control.py +++ b/mslib/msui/socket_control.py @@ -38,7 +38,7 @@ class ConnectionManager(QtCore.QObject): signal_reload = QtCore.pyqtSignal(int, name="reload_wps") signal_message_receive = QtCore.pyqtSignal(str, name="message rcv") signal_message_reply_receive = QtCore.pyqtSignal(str, name="message reply") - signal_message_edited = QtCore.pyqtSignal(str, name="message editted") + signal_message_edited = QtCore.pyqtSignal(str, name="message edited") signal_message_deleted = QtCore.pyqtSignal(str, name="message deleted") signal_new_permission = QtCore.pyqtSignal(int, int, name="new permission") signal_update_permission = QtCore.pyqtSignal(int, int, str, name="update permission") diff --git a/mslib/msui/wms_control.py b/mslib/msui/wms_control.py index bf4827ad3..9bece6451 100644 --- a/mslib/msui/wms_control.py +++ b/mslib/msui/wms_control.py @@ -569,7 +569,7 @@ def initialise_wms(self, base_url, version="1.3.0"): (mr, 2011-02-25) """ - # initialize login cache fomr config file, but do not overwrite existing keys + # initialize login cache from config file, but do not overwrite existing keys http_auth = config_loader(dataset="MSS_auth") auth_username, auth_password = get_auth_from_url_and_name(base_url, http_auth) @@ -788,14 +788,14 @@ def activate_wms(self, wms, cache=False): self.prefetcher = WMSMapFetcher(self.wms_cache) self.prefetcher.moveToThread(self.thread_prefetch) - self.prefetch.connect(self.prefetcher.fetch_maps) # implicitely uses a queued connection + self.prefetch.connect(self.prefetcher.fetch_maps) # implicitly uses a queued connection self.fetcher = WMSMapFetcher(self.wms_cache) self.fetcher.moveToThread(self.thread_fetch) - self.fetch.connect(self.fetcher.fetch_maps) # implicitely uses a queued connection - self.fetcher.finished.connect(self.continue_retrieve_image) # implicitely uses a queued connection - self.fetcher.exception.connect(self.display_exception) # implicitely uses a queued connection - self.fetcher.started_request.connect(self.display_progress_dialog) # implicitely uses a queued connection + self.fetch.connect(self.fetcher.fetch_maps) # implicitly uses a queued connection + self.fetcher.finished.connect(self.continue_retrieve_image) # implicitly uses a queued connection + self.fetcher.exception.connect(self.display_exception) # implicitly uses a queued connection + self.fetcher.started_request.connect(self.display_progress_dialog) # implicitly uses a queued connection # logic to disable fill continents, fill oceans on connection to self.signal_disable_cbs.emit() @@ -1041,7 +1041,7 @@ def cb_valid_time_fwd_click(self): def auto_update(self): """If the auto update check box is checked, let btGetMap emit a - clicked() signal everytime this method is called. + clicked() signal every time this method is called. autoUpdate() should be called from the slots that handle time and level changes. @@ -1482,7 +1482,7 @@ def append_multiple_images(self, imgs): """ images = [x for x in imgs if x] if images: - # Add border around seperate legends + # Add border around separate legends if len(images) > 1: images = [ImageOps.expand(x, border=1, fill="black") for x in images] max_height = int((self.view.plotter.fig.get_size_inches() * self.view.plotter.fig.get_dpi())[1] * 0.99) diff --git a/mslib/mswms/dataaccess.py b/mslib/mswms/dataaccess.py index 3c0758eac..4a04e823f 100644 --- a/mslib/mswms/dataaccess.py +++ b/mslib/mswms/dataaccess.py @@ -199,7 +199,7 @@ class DefaultDataAccess(NWPDataAccess): Constructor needs information on domain ID. """ - # Workaround for the numerical issue concering the lon dimension in + # Workaround for the numerical issue concerning the lon dimension in # NetCDF files produced by netcdf-java 4.3.. def __init__(self, rootpath, domain_id, skip_dim_check=None, **kwargs): @@ -232,7 +232,8 @@ def _determine_filename(self, variable, vartype, init_time, valid_time, reload=T else: logging.error("Could not identify filename. %s %s %s %s %s %s", variable, vartype, init_time, valid_time, type(ex), ex) - raise ValueError(f"variable type {vartype} not available for variable {variable}") + raise ValueError(f"Variable '{variable}' not available for type '{vartype}', " + f"init_time '{init_time}', and valid_time '{valid_time}'") def is_reload_required(self, filenames): return False @@ -293,7 +294,7 @@ def _parse_file(self, filename): try: units(ncvar.units) except (AttributeError, ValueError, pint.UndefinedUnitError, pint.DefinitionSyntaxError): - logging.error("Skipping variable '%s' in file '%s': unparseable units attribute '%s'", + logging.error("Skipping variable '%s' in file '%s': unparsable units attribute '%s'", ncvarname, filename, ncvar.units) continue if len(ncvar.shape) == 4 and vert_name in ncvar.dimensions: diff --git a/mslib/mswms/demodata.py b/mslib/mswms/demodata.py index 6780bd47d..fe22869cb 100644 --- a/mslib/mswms/demodata.py +++ b/mslib/mswms/demodata.py @@ -752,7 +752,7 @@ def get_profile(coordinate, levels, standard_name): (air_pressure, air_potential_temperature, geopotential_height, ertel_potential_vorticity are tested) :param levels: Numerical values of coordinate variable to interpolate at :param standard_name: CF standard name of entity to interpolate at specified points. - :return: two array, one for mean, ond for variance at specified levels. + :return: two array, one for mean, one for variance at specified levels. """ assert coordinate in _PROFILES, coordinate assert standard_name in _PROFILES, standard_name @@ -929,7 +929,7 @@ def create_server_config(self, detailed_information=False): import os import sys -# on a productions system you may want to limit the amout of tracebacks to 0 +# on a productions system you may want to limit the amount of tracebacks to 0 # sys.tracebacklimit = 0 # Configuration of Python's code search path diff --git a/mslib/mswms/gallery_builder.py b/mslib/mswms/gallery_builder.py index af2f399a3..cfb0a97b5 100644 --- a/mslib/mswms/gallery_builder.py +++ b/mslib/mswms/gallery_builder.py @@ -482,7 +482,7 @@ def import_instructions(plot_object, l_type, layer, native_import=None, dataset= inspect.getsource(plot_object._prepare_datafields): style = "hsec" if isinstance(plot_object, HS_GenericStyle) else "vsec" - # Convert range to list, since numpy arrays string representation is unparseable + # Convert range to list, since numpy arrays string representation is unparsable if plot_object.contours: for i in range(len(plot_object.contours)): temp = list(plot_object.contours[i]) @@ -540,7 +540,7 @@ def source_and_import(plot_object, l_type, layer, dataset=""): parent = "HS_GenericStyle" if isinstance(plot_object, HS_GenericStyle) else "VS_GenericStyle" style = "hsec" if isinstance(plot_object, HS_GenericStyle) else "vsec" - # Convert range to list, since numpy arrays string representation is unparseable + # Convert range to list, since numpy arrays string representation is unparsable if plot_object.contours: for i in range(len(plot_object.contours)): temp = list(plot_object.contours[i]) diff --git a/mslib/mswms/mpl_hsec.py b/mslib/mswms/mpl_hsec.py index a5ac68b4d..3b6bd51e6 100644 --- a/mslib/mswms/mpl_hsec.py +++ b/mslib/mswms/mpl_hsec.py @@ -332,7 +332,7 @@ def plot_hsection(self, data, lats, lons, bbox=(-180, -90, 180, 90), logging.debug("Loaded '%s' from basemap cache", key) else: bm = basemap.Basemap(resolution='l', **bm_params) - # read in countries manually, as those are laoded only on demand + # read in countries manually, as those are loaded only on demand bm.cntrysegs, _ = bm._readboundarydata("countries") if basemap_use_cache: BASEMAP_CACHE[key] = (bm.resolution, bm.coastsegs, bm.coastpolygontypes, bm.coastpolygons, diff --git a/mslib/mswms/mpl_hsec_styles.py b/mslib/mswms/mpl_hsec_styles.py index 4d90d1288..fa4ea5118 100644 --- a/mslib/mswms/mpl_hsec_styles.py +++ b/mslib/mswms/mpl_hsec_styles.py @@ -1192,7 +1192,7 @@ def _plot_style(self): # Define colourbars and contour levels for the three styles. For # pressure and height, a terrain colourmap is used (bluish colours for # low altitudes, brownish colours for high altitudes). For potential - # temperature, a rainbow colourmap is used (blue=low temps, red=hight + # temperature, a rainbow colourmap is used (blue=low temps, red=high # temps). if self.style == "PRES": filled_contours = np.arange(120, 551, 10) @@ -1284,7 +1284,7 @@ def _plot_style(self): # Define colourbars and contour levels for the three styles. For # pressure and height, a terrain colourmap is used (bluish colours for # low altitudes, brownish colours for high altitudes). For potential - # temperature, a rainbow colourmap is used (blue=low temps, red=hight + # temperature, a rainbow colourmap is used (blue=low temps, red=high # temps). fcmap = plt.cm.terrain @@ -1327,7 +1327,7 @@ def _plot_style(self): class HS_VIProbWCB_Style_01(MPLBasemapHorizontalSectionStyle): """ Surface Field: Probability of WCB - Total column probability of WCB trajectory occurence, derived from + Total column probability of WCB trajectory occurrence, derived from Lagranto trajectories (TNF 2012 product). """ name = "VIProbWCB" diff --git a/mslib/mswms/mpl_vsec_styles.py b/mslib/mswms/mpl_vsec_styles.py index dc11b9617..b8a4d929d 100644 --- a/mslib/mswms/mpl_vsec_styles.py +++ b/mslib/mswms/mpl_vsec_styles.py @@ -146,7 +146,7 @@ def make_generic_class(name, standard_name, vert, add_data=None, add_contours=No E.g. [("ertel_potential_vorticity", [2, 4, 8, 16], "green", "red", "dashed", 2, True)] cause PV to be plotted for 2, 4, 8, and 16 PVU with dashed green lines, red labels, and line width of 2. The last value defines - wether a stroke effect shall be applied. + whether a stroke effect shall be applied. fix_styles (list, optional): A list of plotting styles, which must be defined in the mslib.mswms.generics.STYLES dictionary. Defaults @@ -1128,7 +1128,7 @@ def _plot_style(self): class VS_ProbabilityOfWCBStyle_01(AbstractVerticalSectionStyle): """ Probability of WCB - Vertical sections of probability of WCB trajectory occurence, + Vertical sections of probability of WCB trajectory occurrence, derived from Lagranto trajectories (TNF 2012 product). """ diff --git a/mslib/mswms/mss_plot_driver.py b/mslib/mswms/mss_plot_driver.py index f6b063660..44f26e834 100644 --- a/mslib/mswms/mss_plot_driver.py +++ b/mslib/mswms/mss_plot_driver.py @@ -36,6 +36,7 @@ from mslib.utils import netCDF4tools import mslib.utils.coordinate as coordinate +from mslib.utils.units import convert_to, units class MSSPlotDriver(metaclass=ABCMeta): @@ -790,9 +791,24 @@ def _load_interpolate_timestep(self): lon_data = ((self.lon_data - left_longitude) % 360) + left_longitude lon_indices = lon_data.argsort() lon_data = lon_data[lon_indices] + # Identify jump in longitudes due to non-global dataset + dlon_data = np.diff(lon_data) + jump = np.where(dlon_data > 2 * dlon)[0] + lons = ((self.lons - left_longitude) % 360) + left_longitude factors = [] + pressures = None + if "air_pressure" not in self.data_vars: + if units(self.vert_units).check("[pressure]"): + pressures = np.log(convert_to( + self.vert_data[::-self.vert_order, np.newaxis], + self.vert_units, "Pa").repeat(len(self.lats), axis=1)) + else: + raise ValueError( + "air_pressure must be available for linear plotting layers " + "with non-pressure axis. Please add to required_datafields.") + # Make sure air_pressure is the first to be evaluated if needed variables = list(self.data_vars) if "air_pressure" in self.data_vars: @@ -803,7 +819,7 @@ def _load_interpolate_timestep(self): var = self.data_vars[name] data[name] = [] if len(var.shape) == 4: - var_data = var[timestep, ::-self.vert_order, ::self.lat_order, :] + var_data = var[:][timestep, ::-self.vert_order, ::self.lat_order, :] else: var_data = var[:][timestep, np.newaxis, ::self.lat_order, :] logging.debug("\tLoaded %.2f Mbytes from data field <%s> at timestep %s.", @@ -813,38 +829,38 @@ def _load_interpolate_timestep(self): logging.debug("\tInterpolating to cross-section path.") # Re-arange longitude dimension in the data field. var_data = var_data[:, :, lon_indices] + if jump: + logging.debug("\tsetting jump data to NaN at %s", jump) + var_data = var_data.copy() + var_data[:, :, jump] = np.nan cross_section = coordinate.interpolate_vertsec(var_data, self.lat_data, lon_data, self.lats, lons) # Create vertical interpolation factors and indices for subsequent variables # TODO: Improve performance for this interpolation in general if len(factors) == 0: - for index_lonlat, alt in enumerate(self.alts): - pressures = cross_section[:, index_lonlat] if name == "air_pressure" \ - else self.vert_data[::-self.vert_order] * (100 if self.vert_units.lower() == "hpa" else 1) - closest = 0 - direction = 1 - for index_altitude, pressure in enumerate(pressures): - if abs(pressure - alt) < abs(pressures[closest] - alt): - closest = index_altitude - direction = 1 if pressure - alt > 0 else -1 - - next_closest = closest + direction - if next_closest >= len(pressures) or next_closest < 0: - next_closest = closest - - if closest == next_closest: - factors.append([[closest, 0.5], [closest, 0.5]]) - else: - distance = abs(pressures[closest] - alt) + abs(pressures[next_closest] - alt) - factors.append( - [[closest, 1 - (abs(pressures[closest] - alt) / distance)], - [next_closest, 1 - (abs(pressures[next_closest] - alt) / distance)]]) + if name == "air_pressure": + pressures = np.log(convert_to(cross_section, self.data_units[name], "Pa")) + for index_lonlat, alt in enumerate(np.log(self.alts)): + pressure = pressures[:, index_lonlat] + idx0 = None + for index_altitude in range(len(pressures) - 1): + if (pressure[index_altitude] <= alt <= pressure[index_altitude + 1]) or \ + (pressure[index_altitude] >= alt >= pressure[index_altitude + 1]): + idx0 = index_altitude + break + if idx0 is None: + factors.append(((0, np.nan), (0, np.nan))) + continue + + idx1 = idx0 + 1 + fac1 = (pressure[idx0] - alt) / (pressure[idx0] - pressure[idx1]) + fac0 = 1 - fac1 + assert 0 <= fac0 <= 1, fac0 + factors.append(((idx0, fac0), (idx1, fac1))) # Interpolate with the previously calculated pressure indices and factors - for index in range(len(self.alts)): - cur_factor = factors[index] - value = cross_section[cur_factor[0][0], index] * cur_factor[0][1] + \ - cross_section[cur_factor[1][0], index] * cur_factor[1][1] + for index, ((idx0, w0), (idx1, w1)) in enumerate(factors): + value = cross_section[idx0, index] * w0 + cross_section[idx1, index] * w1 data[name].append(value) # Free memory. diff --git a/mslib/mswms/wms.py b/mslib/mswms/wms.py index 2b218282c..a95664e66 100644 --- a/mslib/mswms/wms.py +++ b/mslib/mswms/wms.py @@ -561,7 +561,7 @@ def create_service_exception(self, code=None, text="", version="1.3.0"): def get_capabilities(self, query, server_url=None): # ToDo find a more elegant method to do the same - # Preferable we don't want a seperate data_access module to be configured + # Preferable we don't want a separate data_access module to be configured data_access_dict = mswms_settings.data for key in data_access_dict: @@ -808,7 +808,7 @@ def produce_plot(self, query, mode): return self.create_service_exception(text=msg, version=version) elif mode == "getvsec": - # Vertical secton path. + # Vertical section path. path = query.get("PATH") if path is None: return self.create_service_exception(text="PATH not specified", version=version) diff --git a/mslib/static/docs/about.md b/mslib/static/docs/about.md index ee09fb062..7b772c4e5 100644 --- a/mslib/static/docs/about.md +++ b/mslib/static/docs/about.md @@ -4,9 +4,9 @@ The Mission Support System (MSS) is a software that is written by scientists in the field of atmospheric science. The purpose is to have a tool that simplifies the process for planning a scientific flight in -which parameters of the atmosphere are measured. The research aircrafts +which parameters of the atmosphere are measured. The research aircraft typically carry a comprehensive scientific payload comprised of data -aquisition instruments by different companies and research institutions. +acquisition instruments by different companies and research institutions. The measurement of relevant parameters, for example the chemical composition of trace gases, temperature or aerosol particle characteristics, are needed to improve the scientific understanding of diff --git a/mslib/static/templates/idp/idp_login_success.html b/mslib/static/templates/idp/idp_login_success.html index af46f2d04..e81d8ffbb 100644 --- a/mslib/static/templates/idp/idp_login_success.html +++ b/mslib/static/templates/idp/idp_login_success.html @@ -10,7 +10,7 @@

Congratulations! You have successfully logged in to the mscolab server using Identity Provider.

-

Please proceed to log in using the user interface by bellow token.

+

Please proceed to log in using the user interface by below token.

Token : {{token}}
diff --git a/mslib/static/templates/user/reset_password.html b/mslib/static/templates/user/reset_password.html index dd2b2466b..b1dad1f70 100644 --- a/mslib/static/templates/user/reset_password.html +++ b/mslib/static/templates/user/reset_password.html @@ -35,7 +35,7 @@

Reset Password

- {{form.password(class="fpr,form-control form-control-lg is-invalid")}} + {{form.password(class="form-control form-control-lg is-invalid")}}
{% if form.password.errors %} {% for error in form.password.errors %} @@ -47,7 +47,7 @@

Reset Password

- {{form.confirm_password(class="fpr,form-control form-control-lg is-invalid")}} + {{form.confirm_password(class="form-control form-control-lg is-invalid")}}
{% if form.confirm_password.errors %} {% for error in form.confirm_password.errors %} diff --git a/mslib/support/qt_json_view/model.py b/mslib/support/qt_json_view/model.py index 3e2078e4e..9c855e83e 100644 --- a/mslib/support/qt_json_view/model.py +++ b/mslib/support/qt_json_view/model.py @@ -41,7 +41,7 @@ def serialize(self): class JsonSortFilterProxyModel(QtCore.QSortFilterProxyModel): # (msui) - """Show ALL occurences by keeping the parents of each occurence visible.""" + """Show ALL occurrences by keeping the parents of each occurrence visible.""" def filterAcceptsRow(self, sourceRow, sourceParent): """Accept the row if the parent has been accepted.""" diff --git a/mslib/utils/__init__.py b/mslib/utils/__init__.py index b7fbcd507..f6bb11e64 100644 --- a/mslib/utils/__init__.py +++ b/mslib/utils/__init__.py @@ -65,8 +65,8 @@ def setup_logging(args): ch.setLevel(logging.DEBUG) ch.setFormatter(debug_formatter) else: - logger.setLevel(logging.DEBUG) - ch.setLevel(logging.DEBUG) + logger.setLevel(logging.INFO) + ch.setLevel(logging.INFO) ch.setFormatter(default_formatter) logger.addHandler(ch) # File handler (always on DEBUG level) diff --git a/mslib/utils/migration/config_before_nine.py b/mslib/utils/migration/config_before_nine.py index bee4bc1f7..7983e656d 100644 --- a/mslib/utils/migration/config_before_nine.py +++ b/mslib/utils/migration/config_before_nine.py @@ -144,7 +144,7 @@ class MSUIDefaultConfig: WMS_preload = [] # WMS image cache settings: - # this changes on any start of msui, use ths msui_settings.json when you want a persistent path + # this changes on any start of msui, use the msui_settings.json when you want a persistent path wms_cache = os.path.join(tempfile.TemporaryDirectory().name, "msui_wms_cache") # Maximum size of the cache in bytes. diff --git a/mslib/utils/migration/update_json_file_to_version_eight.py b/mslib/utils/migration/update_json_file_to_version_eight.py index 54c33af5e..7746eb24e 100644 --- a/mslib/utils/migration/update_json_file_to_version_eight.py +++ b/mslib/utils/migration/update_json_file_to_version_eight.py @@ -90,7 +90,7 @@ def change_parameters(self): modify_config_file(data_to_save_in_config_file) # read new file read_config_file() - # Todo move this to a seperate function to utils + # Todo move this to a separate function to utils # get all defaults default_options = config_loader(default=True) # get the data from the local file diff --git a/mslib/utils/migration/update_json_file_to_version_nine.py b/mslib/utils/migration/update_json_file_to_version_nine.py index 71b609d69..2f9abe89c 100644 --- a/mslib/utils/migration/update_json_file_to_version_nine.py +++ b/mslib/utils/migration/update_json_file_to_version_nine.py @@ -71,7 +71,7 @@ def change_parameters(self): modify_config_file(data_to_save_in_config_file) # read new file read_config_file() - # Todo move this to a seperate function to utils + # Todo move this to a separate function to utils # get all defaults default_options = config_loader(default=True) # get the data from the local file diff --git a/mslib/utils/netCDF4tools.py b/mslib/utils/netCDF4tools.py index bbd25e95e..cb855520f 100644 --- a/mslib/utils/netCDF4tools.py +++ b/mslib/utils/netCDF4tools.py @@ -260,7 +260,7 @@ def __init__(self, files, exclude=None, skip_dim_check=None, # Create the following: # cdf list of Dataset instances - # cdfVar dictionnary indexed by the variable names + # cdfVar dictionary indexed by the variable names cdf = [cdfm] self._cdf = cdf # Store this now, because dim() method needs it cdfVar = {} diff --git a/mslib/utils/qt.py b/mslib/utils/qt.py index 8a3357121..8503b80c4 100644 --- a/mslib/utils/qt.py +++ b/mslib/utils/qt.py @@ -315,7 +315,7 @@ def hidePopup(self): self.updateText() def timerEvent(self, event): - # After timeout, kill timer, and reenable click on line edit + # After timeout, kill timer, and re-enable click on line edit self.killTimer(event.timerId()) self.closeOnLineEditClick = False @@ -391,7 +391,7 @@ def __init__(self, function): def run(self): try: result = self.function() - # ToDo the capbilities worker member needs the possibility to terminate itselfs. + # ToDo the capbilities worker member needs the possibility to terminate itself. # ToDo refactoring needed if "MSUIWebMapService" in repr(result) and not result.contents: raise NoLayersError diff --git a/mslib/version.py b/mslib/version.py index 934844e40..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.0.0' +__version__ = u'9.1.0' diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..536fb8b65 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +[tool.codespell] +exclude-file = "codespell-ignored-lines.txt" +ignore-words-list = [ + "PRES", + "aircrafts", # this ignore should be removed as soon as mslib.msui.aircrafts is renamed + "degreeE", + "doubleClick", + "indexIn", + "socio-economic", +] diff --git a/pytest.ini b/pytest.ini index 3f0e6d3f9..4cf9ff50f 100644 --- a/pytest.ini +++ b/pytest.ini @@ -6,7 +6,6 @@ log_file = pytest.log log_file_level = DEBUG log_file_format = %(asctime)s %(levelname)s %(message)s log_file_date_format = %Y-%m-%d %H:%M:%S -timeout = 60 filterwarnings = # These namespaces are declared in a way not conformant with PEP420. Not much we can do about that here, we should keep an eye on when this is fixed in our dependencies though. ignore:Deprecated call to `pkg_resources.declare_namespace\('(xstatic|xstatic\.pkg|mpl_toolkits|mpl_toolkits\.basemap_data|sphinxcontrib|zope|fs|fs\.opener)'\)`\.:DeprecationWarning diff --git a/requirements.d/development.txt b/requirements.d/development.txt index fd3c44abc..232063ce6 100644 --- a/requirements.d/development.txt +++ b/requirements.d/development.txt @@ -9,7 +9,6 @@ pytest pytest-qt pytest-xdist pytest-cov -pytest-timeout sphinx sphinx_rtd_theme sphinxcontrib-video diff --git a/setup.py b/setup.py index c0f80484b..1828bfcaf 100644 --- a/setup.py +++ b/setup.py @@ -52,7 +52,7 @@ keywords="mslib", maintainer="Reimar Bauer", maintainer_email="rb.proj@gmail.com", - author="Marc Rautenahaus", + author="Marc Rautenhaus", author_email="wxmetvis@posteo.de", license="Apache-2.0", url="https://github.com/Open-MSS/MSS", diff --git a/tests/_test_mscolab/test_file_manager.py b/tests/_test_mscolab/test_file_manager.py index 1f93cd64f..dde450a14 100644 --- a/tests/_test_mscolab/test_file_manager.py +++ b/tests/_test_mscolab/test_file_manager.py @@ -401,7 +401,7 @@ def test_group_permissions(self): self.fm.add_bulk_permission(operation_group.id, self.user, [self.collaboratoruser.id], "collaborator") assert self.fm.is_member(self.collaboratoruser.id, operation_no_1.id) is True assert self.fm.is_collaborator(self.collaboratoruser.id, operation_no_1.id) - # check that not other catergories get changed + # check that not other categories get changed assert self.fm.is_member(self.collaboratoruser.id, operation_oslo.id) is False self.fm.modify_bulk_permission(operation_group.id, self.user, [self.collaboratoruser.id], "viewer") assert self.fm.is_viewer(self.collaboratoruser.id, operation_no_1.id) diff --git a/tests/_test_mscolab/test_files_api.py b/tests/_test_mscolab/test_files_api.py index 3631f27b4..43dcb4864 100644 --- a/tests/_test_mscolab/test_files_api.py +++ b/tests/_test_mscolab/test_files_api.py @@ -86,7 +86,7 @@ def test_fetch_users_without_permission(self): flight_path, operation = self._create_operation(flight_path="V2") assert self.fm.fetch_users_without_permission(operation.id, self.user_2.id) is False without_permission = self.fm.fetch_users_without_permission(operation.id, self.user.id) - # ToDo after seeding removed use absolut comparison + # ToDo after seeding removed use absolute comparison assert without_permission[-1] == [self.user_2.username, self.user_2.id] def test_fetch_users_with_permission(self): diff --git a/tests/_test_mscolab/test_server_auth_required.py b/tests/_test_mscolab/test_server_auth_required.py index 5280792a3..14ab148e6 100644 --- a/tests/_test_mscolab/test_server_auth_required.py +++ b/tests/_test_mscolab/test_server_auth_required.py @@ -57,7 +57,7 @@ def test_authfunc(self): def test_verify_pw(self): assert verify_pw("user", "testvaluepassword") - assert verify_pw("unknown", "unknow") is False + assert verify_pw("unknown", "unknown") is False assert verify_pw("user", "wrong") is False def test_register_user(self): diff --git a/tests/_test_mscolab/test_sockets_manager.py b/tests/_test_mscolab/test_sockets_manager.py index cdffb9303..574730c6e 100644 --- a/tests/_test_mscolab/test_sockets_manager.py +++ b/tests/_test_mscolab/test_sockets_manager.py @@ -98,7 +98,7 @@ def test_handle_connect(self): def test_join_creator_to_operatiom(self): sio = self._connect() - operation = self._new_operation('new_operation', "example decription") + operation = self._new_operation('new_operation', "example description") with self.app.app_context(): assert self.fm.get_file(int(operation.id), self.user) is False json_config = {"token": self.token, @@ -112,7 +112,7 @@ def test_join_creator_to_operatiom(self): def test_join_collaborator_to_operation(self): self._connect() - operation = self._new_operation('new_operation', "example decription") + operation = self._new_operation('new_operation', "example description") sm = SocketsManager(self.cm, self.fm) sm.join_collaborator_to_operation(self.anotheruser.id, operation.id) perms = Permission(self.anotheruser.id, operation.id, "collaborator") @@ -123,7 +123,7 @@ def test_join_collaborator_to_operation(self): def test_remove_collaborator_from_operation(self): pytest.skip("get_session_id has None result") sio = self._connect() - operation = self._new_operation('new_operation', "example decription") + operation = self._new_operation('new_operation', "example description") sm = SocketsManager(self.cm, self.fm) sm.join_collaborator_to_operation(self.anotheruser.id, operation.id) perms = Permission(self.anotheruser.id, operation.id, "collaborator") @@ -172,7 +172,7 @@ def test_get_messages(self): sio = self._connect() sio.emit('start', {'token': self.token}) - # ToDo same message gets twice emmitted, why? (use a helper function) + # ToDo same message gets twice emitted, why? (use a helper function) sio.emit("chat-message", { "op_id": self.operation.id, "token": self.token, @@ -203,7 +203,7 @@ def test_get_messages(self): def test_get_messages_api(self): sio = self._connect() sio.emit('start', {'token': self.token}) - # ToDo same message gets twice emmitted, why? + # ToDo same message gets twice emitted, why? sio.emit("chat-message", { "op_id": self.operation.id, "token": self.token, diff --git a/tests/_test_msui/test_aircrafts.py b/tests/_test_msui/test_aircraft.py similarity index 96% rename from tests/_test_msui/test_aircrafts.py rename to tests/_test_msui/test_aircraft.py index c83208560..efc72f6ed 100644 --- a/tests/_test_msui/test_aircrafts.py +++ b/tests/_test_msui/test_aircraft.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ - tests._test_msui.test_aircrafts - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + tests._test_msui.test_aircraft + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - This module provides pytest functions to tests msui.aircrafts module + This module provides pytest functions to test the msui.aircrafts module. This file is part of MSS. diff --git a/tests/_test_msui/test_tableview.py b/tests/_test_msui/test_tableview.py index 6f14668e8..3500bc90f 100644 --- a/tests/_test_msui/test_tableview.py +++ b/tests/_test_msui/test_tableview.py @@ -38,7 +38,7 @@ class Test_TableView: @pytest.fixture(autouse=True) def setup(self, qtbot): - # Create an initital flight track. + # Create an initial flight track. initial_waypoints = [ft.Waypoint(flightlevel=0, location="EDMO", comments="take off OP"), ft.Waypoint(48.10, 10.27, 200), ft.Waypoint(52.32, 09.21, 200), diff --git a/tests/_test_mswms/test_wms.py b/tests/_test_mswms/test_wms.py index c614682a3..08494bdc1 100644 --- a/tests/_test_mswms/test_wms.py +++ b/tests/_test_mswms/test_wms.py @@ -170,7 +170,7 @@ def test_produce_hsec_service_exception(self): ("ecmwf_EUR_LL015.PLDiv01", "PLDiv01"), ("ecmwf_EUR_LL015.PLDiv01", "ecmwf_EUR_LL015.PLDav01"), ("ecmwf_EUR_LL015.PLDiv01", "ecmwf_AUR_LL015.PLDiv01"), - ("format=image%2Fpng", "format=omage%2Fpng"), + ("format=image%2Fpng", "format=omage%2Fpng"), # codespell:ignore omage ("bbox=-50.0%2C20.0%2C20.0%2C75.0", "bbox=-abcd%2C20.0%2C20.0%2C75.0")]: environ["QUERY_STRING"] = query_string.replace(orig, fake) result = self.client.get('/?{}'.format(environ["QUERY_STRING"])) @@ -225,7 +225,7 @@ def test_produce_vsec_service_exception(self): ("&time=2012-10-17T12%3A00%3A00Z", ""), ("layers=ecmwf_EUR_LL015.VS_HV01", "layers=ecmwf_AUR_LL015.VS_HV01"), ("layers=ecmwf_EUR_LL015.VS_HV01", "layers=ecmwf_EUR_LL015.VS_HV99"), - ("format=image%2Fpng", "format=omage%2Fpng"), + ("format=image%2Fpng", "format=omage%2Fpng"), # codespell:ignore omage ("path=52.78%2C-8.93%2C48.08%2C11.28", "path=aaaa%2C-8.93%2C48.08%2C11.28"), ("&path=52.78%2C-8.93%2C48.08%2C11.28", ""), ("bbox=201%2C500.0%2C10%2C100.0", "bbox=aaa%2C500.0%2C10%2C100.0")]: diff --git a/tests/data/performance_simple.json b/tests/data/performance_simple.json index 5c20d1a70..420f8448e 100644 --- a/tests/data/performance_simple.json +++ b/tests/data/performance_simple.json @@ -11,5 +11,5 @@ "_comment3": "empty_weight: aircraft weight without fuel (lbs)", "_comment4": "climb/descent: weight(lbs), altitude(ft), duration(min), distance(nm), fuel(lbs)", "_comment5": "cruise: weight(lbs), altitude(ft), total air speed(nm/h), fuel flow(lbs/h)", - "_comment6": "ceiling: polynomial coeficients for relating weight (lbs) with peak flightlevel (hft). Leftmost coefficient is the intercept." + "_comment6": "ceiling: polynomial coefficients for relating weight (lbs) with peak flightlevel (hft). Leftmost coefficient is the intercept." } diff --git a/tutorials/textfiles/tutorial_mscolab.txt b/tutorials/textfiles/tutorial_mscolab.txt index 5180cf8dd..52d8ef741 100644 --- a/tutorials/textfiles/tutorial_mscolab.txt +++ b/tutorials/textfiles/tutorial_mscolab.txt @@ -68,7 +68,7 @@ for the users who have access permission to the operation, we can also change th Here for b, we have changed the permission from collaborator to admin. -we can alo delete a user with a permission by selecting user and clicking on delete button. +we can also delete a user with a permission by selecting user and clicking on delete button. Changing their access roles.... @@ -107,7 +107,7 @@ we can upload files by clicking on upload and browsing for the file. Here, we send the mss logo to all the users to see. -we can also search for a meassage by entering a phrase or complete text and then pressing previous or next as we need to find the message. +we can also search for a message by entering a phrase or complete text and then pressing previous or next as we need to find the message. Next, we close the chat window. @@ -144,10 +144,10 @@ We then open drop down menu of "save to server." It will open a window. -We can either click overwite server waypoints with local waypoints or local waypoints with server waypoints. +We can either click overwrite server waypoints with local waypoints or local waypoints with server waypoints. -We click overwite with local waypoints. +We click overwrite with local waypoints. The server waypoint changes with the work we have done locally. diff --git a/tutorials/textfiles/tutorial_satellitetrack.txt b/tutorials/textfiles/tutorial_satellitetrack.txt index 405420426..8a2f29e7e 100644 --- a/tutorials/textfiles/tutorial_satellitetrack.txt +++ b/tutorials/textfiles/tutorial_satellitetrack.txt @@ -1,7 +1,7 @@ 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. - These flights which can be reffered to as the Testing flights are made to travel in + These flights which can be referred to as the Testing flights are made to travel in the direction of these Satellites by collaborating with these space agencies. Open the top view of the MSS software. diff --git a/tutorials/textfiles/tutorial_wms.txt b/tutorials/textfiles/tutorial_wms.txt index e24ea2529..6c4408a11 100644 --- a/tutorials/textfiles/tutorial_wms.txt +++ b/tutorials/textfiles/tutorial_wms.txt @@ -9,7 +9,7 @@ So, lets start the tutorial to know what is wms in depth. When we open the top view of the map, the web map service is already opened by default. -It collects its data from the server: "open-mss.org" that provides all the meteorological or atmospheric informations as layer lists. +It collects its data from the server: "open-mss.org" that provides all the meteorological or atmospheric information as layer lists. As we click on the server layer option, the layer list window opens that lists out various layers. diff --git a/tutorials/tutorial_mscolab.py b/tutorials/tutorial_mscolab.py index 390d6bcf6..68dbf1954 100644 --- a/tutorials/tutorial_mscolab.py +++ b/tutorials/tutorial_mscolab.py @@ -37,7 +37,7 @@ EMAIL = 'johndoe@gmail.com' PASSWORD = 'johndoe' OPERATION_NAME = 'operation_of_john_doe' -OPERATION_DESCRIPTION = """This is John Doe's operation. He wants his collegues and friends \ +OPERATION_DESCRIPTION = """This is John Doe's operation. He wants his colleagues and friends \ to collaborate on this operation with him in the network. Mscolab, here, \ will be very helpful for Joe with various features to use!""" PATH = os.path.normpath(os.getcwd() + os.sep + os.pardir) @@ -232,7 +232,7 @@ def _adminwindow(): select_listelement(2, sleep=1) pag.sleep(1) create_tutorial_images() - # positions of buttons in the view mscolab admin windo + # positions of buttons in the view mscolab admin window pic = picture("mscolabadminwindow-all-users-without-permission.png") pos = pag.locateOnScreen(pic) left_side = (pos.left, pos.top, 500, 800) diff --git a/tutorials/tutorial_views.py b/tutorials/tutorial_views.py index a520b1b52..df304ef6e 100644 --- a/tutorials/tutorial_views.py +++ b/tutorials/tutorial_views.py @@ -481,7 +481,7 @@ def _tab_add_data(): # marks word pag.doubleClick() type_and_key('Location') - # annother waypoint name + # another waypoint name pag.click(x + xoffset, y - 263, duration=1) pag.sleep(1) pag.doubleClick() diff --git a/tutorials/utils/__init__.py b/tutorials/utils/__init__.py index 4cf865ce5..770aef845 100644 --- a/tutorials/utils/__init__.py +++ b/tutorials/utils/__init__.py @@ -141,7 +141,7 @@ def start(target=None, duration=120, dry_run=False): Note: Uncomment the line pag.press('q') if recording windows do not close in some cases. """ if platform.system() == 'Linux': - # makes shure the keyboard is set to US + # makes sure the keyboard is set to US os.system("setxkbmap -layout us") if target is None: return