{ "info": { "author": "Nobu Kakegawa", "author_email": "nobu@nk113.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Environment :: Web Environment", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Utilities" ], "description": "==================\ntastypie-rpc-proxy\n==================\n\n.. image:: https://badge.fury.io/py/tastypie-rpc-proxy.png\n :alt: Pypi Package\n :target: https://pypi.python.org/pypi/tastypie-rpc-proxy\n.. image:: https://pypip.in/d/tastypie-rpc-proxy/badge.png\n :alt: Downloads\n :target: https://crate.io/packages/tastypie-rpc-proxy\n.. image:: http://www.versioneye.com/python/tastypie-rpc-proxy/badge.png\n :alt: Dependency Status\n :target: http://www.versioneye.com/python/tastypie-rpc-proxy/\n.. image:: https://travis-ci.org/nk113/tastypie-rpc-proxy.png?branch=master\n :alt: Build Status\n :target: http://travis-ci.org/nk113/tastypie-rpc-proxy\n.. image:: https://coveralls.io/repos/nk113/tastypie-rpc-proxy/badge.png\n :alt: Coverage Status\n :target: https://coveralls.io/r/nk113/tastypie-rpc-proxy\n\n\n\nThe concept of **tastypie-rpc-proxy**, an etension of `tastypie-queryset-client`_ - many kudos to the author, is to help coding `tastypie`_ based RPC in easy manner. With **rpc_proxy** you can handle remote `tastypie`_ resources as if operating over local `django`_ model objects. Now you don't need to separately code your business logics and unit tests for both central `django`_ models and API client to read the central data from remote boxes - in other word you can use the same application code for central database-accesible environment and remote API client, **rpc_proxy** looks after everything for you. In common situation you might write following unreadable code to operate remote resource objects behind `tastypie`_ API.\n\n::\n\n headers = {'content-type': 'application/json'}\n auth = ('test', 'test',)\n filters = {\n 'track__item__source_item_id__startswith': 't-2',\n 'language_code': 'ja',\n }\n response = requests.get('http://127.0.0.1:8000/api/v1/meta/tracklocalization/',\n params=filters,\n headers=headers,\n auth=auth)\n title_ja = response.json()['objects'][0]['title']\n\nDon't you think it's convenient if you can code like below to do the same stuff as above?\n\n::\n\n title_ja = Track.objects.get(item__source_item_id__startswith='t-2').localize('ja').title\n\nUsing **rpc_proxy** the code to operate over remote resources looks like this. As you see, this code is 100% compatible with `django`_ model / queryset api terminology so that means this code can be used to operate over both local model objects and remote resource objects. While you might code like this django model / queryset style business logic for the central database-accessible environment - which hosts tasypie resources API as well, until today, at the same time you also might have to write some code for the API client side like next above to access the central data resources which represents actual database. So you have needed to maintain 2 versions of code for local and remote environments actually. **rpc_proxy** is intended for getting you out of this sort of annoying situation. The proxy class tries to access remote `tastypie`_ resources if *API_URL* settings is provided, and to read local models if it's not. All right, take a look once at how **rpc_proxy** works. The **rpc_proxy** also can be used as a simple tastypie client which has similar interfaces as `django`_ queryset API.\n\nFeatures enhanced from tastypie-queryset-client\n===============================================\n\n* data proxy layer, which enables switching between local model access and RPC depending on *API_URL* settings\n* API namespace\n* remote API schema and foreing key caching\n* remote API foreign key object operation\n* supporting custom field type\n\netc.\n\nNotes\n=====\n\n* setting up `django`_ cache backend is strongly recommended to reduce API requests.\n* defining `tastypie`_ resources inheriting *rpc_proxy.resources.ModelResource* is strongly recommended to fully support foreign key operations. \n\nInstallation\n============\n\nPip installation is available. Note that this does only install ``rpc_proxy`` library, doesn't contain example ``example`` application.\n\n::\n\n pip install tastypie-rpc-proxy\n\nQuick Start\n===========\n\n``example`` application is good to start with. Following section goes through the application to describe what you can enjoy from **rpc_proxy**. See the ``example`` application code for the implementation in detail. This test application has models that represent common music data scheme - Album, Track metadata and these localizations. The Item model associates them as parent and child relationship.\n\nDefine models\n-------------\n\nFirst of all, define `django`_ models as usual. The model methods will be implemented on *proxy* classes later instead of on the models so just define model fields here - ``example/models.py``.\n\n::\n\n (...)\n META_TYPES = ((0, 'Track',), (1, 'Album',),)\n\n (...)\n class Item(Model):\n (...)\n meta_type = models.SmallIntegerField(choices=META_TYPES, default=0)\n parents = models.ManyToManyField('self', symmetrical=False, related_name='children', blank=True, null=True)\n source_item_id = models.CharField(max_length=64, unique=True)\n\n\n class Album(BasicLocalizable):\n\n item = models.OneToOneField(Item, primary_key=True)\n title = models.CharField(max_length=255, blank=True, null=False)\n (...)\n\n\n class AlbumLocalization(BasicLocalization, MusicLocalization):\n\n album = models.ForeignKey(Album)\n language_code = models.CharField(max_length=2, choices=getattr(settings, 'LANGUAGES'), blank=False, null=False)\n (...)\n\nDefine resources\n----------------\n\nDesign `tastypie`_ resources carefully. Might need to have various filters, orderings and access controls - ``example/resources.py``. The resources should be defined inheriting *rpc_proxy.resources.ModelResource* class to support foreign key operations.\n\n::\n\n (...)\n from rpc_proxy import resources\n\n (...)\n class Item(resources.ModelResource):\n\n class Meta(BaseMeta):\n\n queryset = models.Item.objects.all()\n resource_name = 'item'\n (...)\n\n parents = fields.ToManyField('example.resources.Item', 'parents', null=True)\n children = fields.ToManyField('example.resources.Item', 'children', null=True)\n (...)\n\n\n class Album(resources.ModelResource):\n\n class Meta(BaseMeta):\n\n queryset = models.Album.objects.all()\n resource_name = 'album'\n (...)\n\n item = fields.ForeignKey(Item, 'item')\n (...)\n\n\n class AlbumLocalization(resources.ModelResource):\n\n class Meta(BaseMeta):\n\n queryset = models.AlbumLocalization.objects.all()\n resource_name = 'albumlocalization'\n (...)\n\n album = fields.ForeignKey(Album, 'album')\n (...)\n\nConfigure URLs\n--------------\n\nSeparate metadata resources from Item resource to demonstrate namespaces - ``example/urls/url.py``\n\n::\n\n (...)\n core_api = Api(api_name='core')\n core_api.register(resources.Item())\n\n meta_api = Api(api_name='meta')\n meta_api.register(resources.Album())\n meta_api.register(resources.AlbumLocalization())\n (...)\n\n urlpatterns = patterns('',\n # v1\n url(r'^api/v1/', include(core_api.urls)),\n url(r'^api/v1/', include(meta_api.urls)),\n # v2\n # ...\n )\n\nCreate proxies\n--------------\n\nNow it's time to code proxy, ``proxies.py`` is expected filename of the module *proxy* classes are defined by default. Write business logics usually we write on django models here. Proxies here are implementing some useful methods for localization - ``example/proxies.py``.\n\n::\n\n (...)\n from example.models import ITEM_TYPES, META_TYPES\n\n (...)\n def get_default_language_code():\n return getattr(settings, 'LANGUAGE_CODE', 'en-US').split('-')[0].lower()\n\n\n (...)\n class Localizable(proxies.Proxy):\n\n class Meta:\n\n abstract = True\n\n def __init_proxy__(self):\n super(Localizable, self).__init_proxy__()\n\n setattr(self, 'localization', getattr(import_module(self.__module__),\n '%sLocalization' % self.__class__.__name__))\n\n @property\n def localizations(self):\n return self.localization.objects.filter(**{\n self.__class__.__name__.lower(): self,\n })\n\n def localize(self, language_code=None):\n self.__init_proxy__()\n\n language_code = language_code if language_code else get_default_language_code()\n localizations = self.localizations.filter(language_code=language_code)\n\n if len(localizations) < 1:\n\n class EmptyLocalization(object):\n\n def __init__(self, *args, **kwargs):\n for key in kwargs:\n setattr(self, key, kwargs[key])\n\n def __getattr__(self, name):\n try:\n return super(EmptyLocalization,\n self).__getattr__(name)\n except AttributeError, e:\n return None\n\n localizations = (EmptyLocalization(language_code=language_code),)\n\n return localizations[0]\n\n\n class Localization(proxies.Proxy):\n\n class Meta:\n\n abstract = True\n\n\n (...)\n class Item(proxies.Proxy):\n\n class Meta:\n\n namespace = 'core'\n\n (...)\n @property\n def meta_type_display(self):\n if 'get_meta_type_display' in dir(self):\n return self.get_meta_type_display()\n\n return META_TYPES[self.meta_type][1]\n\n @property\n def metadata(self):\n try:\n meta = getattr(import_module(self.__module__),\n self.meta_type_display)\n except Exception, e:\n logger.exception(e)\n raise exceptions.ProxyException(_('No metadata model for '\n '%s found.' % self.meta_type_display))\n\n return meta.objects.get(item=self)\n\n\n class Album(Localizable):\n\n pass\n\n\n class AlbumLocalization(Localization):\n\n pass\n\n\nImport proxies\n--------------\n\nAll right, let's call those proxies with the ``manage.py shell``. After loading fixture, import them with no *API_URL* settings like below, then you can see accesses to the local models:\n\n::\n\n TASTYPIE_RPC_PROXY = {\n 'API_NAMESPACE': 'meta',\n 'NON_DEFAULT_ID_FOREIGNKEYS': ('item',),\n 'SUPERUSER_USERNAME': 'test',\n 'SUPERUSER_PASSWORD': 'test',\n }\n\n::\n\n >>> from example.proxies import *\n >>> a = Album.objects.get(item__source_item_id__startswith='a-1')\n [DEBUG: django.db.backends: execute] (0.001) SELECT \"test_album\".\"ctime\", \"test_album\".\"utime\", \"test_album\".\"item_id\", \"test_album\".\"release_date\" FROM \"test_album\" INNER JOIN \"test_item\" ON (\"test_album\".\"item_id\" = \"test_item\".\"id\") WHERE \"test_item\".\"source_item_id\" LIKE a-1% ESCAPE '\\' ; args=(u'a-1%',)\n >>> a.localize('en').title\n [DEBUG: django.db.backends: execute] (0.000) SELECT \"test_item\".\"id\", \"test_item\".\"ctime\", \"test_item\".\"utime\", \"test_item\".\"item_type\", \"test_item\".\"meta_type\", \"test_item\".\"source_item_id\" FROM \"test_item\" WHERE \"test_item\".\"id\" = 1 ; args=(1,)\n [DEBUG: django.db.backends: execute] (0.000) SELECT \"test_albumlocalization\".\"id\", \"test_albumlocalization\".\"ctime\", \"test_albumlocalization\".\"utime\", \"test_albumlocalization\".\"language_code\", \"test_albumlocalization\".\"title\", \"test_albumlocalization\".\"description\", \"test_albumlocalization\".\"artist\", \"test_albumlocalization\".\"label\", \"test_albumlocalization\".\"album_id\" FROM \"test_albumlocalization\" WHERE (\"test_albumlocalization\".\"album_id\" = 1 AND \"test_albumlocalization\".\"language_code\" = en ); args=(1, 'en')\n u'A Pop Song Collection'\n >>> t_en = a.item.children.get(source_item_id__startswith='t-1').metadata.localize('en')\n [DEBUG: django.db.backends: execute] (0.000) SELECT \"test_item\".\"id\", \"test_item\".\"ctime\", \"test_item\".\"utime\", \"test_item\".\"item_type\", \"test_item\".\"meta_type\", \"test_item\".\"source_item_id\" FROM \"test_item\" INNER JOIN \"test_item_parents\" ON (\"test_item\".\"id\" = \"test_item_parents\".\"from_item_id\") WHERE (\"test_item_parents\".\"to_item_id\" = 1 AND \"test_item\".\"source_item_id\" LIKE t-1% ESCAPE '\\' ); args=(1, u't-1%')\n [DEBUG: django.db.backends: execute] (0.000) SELECT \"test_track\".\"ctime\", \"test_track\".\"utime\", \"test_track\".\"item_id\", \"test_track\".\"release_date\", \"test_track\".\"isrc\", \"test_track\".\"length\", \"test_track\".\"trial_start_position\", \"test_track\".\"trial_duration\" FROM \"test_track\" WHERE \"test_track\".\"item_id\" = 2 ; args=(2,)\n [DEBUG: django.db.backends: execute] (0.000) SELECT \"test_item\".\"id\", \"test_item\".\"ctime\", \"test_item\".\"utime\", \"test_item\".\"item_type\", \"test_item\".\"meta_type\", \"test_item\".\"source_item_id\" FROM \"test_item\" WHERE \"test_item\".\"id\" = 2 ; args=(2,)\n [DEBUG: django.db.backends: execute] (0.000) SELECT \"test_tracklocalization\".\"id\", \"test_tracklocalization\".\"ctime\", \"test_tracklocalization\".\"utime\", \"test_tracklocalization\".\"language_code\", \"test_tracklocalization\".\"title\", \"test_tracklocalization\".\"description\", \"test_tracklocalization\".\"artist\", \"test_tracklocalization\".\"label\", \"test_tracklocalization\".\"track_id\" FROM \"test_tracklocalization\" WHERE (\"test_tracklocalization\".\"track_id\" = 2 AND \"test_tracklocalization\".\"language_code\" = en ); args=(2, 'en')\n >>> t_en.title\n u'A Pop Song 1'\n >>> t_en.title = 'A Pop Song 1 revised title'\n >>> t_en.save()\n [DEBUG: django.db.backends: execute] (0.000) SELECT (1) AS \"a\" FROM \"test_tracklocalization\" WHERE \"test_tracklocalization\".\"id\" = 1 LIMIT 1; args=(1,)\n [DEBUG: django.db.backends: execute] (0.000) UPDATE \"test_tracklocalization\" SET \"ctime\" = 2013-06-14 02:04:20, \"utime\" = 2013-07-27 00:47:35.058121, \"language_code\" = en, \"title\" = A Pop Song 1 revised title, \"description\" = Description for the Pop Song 1., \"artist\" = Test, \"label\" = Label Test, \"track_id\" = 2 WHERE \"test_tracklocalization\".\"id\" = 1 ; args=(u'2013-06-14 02:04:20', u'2013-07-27 00:47:35.058121', u'en', 'A Pop Song 1 revised title', u'Description for the Pop Song 1.', u'Test', u'Label Test', 2, 1)\n >>> t_en.title\n 'A Pop Song 1 revised title'\n\nOK then reset database and let's do the same things with *API_URL* settings, you can find that the proxy calls remote `tastypie`_ API this time:\n\n::\n\n TASTYPIE_RPC_PROXY = {\n 'API_NAMESPACE': 'meta',\n 'API_URL': 'http://127.0.0.1:8000/api',\n (...)\n }\n\n::\n\n >>> from example.proxies import *\n (...)\n >>> a = Album.objects.get(item__source_item_id__startswith='a-1')\n [DEBUG: requests.packages.urllib3.connectionpool: _make_request] \"GET /api/v1/meta/album/?item__source_item_id__startswith=a-1 HTTP/1.1\" 200 None\n [DEBUG: rpc_proxy.proxies: to_python] to_python (release_date ): '2013-07-26' -> datetime.date(2013, 7, 26)\n >>> a.localize('en').title\n [INFO: requests.packages.urllib3.connectionpool: _new_conn] Starting new HTTP connection (1): 127.0.0.1\n [DEBUG: requests.packages.urllib3.connectionpool: _make_request] \"GET /api/v1/meta/albumlocalization/?album=1 HTTP/1.1\" 200 None\n [DEBUG: requests.packages.urllib3.connectionpool: _make_request] \"GET /api/v1/meta/albumlocalization/?id__in=1&id__in=2&language_code=en HTTP/1.1\" 200 None\n 'A Pop Song Collection'\n >>> t_en = a.item.children.get(source_item_id__startswith='t-1').metadata.localize('en')\n [DEBUG: rpc_proxy.proxies: __getattr__] item: /api/v1/core/item/1/, need namespace schema (http://127.0.0.1:8000/api/v1/core/)\n (...)\n [DEBUG: rpc_proxy.proxies: _response] getting cache... (/api/v1/core/item/1/)\n [INFO: requests.packages.urllib3.connectionpool: _new_conn] Starting new HTTP connection (1): 127.0.0.1\n [DEBUG: requests.packages.urllib3.connectionpool: _make_request] \"GET /api/v1/core/item/1/ HTTP/1.1\" 200 None\n [DEBUG: rpc_proxy.proxies: _response] setting cache... (/api/v1/core/item/1/ -> {\"ctime\": \"2013-06-13T19:42:56\", \"source_item_id\": \"a-1@some.service\", \"children\": [\"/api/v1/core/item/2/\", \"/api/v1/core/item/3/\", \"/api/v1/core/item/5/\"], \"item_type\": 0, \"meta_type\": 1, \"parents\": [], \"utime\": \"2013-06-13T20:02:38\", \"id\": 1, \"resource_uri\": \"/api/v1/core/item/1/\"})\n [DEBUG: rpc_proxy.proxies: __getattr__] children: ['/api/v1/core/item/2/', '/api/v1/core/item/3/', '/api/v1/core/item/5/'], need namespace schema (http://127.0.0.1:8000/api/v1/core/)\n (...)\n [INFO: requests.packages.urllib3.connectionpool: _new_conn] Starting new HTTP connection (1): 127.0.0.1\n [DEBUG: requests.packages.urllib3.connectionpool: _make_request] \"GET /api/v1/core/item/?id__in=2&id__in=3&id__in=5 HTTP/1.1\" 200 None\n [DEBUG: requests.packages.urllib3.connectionpool: _make_request] \"GET /api/v1/core/item/?source_item_id__startswith=t-1&id__in=2&id__in=3&id__in=5 HTTP/1.1\" 200 None\n [INFO: requests.packages.urllib3.connectionpool: _new_conn] Starting new HTTP connection (1): 127.0.0.1\n [DEBUG: requests.packages.urllib3.connectionpool: _make_request] \"GET /api/v1/meta/track/?item=2 HTTP/1.1\" 200 None\n [DEBUG: rpc_proxy.proxies: to_python] to_python (release_date ): '2013-06-14' -> datetime.date(2013, 6, 14)\n [INFO: requests.packages.urllib3.connectionpool: _new_conn] Starting new HTTP connection (1): 127.0.0.1\n [DEBUG: requests.packages.urllib3.connectionpool: _make_request] \"GET /api/v1/meta/tracklocalization/?track=2 HTTP/1.1\" 200 None\n [DEBUG: requests.packages.urllib3.connectionpool: _make_request] \"GET /api/v1/meta/tracklocalization/?id__in=1&id__in=2&language_code=en HTTP/1.1\" 200 None\n >>> t_en.title\n 'A Pop Song 1'\n >>> t_en.title = 'A Pop Song 1 revised title'\n >>> t_en.save()\n [DEBUG: requests.packages.urllib3.connectionpool: _make_request] \"PUT /api/v1/meta/tracklocalization/1/ HTTP/1.1\" 204 0\n >>> t_en.title\n 'A Pop Song 1 revised title'\n\nThat's it! Hope this enpowers you to write clean code and reduce time to code boring redundant stuff!\n\nTesting proxy code\n==================\n\nUnit tests for proxy classes can be ran in both local `django`_ model and remote `tastypie`_ API context. Those tests should inherit ``rpc_client.test.Proxy`` class. If you are to run the unit tests for both contexts separated settings need to be prepared - API context with *API_URL*, local model context with **NO** *API_URL* settings. Please take a look at how the unit tests for ``example`` application works - see ``runtests.py`` and ``tox.ini``.\n\nAs a simple tastypie client\n===========================\n\nYou can also utilize **rpc_proxy** with no proxy definition - just call remote tastypie API with queryset interface. In this case **rpc_proxy** doesn't need to be imported within django application context. Only standard CRUD / REST operations `tastypie`_ implements by default are supported. See `tastypie-queryset-client`_ for detailed usages.\n\n::\n\n >>> from datetime import datetime\n >>> from rpc_proxy.proxies import *\n >>>\n >>> api = ProxyClient('http://127.0.0.1:8000/api/',\n ... version='v1',\n ... namespace='meta',\n ... auth=('test', 'test',))\n >>> api.proxies\n {'album': queryset_client.client.Model,\n 'albumlocalization': queryset_client.client.Model,\n 'track': queryset_client.client.Model,\n 'tracklocalization': queryset_client.client.Model}\n >>>\n >>> Track = api.track\n >>> track = Track.objects.filter(item__source_item_id__startswith='t-1')[0]\n >>> album = track.item.parents.all()[0].album\n >>> album.release_date = datetime.now().date()\n >>> album.save()\n >>> album.item.children.all()[0].parents.all()[0].album.release_date == datetime.now().date()\n True\n >>> str(album.item.children.all()[0].track) == str(track)\n True\n\n.. note:: You have to uncomment following fields on the Item resource in ``example.resources.py`` and to clear cache to work above expectedly though.\n\n::\n\n (...)\n # album = fields.OneToOneField('example.resources.Album', 'album', null=True)\n # track = fields.OneToOneField('example.resources.Track', 'track', null=True)\n\nNamespace and Resource Endpoint\n===============================\n\nThe final URL of an API resource endpoint consists of:\n\n::\n\n '%s/%s/%s/%s/' % (API_URL, API_VERSION, API_NAMESPACE, resource_name,)\n\nProxy Meta class options\n========================\n\nabstract\n--------\n\n*Boolean*, optional, indicates if the Meta class is abstract class.\n\napi_url\n-------\n\n*String*, optional, base url prefix of the API endpoint, if not given **rpc_proxy** tries to load corresponding django model in local.\n\nauth\n----\n\n*Tuple* or *List*, optional, a combination of username and password to access the API e.g. ``(username, password,)``. SUPERUSER_USERNAME and SUPERUSER_PASSWORD settings variables will be applied by default.\n\nclient\n------\n\n*ProxyClient* class, optional, intended for extending ProxyClient class, *ProxyClient* class by default.\n\nmodel\n-----\n\n`django`_ *Model* class, optional, a model that proxy loads when *API_URL* is not provided in the settings, if this option is not given, the proxy class looks for corresponding model class which has the same name as the proxy class on ``models.py`` module in the same module as ``proxies.py`` belongs to, by default.\n\nnamespace\n---------\n\n*String*, optional, defines namespace of the resource follows to version, *API_NAMESPACE* will be applied if it's not provided e.g. ``core``.\n\nresource_name\n-------------\n\n*String*, optional, defines resource name of the proxy, the name of the proxy class will be applied if not provided e.g. ``'track'``.\n\nversion\n-------\n\n*String*, optional, defines version of the resource follows to *api_url*, ``'v1'`` will be used if *API_VERSION* is not provided.\n\nSettings\n========\n\n**rpc_proxy** accepts following settings variables defined as **TASTYPIE_RPC_PROXY** dictionary in `django`_ settings. The settings look like:\n\n::\n\n TASTYPIE_RPC_PROXY = {\n 'API_URL': 'http://127.0.0.1:8000/api',\n 'SUPERUSER_USERNAME': 'test',\n 'SUPERUSER_PASSWORD': 'test',\n (...)\n }\n\n\nAPI_NAMESPACE\n-------------\n\n*String*, optional, specifies default remote API namespace follows to the version section e.g. ``'core/content'``.\n\nAPI_URL\n-------\n\nString, optional, defines default base prefix URL of remote tastypie API, **rpc_proxy** loads local models as proxy class if this is not specified e.g. ``'https://example.com/django/app/api'``.\n\n.. note:: This value could technically be updated dynamically but it does not take any effect until the application is reloaded. \n\nAPI_VERSION\n-----------\n\nString, optional, defines default versioning of remote API follows to *API_URL* e.g. ``'v1'``.\n\nNON_DEFAULT_ID_FOREIGNKEYS\n--------------------------\n\nTuple or List, optional, defines custom primary key field names appear in remote resouces e.g. ``('user',)``.\n\nSUPERUSER_USERNAME\n------------------\n\nString, optional, defines default username of superuser for API authentication, useful to allow internal system user to operate over all remote resources e.g. ``'test'``.\n\nSUPERUSER_PASSWORD\n------------------\n\nString, optional, defines default password of superuser for API authentication, useful to allow internal system user to operate over all remote resources e.g. ``'test'``.\n\nGitHub\n======\n\nhttps://github.com/nk113/tastypie-rpc-proxy\n\n\n.. _tastypie-queryset-client: https://github.com/ikeikeikeike/tastypie-queryset-client\n.. _tastypie: https://github.com/toastdriven/django-tastypie\n.. _django: https://www.djangoproject.com", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/nk113/tastypie-rpc-proxy/", "keywords": null, "license": "UNKNOWN", "maintainer": null, "maintainer_email": null, "name": "tastypie-rpc-proxy", "package_url": "https://pypi.org/project/tastypie-rpc-proxy/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/tastypie-rpc-proxy/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/nk113/tastypie-rpc-proxy/" }, "release_url": "https://pypi.org/project/tastypie-rpc-proxy/0.3.6/", "requires_dist": null, "requires_python": null, "summary": "An extension of tastypie-queryset-client, designed intended for building RPC based on tastypie.", "version": "0.3.6" }, "last_serial": 875855, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "c7a4dc16a4b1f574dccdbb7e7ec02268", "sha256": "2c4434802aca99083c4a64f3e30344ed9c59e06268837c7939e8503e3dfc9143" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.1.0.tar.gz", "has_sig": false, "md5_digest": "c7a4dc16a4b1f574dccdbb7e7ec02268", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26686, "upload_time": "2013-07-28T09:09:43", "url": "https://files.pythonhosted.org/packages/e9/fd/2a4380e9f05adab45ad910549c9f1f0d8c5b16d1b0cb1e9ed359700496d8/tastypie-rpc-proxy-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "308462f5777466b03849f412102a9641", "sha256": "c352923315d6497d419e6635bff6a6cd99690d767c8eefa3a53dc0d4eaa36f9f" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.1.1.tar.gz", "has_sig": false, "md5_digest": "308462f5777466b03849f412102a9641", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26677, "upload_time": "2013-07-28T15:30:36", "url": "https://files.pythonhosted.org/packages/01/30/ba2c9dff18a6c86c20da4e9c738d27f5778126c9afc343d5ddbd56af88e7/tastypie-rpc-proxy-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "f4375f50cc707adca54f9e93c1feb20a", "sha256": "4dbd2c2c54f74acf54ff2344163bf63e4f5f4e7dbfc951c45fe5766688532797" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.1.2.tar.gz", "has_sig": false, "md5_digest": "f4375f50cc707adca54f9e93c1feb20a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27041, "upload_time": "2013-07-29T13:38:20", "url": "https://files.pythonhosted.org/packages/86/4b/8ddd3c5095acf1b65bcded5842d230c9e77c1b701f1defc76556ac24cf29/tastypie-rpc-proxy-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "185d5834ed1381bddaaf33c62c676570", "sha256": "51de937190fbef1f3a077dabce9e881342ca6f940d1e54a5e13a6865bfe11591" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.1.3.tar.gz", "has_sig": false, "md5_digest": "185d5834ed1381bddaaf33c62c676570", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27167, "upload_time": "2013-07-29T14:00:48", "url": "https://files.pythonhosted.org/packages/4b/11/8c116516d16522b05f67218c7896722b85583674e1e1dcedd3b0c994cd90/tastypie-rpc-proxy-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "027b8a4ab1bbb1d4df9853e38a7c9e3c", "sha256": "642ef728037fcc3e4a95a201c2a7d92731140d4e76916c28f8b945d62aa283f8" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.1.4.tar.gz", "has_sig": false, "md5_digest": "027b8a4ab1bbb1d4df9853e38a7c9e3c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28173, "upload_time": "2013-07-29T23:16:19", "url": "https://files.pythonhosted.org/packages/d1/a0/03dcc9299d9bb66c42b39a38de9fac5bce15cade1da49a0455beded147be/tastypie-rpc-proxy-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "492907979861607c014acd2883262cf7", "sha256": "81b5492c500f01e08bcdb849b3c23076746e4f0680d61535a390df6edcaae735" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.1.5.tar.gz", "has_sig": false, "md5_digest": "492907979861607c014acd2883262cf7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28256, "upload_time": "2013-07-30T03:09:59", "url": "https://files.pythonhosted.org/packages/23/a7/84481dc3309217aa50c7f010e2c6f0e71b9043e5f03ecd92350ccac93d82/tastypie-rpc-proxy-0.1.5.tar.gz" } ], "0.1.6": [ { "comment_text": "", "digests": { "md5": "f91442f668af90780e16465dad7c625e", "sha256": "703074b7a9959a775032ccff373f1155c5e3e1a4170aeced0605699c1afbacbe" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.1.6.tar.gz", "has_sig": false, "md5_digest": "f91442f668af90780e16465dad7c625e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28377, "upload_time": "2013-07-30T17:02:56", "url": "https://files.pythonhosted.org/packages/8b/4d/dd68b03174fc3cde511c6b74333bb34a7d8a0086417b768885ac56d1de7f/tastypie-rpc-proxy-0.1.6.tar.gz" } ], "0.1.8": [ { "comment_text": "", "digests": { "md5": "c4c095d8d013a828afaa58dc4a571c14", "sha256": "51a71d25b4e36130a80426e872705e51ecac7ab5720828b607d7d146c6294534" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.1.8.tar.gz", "has_sig": false, "md5_digest": "c4c095d8d013a828afaa58dc4a571c14", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17414, "upload_time": "2013-08-01T16:22:43", "url": "https://files.pythonhosted.org/packages/e0/ad/25ed47c92b3c81c62d06b448bd2d837c0665a233f0fff0126d58e8454cb5/tastypie-rpc-proxy-0.1.8.tar.gz" } ], "0.1.9": [ { "comment_text": "", "digests": { "md5": "3afb4565cefd7150767f28231e80d8ea", "sha256": "e61e1cce87a04b1c149304e31852cc2188423b1784beabe593c396bf4273ef83" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.1.9.tar.gz", "has_sig": false, "md5_digest": "3afb4565cefd7150767f28231e80d8ea", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17422, "upload_time": "2013-08-01T16:27:10", "url": "https://files.pythonhosted.org/packages/6a/2b/b483273ef0443787bd46e30977cd41f667d6d0306ecaf7aa7c7733169145/tastypie-rpc-proxy-0.1.9.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "398223722e466cabbe9e465e309420d5", "sha256": "b28704fb4536ede76b8ee4a55f3f53e4673cc34f9d07d4f622f0b4593eaf1109" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.2.0.tar.gz", "has_sig": false, "md5_digest": "398223722e466cabbe9e465e309420d5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17429, "upload_time": "2013-08-01T16:36:32", "url": "https://files.pythonhosted.org/packages/85/be/87e97efbaa54776ae3aa68f626bec66036ff51ad1a3b673aff74e2008883/tastypie-rpc-proxy-0.2.0.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "38834de3aec97013f22d80d3c7a21841", "sha256": "6cbde9056045698f3070b5c98c11e66be4e58aa4f94ee71152a3238e86a15c59" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.2.1.tar.gz", "has_sig": false, "md5_digest": "38834de3aec97013f22d80d3c7a21841", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17464, "upload_time": "2013-08-01T18:31:39", "url": "https://files.pythonhosted.org/packages/6b/8a/50aced2c8937d1090a4a0c8cbdfa66616992f34f1595966723bfc18d7e4c/tastypie-rpc-proxy-0.2.1.tar.gz" } ], "0.2.2": [ { "comment_text": "", "digests": { "md5": "2e1344f403c88b3d01c5b59d68247c7b", "sha256": "ff2dafda6ce50dd5d31eb5cd914011ef256fdae5dd1b89fda7130b1aa5827986" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.2.2.tar.gz", "has_sig": false, "md5_digest": "2e1344f403c88b3d01c5b59d68247c7b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17425, "upload_time": "2013-08-01T18:47:47", "url": "https://files.pythonhosted.org/packages/c8/94/1dc98a2b99cda08dc47395411a35138ee519d2a5bb942206e1c6a3b595b2/tastypie-rpc-proxy-0.2.2.tar.gz" } ], "0.2.3": [ { "comment_text": "", "digests": { "md5": "91c847095b2daa15fc048d51de2bc6b6", "sha256": "c2b130fdee02f18022aac13d8389d1081d62eb57bb07b4ae004aedc383cd0ffe" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.2.3.tar.gz", "has_sig": false, "md5_digest": "91c847095b2daa15fc048d51de2bc6b6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17413, "upload_time": "2013-08-02T04:19:44", "url": "https://files.pythonhosted.org/packages/96/57/8139ca74cba5c2ed63be24b7860945a52706b7ede9c011d226a5f0d2251b/tastypie-rpc-proxy-0.2.3.tar.gz" } ], "0.2.4": [ { "comment_text": "", "digests": { "md5": "949e83e53a80bb812f92d8cf949c770c", "sha256": "c8e546a9811736e5ae01884c01202b8f78e206287b10fe9cc224e5e7d8bcb2fa" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.2.4.tar.gz", "has_sig": false, "md5_digest": "949e83e53a80bb812f92d8cf949c770c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17415, "upload_time": "2013-08-02T13:10:33", "url": "https://files.pythonhosted.org/packages/50/fb/78ef68509f566a1b491da99267179731402f5ab0bdcd513094c54f2c32f6/tastypie-rpc-proxy-0.2.4.tar.gz" } ], "0.2.5": [ { "comment_text": "", "digests": { "md5": "2638af64848d65498e1889c86f407ed3", "sha256": "1e93b3e1358855374043b1b30c0e53948946bb5b07ac5ef3480565465971ed3f" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.2.5.tar.gz", "has_sig": false, "md5_digest": "2638af64848d65498e1889c86f407ed3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17405, "upload_time": "2013-08-02T13:40:17", "url": "https://files.pythonhosted.org/packages/e2/a2/bd436bf33630e662b171179080aae449f0de0b03dff26b363f41c9cd4507/tastypie-rpc-proxy-0.2.5.tar.gz" } ], "0.2.6": [ { "comment_text": "", "digests": { "md5": "61d221a3004e6174a5bcd677acc4bffa", "sha256": "b405ead5d911a2bfdea8802b48e5087d20df26e7f4378a99fcfb24a37a6d1616" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.2.6.tar.gz", "has_sig": false, "md5_digest": "61d221a3004e6174a5bcd677acc4bffa", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17677, "upload_time": "2013-08-03T03:25:02", "url": "https://files.pythonhosted.org/packages/52/8f/b16cf17c0f2f2f102fb595914e13305e0e15f4bf195ef9d01bfc7aa0562e/tastypie-rpc-proxy-0.2.6.tar.gz" } ], "0.2.7": [ { "comment_text": "", "digests": { "md5": "e5470807f5d275732b6ba5408112f025", "sha256": "de2ba43c54b9fbc8851e3c2ba78835b367eea8c11f1520a11dd8186656d8a869" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.2.7.tar.gz", "has_sig": false, "md5_digest": "e5470807f5d275732b6ba5408112f025", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17810, "upload_time": "2013-08-04T02:59:36", "url": "https://files.pythonhosted.org/packages/5d/ac/82908abfadb56e0bc55f3f53f377420f061573d18accf19388aa24fa8b2b/tastypie-rpc-proxy-0.2.7.tar.gz" } ], "0.2.8": [ { "comment_text": "", "digests": { "md5": "f8e49037368bc3e0315450311b7194f3", "sha256": "99f29e75847f505da6b9c00c65a71bca468293bdb7fc0fa025aa7e7dcb209789" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.2.8.tar.gz", "has_sig": false, "md5_digest": "f8e49037368bc3e0315450311b7194f3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17814, "upload_time": "2013-08-04T03:10:44", "url": "https://files.pythonhosted.org/packages/a7/37/bc44c5c5d94dc52e4e069a258ec6b7c9a0ed3fbe927367222c7545559395/tastypie-rpc-proxy-0.2.8.tar.gz" } ], "0.2.9": [ { "comment_text": "", "digests": { "md5": "545808f1d87c235cffed867026ad49ab", "sha256": "a3e9335e729335c2b97dfaaa2baef96acd1207d8362625d40b09f96497552c65" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.2.9.tar.gz", "has_sig": false, "md5_digest": "545808f1d87c235cffed867026ad49ab", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17815, "upload_time": "2013-08-04T12:25:53", "url": "https://files.pythonhosted.org/packages/f2/e9/924f9418a9f2ac1d426f836db4bdb9f5f0b0faab4636a3ebd80f429dea6d/tastypie-rpc-proxy-0.2.9.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "271bf1e9d86987cb4ad90f1937a0b1aa", "sha256": "dddb29d5d5e0cce99aa3de2050a7925cfbb792cb3fe480ace61afd085bad7cd7" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.3.0.tar.gz", "has_sig": false, "md5_digest": "271bf1e9d86987cb4ad90f1937a0b1aa", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18069, "upload_time": "2013-08-04T15:04:39", "url": "https://files.pythonhosted.org/packages/92/b7/01fd3efdb3bf8d633ff91d7ba8b8411da25c86b3106788bca6e5e46de22a/tastypie-rpc-proxy-0.3.0.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "411733756568114bdabb4f7c2006d9f4", "sha256": "e3c8610cb43ae2e96c6e35ad625edc33255f6378553883eba76e5ca30e3767f1" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.3.1.tar.gz", "has_sig": false, "md5_digest": "411733756568114bdabb4f7c2006d9f4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18068, "upload_time": "2013-08-04T15:11:03", "url": "https://files.pythonhosted.org/packages/cc/48/079ab087c59846c55dbc938acc3eb76735f12a0952d859168d6c5b794722/tastypie-rpc-proxy-0.3.1.tar.gz" } ], "0.3.2": [ { "comment_text": "", "digests": { "md5": "09d548df767bafa4e1fce588af8c17ed", "sha256": "ccb0498af62ab4f1cc9fca6c200ec933c4efe53d60689645273b04ad21bb8670" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.3.2.tar.gz", "has_sig": false, "md5_digest": "09d548df767bafa4e1fce588af8c17ed", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18114, "upload_time": "2013-09-15T01:37:00", "url": "https://files.pythonhosted.org/packages/13/ae/061b7428ba0e71317e588491db911764adbc011dee5a498774542167965c/tastypie-rpc-proxy-0.3.2.tar.gz" } ], "0.3.3": [ { "comment_text": "", "digests": { "md5": "fe6a830ade397caa333ee7d3d2621e1f", "sha256": "e5b2aa62890b2eedacb36a67fe09c102d59e21a947e1c683e96e15f219ae7e21" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.3.3.tar.gz", "has_sig": false, "md5_digest": "fe6a830ade397caa333ee7d3d2621e1f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17830, "upload_time": "2013-09-18T10:37:52", "url": "https://files.pythonhosted.org/packages/df/1a/219147298de76657911b469d9946cbbcf41f9507e21865881af8b77a2679/tastypie-rpc-proxy-0.3.3.tar.gz" } ], "0.3.4": [ { "comment_text": "", "digests": { "md5": "253e3122ef320923a10aa2e02d1aa611", "sha256": "0354523d063fa4b37904f57d067e6049e8b04ac5f0292bd5980edb6feef7bb48" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.3.4.tar.gz", "has_sig": false, "md5_digest": "253e3122ef320923a10aa2e02d1aa611", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17832, "upload_time": "2013-09-18T10:55:14", "url": "https://files.pythonhosted.org/packages/b9/88/64747c0f9b21db986970d7d7ff54c2c7af355a408cda084cc934394f5631/tastypie-rpc-proxy-0.3.4.tar.gz" } ], "0.3.5": [ { "comment_text": "", "digests": { "md5": "3da067209965d5dfe59eab2496dfa243", "sha256": "c3827ba6fe32d98a7babb2a7a31a1695c2f4bf77c340c666dbee48f34cb06366" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.3.5.tar.gz", "has_sig": false, "md5_digest": "3da067209965d5dfe59eab2496dfa243", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18937, "upload_time": "2013-09-27T08:36:32", "url": "https://files.pythonhosted.org/packages/0a/57/c715331b1f594b74a22b365940b154158470f57d6a0cdffb68eed5af7afb/tastypie-rpc-proxy-0.3.5.tar.gz" } ], "0.3.6": [ { "comment_text": "", "digests": { "md5": "3b8168e8564fbd06e32c9e24490279ed", "sha256": "c2184de5d5c2528e1c99036661c991df59c7c685b8b4b693263738291eccd9ea" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.3.6.tar.gz", "has_sig": false, "md5_digest": "3b8168e8564fbd06e32c9e24490279ed", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18936, "upload_time": "2013-09-28T06:55:04", "url": "https://files.pythonhosted.org/packages/12/2c/5a8e992d0ef6a5caeabfd8d9dfa2f3953520c98f1472f9869425382b8044/tastypie-rpc-proxy-0.3.6.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "3b8168e8564fbd06e32c9e24490279ed", "sha256": "c2184de5d5c2528e1c99036661c991df59c7c685b8b4b693263738291eccd9ea" }, "downloads": -1, "filename": "tastypie-rpc-proxy-0.3.6.tar.gz", "has_sig": false, "md5_digest": "3b8168e8564fbd06e32c9e24490279ed", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18936, "upload_time": "2013-09-28T06:55:04", "url": "https://files.pythonhosted.org/packages/12/2c/5a8e992d0ef6a5caeabfd8d9dfa2f3953520c98f1472f9869425382b8044/tastypie-rpc-proxy-0.3.6.tar.gz" } ] }