Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Set supported python versions
id: set-versions
run: |
echo 'versions=["3.10", "3.11", "3.12", "3.13", "3.14"]' >> "$GITHUB_OUTPUT"
echo 'versions=["3.11", "3.12", "3.13", "3.14"]' >> "$GITHUB_OUTPUT"

lint:
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ v3.8.5
*Release date: In development*

- Add support for Python 3.14
- Remove Python 3.10 support (Python 3.10 reaches end of life in October 2026)

v3.8.4
------
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Getting Started
---------------

Run ``pip install toolium`` to install the latest version from `PyPi <https://pypi.org/project/toolium>`_. It's
highly recommended to use a virtualenv.
highly recommended to use a virtualenv. Toolium requires Python 3.11 or later.

The main dependencies are:

Expand Down
5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ classifiers = [
"Intended Audience :: Other Audience",
"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",
Expand All @@ -43,7 +42,7 @@ classifiers = [
"Topic :: Software Development :: Testing :: BDD",
"Topic :: Text Processing :: Linguistic",
]
requires-python = ">=3.10"
requires-python = ">=3.11"

[project.urls]
Homepage = "https://github.com/telefonica/toolium"
Expand Down Expand Up @@ -105,7 +104,7 @@ exclude_lines = [

[tool.ruff]
line-length = 120
target-version = "py310"
target-version = "py311"

[tool.ruff.lint]
# Rules to enforce
Expand Down
52 changes: 26 additions & 26 deletions toolium/test/utils/test_dataset_replace_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,48 +182,48 @@ def test_replace_param_datetime_language_ignored():

def test_replace_param_today_spanish():
param = replace_param('[TODAY]', language='es')
assert param == datetime.datetime.now(datetime.timezone.utc).strftime('%d/%m/%Y')
assert param == datetime.datetime.now(datetime.UTC).strftime('%d/%m/%Y')


def test_replace_param_today_not_spanish():
param = replace_param('[TODAY]', language='en')
assert param == datetime.datetime.now(datetime.timezone.utc).strftime('%Y/%m/%d')
assert param == datetime.datetime.now(datetime.UTC).strftime('%Y/%m/%d')


def test_replace_param_today_offset():
param = replace_param('[TODAY - 1 DAYS]', language='es')
assert param == datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=1),
datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=1),
'%d/%m/%Y',
)


def test_replace_param_now_spanish():
param = replace_param('[NOW]', language='es')
assert param == datetime.datetime.now(datetime.timezone.utc).strftime('%d/%m/%Y %H:%M:%S')
assert param == datetime.datetime.now(datetime.UTC).strftime('%d/%m/%Y %H:%M:%S')


def test_replace_param_now_not_spanish():
param = replace_param('[NOW]', language='it')
assert param == datetime.datetime.now(datetime.timezone.utc).strftime('%Y/%m/%d %H:%M:%S')
assert param == datetime.datetime.now(datetime.UTC).strftime('%Y/%m/%d %H:%M:%S')


def test_replace_param_now_with_format():
param = replace_param('[NOW(%Y-%m-%dT%H:%M:%SZ)]')
assert param == datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
assert param == datetime.datetime.now(datetime.UTC).strftime('%Y-%m-%dT%H:%M:%SZ')


def test_replace_param_now_with_format_and_decimals_limit():
param = replace_param('[NOW(%Y-%m-%dT%H:%M:%S.%3fZ)]')
param_till_dot = param[: param.find('.')]
assert param_till_dot == datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%dT%H:%M:%S')
assert param_till_dot == datetime.datetime.now(datetime.UTC).strftime('%Y-%m-%dT%H:%M:%S')
assert re.match(param_till_dot + r'\.\d{3}Z', param)


def test_replace_param_now_with_format_and_decimals_limit_beyond_microseconds():
param = replace_param('[NOW(%Y-%m-%dT%H:%M:%S.%12fZ)]')
param_till_dot = param[: param.find('.')]
assert param_till_dot == datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%dT%H:%M:%S')
assert param_till_dot == datetime.datetime.now(datetime.UTC).strftime('%Y-%m-%dT%H:%M:%S')
assert re.match(param_till_dot + r'\.\d{12}Z', param)


Expand All @@ -240,23 +240,23 @@ def test_not_replace_param_now_with_invalid_closing_parenthesis_in_format():
def test_replace_param_now_offset():
param = replace_param('[NOW + 5 MINUTES]', language='es')
assert param == datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=5),
datetime.datetime.now(datetime.UTC) + datetime.timedelta(minutes=5),
'%d/%m/%Y %H:%M:%S',
)


