Skip to content
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

implement #29 #30

Merged
merged 15 commits into from
Jul 29, 2024
Merged

implement #29 #30

merged 15 commits into from
Jul 29, 2024

Conversation

lubaskinc0de
Copy link
Member

its now working like

from dataclasses import dataclass
from typing import Optional

from requests import Session

from dataclass_rest import get
from dataclass_rest.http.requests import RequestsClient


@dataclass
class Todo:
    id: int
    todo: str
    completed: bool
    userId: int


def url_generator(todo_id: Optional[int] = None) -> str:
    if todo_id:
        return f"/todos/{todo_id}"
    return f"/todos/random/"


class RealClient(RequestsClient):
    def __init__(self):
        super().__init__("https://dummyjson.com/", Session())

    @get(url_generator)
    def random_todo(self, todo_id: Optional[int] = None) -> Todo:
        pass


client = RealClient()
print(client.random_todo(5))  # Todo(id=5, todo="Solve a Rubik's cube", completed=False, userId=31)
print(client.random_todo())  # Todo(id=50, todo='Start a band', completed=False, userId=13)

@@ -19,10 +19,12 @@ def rest(
additional_params = {}

def dec(func: Callable) -> Method:
new_url_template = (lambda *args, **kwargs: url_template) if isinstance(url_template, str) else url_template
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably you meant

url_template.format if isinstance(url_template, str) else url_template

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, its better



class MethodSpec:
def __init__(
self,
func: Callable,
url_template: str,
url_template: Union[str | Callable[..., str]],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you actually pass only functions here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

method_spec = parse_func(
func=func,
body_param_name=body_name,
url_template=url_template,
url_template=new_url_template,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's store original string as well. It call be helpful for debugging

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how can i store it? pass it as different argument?

file_params = get_file_params(spec)
skipped_params = url_params + file_params + [body_param_name]
skipped_params = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because we can use function for getting url only when we has access to arguments and its values that passed to handler

like in boundmethod

    def _get_query_params(self, args) -> Any:
        url_params = get_url_params(self.method_spec.url_template, args)
        skipped_params = url_params + self.method_spec.file_param_names + [self.method_spec.body_param_name]
        query_params_type = create_query_params_type(getfullargspec(self.method_spec.func), self.method_spec.func, skipped_params)

        return self.client.request_args_factory.dump(
            args, query_params_type,
        )

def get_url_params(url_template: str) -> List[str]:
parsed_format = string.Formatter().parse(url_template)
def get_url_params(url_template: Callable[..., str], callback_kwargs: dict[str, Any]) -> List[str]:
parsed_format = string.Formatter().parse(url_template(callback_kwargs))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whats that is supposed to do?

@@ -8,8 +8,8 @@
DEFAULT_BODY_PARAM = "body"


def get_url_params(url_template: str) -> List[str]:
parsed_format = string.Formatter().parse(url_template)
def get_url_params(url_template: Callable[..., str], callback_kwargs: dict[str, Any]) -> List[str]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'type' object is not subscriptable

@lubaskinc0de
Copy link
Member Author

now this code works, i tested it on 3.9.8 and 3.12.1 both

from dataclasses import dataclass
from typing import Optional

from requests import Session

from dataclass_rest import get
from dataclass_rest.http.requests import RequestsClient


@dataclass
class Todo:
    id: int
    todo: str
    completed: bool
    userId: int


def url_generator(todo_id: Optional[int] = None) -> str:
    if todo_id:
        return f"/todos/{todo_id}"
    return f"/todos/random/"


def second_url_generator(xxx: str):
    if not xxx:
        return "/todos/random/"

    return f"/todos/random?xxx={xxx}"


class RealClient(RequestsClient):
    def __init__(self):
        super().__init__("https://dummyjson.com/", Session())

    @get(url_generator)
    def todo(self, some_arg: int, *, todo_id: Optional[int] = None, color: str = "green") -> Todo:
        pass

    @get("/todos/random")
    def random(self, hello: str) -> Todo:
        pass

    @get(second_url_generator)
    def random_hello(self, xxx: str) -> Todo:
        pass


client = RealClient()

print(client.todo(5, todo_id=5, color="red"))  # Todo(id=5, todo="Solve a Rubik's cube", completed=False, userId=31)
print(client.todo(5, color="red"))  # Todo(id=50, todo='Start a band', completed=False, userId=13)
print(client.random(hello="world"))  # Todo(id=31, todo='Find a charity and donate to it', completed=True, userId=35)
print(client.random_hello("xxxx"))  # Todo(id=103, todo='Go to a local thrift shop', completed=True, userId=5)

@lubaskinc0de
Copy link
Member Author

looks like I left some unused attributes in MethodSpec after refactoring, I'll fix that tonight when I'm home.

def get_url_params(url_template: str) -> List[str]:
parsed_format = string.Formatter().parse(url_template)
return [x[1] for x in parsed_format]
def get_url_params(url_template: Union[str, Callable[..., str]], arg_spec: Optional[FullArgSpec] = None) -> List[str]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather split into 2 functions. It's strange to get arg_spec for string.
Additionally we can remove try/except below and just call 2 different functions for both cases

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@Tishka17
Copy link
Member

Please, add tests

@Tishka17 Tishka17 changed the base branch from master to develop July 27, 2024 21:43
@Tishka17 Tishka17 merged commit b3510bb into reagento:develop Jul 29, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants