Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support different names for base and non-base environment #180

Merged
merged 33 commits into from May 8, 2024

Conversation

marcoesters
Copy link
Contributor

@marcoesters marcoesters commented Jan 25, 2024

Description

menuinst v1 added the environment name to shortcuts when the packages are installed outside the base environment. This behavior appears to be intended for Windows:

env_suffix = f" ({self.menu.env_name})" if self.menu.env_name else ""

However, env_name is never set. This PR sets env_name outside the base environment.

Add a feature to re-enable this behavior by expanding the schema. Contrary to v1, this is an option now and not standard behavior to allow for more flexibility.

Checklist - did you ...

  • Add a file to the news directory (using the template) for the next release's release notes?
  • Add / update necessary tests?
  • Add / update outdated documentation?

@conda-bot conda-bot added the cla-signed [bot] added once the contributor has signed the CLA label Jan 25, 2024
@marcoesters marcoesters marked this pull request as ready for review January 25, 2024 23:12
@marcoesters marcoesters requested a review from a team as a code owner January 25, 2024 23:12
@jaimergp
Copy link
Contributor

jaimergp commented Jan 26, 2024

I was thinking about the setup we use in napari. The installers basically ship:

  • A base environment with conda and friends
  • A napari-X.Y.Z environment, where X.Y.Z is the version of napari.

If we merge this PR, napari shortcuts will always have that env name appended, which might be redundant (we will see something like napari (napari-0.4.19)). I wonder if this is something we should control at the menuinst level or the constructor level. Maybe it should be a special placeholder in the shortcut name instead? So we make it opt-in?

Something like:

...
   "name": "Spyder 4.0 {{ ENV_NAME_IF_NOT_BASE }}",
...

Too hacky?

Alternatively, we could add a new field non_base_env_suffix that could take a template string like (%s). But that would require schema changes.

@ccordoba12
Copy link

Too hacky?

We are talking with @mrclary to do exactly the same for Spyder! So, if you decide to implement that directly here, we wouldn't need to in our menu.json

@marcoesters
Copy link
Contributor Author

I don't think it's too hacky. This is exactly the behavior that many seem to want.

We could alternatively also define the ENV_NAME that way - that it only renders if it's not the base environment. However, ENV_NAME_IF_NOT_BASE would maintain backwards compatibility with other patch versions of version 2.

@mrclary
Copy link

mrclary commented Jan 26, 2024

We are talking with @mrclary to do exactly the same for Spyder! So, if you decide to implement that directly here, we wouldn't need to in our menu.json

I'm sorry, @ccordoba12, I need to clarify that this is not exactly what we are trying to do with Spyder. What we are doing for Spyder is setting the name of the shortcut as Spyder <major version> for our installer created (non-base) environment, and Spyder <major version> (<env name>) for any other conda environment.

I do not support this PR as it currently is because I don't think menuinst should automatically set any part of the shortcut name, removing flexibility from the developer. This PR would absolutely prevent us from doing what we want to do with Spyder. I would support additional menuinst placeholders or additional menuinst._schema.MenuItems, e.g. in addition to name, have name_if_base and/or name_if_not_base, or similar, with defined precedence.

These would not really do anything for Spyder since menuinst has no way of knowing whether the environment was created by constructor, but they would not prevent us from doing it. So we would still use constructor's pre-install script in combination with spyder's post-link script to distinguish the constructor made environment and modify the spyder-menu.json before menuinst is invoked.

@marcoesters
Copy link
Contributor Author

I think a separate menu item is a better way to go about this. A separate placeholder would still require implicit menuinst logic. For example:

name: App {{ NAME_IF_NOT_BASE }}

would either have to implicitly insert parentheses or would just insert the name without them. Adding an optional name_if_not_base provides more flexibility.

@jaimergp
Copy link
Contributor

The more I think about this the less I see a way out, hah. menuinst is supposed to be not too conda specific. Other package managers could implement hooks to use it with different JSON locations. For example, micromamba or pixi could implement the schema and over there there's no concept of base environment.

I'm not sure I like the idea of adding more items to an implementation agnostic schema, when those items are kind of implementation specific... I need to think more about this 😬

@marcoesters
Copy link
Contributor Author

menuinst does already have the concept of prefix and base_prefix though. RIght now, it's only conda, but utils._default_prefix could be expanded to accommodate other frameworks.

If they do not have a concept like this, they don't have to use these, i.e., prefix and base_prefix will be the same thing.

@ccordoba12
Copy link

I'm sorry, @ccordoba12, I need to clarify that this is not exactly what we are trying to do with Spyder

Ok, sorry for the misunderstanding.

I do not support this PR as it currently is because I don't think menuinst should automatically set any part of the shortcut name

You're probably right: any project that depends on menuinst should be able to decide how to manage to name their shortcuts.

@jaimergp
Copy link
Contributor

jaimergp commented Mar 5, 2024

What if we extend name field into a multi-type field. Right now, it only takes a str (with placeholders), but we could also allow condition-to-str mappings:

