Skip to content

Commit ab020ba

Browse files
authored
Update README.md
large rewrite to accomodate for the developments in core with regards to ways to start robotframework. The most drastic change is the recomendation not to use it.
1 parent ac5ca59 commit ab020ba

File tree

1 file changed

+66
-30
lines changed

1 file changed

+66
-30
lines changed

README.md

Lines changed: 66 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
# compact_testprogram_distribution
1+
# compact testprogram distribution
22

3-
Zipapps are a sensible way to be able to distribute test programms with reasonable dependencies.
3+
Zipapps are a sensible way to be able to distribute test programs with reasonable dependencies.
44

55
For executing robotframework in order to perform production facility / test floor automated tasks
6-
the depency list becomes.:
6+
the dependency list becomes.:
77

88
- The operating system
99
- The non python drivers for the used equipment
@@ -14,8 +14,8 @@ the depency list becomes.:
1414
The only dependency is a python interpreter with a minimum version number, and the limitation
1515
that only zipapp compatible dependencies can be used.
1616

17-
For python versions 3.10 and 3.11 it is recomended to disable zipimport.zipimporter.invalidate_caches
18-
as it has a large performance inpact. Disabeling it, looses the feature to modify the zipapp during
17+
For python versions 3.10 and 3.11 it is recommended to disable zipimport.zipimporter.invalidate_caches
18+
as it has a large performance impact. Disabling it, looses the feature to modify the zipapp during
1919
runtime...
2020

