Skip to content

Adjusting config #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 28, 2024
Merged
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
71 changes: 69 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
version: 2.1

executors:
python-container:
docker:
- image: cimg/python:3.12
python-vm:
machine:
- image: ubuntu-2204:current

workflows:
ci:
jobs:
- lint
- test:
name: Python (<< matrix.python_version >>) - ArangoDB (<< matrix.arangodb_license >>, << matrix.arangodb_version >> << matrix.arangodb_config >>)
matrix:
parameters:
python_version: ["3.10"]
arangodb_config: ["single"]
arangodb_license: ["community"]
arangodb_version: ["3.12"]

jobs:
lint:
docker:
- image: python:latest
executor: python-container
resource_class: small
steps:
- checkout
- run:
@@ -26,3 +42,54 @@ jobs:
- run:
name: Run mypy
command: mypy ./arangoasync
test:
parameters:
python_version:
type: string
arangodb_config:
type: string
arangodb_license:
type: string
arangodb_version:
type: string
executor: python-vm
steps:
- checkout
- run:
name: Setup ArangoDB
command: |
chmod +x starter.sh
./starter.sh ${{ matrix.arangodb_config }} ${{ matrix.arangodb_license }} ${{ matrix.arangodb_version }}
- restore_cache:
key: pip-and-local-cache
- run:
name: Setup Python
command: |
pyenv --version
pyenv install -f << parameters.python_version >>
pyenv global << parameters.python_version >>
- run:
name: Install Dependencies
command: pip install -e .[dev]
- run: docker ps -a
- run: docker logs arango
- run:
name: Run pytest
command: |
mkdir test-results

args=("--junitxml=test-results/junit.xml" "--log-cli-level=DEBUG" "--host" "localhost" "--port=8529")
if [ << parameters.arangodb_config >> = "cluster" ]; then
args+=("--cluster" "--port=8539" "--port=8549")
fi

if [ << parameters.arangodb_license >> = "enterprise" ]; then
args+=("--enterprise")
fi

echo "Running pytest with args: ${args[@]}"
pytest --cov=arango --cov-report=xml --cov-report term-missing --color=yes --code-highlight=yes "${args[@]}"
- store_artifacts:
path: test-results
- store_test_results:
path: test-results
4 changes: 2 additions & 2 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
@@ -24,5 +24,5 @@ jobs:
- name: Install dependencies
run: pip install .[dev]

- name: Generate Sphinx HTML
run: python -m sphinx -b html -W docs docs/_build
- name: Run Sphinx doctest
run: python -m sphinx -b doctest docs docs/_build
5 changes: 3 additions & 2 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -20,5 +20,6 @@ sphinx:
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: docs/requirements.txt
install:
- method: pip
path: .[dev]
94 changes: 53 additions & 41 deletions arangoasync/http.py
Original file line number Diff line number Diff line change
@@ -15,19 +15,31 @@

class HTTPClient(ABC): # pragma: no cover
"""Abstract base class for HTTP clients.

Custom HTTP clients should inherit from this class.

Example:
.. code-block:: python

class MyCustomHTTPClient(HTTPClient):
def create_session(self, host):
pass
async def send_request(self, session, request):
pass
"""

@abstractmethod
def create_session(self, host: str) -> Any:
"""Return a new session given the base host URL.

This method must be overridden by the user.
Note:
This method must be overridden by the user.

Args:
host (str): ArangoDB host URL.

:param host: ArangoDB host URL.
:type host: str
:returns: Requests session object.
:rtype: Any
Returns:
Requests session object.
"""
raise NotImplementedError

@@ -39,37 +51,36 @@ async def send_request(
) -> Response:
"""Send an HTTP request.

This method must be overridden by the user.
Note:
This method must be overridden by the user.

:param session: Session object.
:type session: Any
:param request: HTTP request.
:type request: arangoasync.request.Request
:returns: HTTP response.
:rtype: arangoasync.response.Response
Args:
session (Any): Client session object.
request (Request): HTTP request.

Returns:
Response: HTTP response.
"""
raise NotImplementedError


class AioHTTPClient(HTTPClient):
"""HTTP client implemented on top of [aiohttp](https://docs.aiohttp.org/en/stable/).

:param connector: Supports connection pooling.
By default, 100 simultaneous connections are supported, with a 60-second timeout
for connection reusing after release.
:type connector: aiohttp.BaseConnector | None
:param timeout: Timeout settings.
300s total timeout by default for a complete request/response operation.
:type timeout: aiohttp.ClientTimeout | None
:param read_bufsize: Size of read buffer (64KB default).
:type read_bufsize: int
:param auth: HTTP authentication helper.
Should be used for specifying authorization data in client API.
:type auth: aiohttp.BasicAuth | None
:param compression_threshold: Will compress requests to the server if
the size of the request body (in bytes) is at least the value of this
option.
:type compression_threshold: int
"""HTTP client implemented on top of aiohttp_.

