Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Requests - https://github.com/kennethreitz/requests.

How to make a usable api. The decisions that went into each method call were fantastic. Great test coverage as well. I use package in most python development.



Thanks, I've been hearing a lot about this package, I think it's one I will check out.

Cheers!


This presentation by the author explains the thinking behind it: https://speakerdeck.com/kennethreitz/python-for-humans


requests is very useful, but it always gets mentioned as a good python codebase and I'm not sure I agree. One example:

The first thing many users will do is

  requests.get?
Which tells them that it takes some kwargs, but doesn't tell them what those kwargs are. It's easy, especially for a newcomer, to read "optional arguments that `request` takes" and fail to understand that they should look up the docs on (not-really-encouraged-as-part-of-public-API) function `request`. That's pretty bad; those kwargs are important! (The reason is because requests.get is implemented as a call to request(method, ..., kwargs) but the user doesn't care what the implementation-level reason is.)

Beyond that I did look into the codebase once to investigate a possible bug and there were a few python style things I wanted to fix, but I don't remember them so this comment probably sounds kind of annoying (it would annoy me if I were reading it not writing it...). It didn't strike me a really clean codebase. But yes the library is very useful and I'm sure it's a pretty decent python codebase.

  >>> requests.get?
  Signature: requests.get(url, params=None, **kwargs)
  Docstring:
  Sends a GET request.
  
  :param url: URL for the new :class:`Request` object.
  :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
  :param \*\*kwargs: Optional arguments that ``request`` takes.
Here are all the kwargs the user probably wanted to know but failed to find out and was forced to either browse online docs or the source code:

  def request(method, url, **kwargs):
      """Constructs and sends a :class:`Request <Request>`.
      :param method: method for the new :class:`Request` object.
      :param url: URL for the new :class:`Request` object.
      :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
      :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`.
      :param json: (optional) json data to send in the body of the :class:`Request`.
      :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
      :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
      :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': ('filename', fileobj)}``) for multipart encoding upload.
      :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
      :param timeout: (optional) How long to wait for the server to send data
          before giving up, as a float, or a (`connect timeout, read timeout
          <user/advanced.html#timeouts>`_) tuple.
      :type timeout: float or tuple
      :param allow_redirects: (optional) Boolean. Set to True if POST/PUT/DELETE redirect following is allowed.
      :type allow_redirects: bool
      :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
      :param verify: (optional) if ``True``, the SSL cert will be verified. A CA_BUNDLE path can also be provided.
      :param stream: (optional) if ``False``, the response content will be immediately downloaded.
      :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
      :return: :class:`Response <Response>` object
      :rtype: requests.Response


Looks like you did the legwork of listing the params already, so you might as well send a PR with that docstring.


OK, maybe I will open an issue. The obvious concern is how to avoid duplicating the text among the various HTTP verb functions. In theory python allows the docstring to be manipulated via __doc__. However I don't think there is a precedent for using that mechanism to avoid duplication of docstring content that is considered good style, but perhaps someone could correct me if that is wrong.


You'd probably want to make a metaclass that handled the manipulation of __doc__ for shared verbs if you didn't want to duplicate the data too much.


OK, but in requests they are top-level functions, not methods. Is there anything wrong with the below? I don't think I've seen it done.

  __shared_docstring_content = """
  bar
  baz
  """

  def f():
      "f docstring"
      pass

  f.__doc__ += __shared_docstring_content


  def g():
      "g docstring"
      pass

  g.__doc__ += __shared_docstring_content


I would do simply """f docstring\n%s""" % _shared_docstring, no need for a separate concatenation. However, I wonder whether sphinx would handle this.


This sort of thing works fine. We use it for pandas all the time.


Pandas does this, and I think it works well, even if it's not entirely transparent in the source.


> requests.get?

I was using Python for 8 years and IPython for somewhat 5 years if my memory serves me right but today I have learned that you can invoke help on an object by appending '?'. I guess I might delve into IPython documentation sometime.

Thank you for lengthy and detailed explanation.


Ipython is amazing. "requests.get??" will show you the source (works on modules too). "%pdb on" is another fave to drop straight into the debugger with uncaught exceptions.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: