-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement client base and storage endpoints
* Implement client base and storage endpoints * Update everything based on PR feedback and more * Fix a few types * Remove forgotten comment * Validate that resource_path does not end with "/" * Make supplying token optional * Update installation instructions * Add TODOs to key-value store client * Use imperative mood in docstrings for resource collection clients * Improve iterating dataset items logic when no limit is set
- Loading branch information
Showing
35 changed files
with
1,801 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
root = true | ||
|
||
[*] | ||
indent_style = space | ||
indent_size = 4 | ||
charset = utf-8 | ||
trim_trailing_whitespace = true | ||
insert_final_newline = true | ||
end_of_line = lf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
[flake8] | ||
max_line_length = 150 | ||
# Google docstring convention + D204 & D401 | ||
# TODO enable D100 & D401 | ||
docstring-convention=all | ||
ignore= | ||
D100 | ||
D104 | ||
D203 | ||
D213 | ||
D215 | ||
D400 | ||
D404 | ||
D406 | ||
D407 | ||
D408 | ||
D409 | ||
D413 | ||
per-file-ignores = | ||
tests/*: D |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
name: Lint and test | ||
|
||
on: push | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-20.04 | ||
strategy: | ||
matrix: | ||
python-version: [3.7, 3.8, 3.9] | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- name: Set up Python ${{ matrix.python-version }} | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
|
||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install -e .[dev] | ||
- name: Lint | ||
run: ./lint_and_test.sh lint | ||
|
||
- name: Type check | ||
run: ./lint_and_test.sh types | ||
|
||
- name: Unit tests | ||
run: ./lint_and_test.sh tests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,12 @@ | ||
build | ||
dist | ||
apify_client.egg-info | ||
.venv | ||
.direnv | ||
.envrc | ||
|
||
.mypy_cache | ||
.pytest_cache | ||
|
||
*.egg-info/ | ||
*.egg | ||
|
||
.vscode | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[isort] | ||
include_trailing_comma = True | ||
line_length = 150 | ||
use_parentheses = True | ||
multi_line_output = 3 | ||
sections = FUTURE,STDLIB,FIRSTPARTY,THIRDPARTY,LOCALFOLDER |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#!/usr/bin/env /bin/bash | ||
|
||
set -o errexit | ||
|
||
echo "🔤 isort formatting..." | ||
python3 -m isort src tests | ||
|
||
echo "🎨 autopep8 formatting..." | ||
python3 -m autopep8 --in-place --recursive src tests | ||
|
||
echo "🎉 formatted 🎉" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#!/usr/bin/env bash | ||
|
||
set -u | ||
|
||
checks_to_run=${1:-"everything"} | ||
shift || true | ||
|
||
|
||
lint() { | ||
echo "⛄️ flake8 check..." | ||
python3 -m flake8 src tests | ||
} | ||
|
||
type_check() { | ||
echo "📝 checking types" | ||
python3 -m mypy src | ||
} | ||
|
||
unit_tests() { | ||
echo "👮♀️ running unit tests" | ||
python3 -m pytest -rA tests | ||
} | ||
|
||
|
||
if [ "$checks_to_run" = "lint" ] ; then | ||
lint | ||
elif [ "$checks_to_run" = "types" ] ; then | ||
type_check | ||
elif [ "$checks_to_run" = "tests" ] ; then | ||
unit_tests | ||
elif [ "$checks_to_run" = "everything" ] ; then | ||
lint | ||
type_check | ||
unit_tests | ||
else | ||
echo "Invalid type of test ($checks_to_run) requested. Use lint / types / tests or leave empty to run all tests" | ||
exit 1 | ||
fi | ||
|
||
echo "🎉 success 🎉" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[mypy] | ||
check_untyped_defs = True | ||
disallow_incomplete_defs = True | ||
disallow_untyped_calls = True | ||
disallow_untyped_decorators = True | ||
disallow_untyped_defs = True | ||
no_implicit_optional = True | ||
warn_redundant_casts = True | ||
warn_return_any = True | ||
warn_unreachable = True | ||
warn_unused_ignores = True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[pytest] | ||
addopts = --doctest-modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,52 @@ | ||
import setuptools | ||
import pathlib | ||
|
||
with open("README.md", "r") as fh: | ||
long_description = fh.read() | ||
from setuptools import find_packages, setup | ||
|
||
here = pathlib.Path(__file__).parent.resolve() | ||
|
||
long_description = (here / 'README.md').read_text(encoding='utf-8') | ||
|
||
setup( | ||
name='apify_client', | ||
version='0.0.1', | ||
|
||
setuptools.setup( | ||
name="apify_client", | ||
version="0.0.1", | ||
author="Apify Technologies s.r.o.", | ||
author_email="support@apify.com", | ||
description="Work in progress: Apify API client for Python", | ||
url="https://github.com/apify/apify-client-python", | ||
project_urls={ | ||
'Apify Homepage': 'https://apify.com', | ||
}, | ||
license='Apache Software License', | ||
license_file='LICENSE', | ||
|
||
description='Apify API client for Python', | ||
long_description=long_description, | ||
long_description_content_type="text/markdown", | ||
url="https://github.com/apifytech/apify-client-python", | ||
packages=setuptools.find_packages(), | ||
long_description_content_type='text/markdown', | ||
|
||
classifiers=[ | ||
"Programming Language :: Python :: 3", | ||
"License :: OSI Approved :: MIT License", | ||
"License :: OSI Approved :: Apache Software License", | ||
"Operating System :: OS Independent", | ||
'Intended Audience :: Developers', | ||
'Topic :: Software Development :: Libraries', | ||
], | ||
) | ||
keywords='apify, api, client, scraping, automation', | ||
|
||
package_dir={'': 'src'}, | ||
packages=find_packages(where='src'), | ||
python_requires='>=3.7', | ||
install_requires=['requests ~=2.25.1'], | ||
extras_require={ | ||
'dev': [ | ||
'autopep8 ~= 1.5.4', | ||
'flake8 ~= 3.8.4', | ||
'flake8-commas ~= 2.0.0', | ||
'flake8-docstrings ~= 1.5.0', | ||
'flake8-isort ~= 4.0.0', | ||
'isort ~= 5.7.0', | ||
'mypy ~= 0.790', | ||
'pep8-naming ~= 0.11.1', | ||
'pytest ~= 6.2.1', | ||
], | ||
}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .client import ApifyClient | ||
|
||
__all__ = ['ApifyClient'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
from typing import Optional | ||
|
||
import requests | ||
|
||
|
||
class ApifyClientError(Exception): | ||
"""Base class for errors specific to the Apify API Client.""" | ||
|
||
pass | ||
|
||
|
||
class ApifyApiError(ApifyClientError): | ||
"""Error specific to requests to the Apify API. | ||
An `ApifyApiError` is thrown for successful HTTP requests that reach the API, | ||
but the API responds with an error response. Typically, those are rate limit | ||
errors and internal errors, which are automatically retried, or validation | ||
errors, which are thrown immediately, because a correction by the user is needed. | ||
""" | ||
|
||
def __init__(self, response: requests.models.Response, attempt: int) -> None: | ||
"""Create the ApifyApiError instance. | ||
Args: | ||
response: The response to the failed API call | ||
attempt: Which retry was the request that failed | ||
""" | ||
self.message: Optional[str] = None | ||
self.type: Optional[str] = None | ||
|
||
response_data = response.json() | ||
if 'error' in response_data: | ||
self.message = response_data['error']['message'] | ||
self.type = response_data['error']['type'] | ||
else: | ||
self.message = f'Unexpected error: {response.text}' | ||
|
||
super().__init__(self.message) | ||
|
||
self.name = 'ApifyApiError' | ||
self.status_code = response.status_code | ||
self.attempt = attempt | ||
self.http_method = response.request.method | ||
|
||
# TODO self.client_method | ||
# TODO self.original_stack | ||
# TODO self.path | ||
# TODO self.stack | ||
|
||
|
||
class InvalidResponseBodyError(ApifyClientError): | ||
"""Error caused by the response body failing to be parsed. | ||
This error exists for the quite common situation, where only a partial JSON response is received and | ||
an attempt to parse the JSON throws an error. In most cases this can be resolved by retrying the | ||
request. We do that by identifying this error in the _HTTPClient. | ||
""" | ||
|
||
def __init__(self, response: requests.models.Response) -> None: | ||
"""Create the InvalidResponseBodyError instance. | ||
Args: | ||
response: The response which failed to be parsed | ||
""" | ||
super().__init__('Response body could not be parsed') | ||
|
||
self.name = 'InvalidResponseBodyError' | ||
self.code = 'invalid-response-body' | ||
self.response = response |
Oops, something went wrong.