Args:
connector (aiohttp.BaseConnector | None): Supports connection pooling.
By default, 100 simultaneous connections are supported, with a 60-second
timeout for connection reusing after release.
timeout (aiohttp.ClientTimeout | None): Client timeout settings.
300s total timeout by default for a complete request/response operation.
read_bufsize (int): Size of read buffer (64KB default).
auth (aiohttp.BasicAuth | None): HTTP authentication helper.
Should be used for specifying authorization data in client API.
compression_threshold (int): Will compress requests to the server if the size
of the request body (in bytes) is at least the value of this option.

.. _aiohttp:
https://docs.aiohttp.org/en/stable/
"""

def __init__(
@@ -95,11 +106,12 @@ def __init__(
def create_session(self, host: str) -> ClientSession:
"""Return a new session given the base host URL.

:param host: ArangoDB host URL. Typically, the address and port of a coordinator
(e.g. "http://127.0.0.1:8529").
:type host: str
:returns: Session object.
:rtype: aiohttp.ClientSession
Args:
host (str): ArangoDB host URL. Must not include any paths. Typically, this
is the address and port of a coordinator (e.g. "http://127.0.0.1:8529").

Returns:
aiohttp.ClientSession: Session object, used to send future requests.
"""
return ClientSession(
base_url=host,
@@ -116,12 +128,12 @@ async def send_request(
) -> Response:
"""Send an HTTP request.

:param session: Session object.
:type session: aiohttp.ClientSession
:param request: HTTP request.
:type request: arangoasync.request.Request
:returns: HTTP response.
:rtype: arangoasync.response.Response
Args:
session (aiohttp.ClientSession): Session object used to make the request.
request (Request): HTTP request.

Returns:
Response: HTTP response.
"""
method = request.method
endpoint = request.endpoint
61 changes: 24 additions & 37 deletions arangoasync/request.py
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@


class Method(Enum):
"""HTTP methods."""
"""HTTP methods enum: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS"""

GET = auto()
POST = auto()
@@ -25,31 +25,19 @@ class Method(Enum):
class Request:
"""HTTP request.

:param method: HTTP method.
:type method: request.Method
:param endpoint: API endpoint.
:type endpoint: str
:param headers: Request headers.
:type headers: dict | None
:param params: URL parameters.
:type params: dict | None
:param data: Request payload.
:type data: Any
:param deserialize: Whether the response body should be deserialized.
:type deserialize: bool

:ivar method: HTTP method.
:vartype method: request.Method
:ivar endpoint: API endpoint, for example "_api/version".
:vartype endpoint: str
:ivar headers: Request headers.
:vartype headers: dict | None
:ivar params: URL (query) parameters.
:vartype params: dict | None
:ivar data: Request payload.
:vartype data: Any
:ivar deserialize: Whether the response body should be deserialized.
:vartype deserialize: bool
Args:
method (Method): HTTP method.
endpoint (str): API endpoint.
headers (dict | None): Request headers.
params (dict | None): URL parameters.
data (str | None): Request payload.

Attributes:
method (Method): HTTP method.
endpoint (str): API endpoint.
headers (dict | None): Request headers.
params (dict | None): URL parameters.
data (str | None): Request payload.
"""

__slots__ = (
@@ -58,7 +46,6 @@ class Request:
"headers",
"params",
"data",
"deserialize",
)

def __init__(
@@ -68,23 +55,22 @@ def __init__(
headers: Optional[Headers] = None,
params: Optional[Params] = None,
data: Optional[str] = None,
deserialize: bool = True,
) -> None:
self.method: Method = method
self.endpoint: str = endpoint
self.headers: Headers = self._normalize_headers(headers)
self.params: Params = self._normalize_params(params)
self.data: Optional[str] = data
self.deserialize: bool = deserialize

@staticmethod
def _normalize_headers(headers: Optional[Headers]) -> Headers:
"""Normalize request headers.

:param headers: Request headers.
:type headers: dict | None
:returns: Normalized request headers.
:rtype: dict
Parameters:
headers (dict | None): Request headers.

Returns:
dict: Normalized request headers.
"""
driver_header = f"arangoasync/{__version__}"
normalized_headers: Headers = {
@@ -103,10 +89,11 @@ def _normalize_headers(headers: Optional[Headers]) -> Headers:
def _normalize_params(params: Optional[Params]) -> Params:
"""Normalize URL parameters.

:param params: URL parameters.
:type params: dict | None
:returns: Normalized URL parameters.
:rtype: dict
Parameters:
params (dict | None): URL parameters.

