diff --git a/.gitignore b/.gitignore index 09200104..41f4c58b 100644 --- a/.gitignore +++ b/.gitignore @@ -85,6 +85,7 @@ publish .coverage tmp output +docs/_build .eggs .tox .env diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 218a89c3..189e5743 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,7 @@ v3.7.1 *Release date: In development* +- Add pyproject.toml file for packaging and publishing Toolium - Add text analysis tool to get an overall match of a text against a list of expected characteristics using AI libraries that come with the `ai` extra dependency diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..6a3c9e1c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,154 @@ +[build-system] +requires = ["setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "toolium" +dynamic = ["version", "dependencies", "optional-dependencies"] +authors = [ + {name = "Rubén González Alonso", email = "ruben.gonzalezalonso@telefonica.com"}, +] +description = "Wrapper tool of Selenium and Appium libraries to test web and mobile applications in a single project" +readme = "README.rst" +license = {text = "Apache 2.0"} +keywords = [ + "selenium", + "appium", + "webdriver", + "web_automation", + "mobile_automation", + "page_object", + "visual_testing", + "ai", + "bdd", + "behave", + "pytest" +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: Other Audience", + "License :: OSI Approved :: Apache Software License", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Software Development :: Quality Assurance", + "Topic :: Software Development :: Testing", + "Topic :: Software Development :: Testing :: Acceptance", + "Topic :: Software Development :: Testing :: BDD", + "Topic :: Text Processing :: Linguistic", +] +requires-python = ">=3.10" + +[project.urls] +Homepage = "https://github.com/telefonica/toolium" +Repository = "https://github.com/telefonica/toolium" +Documentation = "http://toolium.readthedocs.org/en/latest" +Changelog = "http://toolium.readthedocs.org/en/latest/changelog.html" +"Bug Tracker" = "https://github.com/telefonica/toolium/issues" + +[tool.setuptools] +packages = [ + "toolium", + "toolium.pageobjects", + "toolium.pageelements", + "toolium.pageelements.playwright", + "toolium.behave", + "toolium.utils", + "toolium.utils.ai_utils" +] + +[tool.setuptools.package-data] +"toolium" = [ + "resources/VisualTestsTemplate.html", + "resources/VisualTests.js", + "resources/VisualTests.css" +] + +[tool.setuptools.dynamic] +version = {file = "VERSION"} +dependencies = {file = ["requirements.txt"]} +optional-dependencies.playwright = {file = ["requirements_playwright.txt"]} +optional-dependencies.ai = {file = ["requirements_ai.txt"]} +optional-dependencies.dev = {file = ["requirements_dev.txt"]} + +[tool.pytest.ini_options] +testpaths = ["toolium/test"] +python_files = ["test_*.py", "*_test.py"] +python_classes = ["Test*"] +python_functions = ["test_*"] +addopts = "-v --tb=short" + +[tool.coverage.run] +source = ["toolium"] +omit = [ + "*/test*", + "*/tests/*", + "*/venv/*", + "*/.venv/*", +] + +[tool.coverage.report] +exclude_lines = [ + "pragma: no cover", + "def __repr__", + "if self.debug:", + "if settings.DEBUG", + "raise AssertionError", + "raise NotImplementedError", + "if 0:", + "if __name__ == .__main__.:", +] + +[tool.black] +line-length = 120 +target-version = ['py310', 'py311', 'py312', 'py313'] +include = '\.pyi?$' +extend-exclude = ''' +/( + # directories + \.eggs + | \.git + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | build + | dist +)/ +''' + +[tool.isort] +profile = "black" +line_length = 120 +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +use_parentheses = true +ensure_newline_before_comments = true + +[tool.ruff] +line-length = 120 +target-version = "py310" +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + "I", # isort + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "UP", # pyupgrade +] +ignore = [ + "E501", # line too long, handled by black + "B008", # do not perform function calls in argument defaults + "C901", # too complex +] + +[tool.ruff.per-file-ignores] +"__init__.py" = ["F401"] diff --git a/requirements_ai.txt b/requirements_ai.txt new file mode 100644 index 00000000..b29f8384 --- /dev/null +++ b/requirements_ai.txt @@ -0,0 +1,4 @@ +spacy~=3.8.7 +sentence-transformers~=5.1 +transformers==4.56.2; python_version < '3.10' +openai~=1.108 \ No newline at end of file diff --git a/requirements_playwright.txt b/requirements_playwright.txt new file mode 100644 index 00000000..7281ffef --- /dev/null +++ b/requirements_playwright.txt @@ -0,0 +1 @@ +playwright~=1.43 \ No newline at end of file diff --git a/setup.py b/setup.py index 85a780b2..812cb255 100644 --- a/setup.py +++ b/setup.py @@ -15,96 +15,13 @@ See the License for the specific language governing permissions and limitations under the License. """ - from setuptools import setup +setup() -def read_file(filepath): - with open(filepath) as f: - return f.read() - - -def get_long_description(): - """Get README content and update rst urls - - :returns: long description - """ - # Get readme content - readme = read_file('README.rst') - - # Change rst urls to ReadTheDocs html urls - docs_url = 'http://toolium.readthedocs.org/en/latest' - description = readme.replace('/CHANGELOG.rst', '{}/changelog.html'.format(docs_url)) - for doc in ['driver_configuration', 'page_objects', 'bdd_integration', 'visual_testing', 'tests_result_analysis']: - description = description.replace('/docs/{}.rst'.format(doc), '{}/{}.html'.format(docs_url, doc)) - return description - +""" +Backward compatibility setup.py -setup( - name='toolium', - version=read_file('VERSION').strip(), - packages=[ - 'toolium', - 'toolium.pageobjects', - 'toolium.pageelements', - 'toolium.pageelements.playwright', - 'toolium.behave', - 'toolium.utils', - 'toolium.utils.ai_utils', - ], - package_data={ - '': [ - 'resources/VisualTestsTemplate.html', - 'resources/VisualTests.js', - 'resources/VisualTests.css', - ] - }, - install_requires=read_file('requirements.txt').splitlines(), - setup_requires=['pytest-runner'], - tests_require=read_file('requirements_dev.txt').splitlines(), - extras_require={ - "playwright": ["playwright~=1.43"], - "ai": [ - "spacy~=3.8.7", - "sentence-transformers~=5.1", - "transformers==4.56.2; python_version < '3.10'", - "openai~=1.108" - ] - }, - test_suite='toolium.test', - author='Rubén González Alonso, Telefónica I+D', - author_email='ruben.gonzalezalonso@telefonica.com', - url='https://github.com/telefonica/toolium', - description='Wrapper tool of Selenium and Appium libraries to test web and mobile applications in a single project', - long_description_content_type='text/x-rst', - long_description=get_long_description(), - keywords=[ - 'selenium', - 'appium', - 'webdriver', - 'web_automation', - 'mobile_automation', - 'page_object', - 'visual_testing', - 'ai', - 'bdd', - 'behave', - 'pytest' - ], - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Intended Audience :: Other Audience', - 'License :: OSI Approved :: Apache Software License', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: 3.12', - 'Programming Language :: Python :: 3.13', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'Topic :: Software Development :: Quality Assurance', - 'Topic :: Software Development :: Testing', - ], - license='Apache 2.0', -) +All package configuration has been moved to pyproject.toml +This file exists only for backward compatibility with older tools. +""" diff --git a/toolium/test/utils/ai_utils/test_text_analysis.py b/toolium/test/utils/ai_utils/test_text_analysis.py index 3d677a4c..df5ee40c 100644 --- a/toolium/test/utils/ai_utils/test_text_analysis.py +++ b/toolium/test/utils/ai_utils/test_text_analysis.py @@ -46,8 +46,7 @@ def configure_default_openai_model(): ) -@pytest.mark.skipif(os.getenv("AZURE_OPENAI_API_KEY") is None, - reason="AZURE_OPENAI_API_KEY environment variable not set") +@pytest.mark.skipif(not os.getenv("AZURE_OPENAI_API_KEY"), reason="AZURE_OPENAI_API_KEY environment variable not set") @pytest.mark.parametrize('input_text, features_list, expected_low, expected_high', get_analysis_examples) def test_get_text_analysis(input_text, features_list, expected_low, expected_high): similarity = json.loads(get_text_criteria_analysis(input_text, features_list, azure=True)) diff --git a/toolium/test/utils/ai_utils/test_text_similarity.py b/toolium/test/utils/ai_utils/test_text_similarity.py index c9ce046d..34aa377f 100644 --- a/toolium/test/utils/ai_utils/test_text_similarity.py +++ b/toolium/test/utils/ai_utils/test_text_similarity.py @@ -69,8 +69,7 @@ def test_get_text_similarity_with_sentence_transformers(input_text, expected_tex ) -@pytest.mark.skipif(os.getenv("AZURE_OPENAI_API_KEY") is None, - reason="AZURE_OPENAI_API_KEY environment variable not set") +@pytest.mark.skipif(not os.getenv("AZURE_OPENAI_API_KEY"), reason="AZURE_OPENAI_API_KEY environment variable not set") @pytest.mark.parametrize('input_text, expected_text, expected_low, expected_high', get_openai_similarity_examples) def test_get_text_similarity_with_azure_openai(input_text, expected_text, expected_low, expected_high): configure_default_openai_model() @@ -96,8 +95,7 @@ def test_assert_text_similarity_with_sentence_transformers_passed(input_text, ex assert_text_similarity(input_text, expected_text, threshold=threshold, similarity_method='sentence_transformers') -@pytest.mark.skipif(os.getenv("AZURE_OPENAI_API_KEY") is None, - reason="AZURE_OPENAI_API_KEY environment variable not set") +@pytest.mark.skipif(not os.getenv("AZURE_OPENAI_API_KEY"), reason="AZURE_OPENAI_API_KEY environment variable not set") @pytest.mark.parametrize('input_text, expected_text, threshold', assert_similarity_passed_examples) def test_assert_text_similarity_with_openai_passed(input_text, expected_text, threshold): configure_default_openai_model() @@ -131,8 +129,7 @@ def test_assert_text_similarity_with_sentence_transformers_failed(input_text, ex ) -@pytest.mark.skipif(os.getenv("AZURE_OPENAI_API_KEY") is None, - reason="AZURE_OPENAI_API_KEY environment variable not set") +@pytest.mark.skipif(not os.getenv("AZURE_OPENAI_API_KEY"), reason="AZURE_OPENAI_API_KEY environment variable not set") @pytest.mark.parametrize('input_text, expected_text, threshold', assert_openai_similarity_failed_examples) def test_assert_text_similarity_with_openai_failed(input_text, expected_text, threshold): configure_default_openai_model()