...
"name": {
  "prefix_is_base": "Something",
  "prefix_is_not_base": "Something (else)"
},
...

I think I like that better, and it's a bit more future proof because if there are more use cases in the future, we won't have to add yet another key, only more conditions to the name mapping.

@mrclary
Copy link

mrclary commented Mar 5, 2024

What if we extend name field into a multi-type field. Right now, it only takes a str (with placeholders), but we could also allow condition-to-str mappings:

...
"name": {
  "prefix_is_base": "Something",
  "prefix_is_not_base": "Something (else)"
},
...

I think I like that better, and it's a bit more future proof because if there are more use cases in the future, we won't have to add yet another key, only more conditions to the name mapping.

@jaimergp, I like this idea.
"prefix_is_base" and "prefix_is_not_base" may be a bit confusing, however. "prefix" and "base" may be mis-interpreted as name prefix and base name, rather than referring to the environment prefix and base environment. Perhaps keys such as "default" and "base_env" might be more clear. Users could specify just "default" and have it apply everywhere, but if "base_env" is specified, then that value is applied in the case of a base environment.

@marcoesters
Copy link
Contributor Author

What if we extend name field into a multi-type field. Right now, it only takes a str (with placeholders), but we could also allow condition-to-str mappings:

...
"name": {
  "prefix_is_base": "Something",
  "prefix_is_not_base": "Something (else)"
},
...

I think I like that better, and it's a bit more future proof because if there are more use cases in the future, we won't have to add yet another key, only more conditions to the name mapping.

@jaimergp, I like this idea. "prefix_is_base" and "prefix_is_not_base" may be a bit confusing, however. "prefix" and "base" may be mis-interpreted as name prefix and base name, rather than referring to the environment prefix and base environment. Perhaps keys such as "default" and "base_env" might be more clear. Users could specify just "default" and have it apply everywhere, but if "base_env" is specified, then that value is applied in the case of a base environment.

Sorry for leaving this dormant - just getting back to this after a long leave of absence.

I do like the mapping idea, but we need to make this backwards compatible. Or do we want to have any string be a potential mapping?

I concur with "default" and "base_env" even though I'd probably want to be more explicit and use "base_environment".

@jaimergp
Copy link
Contributor

I do like the mapping idea, but we need to make this backwards compatible. Or do we want to have any string be a potential mapping?

We should be able to accept a string (original behaviour) or a mapping of conditions to string. Since we have total control over condition keys, we can either get creative with target_environment==base and target_environment!=base (but those are not evaluated, just strings we interpret in that way), or using op-less strings like target_environment_is_base and target_environment_is_not_base.

I don't care much as long as things are documented nicely.

@marcoesters marcoesters changed the title Set env_name when not in base environment Support different names for base and non-base environment Mar 27, 2024
Comment on lines +79 to +80
"target_environment_is_base": "Launch Turtle",
"target_environment_is_not_base": "Launch Turtle ({{ ENV_NAME }})"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking of non-conda implementations of the schema (where there's no "base" environment, like pixi or micromamba), and whether they'll have to deal with these semantics. They'll probably ignore *_is_base, but will have to handle *_is_not_base.

In a way, it looks to me that target_environment_is_not_base is the default case, while target_environment_is_base seems to be a special case in the grand scheme of things.

Should we have this as default and target_environment_is_base, instead? I know I'm bikeshedding a bit, but I wanted to make sure that other angles are considered.

cc @wolfv for awareness.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think default is ambiguous and what's the most common use case for micromamba and pixi is not necessarily the use case for others. I would say that for conda, the base environment case is much more common since the console shortcut, e.g., is installed into the base environment via the installer.

I think explicit is better than implicit.

name = self.metadata["name"].get("target_environment_is_base", "")
if not name:
raise KeyError("Cannot parse `name` from dictionary representation.")
self.metadata["name"] = name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point we have not rendered the {{ variables }}, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct.

The tests for a dictionary representation of the name would have failed by then, so even if code changes render the name at that point, the tests will catch that.

@marcoesters marcoesters requested a review from jaimergp May 3, 2024 15:07
@@ -75,7 +75,7 @@ def placeholders(self) -> Dict[str, str]:
"DISTRIBUTION_NAME": self.base_prefix.name,
"BASE_PYTHON": str(self.base_prefix / "bin" / "python"),
"PREFIX": str(self.prefix),
"ENV_NAME": self.prefix.name,
"ENV_NAME": self.env_name or "",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be false-y? 🤔 I think we don't need the or "" part, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I look at it again, I don't think so. I guess I was overly cautious here.

@jaimergp
Copy link
Contributor

jaimergp commented May 8, 2024

This will need a CEP update.

@jaimergp jaimergp merged commit 0aa4be1 into conda:main May 8, 2024
18 checks passed
@jaimergp jaimergp mentioned this pull request May 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla-signed [bot] added once the contributor has signed the CLA
Projects
Status: 🏁 Done
Development

Successfully merging this pull request may close these issues.

None yet

6 participants