Skip to content

Commit 9cd2ffb

Browse files
committed
feat(profiles): a profile can now be hidden and inherit from other profiles
1 parent 97bf390 commit 9cd2ffb

File tree

4 files changed

+187
-33
lines changed

4 files changed

+187
-33
lines changed

.vscode/launch.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
// "--no-pager",
4646
//"config", "info", "list",
4747
// "analyze",
48-
"profiles", "list"
48+
"-p", "ci",
49+
"profiles", "show"
4950
// "discover", "tests", "--tags"
5051
// "."
5152
]

etc/robot.toml.json

Lines changed: 83 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,7 +1466,14 @@
14661466
},
14671467
"env": {
14681468
"additionalProperties": {
1469-
"type": "string"
1469+
"anyOf": [
1470+
{
1471+
"type": "string"
1472+
},
1473+
{
1474+
"$ref": "#/definitions/StringExpression"
1475+
}
1476+
]
14701477
},
14711478
"default": null,
14721479
"description": "Define environment variables to be set before running tests.\n\nExamples:\n```toml\n[env]\nTEST_VAR = \"test\"\nSECRET = \"password\"\n```\n",
@@ -1561,7 +1568,7 @@
15611568
},
15621569
"extend-args": {
15631570
"default": null,
1564-
"description": "Append extra arguments to be passed to _robot_.\n",
1571+
"description": "Append extra arguments to be passed to _robot_.\n\nExamples:\n```toml\nextend-args = [\"-t\", \"abc\"]\n```\n",
15651572
"items": {
15661573
"type": "string"
15671574
},
@@ -1573,10 +1580,17 @@
15731580
},
15741581
"extend-env": {
15751582
"additionalProperties": {
1576-
"type": "string"
1583+
"anyOf": [
1584+
{
1585+
"type": "string"
1586+
},
1587+
{
1588+
"$ref": "#/definitions/StringExpression"
1589+
}
1590+
]
15771591
},
15781592
"default": null,
1579-
"description": "Append extra environment variables to be set before tests.\n",
1593+
"description": "Append extra environment variables to be set before run.\n\nExamples:\n```toml\n[extend-env]\nEXTRA_VAR = \"value\"\n\n```\n",
15801594
"title": "Extend env",
15811595
"type": [
15821596
"object",
@@ -1789,7 +1803,7 @@
17891803
}
17901804
],
17911805
"default": null,
1792-
"description": "Append extra entries to the paths argument.\n\nExamples:\n```toml\npaths = [\"tests\"]\n```\n",
1806+
"description": "Append extra entries to the paths argument.\n\nExamples:\n```toml\nextend-paths = [\"tests\"]\n```\n",
17931807
"title": "Extend paths"
17941808
},
17951809
"extend-pre-rebot-modifiers": {
@@ -3315,7 +3329,14 @@
33153329
},
33163330
"env": {
33173331
"additionalProperties": {
3318-
"type": "string"
3332+
"anyOf": [
3333+
{
3334+
"type": "string"
3335+
},
3336+
{
3337+
"$ref": "#/definitions/StringExpression"
3338+
}
3339+
]
33193340
},
33203341
"default": null,
33213342
"description": "Define environment variables to be set before running tests.\n\nExamples:\n```toml\n[env]\nTEST_VAR = \"test\"\nSECRET = \"password\"\n```\n",
@@ -3410,7 +3431,7 @@
34103431
},
34113432
"extend-args": {
34123433
"default": null,
3413-
"description": "Append extra arguments to be passed to _robot_.\n",
3434+
"description": "Append extra arguments to be passed to _robot_.\n\nExamples:\n```toml\nextend-args = [\"-t\", \"abc\"]\n```\n",
34143435
"items": {
34153436
"type": "string"
34163437
},
@@ -3422,10 +3443,17 @@
34223443
},
34233444
"extend-env": {
34243445
"additionalProperties": {
3425-
"type": "string"
3446+
"anyOf": [
3447+
{
3448+
"type": "string"
3449+
},
3450+
{
3451+
"$ref": "#/definitions/StringExpression"
3452+
}
3453+
]
34263454
},
34273455
"default": null,
3428-
"description": "Append extra environment variables to be set before tests.\n",
3456+
"description": "Append extra environment variables to be set before run.\n\nExamples:\n```toml\n[extend-env]\nEXTRA_VAR = \"value\"\n\n```\n",
34293457
"title": "Extend env",
34303458
"type": [
34313459
"object",
@@ -3638,7 +3666,7 @@
36383666
}
36393667
],
36403668
"default": null,
3641-
"description": "Append extra entries to the paths argument.\n\nExamples:\n```toml\npaths = [\"tests\"]\n```\n",
3669+
"description": "Append extra entries to the paths argument.\n\nExamples:\n```toml\nextend-paths = [\"tests\"]\n```\n",
36423670
"title": "Extend paths"
36433671
},
36443672
"extend-pre-rebot-modifiers": {
@@ -4029,6 +4057,22 @@
40294057
"null"
40304058
]
40314059
},
4060+
"hidden": {
4061+
"anyOf": [
4062+
{
4063+
"type": "boolean"
4064+
},
4065+
{
4066+
"$ref": "#/definitions/Condition"
4067+
},
4068+
{
4069+
"type": "null"
4070+
}
4071+
],
4072+
"default": null,
4073+
"description": "The profile should be hidden.\nHidden means it is not shown in the list of available profiles.\n\nExamples:\n```toml\nhidden = true\n```\n\n```toml\nhidden = { if = 'environ.get(\"CI\") == \"true\"' }\n```\n",
4074+
"title": "Hidden"
4075+
},
40324076
"includes": {
40334077
"default": null,
40344078
"description": "Select tests by tag. Similarly as name with --test,\ntag is case and space insensitive and it is possible\nto use patterns with `*`, `?` and `[]` as wildcards.\nTags and patterns can also be combined together with\n`AND`, `OR`, and `NOT` operators.\n\nExamples:\n\n```\n--include foo --include bar*\n--include fooANDbar*\n```\n\ncorresponds to the `-i --include tag *` option of _robot_\n",
@@ -4048,6 +4092,35 @@
40484092
"null"
40494093
]
40504094
},
4095+
"inherits": {
4096+
"anyOf": [
4097+
{
4098+
"type": "string"
4099+
},
4100+
{
4101+
"$ref": "#/definitions/StringExpression"
4102+
},
4103+
{
4104+
"items": {
4105+
"anyOf": [
4106+
{
4107+
"type": "string"
4108+
},
4109+
{
4110+
"$ref": "#/definitions/StringExpression"
4111+
}
4112+
]
4113+
},
4114+
"type": "array"
4115+
},
4116+
{
4117+
"type": "null"
4118+
}
4119+
],
4120+
"default": null,
4121+
"description": "Profiles to inherit from.\n\nExamples:\n```toml\ninherits = [\"default\", \"Firefox\"]\n```\n",
4122+
"title": "Inherits"
4123+
},
40514124
"languages": {
40524125
"default": null,
40534126
"description": "Activate localization. `lang` can be a name or a code\nof a built-in language, or a path or a module name of\na custom language file.\n\ncorresponds to the `--language lang *` option of _robot_\n",

packages/robot/src/robotcode/robot/config/model.py

Lines changed: 85 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def field(
9999
return dataclasses.field(*args, **kwargs)
100100

101101

102-
class EvaluationError(Exception):
102+
class EvaluationError(ValueError):
103103
"""Evaluation error."""
104104

105105
def __init__(self, expression: str, message: str):
@@ -155,15 +155,19 @@ def evaluate(self) -> Any:
155155
try:
156156
return safe_eval(self.expr, SAFE_GLOBALS)
157157
except Exception as e:
158-
raise EvaluationError(self.expr, str(e)) from e
158+
raise EvaluationError(self.expr, f"{type(e).__name__}: {e}") from e
159159

160160

161161
@dataclass
162162
class StringExpression(Expression):
163163
"""Expression to evaluate to a string."""
164164

165165
def evaluate(self) -> str:
166-
return str(super().evaluate())
166+
result = super().evaluate()
167+
if result is None:
168+
return ""
169+
170+
return str(result)
167171

168172
def __str__(self) -> str:
169173
return self.evaluate()
@@ -2201,24 +2205,36 @@ def evaluated_with_env(
22012205
for k, v in self.env.items():
22022206
os.environ[k] = str(v)
22032207
if verbose_callback:
2204-
verbose_callback(lambda: f"Set environment variable {k} to {v}")
2208+
verbose_callback(lambda: f"Set environment variable `{k}` to `{v}`")
22052209

22062210
return self.evaluated(verbose_callback)
22072211

22082212

22092213
@dataclass
2210-
class RobotExtraBaseProfile(RobotBaseProfile):
2214+
class RobotExtendBaseProfile(RobotBaseProfile):
22112215
"""Base profile for Robot Framework with Extras."""
22122216

22132217
extend_args: Optional[List[str]] = field(
22142218
description="""\
22152219
Append extra arguments to be passed to _robot_.
2220+
2221+
Examples:
2222+
```toml
2223+
extend-args = ["-t", "abc"]
2224+
```
22162225
"""
22172226
)
22182227

22192228
extend_env: Optional[Dict[str, Union[str, StringExpression]]] = field(
22202229
description="""\
2221-
Append extra environment variables to be set before tests.
2230+
Append extra environment variables to be set before run.
2231+
2232+
Examples:
2233+
```toml
2234+
[extend-env]
2235+
EXTRA_VAR = "value"
2236+
2237+
```
22222238
"""
22232239
)
22242240

@@ -2228,14 +2244,14 @@ class RobotExtraBaseProfile(RobotBaseProfile):
22282244
22292245
Examples:
22302246
```toml
2231-
paths = ["tests"]
2247+
extend-paths = ["tests"]
22322248
```
22332249
"""
22342250
)
22352251

22362252

22372253
@dataclass
2238-
class RobotProfile(RobotExtraBaseProfile):
2254+
class RobotProfile(RobotExtendBaseProfile):
22392255
"""Robot Framework configuration profile."""
22402256

22412257
description: Optional[str] = field(description="Description of the profile.")
@@ -2265,15 +2281,42 @@ class RobotProfile(RobotExtraBaseProfile):
22652281
"""
22662282
)
22672283

2284+
hidden: Union[bool, Condition, None] = field(
2285+
description="""\
2286+
The profile should be hidden.
2287+
Hidden means it is not shown in the list of available profiles.
2288+
2289+
Examples:
2290+
```toml
2291+
hidden = true
2292+
```
2293+
2294+
```toml
2295+
hidden = { if = 'environ.get("CI") == "true"' }
2296+
```
2297+
"""
2298+
)
2299+
22682300
precedence: Optional[int] = field(
22692301
description="""\
22702302
Precedence of the profile. Lower values are executed first. If not set the order is undefined.
22712303
"""
22722304
)
22732305

2306+
inherits: Union[str, StringExpression, List[Union[str, StringExpression]], None] = field(
2307+
description="""\
2308+
Profiles to inherit from.
2309+
2310+
Examples:
2311+
```toml
2312+
inherits = ["default", "Firefox"]
2313+
```
2314+
"""
2315+
)
2316+
22742317

22752318
@dataclass
2276-
class RobotConfig(RobotExtraBaseProfile):
2319+
class RobotConfig(RobotExtendBaseProfile):
22772320
"""Robot Framework configuration."""
22782321

22792322
default_profiles: Union[str, List[str], None] = field(
@@ -2318,14 +2361,32 @@ def select_profiles(
23182361

23192362
names = (*(default_profile or ()),)
23202363

2321-
for name in names:
2364+
def select(name: str) -> None:
2365+
if not name:
2366+
return
2367+
2368+
nonlocal result
2369+
2370+
if verbose_callback:
2371+
verbose_callback(f"Selecting profiles matching '{name}'.")
2372+
23222373
profile_names = [p for p in profiles.keys() if fnmatch.fnmatchcase(p, name)]
23232374

23242375
if not profile_names:
23252376
raise ValueError(f"Can't find any profiles matching the pattern '{name}'.")
23262377

23272378
for v in profile_names:
2328-
result.update({v: profiles[v]})
2379+
p = profiles[v]
2380+
result.update({v: p})
2381+
if p.inherits:
2382+
if isinstance(p.inherits, list):
2383+
for i in p.inherits:
2384+
select(str(i))
2385+
else:
2386+
select(str(p.inherits))
2387+
2388+
for name in names:
2389+
select(name)
23292390

23302391
return result
23312392

@@ -2335,6 +2396,12 @@ def combine_profiles(
23352396
type_hints = get_type_hints(RobotBaseProfile)
23362397
base_field_names = [f.name for f in dataclasses.fields(RobotBaseProfile)]
23372398

2399+
if self.env:
2400+
for k, v in self.env.items():
2401+
os.environ[k] = str(v)
2402+
if verbose_callback:
2403+
verbose_callback(lambda: f"Set environment variable `{k}` to `{v}`")
2404+
23382405
result = RobotBaseProfile(
23392406
**{
23402407
f.name: self._verified_value(f.name, new, type_hints[f.name], self)
@@ -2346,7 +2413,7 @@ def combine_profiles(
23462413
selected_profiles = self.select_profiles(*names, verbose_callback=verbose_callback)
23472414
if verbose_callback:
23482415
if selected_profiles:
2349-
verbose_callback(f"Select profiles: {', '.join(selected_profiles.keys())}")
2416+
verbose_callback(f"Selected profiles: {', '.join(selected_profiles.keys())}")
23502417
else:
23512418
verbose_callback("No profiles selected.")
23522419

@@ -2362,6 +2429,12 @@ def combine_profiles(
23622429
if verbose_callback:
23632430
verbose_callback(f'Using profile "{profile_name}".')
23642431

2432+
if profile.env:
2433+
for k, v in profile.env.items():
2434+
os.environ[k] = str(v)
2435+
if verbose_callback:
2436+
verbose_callback(lambda: f"Set environment variable `{k}` to `{v}`")
2437+
23652438
if profile.detached:
23662439
result = RobotBaseProfile()
23672440

0 commit comments

Comments
 (0)