From 510170fdab293a58de706d3bc7dc8ea2785b1368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Fri, 2 Oct 2020 23:57:44 +0200 Subject: [PATCH] validate path string --- igniter/install_dialog.py | 66 +++++++++++++++++++++++++++++++------ igniter/tools.py | 46 ++++++++++++++++++++++++++ pype/lib/user_settings.py | 12 +++---- tests/igniter/test_tools.py | 16 +++++++++ 4 files changed, 124 insertions(+), 16 deletions(-) create mode 100644 igniter/tools.py create mode 100644 tests/igniter/test_tools.py diff --git a/igniter/install_dialog.py b/igniter/install_dialog.py index 20e570e05f..95ce3b49ce 100644 --- a/igniter/install_dialog.py +++ b/igniter/install_dialog.py @@ -2,9 +2,11 @@ """Show dialog for choosing central pype repository.""" import sys import os + from Qt import QtCore, QtGui, QtWidgets from .install_thread import InstallThread +from .tools import validate_path_string class InstallDialog(QtWidgets.QDialog): @@ -60,7 +62,7 @@ class InstallDialog(QtWidgets.QDialog): """Welcome to Pype

We've detected Pype is not configured yet. But don't worry, - this is as easy as setting one path. + this is as easy as setting one thing.

""") self.main_label.setWordWrap(True) @@ -70,10 +72,25 @@ class InstallDialog(QtWidgets.QDialog): # -------------------------------------------------------------------- self.pype_path_label = QtWidgets.QLabel( - """Set this path to your studio Pype repository to keep in - sync with your studio environment. This can be path or url. + """This can be: +

+

Leave it empty if you want to use Pype version that come with this installation. +

""" ) @@ -233,14 +250,14 @@ class InstallDialog(QtWidgets.QDialog): self.setLayout(main) def _on_select_clicked(self): - fname = QtWidgets.QFileDialog.getExistingDirectory( + filename = QtWidgets.QFileDialog.getExistingDirectory( self, 'Select path') - if fname: - fname = QtCore.QDir.toNativeSeparators(fname) + if filename: + filename = QtCore.QDir.toNativeSeparators(filename) - if os.path.isdir(fname): - self.user_input.setText(fname) + if os.path.isdir(filename): + self.user_input.setText(filename) def _on_ok_clicked(self): self._disable_buttons() @@ -258,8 +275,37 @@ class InstallDialog(QtWidgets.QDialog): self.close() def _path_changed(self, path: str) -> None: - self._path = path - self._status_label.setText(f"selected {path}") + """Validate entered path. + + It can be regular path - in that case we test if it does exist. + It can also be mongodb connection string. In that case we parse it + as url (it should start with `mongodb:`url schema. + + Args: + path (str): path, connection string url or pype token. + + Todo: + It can also be Pype token, binding it to Pype user account. + + """ + valid, reason = validate_path_string(path) + if not valid: + self.user_input.setStyleSheet( + """ + background-color: rgb(32, 19, 19); + color: rgb(255, 69, 0); + """ + ) + self._update_console(reason, True) + else: + self.user_input.setStyleSheet( + """ + background-color: rgb(31, 43, 32) + color: rgb(91, 159, 49) + """ + ) + self._update_console(reason) + self._path = path def _update_console(self, msg: str, error: bool = False) -> None: """Display message. diff --git a/igniter/tools.py b/igniter/tools.py new file mode 100644 index 0000000000..0f5706019a --- /dev/null +++ b/igniter/tools.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +"""Tools used in **Igniter** GUI.""" +import os +import uuid +from urllib.parse import urlparse + +from pymongo import MongoClient +from pymongo.errors import ServerSelectionTimeoutError + + +def validate_path_string(path: str) -> (bool, str): + """Validate string if it is acceptable by Igniter. + + ``path` string can be either regular path, or mongodb url or Pype token. + + Args: + path (str): String to validate. + + Returns: + (bool, str): True if valid, False if not and in second part of tuple + the reason why it failed. + + """ + parsed = urlparse(path) + if parsed.scheme == "mongodb": + # we have mongo connection string. Let's try if we can connect. + client = MongoClient(path, serverSelectionTimeoutMS=1) + try: + client.server_info() + except ServerSelectionTimeoutError: + return False, "Cannot connect to server" + else: + return True, "Connection is successful" + + # test for uuid + try: + uuid.UUID(path) + except ValueError as e: + # not uuid + if not os.path.exists(path): + return False, "Path doesn't exist or invalid token" + return True, "Path exists" + else: + # we have pype token + # todo: implement + return False, "Not implemented yet" diff --git a/pype/lib/user_settings.py b/pype/lib/user_settings.py index 916536d4c3..6fd66204d8 100644 --- a/pype/lib/user_settings.py +++ b/pype/lib/user_settings.py @@ -59,7 +59,7 @@ class ASettingRegistry(ABC): Returns: value (str): Value of the item. - Throws: + Raises: ValueError: If item doesn't exist. """ @@ -127,7 +127,7 @@ class ASettingRegistry(ABC): Returns: value (str): Value of the item. - Throws: + Raises: ValueError: If item doesn't exist. .. _Keyring module: @@ -229,7 +229,7 @@ class IniSettingRegistry(ASettingRegistry): Returns: str: Value of item. - Throws: + Raises: ValueError: If value doesn't exist. """ @@ -249,7 +249,7 @@ class IniSettingRegistry(ASettingRegistry): Returns: str: Item value. - Throws: + Raises: ValueError: If value doesn't exist. """ @@ -272,7 +272,7 @@ class IniSettingRegistry(ASettingRegistry): section (str): Section name. name (str): Name of the item. - Throws: + Raises: ValueError: If item doesn't exist. """ @@ -349,7 +349,7 @@ class JSONSettingRegistry(ASettingRegistry): Returns: value of the item - Throws: + Raises: ValueError: If item is not found in registry file. """ diff --git a/tests/igniter/test_tools.py b/tests/igniter/test_tools.py new file mode 100644 index 0000000000..b87900311a --- /dev/null +++ b/tests/igniter/test_tools.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +from uuid import uuid4 +from igniter.tools import validate_path_string + + +def test_validate_path_string(tmp_path): + # test path + status1, _ = validate_path_string(tmp_path.as_posix()) + assert status1 is True + status2, _ = validate_path_string("booo" + str(uuid4())) + assert status2 is False + + # todo: change when Pype token is implemented + status3, reason = validate_path_string(str(uuid4())) + assert status3 is False + assert reason == "Not implemented yet"