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

Feature.require vs. is_present, is_functional #33114

Closed
mkoeppe opened this issue Jan 4, 2022 · 35 comments
Closed

Feature.require vs. is_present, is_functional #33114

mkoeppe opened this issue Jan 4, 2022 · 35 comments

Comments

@mkoeppe
Copy link
Contributor

mkoeppe commented Jan 4, 2022

(addressing slabbe's questions from #33092 comment:23)

Some questions arise with respect to is_present(),
is_functional() and require():

  • why does Feature.require() not check
    that is_functional() is True?
  • should is_present() always return False
    when is_functional returns False (while
    the method names suggest is_present could
    be True while is_functional is False)?

Choices made in this ticket:

  • only is_present() should be called from outside
  • it always checks that is_functional() returns True
  • the require() method only calls is_present()

A further step, not done in this ticket, would be,
as suggested in comment:14, to rename is_functional
to _is_functional, since only is_present is supposed
to be used from outside.

CC: @seblabbe @orlitzky @kwankyu @saraedum

Component: refactoring

Author: Matthias Koeppe

Branch: f9232e8

Reviewer: Sébastien Labbé

Issue created by migration from https://trac.sagemath.org/ticket/33114

@mkoeppe mkoeppe added this to the sage-9.5 milestone Jan 4, 2022
@saraedum
Copy link
Member

saraedum commented Jan 4, 2022

comment:1

I believe that the original idea was to use this in the build process of SageMath. This influence some of the choices we made back then. If I understand correctly, that's not what we are planning to do anymore.

Anyway, require calls is_present which calls is_functional. At least that's the idea. As far as I recall, is_functional is just meant as a hook that you can override to add an additional check while relying on the generic is_present check. It should maybe be renamed to _is_functional to make this more obvious.

@saraedum
Copy link
Member

saraedum commented Jan 4, 2022

comment:2

So, is_present means: is the feature present and functional.

Similarly, require means: require this feature to be present in the above sense.

I believe that the task here is to improve the documentation of these methods if that is not sufficiently clear.

@seblabbe
Copy link
Contributor

seblabbe commented Jan 4, 2022

comment:3

Ok, this is how I understood the feature code up to today, but the meaning of is_present vs is_functional always perturbed me.

When we speak with someone verbally, it is possible that we observe for example as in #33092 that imagemagick is "installed" on a machine, thus the convert command "is present", but it "is not functional" because it can't handle PNG files for instance. In real life, it happens that a feature is present but not functional. This is why the current design is weird a little (but probably easy to fix, for example by adding a new method is_present_and_functional() that would be used by require() and in the sagemath library.)

What I realised today in #33092 comment:20 is that JoinFeature currently does not follow the same behavior with respect to is_present vs is_functional. Instead, it follows what we would be saying logically: a feature may be present but not functional.

@saraedum
Copy link
Member

saraedum commented Jan 4, 2022

comment:4

Replying to @seblabbe:

Ok, this is how I understood the feature code up to today, but the meaning of is_present vs is_functional always perturbed me.

I'd propose to rename is_present to is_present_and_functional and is_functional to _is_functional. I agree that it's confusing.

What I realised today in #33092 comment:20 is that JoinFeature currently does not follow the same behavior with respect to is_present vs is_functional. Instead, it follows what we would be saying logically: a feature may be present but not functional.

Yes, that is a bug in JoinFeature. (Copied over from the Latte feature from which it was created.)

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Jan 4, 2022

comment:5

I agree with all of the above - except that it's perhaps not necessary to do the renaming is_present -> is_present_and_functional

@seblabbe
Copy link
Contributor

seblabbe commented Jan 5, 2022

comment:6

Replying to @mkoeppe:

I agree with all of the above - except that it's perhaps not necessary to do the renaming is_present -> is_present_and_functional

I agree, I was thinking the same. When is_present_and_functional() return False, the first question that comes is whether it is because it is not functional or whether it is not present. Thus the next question to ask is whether is_present() return True or False. Thus we need both is_present_and_functional() and is_present().

Maybe the require() should raise a different type of error when it is not present vs not functional. Currently, when a feature is not functional the error message says the feature is not present which is weird. See #33092 comment:27.

@saraedum
Copy link
Member

saraedum commented Jan 5, 2022

comment:7

Replying to @seblabbe:

Replying to @mkoeppe:

I agree with all of the above - except that it's perhaps not necessary to do the renaming is_present -> is_present_and_functional

I agree, I was thinking the same. When is_present_and_functional() return False, the first question that comes is whether it is because it is not functional or whether it is not present. Thus the next question to ask is whether is_present() return True or False. Thus we need both is_present_and_functional() and is_present().

So, is_functional was never meant to be exposed to the user. It should really be protected with a _. It is also only meant as a hook for the Executable feature. I would not change that. Similarly _is_present is not meant to be exposed to the user in any way.

I don't think you need both is_functional and is_present for the user. I don't think you really need to distinguish why a feature can't be used like that, i.e., in a machine-readable way. What would be your use case? Instead, the checks can return a FeatureTestResult to provide a lot of detail why something is not sufficient.

Maybe the require() should raise a different type of error when it is not present vs not functional. Currently, when a feature is not functional the error message says the feature is not present which is weird. See #33092 comment:27.

Currently, require says not available. We could change that wording of course. The rest of the error message is pulled out of the FeatureTestResult if available.

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Jan 5, 2022

comment:8

Replying to @saraedum:

I don't think you need both is_functional and is_present for the user. I don't think you really need to distinguish why a feature can't be used like that, i.e., in a machine-readable way. What would be your use case? Instead, the checks can return a FeatureTestResult to provide a lot of detail why something is not sufficient.

+1

@seblabbe
Copy link
Contributor

seblabbe commented Jan 8, 2022

comment:9

Replying to @saraedum:

Replying to @seblabbe:

Maybe the require() should raise a different type of error when it is not present vs not functional. Currently, when a feature is not functional the error message says the feature is not present which is weird. See #33092 comment:27.

Currently, require says not available. We could change that wording of course. The rest of the error message is pulled out of the FeatureTestResult if available.

Well, the full context of that line is FeatureNotPresentError: imagemagick is not available. When I read this and I try to interpret it, I understand that the command convert was simply not found on the machine. This is not the information that we want to give. The situation we have here is more tricky. The convert is available, the problem is that it does not work well. And here we should not say to the user "here is how to install convert" as we do currently.

Or, maybe, I am wrong on the meaning of the word feature or the word present? For you, what is the definition of a feature? For example, when ffmpeg is found in the PATH but can't produce a gif from a png. Is ffmpeg a feature? or rather ffmpeg + some garenty that it can do something? For me, in this case, the feature ffmpeg is present but it is not functional. Therefore we should not raise a FeatureNotPresentError and tell the user to install the feature, but rather raise a FeatureNotFunctionalError and tell some more meaningfull message to the user which needs to deal with this tricky situation.

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Jan 9, 2022

comment:10

Given that features map to optional tags, we should avoid semantics more complicated than "present" vs. "not present".

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Jan 9, 2022

comment:11

If there is an actual use case for distinguishing different levels of "presence" for a feature (present, functional, awesome, spiffy) - then it would be clearer to actually define separate features for these levels.

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Jan 9, 2022

comment:12

Replying to @seblabbe:

we should not raise a FeatureNotPresentError and tell the user to install the feature, but rather raise a FeatureNotFunctionalError and tell some more meaningful message to the user which needs to deal with this tricky situation.

+1 on better messages where possible, but I don't think it's useful to have a separate exception class.

@seblabbe
Copy link
Contributor

seblabbe commented Jan 9, 2022

comment:13

Thanks for the answers. I agree to keep it simple and binary YES/NO. I do not have use cases for more levels of presence.

I allow myself to ask whether is_present() is still the good yes/no question we want to ask with the current design? Maybe a better name for it exists? Possibly is_present_and_functional() as suggested earlier? or something else?

I agree that my main point boils down to give good information to the user when require() fails.

@slel
Copy link
Member

slel commented Jan 12, 2022

comment:14

Maybe rename is_functional to _is_functional and is_presenttois_functional`?

@mkoeppe mkoeppe modified the milestones: sage-9.5, sage-9.6 Jan 12, 2022
@seblabbe
Copy link
Contributor

comment:16

Replying to @slel:

Maybe rename is_functional to _is_functional and is_presenttois_functional`?

Personaly, I don't disagree.

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Mar 5, 2022

Dependencies: #31292

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Mar 6, 2022

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Mar 6, 2022

comment:19

Here's a minimal change to improve the situation.


Last 10 new commits:

6c35717sage.features.FileFeature: Replace method absolute_path by absolute_filename, with deprecation
66d79f8sage.features.FileFeature.absolute_path: Fixup try...except...else
cad9f0fsage.features.FileFeature.absolute_filename: New abstract method
57531d0src/sage/features/__init__.py: Document why importing sage.misc.superseded can fail
66b8125sage.features.FileFeature: Add doc
d631a03src/sage/features/__init__.py: Fix docstring markup
e9568e9FileFeature.absolute_filename: Fix docstring
ec97570Merge #31292
df2d065JoinFeature.is_functional: Deprecate
297e611Executable.is_functional: Document that it should not be called directly

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Mar 6, 2022

Commit: 297e611

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Mar 6, 2022

Author: Matthias Koeppe

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Mar 6, 2022

comment:20

(Last 2 commits only; it is on top of #31292)

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Mar 6, 2022

Branch pushed to git repo; I updated commit sha1. New commits:

21d4004src/sage/features/imagemagick.py: Remove an is_functional doctest
f9232e8src/sage/features/join_feature.py: Update doctest output with deprecation warning

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Mar 6, 2022

Changed commit from 297e611 to f9232e8

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Mar 6, 2022

comment:24

(Last 4 commits only; it's on top of #31292.)

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Mar 17, 2022

Changed dependencies from #31292 to none

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Mar 25, 2022

comment:26

Let's get this in please

@seblabbe
Copy link
Contributor

comment:27

works for me. Thanks for this improvement.

I think a next step further is, as suggested in comment:14, to rename is_functional to _is_functional since only is_present is supposed to be used from outside.

@seblabbe
Copy link
Contributor

Reviewer: Sébastien Labbé

@mkoeppe
Copy link
Contributor Author

mkoeppe commented Mar 25, 2022

comment:28

Thanks!

@vbraun
Copy link
Member

vbraun commented Mar 30, 2022

@seblabbe
Copy link
Contributor

Changed commit from f9232e8 to none

@seblabbe
Copy link
Contributor

comment:30

updated description with choices made in this ticket

@seblabbe

This comment has been minimized.

@seblabbe

This comment has been minimized.

@slel

This comment has been minimized.

mkoeppe added a commit to mkoeppe/sage that referenced this issue Jun 8, 2024
vbraun pushed a commit to vbraun/sage that referenced this issue Jun 10, 2024
…`sage.features`: Remove deprecated methods

    
<!-- ^^^^^
Please provide a concise, informative and self-explanatory title.
Don't put issue numbers in there, do this in the PR body below.
For example, instead of "Fixes sagemath#1234" use "Introduce new method to
calculate 1+1"
-->
<!-- Describe your changes here in detail -->

<!-- Why is this change required? What problem does it solve? -->
<!-- If this PR resolves an open issue, please link to it here. For
example "Fixes sagemath#12345". -->
- Fixes sagemath#35255

Removes methods deprecated in:
- sagemath#31292 (2022)
- sagemath#33114 (2022)
<!-- If your change requires a documentation PR, please link it
appropriately. -->

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it
appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
<!-- Feel free to remove irrelevant items. -->

- [x] The title is concise, informative, and self-explanatory.
- [ ] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [ ] I have created tests covering the changes.
- [ ] I have updated the documentation accordingly.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on
- sagemath#12345: short description why this is a dependency
- sagemath#34567: ...
-->

<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
    
URL: sagemath#37312
Reported by: Matthias Köppe
Reviewer(s): Kwankyu Lee
vbraun pushed a commit to vbraun/sage that referenced this issue Jun 16, 2024
…`sage.features`: Remove deprecated methods

    
<!-- ^^^^^
Please provide a concise, informative and self-explanatory title.
Don't put issue numbers in there, do this in the PR body below.
For example, instead of "Fixes sagemath#1234" use "Introduce new method to
calculate 1+1"
-->
<!-- Describe your changes here in detail -->

<!-- Why is this change required? What problem does it solve? -->
<!-- If this PR resolves an open issue, please link to it here. For
example "Fixes sagemath#12345". -->
- Fixes sagemath#35255

Removes methods deprecated in:
- sagemath#31292 (2022)
- sagemath#33114 (2022)
<!-- If your change requires a documentation PR, please link it
appropriately. -->

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it
appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
<!-- Feel free to remove irrelevant items. -->

- [x] The title is concise, informative, and self-explanatory.
- [ ] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [ ] I have created tests covering the changes.
- [ ] I have updated the documentation accordingly.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on
- sagemath#12345: short description why this is a dependency
- sagemath#34567: ...
-->

<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
    
URL: sagemath#37312
Reported by: Matthias Köppe
Reviewer(s): Kwankyu Lee
vbraun pushed a commit to vbraun/sage that referenced this issue Jun 16, 2024
…`sage.features`: Remove deprecated methods

    
<!-- ^^^^^
Please provide a concise, informative and self-explanatory title.
Don't put issue numbers in there, do this in the PR body below.
For example, instead of "Fixes sagemath#1234" use "Introduce new method to
calculate 1+1"
-->
<!-- Describe your changes here in detail -->

<!-- Why is this change required? What problem does it solve? -->
<!-- If this PR resolves an open issue, please link to it here. For
example "Fixes sagemath#12345". -->
- Fixes sagemath#35255

Removes methods deprecated in:
- sagemath#31292 (2022)
- sagemath#33114 (2022)
<!-- If your change requires a documentation PR, please link it
appropriately. -->

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it
appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
<!-- Feel free to remove irrelevant items. -->

- [x] The title is concise, informative, and self-explanatory.
- [ ] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [ ] I have created tests covering the changes.
- [ ] I have updated the documentation accordingly.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on
- sagemath#12345: short description why this is a dependency
- sagemath#34567: ...
-->

<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
    
URL: sagemath#37312
Reported by: Matthias Köppe
Reviewer(s): Kwankyu Lee
vbraun pushed a commit to vbraun/sage that referenced this issue Jun 17, 2024
…`sage.features`: Remove deprecated methods

    
<!-- ^^^^^
Please provide a concise, informative and self-explanatory title.
Don't put issue numbers in there, do this in the PR body below.
For example, instead of "Fixes sagemath#1234" use "Introduce new method to
calculate 1+1"
-->
<!-- Describe your changes here in detail -->

<!-- Why is this change required? What problem does it solve? -->
<!-- If this PR resolves an open issue, please link to it here. For
example "Fixes sagemath#12345". -->
- Fixes sagemath#35255

Removes methods deprecated in:
- sagemath#31292 (2022)
- sagemath#33114 (2022)
<!-- If your change requires a documentation PR, please link it
appropriately. -->

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it
appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
<!-- Feel free to remove irrelevant items. -->

- [x] The title is concise, informative, and self-explanatory.
- [ ] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [ ] I have created tests covering the changes.
- [ ] I have updated the documentation accordingly.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on
- sagemath#12345: short description why this is a dependency
- sagemath#34567: ...
-->

<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
    
URL: sagemath#37312
Reported by: Matthias Köppe
Reviewer(s): Kwankyu Lee
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants