Thanks to visit codestin.com
Credit goes to github.com

Skip to content

deprecate / remove "pythonpathsetter" #5384

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

Closed
franzhaas opened this issue Mar 25, 2025 · 8 comments
Closed

deprecate / remove "pythonpathsetter" #5384

franzhaas opened this issue Mar 25, 2025 · 8 comments

Comments

@franzhaas
Copy link
Contributor

pythonpathsetter is a module that modifies the sys.path in a way that it is possible to run robot-related scripts without having robot installed in your environment.

This makes robot fail in very wired ways IF.:

  • you use a zipapp/frozen app which runs a script or the content of a script without importing robot first
  • you use a scripts=["src/robot/run.py"] instead of an entry point in setup.py
  • you copy code into your repl for experimentation

While it is possible to work around this for zipapp and frozen app usage, it is the main source of effort. The problem tends only to manifest when the frozen executable is built, making debugging hard and experimentation slow. It is hard to comprehend how seemingly innocent changes (run main / call main) break and fix things, and at least for me, I might be using imprecise language and end up mixing run vs call in communication.

In most circumstances, I believe that this concept is the better solution.:

PYTHONPATH=/path/to/your/robotdir/src/robot/ python src/robot/libdoc.py

It makes the productive robot code simpler, it makes it more visible that the sys.modules gets tinkered with.

Many solutions to support running robot-related scripts outside of an installed robot are possible, but it is not the use case I use, so I would like to leave this up to the real users.

This change might break the workflow of some people, so depricating first and collecting feedback should be the right step.

@pekkaklarck
Copy link
Member

pekkaklarck commented Mar 27, 2025

The reason why pythonpathsetter was created, is that back then it wasn't as convenient to run Python modules as scripts as it is nowadays. Although I sometimes run python src/robot/libdoc.py, which requires the logic provided by pythonpathsetter, during development, I tend to agree that the problems are bigger than benefits nowadays.

The proposed alternative to use

PYTHONPATH=src/robot python src/robot/libdoc.py

instead once pythonpathsetter is gone isn't that good, though, because having src/robot in sys.path can cause (and has caused) strange problems. I believe the proper way to do that is:

PYTHONPATH=src python -m robot.libdoc

The above is not as convenient as python src/robot/libdoc.py that works nowadays, but I doubt this approach is used so often that it would cause problems. I certainly can live with it.

@pekkaklarck
Copy link
Member

Although I doubt pythonpathsetter functionality is widely needed, it's best to deprecate it first and only remove it in a major version. We could deprecate it in RF 7.3 (or 7.4) and then remove it RF 8. On the code level deprecation shouldn't need much more than adding warnings.warn(message) to the pythonpathsetter module itself. In addition to that, the User Guide needs to be studied to see is using the old approach still recommended somewhere. Are you @franzhaas interested to do this?

@pekkaklarck
Copy link
Member

Hmm, I thought it would still be possible to run python src/robot without pythonpathsetter, but it turned out that also what won't work. That's somewhat annoying, because then there's no way to run Robot as a script. What's worse, if you have robot installed somewhere else, running python src/robot succeeds but runs the installed Robot not the one under src. That can lead to really hard to debug failures, especially when this currently works.

If we decide to remove pythonpathsetter, I pretty strongly believe we should prohibit users from running python src/robot or python src/robot.libdoc.py and provide a clear error if they try to do that. The problem is that this may cause similar problems than having pythonpathsetter making its removal rather useless.

Could you @franzhaas test that if you remove pythonpathsetter and raise an exception if someone runs e.g. python src/libdoc.py, does everything work fine with frozen apps?

@franzhaas
Copy link
Contributor Author

I think the only case where there is a problem when running robot as a script is when this is done from a source tree which was not installed into the environment, and the pythonpath was not adjusted.

I planned to go something like that:

if __name__ == '__main__' and 'robot' not in sys.modules:
    try:
        import robot as __ignore
        asssert pathlib.Path(__file__).parent.absolute() == pathlib.Path(__ignore.__file__).parent.absolute(), "you run robot/run.py using a robot installation from a different path... this is not suported"
    except ModuleNotFoundError:
        print("depricated running without having python path setup proactively, please either install or configure python path before running run.py")
        import pythonpathsetter

