Skip to content

Commit e44e131

Browse files
authored
Fix update status (#222)
* fix update status * remove codacy
1 parent 6796e7b commit e44e131

8 files changed

Lines changed: 152 additions & 87 deletions

File tree

.github/workflows/testing-and-deployment.yml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
- uses: actions/checkout@v4
2626

2727
- name: Set up Python ${{ matrix.python-version }}
28-
uses: actions/setup-python@v5
28+
uses: actions/setup-python@v6
2929
with:
3030
python-version: ${{ matrix.python-version }}
3131
cache: pip
@@ -44,22 +44,23 @@ jobs:
4444
pytest -v --cov keepa --cov-report xml
4545
4646
- uses: codecov/codecov-action@v4
47-
if: matrix.python-version == '3.13'
47+
if: matrix.python-version == '3.14'
4848
name: Upload coverage to codecov
4949

5050
- name: Build wheel
51-
if: matrix.python-version == '3.13'
51+
if: matrix.python-version == '3.14'
5252
run: |
5353
pip install build --disable-pip-version-check
5454
python -m build
5555
5656
- name: Upload wheel
57-
if: matrix.python-version == '3.13'
58-
uses: actions/upload-artifact@v4
57+
if: matrix.python-version == '3.14'
58+
uses: actions/upload-artifact@v6
5959
with:
6060
name: keepa-wheel
6161
path: dist/
6262
retention-days: 1
63+
if-no-files-found: error
6364

6465
release:
6566
name: Upload release to PyPI
@@ -73,7 +74,7 @@ jobs:
7374
id-token: write # Required for PyPI publishing
7475
contents: write # Required for creating GitHub releases
7576
steps:
76-
- uses: actions/download-artifact@v4
77+
- uses: actions/download-artifact@v7
7778
with:
7879
path: dist/
7980
- name: Flatten directory structure

.pre-commit-config.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ repos:
1010
- id: blackdoc
1111
files: \.py$
1212
- repo: https://github.com/astral-sh/ruff-pre-commit
13-
rev: v0.14.10
13+
rev: v0.15.2
1414
hooks:
1515
- id: ruff-check
1616
args: [--fix, --exit-non-zero-on-fix]
@@ -41,9 +41,13 @@ repos:
4141
args: [--branch, main]
4242
- id: requirements-txt-fixer
4343
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
44-
rev: v2.15.0
44+
rev: v2.16.0
4545
hooks:
4646
- id: pretty-format-toml
4747
args: [--autofix]
4848
- id: pretty-format-yaml
4949
args: [--autofix, --indent, '2']
50+
- repo: https://github.com/abravalheri/validate-pyproject
51+
rev: v0.25
52+
hooks:
53+
- id: validate-pyproject

README.rst

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,10 @@ Python keepa Client Library
1414
.. image:: https://codecov.io/gh/akaszynski/keepa/branch/main/graph/badge.svg
1515
:target: https://codecov.io/gh/akaszynski/keepa
1616

17-
.. image:: https://app.codacy.com/project/badge/Grade/9452f99f297c4a6eac14e2d21189ab6f
18-
:target: https://www.codacy.com/gh/akaszynski/keepa/dashboard?utm_source=github.com&utm_medium=referral&utm_content=akaszynski/keepa&utm_campaign=Badge_Grade
19-
2017

2118
This Python library allows you to interface with the API at `Keepa
22-
<https://keepa.com/>`_ to query for Amazon product information and
23-
history. It also contains a plotting module to allow for plotting of
24-
a product.
19+
<https://keepa.com/>`_ to query for Amazon product information and history. It
20+
also contains a plotting module to allow for plotting of a product.
2521

2622
Sign up for `Keepa Data Access <https://get.keepa.com/d7vrq>`_.
2723

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
build-backend = "flit_core.buildapi"
33
requires = ["flit_core >=3,<4"]
44

5-
[mypy]
6-
plugins = "pydantic.mypy"
7-
85
[project]
96
authors = [
107
{name = "Alex Kaszynski", email = "akascap@gmail.com"}
@@ -54,6 +51,9 @@ test = [
5451
Documentation = "https://keepaapi.readthedocs.io/en/latest/"
5552
Source = "https://github.com/akaszynski/keepa"
5653

54+
[tool.mypy]
55+
plugins = "pydantic.mypy"
56+
5757
[tool.pytest.ini_options]
5858
addopts = "--cov=keepa --cov-fail-under=85"
5959
asyncio_default_fixture_loop_scope = "function"

src/keepa/keepa_async.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def time_to_refill(self) -> float:
130130

131131
async def update_status(self) -> None:
132132
"""Update available tokens."""
133-
self.status = await self._request("token", {"key": self.accesskey}, wait=False)
133+
await self._request("token", {"key": self.accesskey}, wait=False)
134134

135135
async def wait_for_tokens(self) -> None:
136136
"""Check if there are any remaining tokens and waits if none are available."""

src/keepa/keepa_sync.py

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,14 @@ class Keepa:
4040
server has not issued a response for timeout seconds. Setting this to
4141
0.0 disables the timeout, but will cause any request to hang
4242
indefiantly should keepa.com be down
43-
logging_level: string, default: "DEBUG"
43+
logging_level: str, default: "DEBUG"
4444
Logging level to use. Default is "DEBUG". Other options are "INFO",
4545
"WARNING", "ERROR", and "CRITICAL".
46+
check_key : bool, default: True
47+
Check the keepa key on initialization and update the number of
48+
available tokens. This is a free check and does not cost any tokens,
49+
but does slow down the time to initialize. Disable this to speed up
50+
init at the risk of using an invalid key when querying for a product.
4651
4752
Examples
4853
--------
@@ -81,7 +86,13 @@ class Keepa:
8186
status: Status
8287
_timeout: float
8388

84-
def __init__(self, accesskey: str, timeout: float = 10.0, logging_level: str = "DEBUG") -> None:
89+
def __init__(
90+
self,
91+
accesskey: str,
92+
timeout: float = 10.0,
93+
logging_level: str = "DEBUG",
94+
check_key: bool = False,
95+
) -> None:
8596
"""Initialize server connection."""
8697
self.accesskey = accesskey
8798
self.tokens_left = 0
@@ -93,9 +104,11 @@ def __init__(self, accesskey: str, timeout: float = 10.0, logging_level: str = "
93104
raise TypeError("logging_level must be one of: " + ", ".join(levels))
94105
log.setLevel(logging_level)
95106

96-
# Don't check available tokens on init
107+
# Check available tokens on init
97108
log.info("Using key ending in %s", accesskey[-6:])
98109
self.status = Status()
110+
if check_key:
111+
self.update_status()
99112

100113
@property
101114
def time_to_refill(self) -> float:
@@ -114,6 +127,20 @@ def time_to_refill(self) -> float:
114127
0.0
115128
116129
"""
130+
if (
131+
self.status.refillRate is None
132+
or self.status.refillIn is None
133+
or self.status.timestamp is None
134+
):
135+
self.update_status()
136+
137+
if (
138+
self.status.refillRate is None
139+
or self.status.refillIn is None
140+
or self.status.timestamp is None
141+
):
142+
raise RuntimeError("Failed to update status")
143+
117144
# Get current timestamp in milliseconds from UNIX epoch
118145
now = int(time.time() * 1000)
119146
time_at_refill = self.status.timestamp + self.status.refillIn
@@ -130,11 +157,10 @@ def time_to_refill(self) -> float:
130157
# Return value in seconds
131158
return time_to_refill / 1000.0
132159

133-
def update_status(self) -> dict[str, Any]:
160+
def update_status(self) -> None:
134161
"""Update available tokens."""
135-
status = self._request("token", {"key": self.accesskey}, wait=False)
136-
self.status = status
137-
return status
162+
# number of available tokens is always returned
163+
self._request("token", {"key": self.accesskey}, wait=False)
138164

139165
def wait_for_tokens(self) -> None:
140166
"""Check if there are any remaining tokens and waits if none are available."""
@@ -143,7 +169,7 @@ def wait_for_tokens(self) -> None:
143169
# Wait if no tokens available
144170
if self.tokens_left <= 0:
145171
tdelay = self.time_to_refill
146-
log.warning("Waiting %.0f seconds for additional tokens" % tdelay)
172+
log.warning("Waiting %.0f seconds for additional tokens", tdelay)
147173
time.sleep(tdelay)
148174
self.update_status()
149175

@@ -632,6 +658,11 @@ def query(
632658
if offers > 100 or offers < 20:
633659
raise ValueError('Parameter "offers" must be between 20 and 100')
634660

661+
if self.status.refillRate is None or self.status.refillIn is None:
662+
self.update_status()
663+
if self.status.refillRate is None or self.status.refillIn is None:
664+
raise RuntimeError("Failed to update status")
665+
635666
# Report time to completion
636667
if self.status.refillRate is not None:
637668
tcomplete = (
@@ -797,7 +828,7 @@ def _product_query(self, items, product_code_is_asin=True, **kwargs):
797828
to_datetime = kwargs.pop("to_datetime", True)
798829

799830
# Query and replace csv with parsed data if history enabled
800-
wait = kwargs.get("wait")
831+
wait = bool(kwargs.get("wait"))
801832
kwargs.pop("wait", None)
802833
raw_response = kwargs.pop("raw", False)
803834
response = self._request("product", kwargs, wait=wait, raw_response=raw_response)
@@ -956,7 +987,7 @@ def best_sellers_query(
956987

957988
def search_for_categories(
958989
self, searchterm: str, domain: str | Domain = "US", wait: bool = True
959-
) -> list:
990+
) -> dict[str, Any]:
960991
"""
961992
Search for categories from Amazon.
962993

0 commit comments

Comments
 (0)