Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 31 additions & 12 deletions menuinst/_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ def Field(*args, **kwargs):
return _Field(*args, **kwargs)


class MenuItemNameDict(BaseModel):
class TargetIsBaseConStr(BaseModel):
"""
Variable menu item name.
Use this dictionary if the menu item name depends on installation parameters
such as the target environment.
Variable that depends on whether or not the the installation is in the base env.

This can help configure the menu item on if the system is in a base environment.
"""

target_environment_is_base: Optional[constr(min_length=1)] = Field(
Expand All @@ -78,6 +78,21 @@ class MenuItemNameDict(BaseModel):
description=("Name when target environment is not the base environment."),
)

class TargetIsBaseConList(BaseModel):
"""
Variable that depends on whether or not the the installation is in the base env.

This can help configure the menu item on if the system is in a base environment.
"""

target_environment_is_base: Optional[conlist(str, min_items=1)] = Field(
None,
description=("Name when target environment is the base environment."),
)
target_environment_is_not_base: Optional[conlist(str, min_items=1)] = Field(
None,
description=("Name when target environment is not the base environment."),
)

class BasePlatformSpecific(BaseModel):
"""
Expand All @@ -88,12 +103,12 @@ class BasePlatformSpecific(BaseModel):
* Default value is always `None`.
"""

name: Optional[Union[constr(min_length=1), MenuItemNameDict]] = Field(
name: Optional[Union[constr(min_length=1), TargetIsBaseConStr]] = Field(
None,
description=(
"""
The name of the menu item. Can be a dictionary if the name depends on
installation parameters. See `MenuItemNameDict` for details.
installation parameters. See `TargetIsBaseConStr` for details.
"""
),
)
Expand All @@ -105,7 +120,7 @@ class BasePlatformSpecific(BaseModel):
None,
description=("Path to the file representing or containing the icon."),
)
command: Optional[conlist(str, min_items=1)] = Field(
command: Optional[conlist(str, min_items=1), TargetIsBaseConList] = Field(
None,
description=(
"""
Expand All @@ -119,7 +134,7 @@ class BasePlatformSpecific(BaseModel):
description=(
"""
Working directory for the running process.
Defaults to user directory on each platform.
Defaults to user recipe/owl-mcam_viewer-menu-unix.jsondirectory on each platform.
"""
),
)
Expand Down Expand Up @@ -322,7 +337,7 @@ class Linux(BasePlatformSpecific):
"""
),
)
StartupWMClass: Optional[str] = Field(
StartupWMClass: Optional[str, TargetIsBaseConStr] = Field(
None,
description=(
"""
Expand All @@ -331,7 +346,7 @@ class Linux(BasePlatformSpecific):
"""
),
)
TryExec: Optional[str] = Field(
TryExec: Optional[str, TargetIsBaseConStr] = Field(
None,
description=(
"""
Expand All @@ -350,6 +365,10 @@ class Linux(BasePlatformSpecific):
"""
),
)
run_in_bash: Optional[bool] = Field(
True,
description=("Whether to activate the target environment before running `command`."),
)


class MacOS(BasePlatformSpecific):
Expand Down Expand Up @@ -620,7 +639,7 @@ class Platforms(BaseModel):
class MenuItem(BaseModel):
"Instructions to create a menu item across operating systems."

name: Union[constr(min_length=1), MenuItemNameDict] = Field(
name: Union[constr(min_length=1), TargetIsBaseConStr] = Field(
...,
description=(
"""
Expand All @@ -633,7 +652,7 @@ class MenuItem(BaseModel):
...,
description=("A longer description of the menu item. Shown on popup messages."),
)
command: conlist(str, min_items=1) = Field(
command: Union[conlist(str, min_items=1), TargetIsBaseConList] = Field(
...,
description=(
"""
Expand Down
27 changes: 25 additions & 2 deletions menuinst/platforms/linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@ def _update_desktop_database(self):
def _command(self) -> str:
parts = []
precommand = self.render_key("precommand")
if isinstance(precommand, dict):
if self.menu.prefix.samefile(self.menu.base_prefix):
precommand = precommand.get("target_environment_is_base", "")
else:
precommand = precommand.get("target_environment_is_not_base", "")
if precommand:
parts.append(precommand)
if self.metadata["activate"]:
Expand All @@ -228,8 +233,17 @@ def _command(self) -> str:
else:
activate = "shell.bash activate"
parts.append(f'eval "$("{conda_exe}" {activate} "{self.menu.prefix}")"')
parts.append(" ".join(UnixLex.quote_args(self.render_key("command"))))
return "bash -c " + shlex.quote(" && ".join(parts))
command = self.render_key("command")
if isinstance(command, dict):
if self.menu.prefix.samefile(self.menu.base_prefix):
command = command.get("target_environment_is_base", "")
else:
command = command.get("target_environment_is_not_base", "")
parts.append(" ".join(UnixLex.quote_args(command)))
if self.metadata["run_in_bash"]:
return "bash -c " + shlex.quote(" && ".join(parts))
else:
return " && ".join(parts)

def _write_desktop_file(self):
if self.location.exists():
Expand Down Expand Up @@ -263,6 +277,15 @@ def _write_desktop_file(self):
value = self.render_key(key)
if value is None:
continue
if isinstance(value, dict):
if self.menu.prefix.samefile(self.menu.base_prefix):
value = value.get("target_environment_is_base", "")
else:
value = value.get("target_environment_is_not_base", "")
if not value:
raise ValueError(f"Cannot parse `{key}` from dictionary representation.")

# Now parse as bool/list/str
if isinstance(value, bool):
value = str(value).lower()
elif isinstance(value, (list, tuple)):
Expand Down