def test_replace_param_now_offset_with_format():
param = replace_param('[NOW(%Y-%m-%dT%H:%M:%SZ) + 5 MINUTES]')
assert param == datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=5),
datetime.datetime.now(datetime.UTC) + datetime.timedelta(minutes=5),
'%Y-%m-%dT%H:%M:%SZ',
)


def test_replace_param_today_offset_and_more():
param = replace_param('The day [TODAY - 1 DAYS] was yesterday', language='es')
offset_date = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=1),
datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=1),
'%d/%m/%Y',
)
assert param == f'The day {offset_date} was yesterday'
Expand All @@ -265,7 +265,7 @@ def test_replace_param_today_offset_and_more():
def test_replace_param_today_offset_and_more_not_spanish():
param = replace_param('The day [TODAY - 1 DAYS] was yesterday', language='it')
offset_date = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=1),
datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=1),
'%Y/%m/%d',
)
assert param == f'The day {offset_date} was yesterday'
Expand All @@ -274,7 +274,7 @@ def test_replace_param_today_offset_and_more_not_spanish():
def test_replace_param_now_offset_and_more():
param = replace_param('I will arrive at [NOW + 10 MINUTES] tomorrow', language='es')
offset_datetime = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=10),
datetime.datetime.now(datetime.UTC) + datetime.timedelta(minutes=10),
'%d/%m/%Y %H:%M:%S',
)
assert param == f'I will arrive at {offset_datetime} tomorrow'
Expand All @@ -283,7 +283,7 @@ def test_replace_param_now_offset_and_more():
def test_replace_param_now_offset_and_more_not_spanish():
param = replace_param('I will arrive at [NOW + 10 MINUTES] tomorrow', language='it')
offset_datetime = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=10),
datetime.datetime.now(datetime.UTC) + datetime.timedelta(minutes=10),
'%Y/%m/%d %H:%M:%S',
)
assert param == f'I will arrive at {offset_datetime} tomorrow'
Expand All @@ -292,7 +292,7 @@ def test_replace_param_now_offset_and_more_not_spanish():
def test_replace_param_now_offset_with_format_and_more():
param = replace_param('I will arrive at [NOW(%Y-%m-%dT%H:%M:%SZ) + 10 MINUTES] tomorrow')
offset_datetime = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=10),
datetime.datetime.now(datetime.UTC) + datetime.timedelta(minutes=10),
'%Y-%m-%dT%H:%M:%SZ',
)
assert param == f'I will arrive at {offset_datetime} tomorrow'
Expand All @@ -301,7 +301,7 @@ def test_replace_param_now_offset_with_format_and_more():
def test_replace_param_now_offset_with_format_and_more_language_is_irrelevant():
param = replace_param('I will arrive at [NOW(%Y-%m-%dT%H:%M:%SZ) + 10 MINUTES] tomorrow', language='ru')
offset_datetime = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=10),
datetime.datetime.now(datetime.UTC) + datetime.timedelta(minutes=10),
'%Y-%m-%dT%H:%M:%SZ',
)
assert param == f'I will arrive at {offset_datetime} tomorrow'
Expand All @@ -310,7 +310,7 @@ def test_replace_param_now_offset_with_format_and_more_language_is_irrelevant():
def test_replace_param_today_offset_with_format_and_more_with_extra_spaces():
param = replace_param('The date [NOW(%Y-%m-%dT%H:%M:%SZ) - 1 DAYS ] was yesterday')
offset_date = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=1),
datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=1),
'%Y-%m-%dT%H:%M:%SZ',
)
assert param == f'The date {offset_date} was yesterday'
Expand All @@ -319,7 +319,7 @@ def test_replace_param_today_offset_with_format_and_more_with_extra_spaces():
def test_replace_param_today_offset_and_more_with_extra_spaces():
param = replace_param('The day [TODAY - 1 DAYS ] was yesterday', language='es')
offset_date = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=1),
datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=1),
'%d/%m/%Y',
)
assert param == f'The day {offset_date} was yesterday'
Expand All @@ -328,7 +328,7 @@ def test_replace_param_today_offset_and_more_with_extra_spaces():
def test_replace_param_today_offset_and_more_at_the_end():
param = replace_param('Yesterday was [TODAY - 1 DAYS]', language='es')
offset_date = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=1),
datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=1),
'%d/%m/%Y',
)
assert param == f'Yesterday was {offset_date}'
Expand All @@ -337,7 +337,7 @@ def test_replace_param_today_offset_and_more_at_the_end():
def test_replace_param_today_offset_and_more_at_the_beginning():
param = replace_param('[TODAY - 1 DAYS] is yesterday', language='es')
offset_date = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=1),
datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=1),
'%d/%m/%Y',
)
assert param == f'{offset_date} is yesterday'
Expand All @@ -349,11 +349,11 @@ def test_replace_param_today_offsets_and_more():
language='es',
)
offset_date = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=1),
datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=1),
'%d/%m/%Y',
)
offset_datetime = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=10),
datetime.datetime.now(datetime.UTC) + datetime.timedelta(minutes=10),
'%d/%m/%Y %H:%M:%S',
)
assert param == f'The day {offset_date} was yesterday and I have an appointment at {offset_datetime}'
Expand All @@ -365,11 +365,11 @@ def test_replace_param_now_offsets_with_format_and_more():
'and I have an appointment at [NOW(%Y-%m-%dT%H:%M:%SZ) + 10 MINUTES]',
)
offset_date = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=1),
datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=1),
'%Y-%m-%dT%H:%M:%SZ',
)
offset_datetime = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=10),
datetime.datetime.now(datetime.UTC) + datetime.timedelta(minutes=10),
'%Y-%m-%dT%H:%M:%SZ',
)
assert param == f'The date {offset_date} was yesterday and I have an appointment at {offset_datetime}'
Expand All @@ -381,11 +381,11 @@ def test_replace_param_now_offsets_with_and_without_format_and_more():
language='es',
)
offset_date = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=1),
datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=1),
'%Y-%m-%dT%H:%M:%SZ',
)
offset_datetime = datetime.datetime.strftime(
datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=10),
datetime.datetime.now(datetime.UTC) + datetime.timedelta(minutes=10),
'%d/%m/%Y %H:%M:%S',
)
assert param == f'The date {offset_date} was yesterday and I have an appointment at {offset_datetime}'
Expand Down
15 changes: 2 additions & 13 deletions toolium/test_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import logging
import unittest

