Skip to content

Commit

Permalink
Merge pull request #8 from ponytailer/ut-dev
Browse files Browse the repository at this point in the history
add ut and bugfix
  • Loading branch information
ponytailer authored Aug 11, 2023
2 parents 84f9a57 + e739903 commit 9057734
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 39 deletions.
5 changes: 2 additions & 3 deletions pydantic_client/clients/aiohttp_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@
class AIOHttpClient(AbstractClient):
runner_class: Type[Proxy] = AsyncClientProxy

def __init__(self, base_url: str, session: ClientSession = ClientSession()):
self.session = session
def __init__(self, base_url: str):
self.base_url = base_url

async def do_request(self, request: HttpRequest) -> Any:
data, json = self.parse_request(request)
async with self.session as session:
async with ClientSession() as session:
try:
req = session.request(
url=self.base_url + request.url,
Expand Down
10 changes: 7 additions & 3 deletions pydantic_client/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import logging
import re
from typing import Any, Dict
from urllib.parse import urlparse
from urllib.parse import urlparse, parse_qsl

from pydantic import BaseModel

Expand Down Expand Up @@ -32,16 +32,20 @@ def _apply_args(self, *args, **kwargs) -> Dict[str, Any]:

def _get_url(self, args) -> str:
keys = self.querystring_pattern.findall(self.method_info.url)
query_args = {arg: args.pop(arg) for arg, val in args.items() if
query_args = {arg: val for arg, val in args.items() if
arg in keys and val}

for key in keys:
args.pop(key, None)

url = self.method_info.url.format(**query_args)

url_result = urlparse(url)
if "{" in url_result.path:
logger.warning(f"Not formatted args in url path: {url}")

querystring = "&".join(
f"{k}={v}" for k, v in url_result.query if "{" not in v
f"{k}={v}" for k, v in parse_qsl(url_result.query) if "{" not in v
)
return url_result.path + "?" + querystring if querystring else url_result.path

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pydantic-client"
version = "0.1.7"
version = "0.1.8"
description = "Http client base pydantic, with requests or aiohttp"
authors = ["ponytailer <[email protected]>"]
readme = "README.md"
Expand Down
6 changes: 6 additions & 0 deletions tests/book.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from pydantic import BaseModel


class Book(BaseModel):
name: str
age: int
36 changes: 36 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import pytest

from pydantic_client import delete, get, post, put, RequestsClient
from tests.book import Book


class R(RequestsClient):
def __init__(self):
super().__init__("http://localhost")

@get("/books/{book_id}?query={query}")
def get_book(self, book_id: int, query: str) -> Book:
...

@get("/books/{book_id}")
def get_raw_book(self, book_id: int):
...

@post("/books", form_body=True)
def create_book_form(self, book: Book) -> Book:
""" will post the form with book"""
...

@put("/books/{book_id}")
def change_book(self, book_id: int, book: Book) -> Book:
"""will put the json body"""
...

@delete("/books/{book_id}")
def delete_book(self, book_id: int) -> Book:
...


@pytest.fixture
def client():
yield R()
42 changes: 42 additions & 0 deletions tests/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import requests


class MockResponse:

def __init__(self, code, response):
self.code = code
self.response = response

@property
def ok(self):
return int(self.code) == 200

def json(self):
return self.response

def raise_for_status(self):
if not self.ok:
raise

@property
def status_code(self):
return self.code


def mock_requests(
monkeypatch,
response=None,
code=200
):

def mock_call(mock_return_value):
def mock(*args, **kwargs):
return MockResponse(**mock_return_value)

return mock

return_value = {"code": code, "response": response or {}}
monkeypatch.setattr(
requests.Session, "request",
mock_call(return_value)
)
59 changes: 27 additions & 32 deletions tests/test_client.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,40 @@
import unittest
import pytest

from pydantic import BaseModel
from tests.book import Book
from tests.helpers import mock_requests

from pydantic_client import delete, get, post, put, RequestsClient

@pytest.fixture
def mock_get_book(monkeypatch):
mock_resp = {"name": "name", "age": 1}
yield mock_requests(monkeypatch, response=mock_resp)

class Book(BaseModel):
name: str
age: int

def test_get(client, mock_get_book):
book: Book = client.get_book(1, "world")
assert book.name == "name"
assert book.age == 1

class R(RequestsClient):
def __init__(self):
super().__init__("http://localhost")

@get("/books/{book_id}?query={query}")
def get_book(self, book_id: int, query: str) -> Book:
...
def test_get_raw(client, mock_get_book):
book: dict = client.get_raw_book(1)
assert book["name"] == "name"
assert book["age"] == 1

@post("/books", form_body=True)
def create_book_form(self, book: Book) -> Book:
""" will post the form with book"""
...

@put("/books/{book_id}")
def change_book(self, book_id: int, book: Book) -> Book:
"""will put the json body"""
...
def test_post_form(client, mock_get_book):
book: Book = client.create_book_form(Book(name="name", age=2))
assert book.name == "name"
assert book.age == 1

@delete("/books/{book_id}")
def change_book(self, book_id: int) -> Book:
...

def test_put(client, mock_get_book):
book: Book = client.change_book(1, Book(name="name", age=2))
assert book.name == "name"
assert book.age == 1

class TestClient(unittest.TestCase):

def setUp(self):
self.test_client = R()

def tearDown(self):
self.test_client = None

def test_get(self):
...
def test_delete(client, mock_get_book):
book: Book = client.delete_book(1)
assert book.name == "name"
assert book.age == 1

0 comments on commit 9057734

Please sign in to comment.