mirror of
https://github.com/kennethreitz-archive/py-reqcache.git
synced 2026-06-05 23:30:17 +00:00
Initial import.
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
build
|
||||
dist
|
||||
env
|
||||
*.py[c,o]
|
||||
*.bak
|
||||
*.swp
|
||||
*.egg-info
|
||||
.DS_Store
|
||||
@@ -0,0 +1 @@
|
||||
Kyle Jensen - https://github.com/kljensen/
|
||||
@@ -0,0 +1,13 @@
|
||||
Copyright (c) 2012 Kyle L. Jensen <kljensen@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
@@ -0,0 +1,36 @@
|
||||
.PHONY: all pep8 pyflakes clean dev
|
||||
|
||||
GITIGNORES=$(shell cat .gitignore |tr "\\n" ",")
|
||||
|
||||
all: pep8
|
||||
|
||||
pep8: .gitignore env
|
||||
@bin/virtual-env-exec pep8 . --exclude=$(GITIGNORES)
|
||||
|
||||
pyflakes: env
|
||||
@bin/virtual-env-exec pyflakes reqcache tests
|
||||
|
||||
pylint: env
|
||||
@bin/virtual-env-exec pylint reqcache 2>&1 |less
|
||||
|
||||
dev: env env/.pip
|
||||
|
||||
env:
|
||||
@virtualenv --distribute env
|
||||
|
||||
env/.pip: env cfg/requirements.txt
|
||||
@bin/virtual-env-exec pip install -r cfg/requirements.txt
|
||||
@bin/virtual-env-exec pip install -e .
|
||||
@touch env/.pip
|
||||
|
||||
test: env/.pip
|
||||
@bin/virtual-env-exec testify tests
|
||||
|
||||
shell:
|
||||
@bin/virtual-env-exec ipython
|
||||
|
||||
devclean:
|
||||
@rm -rf env
|
||||
|
||||
clean:
|
||||
@rm -rf build dist env
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
py-reqcache: Caching for Python's Request Package
|
||||
=========================
|
||||
|
||||
py-reqcache is a Python_ package that provides caching for
|
||||
the Requests_ HTTP library. It's based on the wonderful
|
||||
Requests-Cache_ libary by Roman Haritonov and uses the
|
||||
backends from that project. The main difference is that
|
||||
this package uses the Requests_ API hooks instead of
|
||||
monkeypatching.
|
||||
|
||||
|
||||
Example usage
|
||||
----------
|
||||
|
||||
import requests
|
||||
import reqcache
|
||||
|
||||
c = reqcache.ReqCache("foo", "memory")
|
||||
|
||||
r = requests.get('http://github.com', hooks=c.hooks)
|
||||
print getattr(r, "from_cache", False)
|
||||
|
||||
r = requests.get('http://github.com', hooks=c.hooks)
|
||||
print getattr(r, "from_cache", False)
|
||||
|
||||
|
||||
Contribute
|
||||
----------
|
||||
|
||||
#. Fork the project on github to start making your changes
|
||||
#. Send pull requests with your bug fixes or features
|
||||
#. Submit and create issues on github
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
.. _Python: http://www.python.org/
|
||||
.. _Requests: http://www.python-requests.org
|
||||
.. _Requests-Cache: https://github.com/reclosedev/requests-cache
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
source env/bin/activate
|
||||
$@
|
||||
@@ -0,0 +1,7 @@
|
||||
testify
|
||||
pep8
|
||||
pyflakes
|
||||
ipython
|
||||
pylint
|
||||
requests
|
||||
requests-cache
|
||||
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
reqcache
|
||||
~~~~~~~~
|
||||
|
||||
:copyright: (c) 2012 by Firstname Lastname.
|
||||
:license: ISC, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'reqcache'
|
||||
__version__ = '0.0.1'
|
||||
__description__ = 'Python Requests Caching'
|
||||
__url__ = 'https://github.com/kljensen/py-reqcache'
|
||||
__build__ = 0
|
||||
__author__ = 'Kyle Jensen'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = 'Copyright 2012 Kyle Jensen'
|
||||
|
||||
|
||||
from .models import ReqCache
|
||||
@@ -0,0 +1,126 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
This module contains the primary objects for caching responses
|
||||
for the Python Requests library.
|
||||
|
||||
:copyright: (c) 2012 by Kyle Jensen.
|
||||
:license: ISC, see LICENSE for more details.
|
||||
"""
|
||||
import hashlib
|
||||
import datetime
|
||||
import requests
|
||||
from requests_cache import backends
|
||||
|
||||
|
||||
class ReqCache(object):
|
||||
|
||||
def __init__(self, cache_name, backend,
|
||||
allowable_codes=(200,),
|
||||
allowable_methods=('GET',),
|
||||
expire_after=None,
|
||||
**backend_options):
|
||||
|
||||
super(ReqCache, self).__init__()
|
||||
self.cache_name = cache_name
|
||||
self.backend = backend
|
||||
self.allowable_codes = allowable_codes
|
||||
self.allowable_methods = allowable_methods
|
||||
self.expire_after = expire_after
|
||||
|
||||
try:
|
||||
self.cache = backends.registry[self.backend](
|
||||
cache_name,
|
||||
**backend_options
|
||||
)
|
||||
except KeyError:
|
||||
raise ValueError('Unsupported backend "%s" try one of: %s' %
|
||||
(backend, ', '.join(backends.registry.keys())))
|
||||
|
||||
@staticmethod
|
||||
def reqresp_to_key(r):
|
||||
"""
|
||||
Accepts a Request or Reponse object, returns a string key for
|
||||
storing the cached response in a dictionary-like object.
|
||||
"""
|
||||
if isinstance(r, requests.Response):
|
||||
request = r.request
|
||||
else:
|
||||
request = r
|
||||
|
||||
key = "method={0} url={1}".format(
|
||||
request.method,
|
||||
request.full_url,
|
||||
)
|
||||
|
||||
if request.method in ("POST", "PUT"):
|
||||
data = request._encode_params(getattr(r, 'data', {}))
|
||||
key = "{0} datahash={2}".format(
|
||||
key,
|
||||
hashlib.sha224(data).hexdigest(),
|
||||
)
|
||||
return key
|
||||
|
||||
def to_cache(self, response):
|
||||
"""
|
||||
Save a response to the cache.
|
||||
"""
|
||||
if (response.status_code in self.allowable_codes
|
||||
and response.request.method in self.allowable_methods
|
||||
and not hasattr(response, 'from_cache')):
|
||||
|
||||
key = self.reqresp_to_key(response)
|
||||
self.cache.save_response(key, response)
|
||||
|
||||
return response
|
||||
|
||||
def from_cache(self, request):
|
||||
"""
|
||||
Retrieve a response from the cache given a request.
|
||||
"""
|
||||
if request.method in self.allowable_methods:
|
||||
key = self.reqresp_to_key(request)
|
||||
response, timestamp = self.cache.get_response_and_time(key)
|
||||
|
||||
if response:
|
||||
difference = datetime.datetime.now() - timestamp
|
||||
|
||||
if (self.expire_after is not None
|
||||
and difference >
|
||||
datetime.timedelta(minutes=self.expire_after)):
|
||||
self.cache.del_cached_url(key)
|
||||
else:
|
||||
request.sent = True
|
||||
request.response = response
|
||||
request.response.request = request
|
||||
request.response.from_cache = True
|
||||
return request
|
||||
|
||||
@property
|
||||
def hooks(self):
|
||||
return {
|
||||
"pre_request": self.from_cache,
|
||||
"response": self.to_cache,
|
||||
}
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
def explain_cache_result(response):
|
||||
was_cached = getattr(response, "from_cache", False)
|
||||
if was_cached:
|
||||
source = "cache"
|
||||
else:
|
||||
source = "interwebs"
|
||||
|
||||
msg = "Got response from {0} for {1}".format(
|
||||
source,
|
||||
ReqCache.reqresp_to_key(response.request),
|
||||
)
|
||||
print msg
|
||||
|
||||
reqcache = ReqCache("test", "memory")
|
||||
|
||||
r = requests.get('http://github.com', hooks=reqcache.hooks)
|
||||
explain_cache_result(r)
|
||||
|
||||
r = requests.get('http://github.com', hooks=reqcache.hooks)
|
||||
explain_cache_result(r)
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
from distutils.core import setup
|
||||
|
||||
PACKAGES = ['reqcache']
|
||||
|
||||
|
||||
def get_init_val(val, packages=PACKAGES):
|
||||
pkg_init = "%s/__init__.py" % PACKAGES[0]
|
||||
value = '__%s__' % val
|
||||
fn = open(pkg_init)
|
||||
for line in fn.readlines():
|
||||
if line.startswith(value):
|
||||
return line.split('=')[1].strip().strip("'")
|
||||
|
||||
|
||||
setup(
|
||||
name='py-%s' % get_init_val('title'),
|
||||
version=get_init_val('version'),
|
||||
description=get_init_val('description'),
|
||||
long_description=open('README.rst').read(),
|
||||
author=get_init_val('author'),
|
||||
url=get_init_val('url'),
|
||||
package_data={'': ['LICENSE', 'NOTICE']},
|
||||
license=get_init_val('license'),
|
||||
packages=PACKAGES
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
import testify
|
||||
import requests
|
||||
from reqcache.models import ReqCache
|
||||
|
||||
|
||||
class ReqCacheTestCase(testify.TestCase):
|
||||
|
||||
@testify.setup
|
||||
def create_cache(self):
|
||||
self.rcache = ReqCache("test", "memory")
|
||||
|
||||
@testify.teardown
|
||||
def clear_cache(self):
|
||||
self.rcache = None
|
||||
|
||||
def test_basic_caching(self):
|
||||
|
||||
r = requests.get('http://github.com', hooks=self.rcache.hooks)
|
||||
self.assertFalse(getattr(r, "from_cache", False))
|
||||
|
||||
r = requests.get('http://github.com', hooks=self.rcache.hooks)
|
||||
self.assertTrue(getattr(r, "from_cache", False))
|
||||
Reference in New Issue
Block a user