HyperRobotFrameworkPlugin icon indicating copy to clipboard operation
HyperRobotFrameworkPlugin copied to clipboard

keywords collecting with Hybrid library

Open mfo7mfo7mfo7 opened this issue 1 year ago • 4 comments

Hi @jnhyperion Thank you again for your support.

Please correct me if I'm wrong. Robot Hybrid library is a common way to implement keyword. https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#hybrid-library-api I found keywords are not parsed correctly, or checked improper way.

example1

BuiltIn Telnet library

image image image

Get Keyword Names is not a keyword but it checked as valid one.

example 2

i write a demo code for test hybrid library keyword collection. image

  • Hybrid library are collecting keywords by the function: get_keyword_names()
    • Not A Keyword should not be parsed as keyword for example.
    • Run, Get Name, Sleep are keywords but don't check well.

Here are the demo code for your reference. Thank you. Cheers!

# demo.robot

*** Settings ***
Library    demo.Zoo    AS     Zoo

*** Test Cases ***
Test Zoo
    Zoo.Run
    ${name}=     Zoo.Get Name
    Log To Console    ${name}

    Zoo.Switch    dog
    ${name}=     Zoo.Get Name
    Log To Console    ${name}

    Zoo.Run
    Zoo.Sleep

# demo.py

class Animal:
    def __init__(self, name, speed):
        """Initialize an animal with a name and speed."""
        self.name = name
        self.speed = speed

    def get_name(self):
        """Returns the name of the animal."""
        return self.name

    def run(self):
        """Simulates the animal running."""
        return f"{self.name} runs at {self.speed} km/h."

    def sleep(self):
        """Simulates the animal sleeping."""
        return f"{self.name} is sleeping."

import inspect

class Zoo:
    def __init__(self):
        """Initialize the Zoo with a default animal and animal options."""
        self.animals = {
            "cat": Animal(name="Cat", speed=30),
            "dog": Animal(name="Dog", speed=40),
            "lion": Animal(name="Lion", speed=50),
            "elephant": Animal(name="Elephant", speed=25)
        }
        self.current_animal = self.animals["cat"]

    def switch(self, animal_name):
        """Switch the current animal to another animal in the zoo."""
        if animal_name in self.animals:
            self.current_animal = self.animals[animal_name]
        else:
            raise ValueError(f"Animal '{animal_name}' not found in the zoo.")

    def not_a_keyword(self):
        pass

    def get_keyword_names(self):
        """Returns the names of all keywords in this library and the current animal."""
        not_keyword_list = ['not_a_keyword', 'get_keyword_names']


        zoo_methods = [method for method in dir(self) if callable(getattr(self, method)) and not method.startswith("_")]
        for k in not_keyword_list:
            try:
                zoo_methods.remove(k)
            except ValueError:
                pass  # do nothing!

        animal_methods = [method for method in dir(self.current_animal) if callable(getattr(self.current_animal, method)) and not method.startswith("_")]
        publish_kws = zoo_methods + animal_methods
        print(f'publish_kws: {publish_kws}')
        return publish_kws

    def __getattr__(self, name):
        """Delegate attribute access to the current animal if not found in Zoo."""
        if hasattr(self.current_animal, name):
            return getattr(self.current_animal, name)
        raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")

mfo7mfo7mfo7 avatar Oct 25 '24 19:10 mfo7mfo7mfo7

  1. For the special methods in the robot library class, plugin should not parse them as valid keywords, this can be improved. image

  2. For your example2, the keywords are generated dynamically during robot runtime, the plugin will never know the keyword names before the robot files are executed, in this case, the library should provide a pyi file to allow plugin to parse the keywords, please see the example of SeleniumLibrary, also refer to: https://github.com/jnhyperion/HyperRobotFrameworkPlugin/issues/67

jnhyperion avatar Oct 28 '24 02:10 jnhyperion

Hi @jnhyperion thank you again for prompt reply. Basically Example 1 and 2 are same implemented by Hybrid library practices.

Telnet is also the Robot Framework standard libraries, but it doesn't provide pyi officially. (actually Telnet probably is also hard to provide its pyi file since it's grabbing telnetlib's function as its own keywords via get_keyword_names)

As you mentioned that it's generated runtime, sounds like it's hard to do it by HyperRobotFrameworkPlugin. I'm not sure why robocorp's plugin can parse runtime keywords from hybrid/dynamic library. ( just guess maybe you are using more pyCharm plugin way to implement plugin.) https://plugins.jetbrains.com/plugin/16086-robot-framework-language-server

Your plugin is way better better better than robocorp's. Truly! But without runtime keyword parsing, it's kind of struggle with some Robot standard libraries and custom hybrid libraries.

Please consider to add this feature. Thank you. Cheers!!!!

mfo7mfo7mfo7 avatar Oct 28 '24 23:10 mfo7mfo7mfo7

@mfo7mfo7mfo7 great to know some other plugins can do this by magics, let me have some research anyway :)

jnhyperion avatar Oct 29 '24 02:10 jnhyperion

Relying on pyi files to get keywords is not very good approach. For example, SeleniumLibrary has plugin interface that can add add or modify keywords at load time and and while its possible to ship pyi for the plugin, there's no way to associate that to the actual instance of SeleniumLibrary. Same thing with BrowserLibrary, one can add keywords on similar way and write those new keywords in java/type script and then the library itself will do the heavy lifting to expose those to robot framework itself.

Your plugin is way better better better than robocorp's.

And robocorp's LSP is no more. Company stopped and shifted to out of RF ecosystem. However https://github.com/robotcodedev/robotcode is what community at large favours. While i have not even used pycharm so can't say anything but robotcode lsp had a release few weeks ago that said "initial pycharm/intellij support"

rasjani avatar Jan 22 '25 17:01 rasjani