That way, as long as the pyton path is configured (by installation, or by any other means) the script works.

The thing that would make the life easier for zipapps/frozen apps is if robot behaved more predictably. So "running the code by evaling it from a string", "calling the same code as a function from a module", and "running the python file with the code in it" shall all do the same.

Preventing running the src/robot/run.py as a script would not help my goals much. (except for maybe a more helpful error message)

@pekkaklarck
Copy link
Member

After thinking this a bit more, I'd prefer not to remove the support to use python path/to/robot, python path/to/robot/libdoc.py and so on. The reasons are:

  • This functionality is convenient if you just have the source code so that it's not installed. Setting PYTHONPATH separately is not that hard, but it's still an extra step.
  • The change is backwards incompatible. Doing that with a deprecation period is possible, but it still require users depending on the current functionality to update their workflows.
  • Deprecation and removal is quite a lot of work. Code changes aren't that big, but the amount of documentation that should be updated is big. We needed to update the --help text of Robot, Rebot and Libdoc as well as their respective User Guide sections, and that needs to be done both when the feature is deprecated and when it is removed. In addition to that, explaining this in the release notes is some effort.

Could you @franzhaas explain the problems pythonpathsetter causes for you in some more detail? Instead of removing pythonpathsetter, we could try to find ways to change it so that it doesn't cause problems for you. For example, if it's a problem that importing pythonpathsetter has side effects, we could change the logic so that we use something like from pythonpathsetter import set_pythonpath; set_pythonpath() instead of just import pythonpathsetter.

Could you also explain what kind of workaround code you need to use currently? If it's not too complicated, needing to use such workarounds could still be a smaller problem than the problems associated with pythonpathsetter removal.

@franzhaas
Copy link
Contributor Author

I think what you are looking for is

try:
   import pythonpathsetter
except:
   pass

This will make robot/run.py run in an environment with robotframework installed (currently, it does so only if pythonpathsetter is loadable, robot.pythonpathsetter, the "regular" way to address this module does not help).

I do not think that this is a good idea, as it adds yet another way the pythonpath can be defined when using robotframework.

@franzhaas franzhaas reopened this Apr 9, 2025
@franzhaas franzhaas closed this as not planned Won't fix, can't repro, duplicate, stale Apr 9, 2025
@pekkaklarck
Copy link
Member

Adding try/except around import pythonpathsetter would be much better (especially much easier) than deprecating and removing pythonpathsetter. I just don't understand in what kind of context import pythonpathsetter would fail. Could you clarify that so that I could reproduce the issue as well?

pekkaklarck added a commit that referenced this issue Apr 27, 2025
Use a dedicated method instead.

The main motivation is avoiding linting errors from unused imports
(see #5387), but this may also help with issues `pythonpathsetter` has
caused (#5384).
@franzhaas
Copy link
Contributor Author

Have you tried the suggestions from the initial issue description? Changing setup.py is probably the least effort.

But to clarify, there is no issue.

These goals.:

  • RF inspects the environment and modifies it to make things better.
  • RF runs in a stable and deterministic environment which behaves predictably
    • behavior in the repl, in your ipython notebook and in your robotframework execution do match
    • Developers can choose the time and tool to explore their environment (what can i import?)
    • Setting up the environment is left to dedicated tools
    • RF does not interfere with what these tools do

are mutually exclusive.

@pekkaklarck it would have saved both of us a lot of time if you would have stated this goal early instead of encouraging a PR.

If you want to go zipapp/frozenapp or similar these things may work for you.:

  • install a pythonpathsetter.py module -> (btw mine will need to be adapted in the future due to commit e1f378d)
  • avoid parts of robotframework which deal with environment improvement (last time i checked this meant, don't execute scripts, don't eval file content, only import and call)

There are examples here.: https://github.com/MarketSquare/compact_testprogram_distribution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants