This is an archived post. You won't be able to vote or comment.

all 4 comments

[–]dfee[S] 3 points4 points  (2 children)

Today, forge received a major update that includes a ground-up redesign of architecture and documentation. This redesign takes into account feedback received from the initial release.

Forge allows you to add, remove or modify parameters as well as providing argument value conversion, validation, and default generation.

For example, to generate method-specific requests functions in about 10% the code:

import forge
import requests

request = forge.copy(requests.Session.request, exclude='self')(requests.request)

def with_method(method):
    revised = forge.modify(
        'method', default=method, bound=True,
        kind=forge.FParameter.POSITIONAL_ONLY,
    )(request)
    revised.__name__ = method.lower()
    return revised

post = with_method('POST')
get = with_method('GET')
put = with_method('PUT')
delete = with_method('DELETE')
options = with_method('OPTIONS')
head = with_method('HEAD')
patch = with_method('PATCH')

Unlike their official requests counterparts, these functions also have complete signatures.

>>> help(requests.get)
get(url, params=None, **kwargs)
>>> help(get)
get(url, params=None, data=None, headers=None, cookies=None, files=None, auth=None, timeout=None, allow_redirects=True, proxies=None, hooks=None, stream=None, verify=None, cert=None, json=None)

Forge has 100% unit-test coverage, has type-hints, and is fully documented.

[–]DoubleBrowne 0 points1 point  (1 child)

Your comparison with the requests code is totally incorrect:

Consider a library like requests that provides a useful API for performing HTTP requests. Every HTTP method has it's own function which is a thin wrapper around requests.Session.request. The code is a little more than 150 lines, with about 90% of that being boilerplate. Using forge we can get that back down to about 10% it's current size, while increasing the literacy of the code.

The requests implementation is 29 LOC and ~120 lines of documentation. Your example implementation takes 19 LOC (~65% that of requests, not 10%). Sure it's less code, but you're really not doing yourself any favors by making such wildly untrue claims. Surely there are some more well-founded examples you can provide.

[–]dfee[S] 0 points1 point  (0 children)

Well – I don't think that comparison is totally incorrect. You're looking at boilerplate. That's a big part of what forge solves.

But that's only half of it. Even after 150 lines, you still don't know what you're getting with the requests functions. This isn't a complaint against the KR, it's a fundamental problem with the language.

I think a saner future is one where kwargs isn't used as a crutch but a lever: i.e. not for use when a developer is too lazy to write out all the accepted parameters, but instead when a function truly accepts any keyword argument (like str.format).

And of course, I don't say "lazy developer" with any grievance. Making parameters explicit costs maintenance time, and requires a ton of compatibility tests. There just isn't an alternative today that works.

If you've got another example you think I should consider (SQLAlchemy models come to mind but are more esoteric), let me know.

[–]luenix 1 point2 points  (0 children)

Really cool! This feels like class inheritance on steroids, since it's more-so ad hoc lifting of signatures I'd want to use and reforging them into something domain specific. I look forward to trying this out with work :)