Procházet zdrojové kódy

improve style and props parsing to support multi-word props #98

Falko Schindler před 2 roky
rodič
revize
7dbd4c421b
2 změnil soubory, kde provedl 22 přidání a 13 odebrání
  1. 21 10
      nicegui/elements/element.py
  2. 1 3
      tests/test_element.py

+ 21 - 10
nicegui/elements/element.py

@@ -1,5 +1,6 @@
 from __future__ import annotations
 
+import shlex
 from typing import Dict, Optional
 
 import justpy as jp
@@ -69,13 +70,18 @@ class Element:
         Styles are separated with a semicolon.
         This can be helpful if the predefined style sheet definitions by NiceGUI are not wanted in a particular styling.
         '''
-        def str_to_dict(s: Optional[str]) -> Dict[str, str]:
-            return dict((word.strip() for word in part.split(':')) for part in s.strip('; ').split(';')) if s else {}
-        style_dict = str_to_dict((self.view.style or '').strip('; ')) if replace is None else {}
-        for key in str_to_dict(remove):
+        def parse_style(text: Optional[str]) -> Dict[str, str]:
+            if not text:
+                return {}
+            lexer = shlex.shlex(text, posix=True)
+            lexer.whitespace = ';'
+            lexer.wordchars += ':- '
+            return dict(map(str.strip, word.split(':', 1)) for word in lexer)
+        style_dict = parse_style((self.view.style or '').strip('; ')) if replace is None else {}
+        for key in parse_style(remove):
             del style_dict[key]
-        style_dict.update(str_to_dict(add))
-        style_dict.update(str_to_dict(replace))
+        style_dict.update(parse_style(add))
+        style_dict.update(parse_style(replace))
         new_style = ';'.join(f'{key}:{value}' for key, value in style_dict.items())
         if self.view.style != new_style:
             self.view.style = new_style
@@ -89,14 +95,19 @@ class Element:
         Every prop passed to the `remove` parameter will be removed from the element.
         This can be helpful if the predefined props by NiceGUI are not wanted in a particular styling.
         '''
-        def str_to_dict(s: Optional[str]) -> Dict[str, str]:
-            return {prop.split('=')[0]: prop.split('=')[1] if '=' in prop else True for prop in s.split()} if s else {}
+        def parse_props(text: Optional[str]) -> Dict[str, str]:
+            if not text:
+                return {}
+            lexer = shlex.shlex(text, posix=True)
+            lexer.whitespace = ' '
+            lexer.wordchars += '=-'
+            return dict(word.split('=', 1) if '=' in word else (word, True) for word in lexer)
         needs_update = False
-        for key in str_to_dict(remove):
+        for key in parse_props(remove):
             if getattr(self.view, key, None) is not None:
                 needs_update = True
             setattr(self.view, key, None)
-        for key, value in str_to_dict(add).items():
+        for key, value in parse_props(add).items():
             if getattr(self.view, key, None) != value:
                 needs_update = True
             setattr(self.view, key, value)

+ 1 - 3
tests/test_element.py

@@ -1,5 +1,4 @@
 
-import pytest
 from nicegui import ui
 from selenium.webdriver.common.action_chains import ActionChains
 from selenium.webdriver.common.by import By
@@ -46,10 +45,9 @@ def test_styling_joystick(screen: Screen):
     assert 'shadow-lg' in joystick.get_attribute('class')
 
 
-@pytest.mark.skip(reason='not jet fixed; see https://github.com/zauberzeug/nicegui/issues/98')
 def test_input_with_multi_word_error_message(screen: Screen):
     input = ui.input(label='some input')
-    ui.button('set error', on_click=lambda: input.props('error-message="Some multi word error message" error=error'))
+    ui.button('set error', on_click=lambda: input.props('error error-message="Some multi word error message"'))
 
     screen.open('/')
     screen.should_not_contain('Some multi word error message')