diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..f4952ba
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,8 @@
+version: 2
+updates:
+- package-ecosystem: pip
+ directory: "/"
+ schedule:
+ interval: daily
+ time: "10:00"
+ open-pull-requests-limit: 10
diff --git a/.pylintrc b/.pylintrc
index ccf3cb6..1db55e1 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -10,8 +10,6 @@ ignore=conf.py
init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.dirname(find_pylintrc()))"
[pre-commit-hook]
-# C0122: Misplaced comparison constant (tests use Yoda conditions).
-# C0330: Wrong hanging indentation (conflicts with `black`).
# W0621: Redefining name from outer scope (conflicts with pytest fixtures).
-disable=C0122,C0330,W0621
-limit=10.0
+disable=W0621
+limit=10
diff --git a/.travis.yml b/.travis.yml
index 4f83f82..2d73e11 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,7 +13,6 @@ python:
- "3.8"
- "3.7"
- "3.6"
- - "3.5"
# Disabled until typed_ast (used by pylint) is fixed.
# See https://github.com/python/typed_ast/issues/134
# - "pypy3"
diff --git a/countdoom/cli.py b/countdoom/cli.py
index c2e03da..a390f0d 100644
--- a/countdoom/cli.py
+++ b/countdoom/cli.py
@@ -105,7 +105,7 @@ def check_positive(value) -> int:
int_value = int(value)
if int_value <= 0:
raise argparse.ArgumentTypeError(
- "{} is an invalid positive integer value".format(value)
+ f"{value} is an invalid positive integer value"
)
return int_value
@@ -127,7 +127,7 @@ def check_positive(value) -> int:
'--v',
'--version',
action='version',
- version='%(prog)s {version}'.format(version=countdoom.__version__),
+ version=f'%(prog)s {countdoom.__version__}',
)
parser.add_argument(
'-h',
diff --git a/countdoom/client.py b/countdoom/client.py
index 9baf7f1..35060bc 100644
--- a/countdoom/client.py
+++ b/countdoom/client.py
@@ -160,17 +160,21 @@ async def _fetch(self, url: str, timeout: int = None) -> str:
raise CountdoomClientError("Session not started.")
try:
- async with async_timeout.timeout(timeout):
- async with self._session.get(url, timeout=timeout) as resp:
- if resp.status != 200:
- raise AssertionError
- return await resp.text()
- except AssertionError:
+ async with (
+ async_timeout.timeout(timeout),
+ self._session.get(url, timeout=timeout) as resp
+ ):
+ if resp.status != 200:
+ raise AssertionError
+ return await resp.text()
+ except AssertionError as exc:
await self.close()
- raise CountdoomClientError("Page not found.")
- except OSError:
+ raise CountdoomClientError("Page not found.") from exc
+ except OSError as exc:
await self.close()
- raise CountdoomClientError("Cannot connect to website. Check URL.")
+ raise CountdoomClientError(
+ "Cannot connect to website. Check URL."
+ ) from exc
async def _extract_sentence(self) -> None:
"""
@@ -187,20 +191,20 @@ async def _extract_sentence(self) -> None:
self._sentence = re.sub(r'\s+', ' ', sentence).strip()
if not self._sentence:
raise ValueError()
- except IndexError:
+ except IndexError as exc:
_LOGGER.error(
"No sentence found using selector %s. Check for source "
"website design changes.",
self.SELECTOR,
)
- raise CountdoomClientError("No sentence found.")
- except ValueError:
+ raise CountdoomClientError("No sentence found.") from exc
+ except ValueError as exc:
_LOGGER.error(
"Empty sentence found using selector %s. Check for source "
"website design changes.",
self.SELECTOR,
)
- raise CountdoomClientError("Empty sentence found.")
+ raise CountdoomClientError("Empty sentence found.") from exc
_LOGGER.debug("Sentence found: %s", self._sentence)
async def close(self) -> None:
@@ -223,11 +227,11 @@ def _sentence_to_countdown(self) -> None:
try:
self._countdown = self.sentence_to_countdown(self._sentence)
- except AttributeError:
+ except AttributeError as exc:
_LOGGER.error(
"Regex pattern yielded no result for : %s", self._sentence
)
- raise CountdoomClientError("Sentence not parsable.")
+ raise CountdoomClientError("Sentence not parsable.") from exc
_LOGGER.debug("Countdown value: %s", self._countdown)
@classmethod
diff --git a/setup.cfg b/setup.cfg
index fc7ad27..1bb3986 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -30,7 +30,8 @@ ignore_missing_imports = true
# Configure pytest
# See https://docs.pytest.org/
[tool:pytest]
-collect_ignore = ['setup.py']
-addopts = --strict
+addopts =
+ --ignore=setup.py,
+ --strict-markers
markers =
live
diff --git a/setup.py b/setup.py
index 2ae4a47..8d2b2d3 100644
--- a/setup.py
+++ b/setup.py
@@ -15,10 +15,10 @@
from setuptools import find_packages, setup
# Load documentation for PyPI.
-with open('README.rst') as readme_file:
+with open('README.rst', encoding="utf-8") as readme_file:
README = readme_file.read()
-with open('CHANGELOG.rst') as history_file:
+with open('CHANGELOG.rst', encoding="utf-8") as history_file:
HISTORY = history_file.read()
# Define extra requirements for different installation environments.
@@ -88,9 +88,9 @@
# Define URLs.
DOCS_URL = 'https://countdoom.readthedocs.io/'
-HISTORY_URL = '{}en/latest/changelog.html'.format(DOCS_URL)
+HISTORY_URL = f'{DOCS_URL}en/latest/changelog.html'
REPO_URL = 'https://github.com/renemarc/countdoom'
-ISSUES_URL = '{}/issues'.format(REPO_URL)
+ISSUES_URL = f'{REPO_URL}/issues'
setup(
author='René-Marc Simard',
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 8c8dfe3..d603725 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -23,7 +23,7 @@ def _setup_mock_server(mocked: aioresponses) -> None:
:param mocked: aiohttp response
"""
- prefix = '
'.format(CountdoomClient.SELECTOR[1:])
+ prefix = f''
suffix = '
'
string = "IT IS 1 MINUTE TO MIDNIGHT"
mocked.get(
@@ -119,7 +119,7 @@ async def test_cli_request_version(capsys: CaptureFixture) -> None:
assert exception.type == SystemExit
assert exception.value.code == 0
- assert "countdoom {}".format(countdoom.__version__) in output[0]
+ assert f"countdoom {countdoom.__version__}" in output[0]
@pytest.mark.asyncio
@@ -271,7 +271,7 @@ async def test_cli_request_internal_error(capsys: CaptureFixture) -> None:
:param capsys: System-level capture fixture
"""
with aioresponses() as mocked:
- prefix = ''.format(CountdoomClient.SELECTOR[1:])
+ prefix = f''
suffix = '
'
string = ' '
mocked.get(
diff --git a/tests/test_client.py b/tests/test_client.py
index 0085d9e..bdb325d 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -122,7 +122,7 @@ def response() -> Response:
:return: Request response
"""
- return requests.get(CountdoomClient.CLOCK_URL)
+ return requests.get(CountdoomClient.CLOCK_URL, timeout=5)
def _get_path(string: str) -> str:
@@ -142,16 +142,13 @@ def _setup_servers(httpserver: HTTPServer) -> None:
:param httpserver: HTTP Server
"""
- prefix = ''.format(CountdoomClient.SELECTOR[1:])
+ prefix = f''
suffix = '
'
sentences = SENTENCES_VALID + SENTENCES_INVALID
- # sentences = SENTENCES_VALID
- # for sentence in SENTENCES_INVALID:
- # sentences.append(sentence)
for sentence in sentences:
path = _get_path(sentence[0])
- httpserver.expect_request('/{}'.format(path)).respond_with_data(
+ httpserver.expect_request(f'/{path}').respond_with_data(
prefix + sentence[0] + suffix
)
@@ -197,7 +194,7 @@ async def test_valid_sentence(httpserver: HTTPServer, sentence: str) -> None:
client = CountdoomClient()
path = _get_path(sentence)
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
setattr(client, 'CLOCK_URL', clock_url)
data = await client.fetch_data()
@@ -223,7 +220,7 @@ async def test_valid_countdown(
client = CountdoomClient()
path = _get_path(sentence)
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
setattr(client, 'CLOCK_URL', clock_url)
data = await client.fetch_data()
@@ -249,7 +246,7 @@ async def test_valid_minutes(
client = CountdoomClient()
path = _get_path(sentence)
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
setattr(client, 'CLOCK_URL', clock_url)
data = await client.fetch_data()
@@ -275,7 +272,7 @@ async def test_valid_clock(
client = CountdoomClient()
path = _get_path(sentence)
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
setattr(client, 'CLOCK_URL', clock_url)
data = await client.fetch_data()
@@ -302,7 +299,7 @@ async def test_valid_time(
client = CountdoomClient()
path = _get_path(sentence)
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
setattr(client, 'CLOCK_URL', clock_url)
data = await client.fetch_data()
@@ -329,7 +326,7 @@ async def test_invalid_minutes(
client = CountdoomClient()
path = _get_path(sentence)
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
setattr(client, 'CLOCK_URL', clock_url)
with pytest.raises(CountdoomClientError) as err:
await client.fetch_data()
@@ -356,7 +353,7 @@ async def test_invalid_clock(
client = CountdoomClient()
path = _get_path(sentence)
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
setattr(client, 'CLOCK_URL', clock_url)
with pytest.raises(CountdoomClientError) as err:
await client.fetch_data()
@@ -383,7 +380,7 @@ async def test_invalid_time(
client = CountdoomClient()
path = _get_path(sentence)
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
setattr(client, 'CLOCK_URL', clock_url)
with pytest.raises(CountdoomClientError) as err:
await client.fetch_data()
@@ -399,16 +396,16 @@ async def test_invalid_selector(httpserver: HTTPServer) -> None:
:param httpserver: HTTP Server
"""
- prefix = ''.format(CountdoomClient.SELECTOR[1:])
+ prefix = f''
suffix = '
'
string = "IT IS 1 AND A HALF MINUTE TO MIDNIGHT"
path = 'test_invalid_selector'
- httpserver.expect_request('/{}'.format(path)).respond_with_data(
+ httpserver.expect_request(f'/{path}').respond_with_data(
prefix + string + suffix
)
client = CountdoomClient()
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
selector = '.wrong-id-' + str(random.randint(0, 100000000))
setattr(client, 'CLOCK_URL', clock_url)
setattr(client, 'SELECTOR', selector)
@@ -425,16 +422,16 @@ async def test_htmlized_sentence(httpserver: HTTPServer) -> None:
:param httpserver: HTTP Server
"""
- prefix = ''.format(CountdoomClient.SELECTOR[1:])
+ prefix = f''
suffix = '
'
string = " IT IS STILL 1 MINUTE TO MIDNIGHT"
path = 'test_htmlized_sentence'
- httpserver.expect_request('/{}'.format(path)).respond_with_data(
+ httpserver.expect_request(f'/{path}').respond_with_data(
prefix + string + suffix
)
client = CountdoomClient()
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
setattr(client, 'CLOCK_URL', clock_url)
data = await client.fetch_data()
@@ -450,16 +447,16 @@ async def test_empty_sentence(httpserver: HTTPServer) -> None:
:param httpserver: HTTP Server
"""
- prefix = ''.format(CountdoomClient.SELECTOR[1:])
+ prefix = f''
suffix = '
'
string = ' '
path = 'test_empty_sentence'
- httpserver.expect_request('/{}'.format(path)).respond_with_data(
+ httpserver.expect_request(f'/{path}').respond_with_data(
prefix + string + suffix
)
client = CountdoomClient()
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
setattr(client, 'CLOCK_URL', clock_url)
with pytest.raises(CountdoomClientError) as err:
await client.fetch_data()
@@ -500,16 +497,16 @@ async def test_formatted_time(httpserver: HTTPServer) -> None:
:param httpserver: HTTP Server
"""
- prefix = ''.format(CountdoomClient.SELECTOR[1:])
+ prefix = f''
suffix = '
'
string = "IT IS 16 MINUTES TO MIDNIGHT"
path = 'test_formatted_time'
- httpserver.expect_request('/{}'.format(path)).respond_with_data(
+ httpserver.expect_request(f'/{path}').respond_with_data(
prefix + string + suffix
)
client = CountdoomClient()
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
setattr(client, 'CLOCK_URL', clock_url)
data = await client.fetch_data()
@@ -526,7 +523,7 @@ async def test_url_not_found(httpserver: HTTPServer) -> None:
"""
path = 'test_url_not_found'
client = CountdoomClient()
- clock_url = httpserver.url_for('/{}'.format(path))
+ clock_url = httpserver.url_for(f'/{path}')
setattr(client, 'CLOCK_URL', clock_url)
with pytest.raises(CountdoomClientError) as err:
await client.fetch_data()
diff --git a/tests/test_package.py b/tests/test_package.py
index 468428c..8356388 100644
--- a/tests/test_package.py
+++ b/tests/test_package.py
@@ -19,11 +19,11 @@ def test_package_main() -> None:
This check uses a subprocess to validate the package, since the
package's __main__.py cannot be imported for tests.
"""
- process = subprocess.Popen(
+ with subprocess.Popen(
['python', '-m', 'countdoom', '--version'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
- )
- stdout = process.communicate()[0]
+ ) as process:
+ stdout = process.communicate()[0]
- assert 'countdoom {}'.format(countdoom.__version__) in str(stdout)
+ assert f'countdoom {countdoom.__version__}' in str(stdout)
diff --git a/tox.ini b/tox.ini
index ff18480..a4d76a1 100644
--- a/tox.ini
+++ b/tox.ini
@@ -6,7 +6,7 @@
# See https://tox.readthedocs.io/
[tox]
-envlist = lint, py3{5,6,7,8}, pypy3
+envlist = lint, py3{6,7,8}, pypy3
skip_missing_interpreters = true
[travis]
@@ -14,7 +14,6 @@ python =
3.8: py38
3.7: py37
3.6: py36
- 3.5: py35
[testenv]
setenv =