2121
### Using pdm with pdm-packer
@@ -30,9 +30,9 @@ A python only zipapp without any native code.
3030
```
3131
At this point you are presented with robot output...
3232

33-
### going limbo
33+
### Minimal Zipapp Build (a.k.a. Limbo Mode)
3434

35-
lets reduce the size of the zipapp.:
35+
let’s reduce the size of the zipapp.:
3636

3737
``` bash
3838
$ cd examples\basic
@@ -41,7 +41,7 @@ lets reduce the size of the zipapp.:
4141
$ py zipapprobot.pyz .
4242
```
4343

44-
This comes out at less then 2MB...
44+
This results in a zipapp of less than 2MB in size, making it highly portable.
4545

4646
## Performance impact
4747

@@ -62,38 +62,74 @@ The limbo zipapp is faster than the native version on my setup for this example.
6262

6363
This is not supported, and generally a bad idea.
6464

65-
However this is technically possible by using importlib.util, and either https://github.com/SeaHOH/memimport or importlib.resources. Thus said, this is hacky and a bit of toppic. There is a example how this _can_ be achieved. In the example directory, but this is a proof that this can generally be achieved, but nothing more than that.
65+
However this is technically possible by using importlib.util, and either https://github.com/SeaHOH/memimport or importlib.resources. Thus said, this is hacky
66+
and a bit off topic. There is an example of how this _can_ be achieved. In the example directory, it is a proof that this can generally be achieved, but
67+
nothing more than that.
6668

67-
How well this can be donne heavily depends on the native code in question. Polars smoothly allows to load just the pyd file, and the rest from zipfile, numpy is hard...
69+
The feasibility of this approach heavily depends on the specific native code. For instance, polars works relatively well, whereas numpy presents significant challenges.
6870

69-
### Open points for improvement
71+
## cx_freeze
7072

71-
#### Windows
73+
cx_freeze can create many targets, the one I personally find most interesting is bdist_appimage (currently linux only). The resulting file with 34MBytes is reasonably
74+
close to the size of a python installer (28MBytes), and is a self contained, single file executable. Being dependent only of the operating system and drivers.
7275

73-
The given example clutters the tmp directory. This can be solved by using a
74-
bootstraping process to prepare the environment, and a seperate process to use
75-
it, so when this child process terminated, all file handles to the environment
76-
are closed and the directory can be removed.
76+
cx_freeze does use script entry points.
7777

78-
#### Linux / MacOS / XXXBSD
78+
Robotframework does come with a script, which is documented [here](https://robot-framework.readthedocs.io/en/latest/autodoc/robot.html#module-robot.run).
7979

80-
The methods to handle native code have not been tried there.
80+
What is not documented (and as far as I understand from this [discussion](https://github.com/robotframework/robotframework/issues/5384) will not be, this
81+
[pull request](https://github.com/robotframework/robotframework/pull/5390) was provided to remove pythonpathsetter), is that this script needs to live in
82+
the source tree, and can not use an installed robotframework, like in the zipapp/frozenapp/etc use case.
8183

82-
## using frozen executables
83-
Different to Zipapp, they bring their own interpreter and are not cross platform. There are examples for windows and linux inside the .github/workflows directory.
84+
### background
85+
It is possible to use robotframework straight from the source tree, without installation or configuring PYTHONPATH. This feature is not documented in the
86+
end user documentation, and not explained in the CONTRIBUTING.rst.
8487

85-
Keep in mind that robotframework loads keyword libraries in a way that is not understood by the freezing process, so it is necessary to manually specify which modules to add to the frozen executable. The example source code can be found in `pyproject.toml`
88+
This is implemented using the `pythonpathsetter` module which can be loaded by `import pythonpathsetter` when the robotframework is run from the script,
89+
additionally by `import robot.pythonpathsetter` when the script runs inside an environment where robotframework was installed into, and only using
90+
`import robot.pythonpathsetter`. This module changes the the `sys.path` at runtime, which can cause severe confusion when debugging dependency issues.
8691

87-
# Interesting alternatives which provide an alternative set of advantages/drawbacks
92+
These are the symptoms to look out for.:
93+
1 is that robotframework fails, as pythonpathsetter can not be imported.
94+
2 you can use ```import robot; robot.run()``` when debugging from a REPL.
8895

89-
- memimport allows to import pyd files from within zipfiles. But needs to be loaded itself by other means.
90-
- pyoxidizer creates a true single file executable.
91-
- [RobotFramework AIO is an all-in-one installer for Robot Framework, integrating preconfigured VSCodium and python to simplify setup and execution of test automation on both Windows and Linux systems.](https://github.com/test-fullautomation/RobotFramework_AIO)
92-
- shiv
93-
- pex
96+
In total at the time of writing there are 34 instances of ```sys.path``` and 89 ```__file__```in the source, all of them bring the risk of causing issues
97+
with zipapp/frozenapp usage. When I went over the source the first time, I missed how the ```pythonpathsetter``` can cause issues.
9498

95-
# Infrastructure that is suitable to handle the environments
99+
### solutions
100+
#### make sure pythonpathsetter exits
101+
Install a ```pythonpathsetter.py``` into your environment. Be aware future releases of robotframework will call a ```pythonpathsetter.set_pythonpath```
102+
which is in the source tree where you would expect ```robot.pythonpathsetter.set_pythonpath```. It doesnt need to do anything but if it is missing the code
103+
will not work. This change is introduced in response to linter messages.
96104

97-
- chocolatey
98-
- salt
105+
#### do not use robotframework distributed scripts
106+
Provide your own start script.
107+
108+
#### do not modify the ```sys.path``` (would need to come from upstream)
109+
Placing this code into the src directory, next to the robot directory of the source distribution. Using this code allows the robot code base to reduce
110+
the modifications of the ```sys.path```, while keeping the feature to use robotframework straight from the source directory.
111+
112+
```python
113+
import pathlib
114+
115+
if __name__ == "__main__":
116+
try:
117+
source = (pathlib.Path(__file__).parent / "robot" / "run.py")
118+
with source.open() as run:
119+
source_code = run.read()
120+
except Exception as e:
121+
print(f"""run_rf is a tool allowing you to start robotframework from a source tree without installing anything. Exception {e} occurred.
122+
123+
This script should not be used outside of robotframework development, and is not part of robotframework itself.""")
124+
exec(source_code)
125+
```
126+
127+
### consequence
128+
There are alternatives available.
129+
130+
- docker (way more heavy weight, user rights need to be managed)
131+
- astral [uv](https://docs.astral.sh/uv/) ```uvx --from robotframework==7.2.2 --with numpy==2.2.6 robot``` (not a single file, needs access to wheels...)
99132
- ...
133+
134+
I see value in frozen/zipapps and encourage everyone who is interested to tinker with them in an effort to learn. They are often faster than regular
135+
environments, easier to deploy and manage. However I would not recommend using them in a productive environment.

0 commit comments

Comments
 (0)