{"id":15018724,"url":"https://github.com/robotframework/pythonlibcore","last_synced_at":"2025-04-12T01:04:15.532Z","repository":{"id":46951729,"uuid":"80674254","full_name":"robotframework/PythonLibCore","owner":"robotframework","description":"Tools to ease creating larger test libraries for Robot Framework using Python","archived":false,"fork":false,"pushed_at":"2025-03-06T11:02:21.000Z","size":217,"stargazers_count":67,"open_issues_count":3,"forks_count":25,"subscribers_count":14,"default_branch":"main","last_synced_at":"2025-04-12T01:04:09.229Z","etag":null,"topics":["library","pyhton","robotframework","test-automation"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robotframework.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-02-01T23:12:22.000Z","updated_at":"2025-03-14T10:19:19.000Z","dependencies_parsed_at":"2024-09-07T01:31:36.866Z","dependency_job_id":"7c19e514-4a7d-45d2-8b0f-2ab6b77d2a8a","html_url":"https://github.com/robotframework/PythonLibCore","commit_stats":{"total_commits":244,"total_committers":12,"mean_commits":"20.333333333333332","dds":"0.30327868852459017","last_synced_commit":"ac375752c80a95b28d13e4c744a381f4dfbb4862"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotframework%2FPythonLibCore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotframework%2FPythonLibCore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotframework%2FPythonLibCore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotframework%2FPythonLibCore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robotframework","download_url":"https://codeload.github.com/robotframework/PythonLibCore/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248501861,"owners_count":21114683,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["library","pyhton","robotframework","test-automation"],"created_at":"2024-09-24T19:52:22.214Z","updated_at":"2025-04-12T01:04:15.510Z","avatar_url":"https://github.com/robotframework.png","language":"Python","readme":"# Python Library Core\n\nTools to ease creating larger test libraries for [Robot\nFramework](http://robotframework.org) using Python. The Robot Framework\n[hybrid](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#hybrid-library-api)\nand [dynamic library\nAPI](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#dynamic-library-api)\ngives more flexibility for library than the static library API, but they\nalso sets requirements for libraries which needs to be implemented in\nthe library side. PythonLibCore eases the problem by providing simpler\ninterface and handling all the requirements towards the Robot Framework\nlibrary APIs.\n\nCode is stable and is already used by\n[SeleniumLibrary](https://github.com/robotframework/SeleniumLibrary/)\nand\n[Browser library](https://github.com/MarketSquare/robotframework-browser/).\nProject supports two latest version of Robot Framework.\n\n[![Version](https://img.shields.io/pypi/v/robotframework-pythonlibcore.svg)](https://pypi.python.org/pypi/robotframework-pythonlibcore/)\n[![Actions Status](https://github.com/robotframework/PythonLibCore/workflows/CI/badge.svg)](https://github.com/robotframework/PythonLibCore/actions)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n\n## Usage\n\nThere are two ways to use PythonLibCore, either by\n`HybridCore` or by using `DynamicCore`. `HybridCore` provides support for\nthe hybrid library API and `DynamicCore` provides support for dynamic library API.\nConsult the Robot Framework [User\nGuide](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#creating-test-libraries),\nfor choosing the correct API for library.\n\nRegardless which library API is chosen, both have similar requirements.\n\n1)  Library must inherit either the `HybridCore` or `DynamicCore`.\n2)  Library keywords must be decorated with Robot Framework\n    [\\@keyword](https://github.com/robotframework/robotframework/blob/master/src/robot/api/deco.py)\n    decorator.\n3)  Provide a list of class instances implementing keywords to\n    `library_components` argument in the `HybridCore` or `DynamicCore` `__init__`.\n\nIt is also possible implement keywords in the library main class, by marking method with\n`@keyword` as keywords. It is not required pass main library instance in the\n`library_components` argument.\n\nAll keyword, also keywords implemented in the classes outside of the\nmain library are available in the library instance as methods. This\nautomatically publish library keywords in as methods in the Python\npublic API.\n\nThe example in below demonstrates how the PythonLibCore can be used with\na library.\n\n## Installation\nTo install this library, run the following command in your terminal:\n``` bash\npip install robotframework-pythonlibcore\n```\nThis command installs the latest version of `robotframework-pythonlibcore`, ensuring you have all the current features and updates.\n\n# Example\n\n``` python\n\"\"\"Main library.\"\"\"\n\nfrom robotlibcore import DynamicCore\n\nfrom mystuff import Library1, Library2\n\n\nclass MyLibrary(DynamicCore):\n    \"\"\"General library documentation.\"\"\"\n\n    def __init__(self):\n        libraries = [Library1(), Library2()]\n        DynamicCore.__init__(self, libraries)\n\n    @keyword\n    def keyword_in_main(self):\n        pass\n```\n\n``` python\n\"\"\"Library components.\"\"\"\n\nfrom robotlibcore import keyword\n\n\nclass Library1(object):\n\n    @keyword\n    def example(self):\n        \"\"\"Keyword documentation.\"\"\"\n        pass\n\n    @keyword\n    def another_example(self, arg1, arg2='default'):\n        pass\n\n    def not_keyword(self):\n        pass\n\n\nclass Library2(object):\n\n    @keyword('Custom name')\n    def this_name_is_not_used(self):\n        pass\n\n    @keyword(tags=['tag', 'another'])\n    def tags(self):\n        pass\n```\n\n# Plugin API\n\nIt is possible to create plugin API to a library by using PythonLibCore.\nThis allows extending library with external Python classes. Plugins can\nbe imported during library import time, example by defining argumet in\nlibrary [\\_\\_init\\_\\_]{.title-ref} which allows defining the plugins. It\nis possible to define multiple plugins, by seperating plugins with with\ncomma. Also it is possible to provide arguments to plugin by seperating\narguments with semicolon.\n\n``` python\nfrom robot.api.deco import keyword  # noqa F401\n\nfrom robotlibcore import DynamicCore, PluginParser\n\nfrom mystuff import Library1, Library2\n\n\nclass PluginLib(DynamicCore):\n\n    def __init__(self, plugins):\n        plugin_parser = PluginParser()\n        libraries = [Library1(), Library2()]\n        parsed_plugins = plugin_parser.parse_plugins(plugins)\n        libraries.extend(parsed_plugins)\n        DynamicCore.__init__(self, libraries)\n```\n\nWhen plugin class can look like this:\n\n``` python\nclass MyPlugi:\n\n    @keyword\n    def plugin_keyword(self):\n        return 123\n```\n\nThen Library can be imported in Robot Framework side like this:\n\n``` robotframework\nLibrary    ${CURDIR}/PluginLib.py    plugins=${CURDIR}/MyPlugin.py\n```\n\n# Translation\n\nPLC supports translation of keywords names and documentation, but arguments names, tags and types\ncan not be currently translated. Translation is provided as a file containing\n[Json](https://www.json.org/json-en.html) and as a\n[Path](https://docs.python.org/3/library/pathlib.html) object. Translation is provided in\n`translation` argument in the `HybridCore` or `DynamicCore` `__init__`. Providing translation\nfile is optional, also it is not mandatory to provide translation to all keyword.\n\nThe keys of json are the methods names, not the keyword names, which implements keyword. Value\nof key is json object which contains two keys: `name` and `doc`. `name` key contains the keyword\ntranslated name and `doc` contains keyword translated documentation. Providing\n`doc` and `name` is optional, example translation json file can only provide translations only\nto keyword names or only to documentatin. But it is always recomended to provide translation to\nboth `name` and `doc`.\n\nLibrary class documentation and instance documetation has special keys, `__init__` key will\nreplace instance documentation and `__intro__` will replace libary class documentation.\n\n## Example\n\nIf there is library like this:\n```python\nfrom pathlib import Path\n\nfrom robotlibcore import DynamicCore, keyword\n\nclass SmallLibrary(DynamicCore):\n    \"\"\"Library documentation.\"\"\"\n\n    def __init__(self, translation: Path):\n        \"\"\"__init__ documentation.\"\"\"\n        DynamicCore.__init__(self, [], translation.absolute())\n\n    @keyword(tags=[\"tag1\", \"tag2\"])\n    def normal_keyword(self, arg: int, other: str) -\u003e str:\n        \"\"\"I have doc\n\n        Multiple lines.\n        Other line.\n        \"\"\"\n        data = f\"{arg} {other}\"\n        print(data)\n        return data\n\n    def not_keyword(self, data: str) -\u003e str:\n        print(data)\n        return data\n\n    @keyword(name=\"This Is New Name\", tags=[\"tag1\", \"tag2\"])\n    def name_changed(self, some: int, other: int) -\u003e int:\n        \"\"\"This one too\"\"\"\n        print(f\"{some} {type(some)}, {other} {type(other)}\")\n        return some + other\n```\n\nAnd when there is translation file like:\n```json\n{\n    \"normal_keyword\": {\n        \"name\": \"other_name\",\n        \"doc\": \"This is new doc\"\n    },\n    \"name_changed\": {\n        \"name\": \"name_changed_again\",\n        \"doc\": \"This is also replaced.\\n\\nnew line.\"\n    },\n    \"__init__\": {\n        \"name\": \"__init__\",\n        \"doc\": \"Replaces init docs with this one.\"\n    },\n    \"__intro__\": {\n        \"name\": \"__intro__\",\n        \"doc\": \"New __intro__ documentation is here.\"\n    },\n}\n```\nThen `normal_keyword` is translated to `other_name`. Also this keyword documentions is\ntranslted to `This is new doc`. The keyword is `name_changed` is translted to\n`name_changed_again` keyword and keyword documentation is translted to\n`This is also replaced.\\n\\nnew line.`. The library class documentation is translated\nto `Replaces init docs with this one.` and class documentation is translted to\n`New __intro__ documentation is here.`\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobotframework%2Fpythonlibcore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobotframework%2Fpythonlibcore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobotframework%2Fpythonlibcore/lists"}