robotcode
robotcode copied to clipboard
[BUG] variable defined via .py in the *** Settings *** section are visible in *** Test Cases *** but not *** Settings *** itself which causes several side effects
Describe the bug Invalid vscode plugin warnings that cause multiple issues
Using VS code plugin Name: RobotCode - Robot Framework Support Id: d-biehl.robotcode Description: Robot Framework IntelliSense, linting, test execution and debugging, code formatting, refactoring, and many more Version: 0.73.3 Publisher: Daniel Biehl VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=d-biehl.robotcode
- blah.robot
*** Settings ***
Variables variables.py
Library MyLib ${MY_VAR} AS MyFavLib # generates warning saying that MY_VAR does not exist
*** Test Cases ***
My Test
Log ${MY_VAR} # does not generate above warning and indicates (suite variable [imported]) ${MY_VAR}
MyFavLib.do_something # this is also generating a warning which is likely due to the fact that vscode extension considers this lib un-initialized. At runtime everything is fine however suppressing a warning on each keyword usage is not very practical
- variables.py
def get_variables() -> dict:
return {
"MY_VAR": "whatever",
}
Desktop (please complete the following information): Version: 1.85.2 Commit: 8b3775030ed1a69b13e4f4c628c612102e30a681 Date: 2024-01-18T06:40:11.430Z Electron: 25.9.7 ElectronBuildId: 26354273 Chromium: 114.0.5735.289 Node.js: 18.15.0 V8: 11.4.183.29-electron.0 OS: Darwin arm64 22.4.0
Your example is running for me, but you define a variable with a simple type. For complex types the evaluation is not possible at the moment, see #174 and #125 and #128 for the reason.
Do you use a complex type like dict, list or instances that are not derrived from simple types?
if yes:
A workaround can be, if the library is otherwise loaded correctly, say RobotCode it should ignore this error. Just put a comment at the end of the line of your import, like this
*** Settings ***
Variables variables.py
Library MyLib ${MY_VAR} AS MyFavLib # robotcode: ignore
there is also a quick fix available over the error, just put your cursor on the error and then a yellow light bulb should appear, here you can select Disable ...Error for this line
If this is not working, you need to define the argument with an default value and maybe initialize your library only if robot is really running and not in LibDoc mode, see here https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#detecting-is-robot-framework-running for an explanation. This works with robotframework version 6.1 and above. Here is an example:
from robot.libraries.BuiltIn import BuiltIn
class MyLib:
def __init__(self, a_var = None) -> None:
self.a_var = a_var
if BuiltIn().robot_running():
... # do the real initialization
def do_something(self) -> None:
print(self.a_var)
if you need it for Robot < 6.1 there is another solution, but I can find it at the moment. If you need this, ask me, then I can search for it.
Hope this helps a bit.
Yes, indeed, it is a mix of primitive and complex types, sometimes it is class types also. A more representative example below.
def get_variables() -> dict:
name1 = "blah"
name2 = "blah2"
config = SomeClass( input=[
OtherClass(name1, 1.0, ClassTypeOne),
OtherClass(name2, 3.0, ClassTypeTwo),
] )
return {
"MY_VAR": config,
"name1" : name1,
"name2": name2,
}
Do you use a complex type like dict, list or instances that are not derrived from simple types?
I have tried this initially the problem is it ignores the error with the library load however, it causes some unpleasant side effects which makes it impractical.
- all keywords from the library are highlighted as unknown which then means one needs to ignore error on each line where it is used.
- auto complete for keywords no longer working
# robotcode: ignore Just put a comment at the end of the line of your import
Checking if the robot is running in the library init has only helped if a similar check is done in the get_variables() function which sits in the user space
Question: Since adding this check in the library is transparent to the user, I don't see a problem with it and it is a good enough solution, however is there a way to avoid having to add this check in the variables.py file where the get_variables() function lives? Any ideas on this are greatly appreciated. It completely solved the problem once I added this check in both lib and variables.py file and autocomplete started working etc, However, because the variables.py sits in the user space I was wondering if there is a way not to do this, particularly because the check is not very clean my use case as I still need to provide some values for everything to work but not others. Please see example below.
def get_variables() -> dict:
name1 = "blah"
name2 = "blah2"
if not BuiltIn().robot_running():
return {
"MY_VAR": "ROBOT_NOT_RUNNING",
# unfortunately I can't omit these entirely because it is used as a variable in embedded keyword
# like Hey ${name1} Do Something Useful and If I don't include when robot is not running it will cause the plugin to
# highlight a bunch of errors saying variable in the keyword is not recongnized, again this is not a run time problem
# but only during test creation which will cause false positive errors everywhere
"name1" : name1,
"name2": name2,
}
config = SomeClass( input=[
OtherClass(name1, 1.0, ClassTypeOne),
OtherClass(name2, 3.0, ClassTypeTwo),
] )
return {
"MY_VAR": config,
"name1" : name1,
"name2": name2,
}
adding
if BuiltIn().robot_running():to the library init
I am on latest robot so no need for the other solution unless it helps with above point.
if you need it for Robot < 6.1 there is another solution,
what exactly do you mean with user space ?
what exactly do you mean with
user space?
by user space I simply mean the user of the library would create an appropriate variables.py file before they run any test that utilizes said library. Since I don't want the user of the library to be burdened with having to remember to include if not BuiltIn().robot_running(): clause in the variables file just to get the VS plug-in to behave nicely, I was wondering if there is a cleaner way to make the plugin to work. I am ok adding code to the robot library itself since it is transparent to the end user but not the variable's file because it now requires that user of the robot library takes additional steps that are not affecting runtime but impair development of test cases in VScode with the plugin.
P.S. Hopefully this clarifies.
At the moment I cache some informations about variables from python files, one if these infos is, if this variable is statically reproducible, this fits only for simple types like int, float, str,... for more complex type like list, dictionaries or instances of classes this is not really possible.
At a Library Import where you use variables, only the variables that statically resolved are given to the LibDoc generator algorithm, that's why the error Variable not exists happens.
this is at the moment just loud thinking and collecting some ideas and to not forget these ideas:
-
Maybe I can say that other variables that are not statically resolvable, like dicts, lists, objects etc. get the value
None, so that this variable can be resolved when generating the LibraryDoc. However, care must then be taken in the library implementation to ensure that None can also be passed to the parameter, i.e. if typehints are used, so that RobotFramework converts the type correctly and does not report an error about cannot convert value to type xy. The type must then be given a TypeHint that it can also be None, i.e.Optional[WhatEverType]orWhatEverType | None. And in the constructor you must react to the fact that the value may also be None. -
Another idea would be to introduce a setting where you can list the libraries for which the specified arguments do not have to be passed or default values can be specified if the LibDoc is generated for them. This may not work with dynamic or hybrid libraries.
-
One of the most important points when writing RobotFramework libraries is that a documentation can be created with the LibDoc tool on the command line. There you can actually only specify strings as parameters...
-
You could also check whether the value variable can be serialized in some form and then deserialized again (pickle, json, whatever) and implement this de/serialization as a RobotFramework typehint/type converter
What do you think?
I am not sure I fully understand the implications of these options since my understanding the of the framework is very superficial. However, based on my uneducated observation the VS code extension appears to think that the variable does not exist, which does not sound intuitive. The variable does exist and due to some internal extension processing, can't be processed because it is not "statically reproducible".
Is this really necessary for the extension to be able to reproduce it? I assume yes, for hover hints etc, but can't it just sacrifice some features on the "statically not reproducible" variables but at least recognize it as a valid variable? Also perhaps for complex type you can just hint with the python code instead of values, but not sure if that would be possible
here is the actual config with error:
Ok, as a first solution I have implemented a new setting where you can specify a list of libraries where the given arguments are ignored at analysis time, search in vscode settings for robotcode.analysis.cache.ignoreArgumentsForLibrary
Here you can add the name of your library in the described way. Take care that you choose the right scope User/Workspace(/Folder/...)
i will leave this issue open, because I think I implement the other variants too, but I have to think about it a little bit more.
However, please try the first solution and let me know if this solves your problem!