Coverage for gws-app/gws/lib/style/core.py: 86%

35 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-05 13:35 +0200

1"""Style object and constructors.""" 

2 

3from typing import Optional 

4 

5import gws 

6 

7from . import parser, icon 

8 

9 

10# parsing depends on whenever the context is `trusted` (=config) or not (=request) 

11 

12def from_dict(d: dict, opts: parser.Options = None) -> 'Object': 

13 """Create a style object from a dict. 

14 

15 The dict can contain ``cssSelector``, ``text`` (CSS text) and ``values`` (a dict of style values). 

16 Values from ``values`` override those parsed from ``text``. 

17 

18 Args: 

19 d: A dict with style properties. 

20 opts: Parser options. Defaults to untrusted and strict. 

21 

22 Returns: 

23 A style object. 

24 

25 Raises: 

26 ``gws.Error``: If a property or value is invalid and the parser is strict. 

27 """ 

28 vals = {} 

29 opts = opts or parser.Options(trusted=False, strict=True) 

30 

31 s = d.get('text') 

32 if s: 

33 vals.update(parser.parse_text(s, opts)) 

34 

35 s = d.get('values') 

36 if s: 

37 vals.update(parser.parse_dict(gws.u.to_dict(s), opts)) 

38 

39 return Object( 

40 d.get('cssSelector', ''), 

41 d.get('text', ''), 

42 gws.StyleValues(vals), 

43 ) 

44 

45 

46def from_config(cfg: gws.Config, opts: parser.Options = None) -> 'Object': 

47 """Create a style object from a configuration. 

48 

49 Args: 

50 cfg: Style configuration. 

51 opts: Parser options. Defaults to trusted and strict. 

52 

53 Returns: 

54 A style object. 

55 

56 Raises: 

57 ``gws.Error``: If a property or value is invalid and the parser is strict. 

58 """ 

59 return from_dict( 

60 gws.u.to_dict(cfg), 

61 opts or parser.Options(trusted=True, strict=True)) 

62 

63 

64def from_props(props: gws.Props, opts: parser.Options = None) -> 'Object': 

65 """Create a style object from client properties. 

66 

67 Args: 

68 props: Style properties. 

69 opts: Parser options. Defaults to untrusted and non-strict. 

70 

71 Returns: 

72 A style object. 

73 """ 

74 return from_dict( 

75 gws.u.to_dict(props), 

76 opts or parser.Options(trusted=False, strict=False)) 

77 

78 

79## 

80 

81 

82class Config(gws.Config): 

83 """Feature style""" 

84 

85 cssSelector: Optional[str] 

86 """CSS selector""" 

87 text: Optional[str] 

88 """raw style content""" 

89 values: Optional[dict] 

90 """style values""" 

91 

92 

93class Props(gws.Props): 

94 

95 cssSelector: Optional[str] 

96 """CSS selector""" 

97 values: Optional[dict] 

98 """Style values""" 

99 

100 

101class Object(gws.Style): 

102 """Style object.""" 

103 

104 def __init__(self, selector, text, values): 

105 """Create a style object. 

106 

107 Args: 

108 selector: CSS selector. 

109 text: Raw CSS text. 

110 values: Parsed style values. 

111 """ 

112 self.cssSelector = selector 

113 self.text = text 

114 self.values = values 

115 

116 def props(self, user): 

117 ico = self.values.icon 

118 if ico and isinstance(ico, icon.ParsedIcon): 

119 ico = icon.to_data_url(ico) 

120 else: 

121 # NB if icon is not parsed, don't give it back 

122 ico = '' 

123 

124 return Props( 

125 cssSelector=self.cssSelector or '', 

126 values=gws.u.merge(self.values, icon=ico), 

127 )