Returns:
dict: Normalized URL parameters.
"""
normalized_params: Params = {}

51 changes: 17 additions & 34 deletions arangoasync/response.py
Original file line number Diff line number Diff line change
@@ -11,39 +11,24 @@
class Response:
"""HTTP response.
:param method: HTTP method.
:type method: request.Method
:param url: API URL.
:type url: str
:param headers: Response headers.
:type headers: dict | None
:param status_code: Response status code.
:type status_code: int
:param status_text: Response status text.
:type status_text: str
:param raw_body: Raw response body.
:type raw_body: str
Parameters:
method (Method): HTTP method.
url (str): API URL.
headers (dict | None): Response headers.
status_code (int): Response status code.
status_text (str): Response status text.
raw_body (bytes): Raw response body.
:ivar method: HTTP method.
:vartype method: request.Method
:ivar url: API URL.
:vartype url: str
:ivar headers: Response headers.
:vartype headers: dict | None
:ivar status_code: Response status code.
:vartype status_code: int
:ivar status_text: Response status text.
:vartype status_text: str
:ivar raw_body: Raw response body.
:vartype raw_body: str
:ivar body: Response body after processing.
:vartype body: Any
:ivar error_code: Error code from ArangoDB server.
:vartype error_code: int
:ivar error_message: Error message from ArangoDB server.
:vartype error_message: str
:ivar is_success: True if response status code was 2XX.
:vartype is_success: bool
Attributes:
method (Method): HTTP method.
url (str): API URL.
headers (dict | None): Response headers.
status_code (int): Response status code.
status_text (str): Response status text.
raw_body (bytes): Raw response body.
error_code (int | None): Error code from ArangoDB server.
error_message (str | None): Error message from ArangoDB server.
is_success (bool | None): True if response status code was 2XX.
"""

__slots__ = (
@@ -52,7 +37,6 @@ class Response:
"headers",
"status_code",
"status_text",
"body",
"raw_body",
"error_code",
"error_message",
@@ -76,7 +60,6 @@ def __init__(
self.raw_body: bytes = raw_body

# Populated later
self.body: Optional[str] = None
self.error_code: Optional[int] = None
self.error_message: Optional[str] = None
self.is_success: Optional[bool] = None
6 changes: 6 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -12,14 +12,20 @@
"sphinx.ext.autodoc",
"sphinx.ext.doctest",
"sphinx.ext.viewcode",
"sphinx.ext.napoleon",
"sphinx.ext.intersphinx",
]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
html_theme = "sphinx_rtd_theme"
master_doc = "index"

autodoc_member_order = "bysource"
autodoc_typehints = "none"

intersphinx_mapping = {
"aiohttp": ("https://docs.aiohttp.org/en/stable/", None),
}

napoleon_google_docstring = True
napoleon_numpy_docstring = False
napoleon_attr_annotations = True
1 change: 0 additions & 1 deletion docs/requirements.txt

This file was deleted.

45 changes: 3 additions & 42 deletions docs/specs.rst
Original file line number Diff line number Diff line change
@@ -4,50 +4,11 @@ API Specification
This page contains the specification for all classes and methods available in
python-arango-async.

.. _AioHTTPClient:

AioHTTPClient
=================

.. autoclass:: arangoasync.http.AioHTTPClient
:members:

.. _DefaultHTTPClient:

DefaultHTTPClient
=================

.. autoclass:: arangoasync.http.DefaultHTTPClient
:members:

.. _HTTPClient:

HTTPClient
==========

.. autoclass:: arangoasync.http.HTTPClient
.. automodule:: arangoasync.http
:members:

.. _Method:

Method
=======

.. autoclass:: arangoasync.request.Method
.. automodule:: arangoasync.request
:members:

.. _Request:

Request
=======

.. autoclass:: arangoasync.request.Request
:members:

.. _Response:

Response
========

.. autoclass:: arangoasync.response.Response
.. automodule:: arangoasync.response
:members:
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ dev = [
"pytest-asyncio>=0.23.8",
"pytest-cov>=5.0",
"sphinx>=7.3",
"sphinx_rtd_theme",
"sphinx_rtd_theme>=2.0",
"types-setuptools",
]

15 changes: 15 additions & 0 deletions tests/static/cluster-3.12.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[starter]
mode = cluster
local = true
address = 0.0.0.0
port = 8528

[auth]
jwt-secret = /tests/static/keyfile

[args]
all.database.password = passwd
all.database.extended-names = true
all.log.api-enabled = true
all.javascript.allow-admin-execute = true
all.server.options-api = admin
1 change: 1 addition & 0 deletions tests/static/keyfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
secret
13 changes: 13 additions & 0 deletions tests/static/single-3.12.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[starter]
mode = single
address = 0.0.0.0
port = 8528

[auth]
jwt-secret = /tests/static/keyfile

[args]
all.database.password = passwd
all.database.extended-names = true
all.javascript.allow-admin-execute = true
all.server.options-api = admin