from toolium.config_driver import get_error_message_from_exception, get_error_message_from_traceback
from toolium.config_driver import get_error_message_from_traceback
from toolium.config_files import ConfigFiles
from toolium.driver_wrappers_pool import DriverWrappersPool
from toolium.jira import change_all_jira_status
Expand Down Expand Up @@ -65,18 +65,7 @@ def setUp(self):
def tearDown(self):
# Get error message from unittest errors
error_message = ''
if hasattr(self._outcome, 'errors') and len(self._outcome.errors) > 0:
# Python <3.11
exception_info = self._outcome.errors[-1][1]
if exception_info:
exception = exception_info[1]
error_message = get_error_message_from_exception(exception)
elif (
not hasattr(self._outcome, 'errors')
and hasattr(self._outcome.result, 'failures')
and len(self._outcome.result.failures) > 0
):
# Python >=3.11
if hasattr(self._outcome.result, 'failures') and len(self._outcome.result.failures) > 0:
traceback = self._outcome.result.failures[0][1]
error_message = get_error_message_from_traceback(traceback)

Expand Down
10 changes: 5 additions & 5 deletions toolium/utils/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,10 @@ def _replace_param_replacement(param, language):
# make sure random is not made up of digits only, by forcing the first char to be a letter
'[RANDOM]': ''.join([r.choice(string.ascii_lowercase), *(r.choice(alphanums) for i in range(7))]),
'[RANDOM_PHONE_NUMBER]': _get_random_phone_number,
'[TIMESTAMP]': str(int(datetime.datetime.timestamp(datetime.datetime.now(datetime.timezone.utc)))),
'[DATETIME]': str(datetime.datetime.now(datetime.timezone.utc).strftime(datetime_format)),
'[NOW]': str(datetime.datetime.now(datetime.timezone.utc).strftime(date_format)),
'[TODAY]': str(datetime.datetime.now(datetime.timezone.utc).strftime(date_day_format)),
'[TIMESTAMP]': str(int(datetime.datetime.timestamp(datetime.datetime.now(datetime.UTC)))),
'[DATETIME]': str(datetime.datetime.now(datetime.UTC).strftime(datetime_format)),
'[NOW]': str(datetime.datetime.now(datetime.UTC).strftime(date_format)),
'[TODAY]': str(datetime.datetime.now(datetime.UTC).strftime(date_day_format)),
r'\[ROUND:(.*?)::(\d*)\]': _get_rounded_float_number,
'[SHARP]': '#',
}
Expand Down Expand Up @@ -348,7 +348,7 @@ def _date_matcher():
return re.match(r'\[(NOW(?:\((?:.*)\)|)|TODAY)(?:\s*([\+|-]\s*\d+)\s*(\w+)\s*)?\]', param)

def _offset_datetime(amount, units):
now = datetime.datetime.now(datetime.timezone.utc)
now = datetime.datetime.now(datetime.UTC)
if not amount or not units:
return now
the_amount = int(amount.replace(' ', ''))
Expand Down
Loading