Lispython / human_curl

Simple Human wrapper for cURL library
http://h.wrttn.me/human_curl
Other
205 stars 43 forks source link

debug info in stdout #9

Closed imbolc closed 12 years ago

imbolc commented 12 years ago

Привет :) Чего-то в stdout заголовки сыпятся. И дефолтное значение allow_redirects не совпадают с requests.

>>> import requests
>>> import human_curl
>>> requests.get('http://google.com/')
<Response [200]>
>>> human_curl.get('http://google.com/')
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Sat, 05 Nov 2011 21:13:22 GMT
Expires: Mon, 05 Dec 2011 21:13:22 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
<Response: 301 >
Lispython commented 12 years ago

Из транка брал? Какая версия / ревизия? Воспроизвести не смог.

Попробовал в ipython и python:

(venv)alex@googleee:/tmp$ python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import human_curl
>>> human_curl.get('http://google.com/')
<Response: 301 >

По поводу редиректов. Не смотря на то, что requests отличная библиотека, некоторые моменты я считаю не совсем верными. Поэтому allow_redirects нужно указывать явно :-)

imbolc commented 12 years ago

Ставил из pypi, в транке всё ок.

Насчёт requests, они уже стали стандартом де-факто. Меня привлекло в либе именно это. Всё уже написано через requests. Но понадобилось через соксы работать, а урллиб этого не умеет. Думаю, подобное отношение будет и у большинства новых юзеров либы. Было бы круто сделать полную совместимость с requests. Если тебе лень, я готов поработать над этим. Всё равно мне это нужно, лучше уж нормально сделать, чем костыль. А весь несовместимый функционал можно вынести отдельно. Просто как обёртки к совместимой базе.

Ещё заметил несовместимость. В requests словарь proxies, а у тебя кортеж proxy.

Вообще, отличная либа, респекты :) Случайно нашёл, очень рад :)

Lispython commented 12 years ago

Ранова-то им до стандарта дефакто ;-) Хотя бы потому, что API менялось на моей памяти :-)

Полной совместимости нет не потому, что мне лень, а потому, что некоторые моменты в requests неоднозначны. Если хочешь что-то добавить/исправить форкни и сделай пулреквест. Для совместимости можно конечно написать обертку для Request, которая будет приводить параметры request совместимые к виду, который тут принят. Но сомнительное решение.

Смысл передавать в качестве прокси словарь? Чтобы передать несколько типов прокси?

imbolc commented 12 years ago

Смысл для requests? Подозреваю, что просто взяли из урллиб, там же словарь. А общий смысл совместимости в совместимости. Чтобы облегчить переход с requests на human_curl. Ведь если у человека написано много под requests, он не будет переписывать. Он набросает быстро эту самую обёртку. Совместимость с requests мне кажется киллер-фичей этой либы.

Lispython commented 12 years ago

Вообще я не против совместимости, но без фанатизма.

Если рассматривать данный конкретный случай с прокси, то я не считаю обоснованным применять словарь.

Более того, посмотрев исходники urllib2 я заметил, что значение словаря 'http://joe:password@proxy.example.com:3128' все равно парсится c танцами и бубнами и в конечном итоге возвращает кортеж.

http://hg.python.org/cpython/file/62fa61f2ee7d/Lib/urllib2.py#l625

@kennethreithz, насколько я понял, не против перейти к формату кортежей

Если сделаешь, чтобы Request принимал словарь, то я не против и занесу изменения в основную ветку.

imbolc commented 12 years ago

Вроде подразумевался у тебя dict. Даже в описании Request вижу. Мне по удобочитаемости кортеж не нравится, особенно если с паролем. C гитхабом не работал вообще, сюда скину, может внесёшь когда будешь там править что-нибудь :)


def proxy_dict_to_tuple(proxy):
    ''' 
        >>> proxy_dict_to_tuple({'http': '127.0.0.1:9050'})
        (('http', ('127.0.0.1', '9050')),)
        >>> proxy_dict_to_tuple({'http': 'username:password@127.0.0.1:9050'})
        (('http', ('127.0.0.1', '9050', ('username', 'password'))),)
    '''
    ret = []
    for k, v in proxy.iteritems():
        scheme, user, password, host_port = urllib2._parse_proxy(v)
        host, port = host_port.split(':', 1)
        if user:
            ret.append((k, (host, port, (user, password))))
        else:
            ret.append((k, (host, port)))
    return tuple(ret)
Lispython commented 12 years ago

Сначала я действительно считал возможным передавать несколько прокси в конструктор:

(('http', ('127.0.0.1', 9050)),
('https', ('127.0.0.1', 9050, ('username', 'password'))),
('socks4', ('127.0.0.1', 8118)))

Так же предполагалось, что можно будет использовать словарь с ключами "https", "https", "socks", но дойдя до реализации, я так и не решил, какой же из переданных прокси использовать, если передано несколько. Решил, что перебор прокси серверов - это не дело самой либы, а уже той программы, в которой либа используется. Чуть позже я понял, что ключи словаря в urllib2 имеют несколько иное значение, чем я думал...

Вот допустим у нас в словаре передано несколько ключей, твоя функция вернула кортеж кортежей, то какой прокси использовать? Можно брать первый, но тогда смысла в других переданных ключах нет. Это избыточные данные, которые могут порождать ошибки. А словарь с одним ключом ... и получится костыль, про который ты говорил выше :-)

В urllib2 применение словаря вполне обоснованно, ключи должны быть уникальными. Поэтому для HttpHandler, будет вызван метод http_open, для HttpsHandler https_open, для ftp ftp_open.

Собственно вот он и есть камень преткновения из-за которого я решил отказаться от словаря. Есть идеи как решать проблему выбора прокси из того что вернет proxy_dict_to_tuple?

ps. С гитхабом работать просто. Нажимаешь сверху кнопочку fork, затем клонируешь репозиторий к себе на комп с помощью git clone git://github.com/imbolc/reponame, вносишь изменения git commit -m && git push. Жмякаешь на странице своего репозитория на кнопочку pull request.

imbolc commented 12 years ago

Мне кажется важной только совместимость с requests на уровне апи. Если даже либа не покрывает все возможности requests в рамках возможностей можно сделать совместимость. Например, если передано больше одного прокси кидать исключение.