or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

constants.mdexpressions.mdfactories.mdindex.mdlicensing.mdsymbols.md

expressions.mddocs/

0

# Expression Utilities

1

2

Utility functions for manipulating, combining, and validating license expressions. These functions provide additional capabilities beyond the core Licensing class, including expression combination, symbol validation, and specialized processing functions.

3

4

## Capabilities

5

6

### Expression Combination

7

8

Combine multiple license expressions into a single expression using boolean logic.

9

10

```python { .api }

11

def combine_expressions(

12

expressions,

13

relation: str = "AND",

14

unique: bool = True,

15

licensing = None

16

) -> LicenseExpression:

17

"""

18

Combine multiple license expressions with the specified boolean relation.

19

20

Parameters:

21

- expressions: List or tuple of license expression strings or LicenseExpression objects

22

- relation: Boolean relation to use ("AND" or "OR")

23

- unique: Remove duplicate expressions before combining

24

- licensing: Licensing instance to use for parsing (default: creates new instance)

25

26

Returns:

27

Combined LicenseExpression object, or None if expressions is empty

28

29

Raises:

30

- TypeError: If expressions is not a list/tuple or relation is invalid

31

"""

32

```

33

34

### Symbol Validation

35

36

Validate collections of license symbols for correctness and consistency.

37

38

```python { .api }

39

def validate_symbols(symbols, validate_keys: bool = False) -> tuple:

40

"""

41

Validate a collection of license symbols.

42

43

Parameters:

44

- symbols: Iterable of LicenseSymbol objects to validate

45

- validate_keys: Whether to validate that keys are proper license identifiers

46

47

Returns:

48

Tuple of (warnings, errors) where each is a list of validation messages

49

"""

50

```

51

52

### Symbol Utility Functions

53

54

Convert and process license symbols.

55

56

```python { .api }

57

def as_symbols(symbols) -> list:

58

"""

59

Convert symbol strings/objects to LicenseSymbol instances.

60

61

Parameters:

62

- symbols: Iterable of strings or LicenseSymbol objects

63

64

Returns:

65

List of LicenseSymbol objects

66

"""

67

68

def ordered_unique(seq) -> list:

69

"""

70

Return unique items from sequence while preserving order.

71

72

Parameters:

73

- seq: Input sequence to deduplicate

74

75

Returns:

76

List with unique items in original order

77

"""

78

```

79

80

## Usage Examples

81

82

### Combining Expressions

83

84

```python

85

from license_expression import combine_expressions, get_spdx_licensing

86

87

# Combine with default AND relation

88

expressions = ['MIT', 'Apache-2.0', 'BSD-3-Clause']

89

combined = combine_expressions(expressions)

90

print(str(combined)) # 'MIT AND Apache-2.0 AND BSD-3-Clause'

91

92

# Combine with OR relation

93

combined_or = combine_expressions(expressions, relation='OR')

94

print(str(combined_or)) # 'MIT OR Apache-2.0 OR BSD-3-Clause'

95

96

# Remove duplicates (default behavior)

97

duplicate_expressions = ['MIT', 'Apache-2.0', 'MIT', 'BSD-3-Clause']

98

combined_unique = combine_expressions(duplicate_expressions)

99

print(str(combined_unique)) # 'MIT AND Apache-2.0 AND BSD-3-Clause'

100

101

# Keep duplicates

102

combined_with_dupes = combine_expressions(duplicate_expressions, unique=False)

103

print(str(combined_with_dupes)) # 'MIT AND Apache-2.0 AND MIT AND BSD-3-Clause'

104

```

105

106

### Working with License Expression Objects

107

108

```python

109

from license_expression import combine_expressions, get_spdx_licensing

110

111

licensing = get_spdx_licensing()

112

113

# Combine parsed expressions

114

expr1 = licensing.parse('MIT OR Apache-2.0')

115

expr2 = licensing.parse('GPL-2.0')

116

expr3 = licensing.parse('BSD-3-Clause')

117

118

combined = combine_expressions([expr1, expr2, expr3], relation='OR')

119

print(str(combined)) # '(MIT OR Apache-2.0) OR GPL-2.0 OR BSD-3-Clause'

120

```

121

122

### Custom Licensing Instance

123

124

```python

125

from license_expression import combine_expressions, Licensing, LicenseSymbol

126

127

# Create custom licensing with specific symbols

128

custom_symbols = [

129

LicenseSymbol('CustomLicense1'),

130

LicenseSymbol('CustomLicense2'),

131

]

132

custom_licensing = Licensing(custom_symbols)

133

134

# Use custom licensing for combination

135

expressions = ['CustomLicense1', 'CustomLicense2']

136

combined = combine_expressions(expressions, licensing=custom_licensing)

137

print(str(combined)) # 'CustomLicense1 AND CustomLicense2'

138

```

139

140

### Single Expression Handling

141

142

```python

143

# Single expression returns the expression itself

144

single = combine_expressions(['MIT'])

145

print(str(single)) # 'MIT'

146

147

# Empty expressions return None

148

empty = combine_expressions([])

149

print(empty) # None

150

151

# None input returns None

152

none_result = combine_expressions(None)

153

print(none_result) # None (but raises TypeError)

154

```

155

156

### Symbol Validation

157

158

```python

159

from license_expression import validate_symbols, LicenseSymbol

160

161

# Create test symbols with various issues

162

symbols = [

163

LicenseSymbol('MIT'),

164

LicenseSymbol('Apache-2.0'),

165

LicenseSymbol('MIT'), # Duplicate key

166

LicenseSymbol('CustomLicense', ['MIT']), # Alias conflicts with existing key

167

'InvalidSymbol', # Not a LicenseSymbol object

168

LicenseSymbol('GPL-2.0', is_exception=True), # Invalid exception

169

]

170

171

warnings, errors = validate_symbols(symbols)

172

print("Warnings:", warnings)

173

print("Errors:", errors)

174

175

# Validate with key checking

176

warnings, errors = validate_symbols(symbols, validate_keys=True)

177

print("Key validation errors:", errors)

178

```

179

180

### Symbol Conversion and Processing

181

182

```python

183

from license_expression import as_symbols, ordered_unique

184

185

# Convert mixed symbol types to LicenseSymbol objects

186

mixed_symbols = ['MIT', LicenseSymbol('Apache-2.0'), 'GPL-2.0']

187

symbol_objects = as_symbols(mixed_symbols)

188

for symbol in symbol_objects:

189

print(type(symbol), symbol.key) # All are LicenseSymbol instances

190

191

# Remove duplicates while preserving order

192

duplicate_list = ['MIT', 'Apache-2.0', 'MIT', 'GPL-2.0', 'Apache-2.0']

193

unique_list = ordered_unique(duplicate_list)

194

print(unique_list) # ['MIT', 'Apache-2.0', 'GPL-2.0']

195

```

196

197

## Advanced Token Processing

198

199

The library includes internal functions for advanced expression parsing and token processing:

200

201

```python { .api }

202

def build_symbols_from_unknown_tokens(tokens) -> dict:

203

"""Build license symbols from unknown tokens during parsing."""

204

205

def build_token_groups_for_with_subexpression(tokens) -> list:

206

"""Build token groups for WITH subexpression processing."""

207

208

def is_with_subexpression(tokens_tripple) -> bool:

209

"""Check if a token triplet represents a WITH subexpression."""

210

211

def replace_with_subexpression_by_license_symbol(tokens, strict: bool = False) -> list:

212

"""Replace WITH subexpressions with license symbols in token stream."""

213

```

214

215

Note: These functions are primarily for internal use and advanced customization scenarios.

216

217

## Error Handling

218

219

Expression utility functions include comprehensive error handling:

220

221

```python

222

from license_expression import combine_expressions

223

224

# Invalid relation parameter

225

try:

226

combine_expressions(['MIT', 'Apache-2.0'], relation='INVALID')

227

except TypeError as e:

228

print(f"Error: {e}")

229

230

# Invalid expressions parameter type

231

try:

232

combine_expressions('MIT') # String instead of list

233

except TypeError as e:

234

print(f"Error: {e}")

235

236

# Invalid expressions in list

237

try:

238

combine_expressions([123, 'MIT']) # Number in list

239

except Exception as e:

240

print(f"Error: {e}")

241

```