{ "info": { "author": "Loren Davie", "author_email": "code@axilent.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "Sharrock\n========\n\nSharrock is a Python-based RPC framework design for easy integration into Django. It was created because of my frustrations with the way that many existing REST-based RPC frameworks work. Sharrock is based on the idea that while sometimes it is a good idea to represent RPC as resources (the REST model), other times plain old function calls are what you want.\n\nThe central idea of Sharrock is the *descriptor*, a declarative model that both represents the function call at the code level, and additionally provides automatically generated API documentation.\n\nFollowing the tradition of naming Django projects after Jazz musicians, Sharrock is named after [Sonny Sharrock](http://en.wikipedia.org/wiki/Sonny_Sharrock \"Sonny Sharrock Wikipedia page\").\n\nCurrent release is version 0.5.\n\n\nBasic Parts\n-----------\n*\tA *function descriptor* syntax that provides information in both a machine and human readable format about the available functions a service provides, including details of acceptable parameters and return values. The function descriptor also provides the basis for *automated API documentation*.\n*\tA *transport layer* that handles function calls and their return values. Initially Sharrock uses HTTP as a transport layer, but later on I'd like to add a ProtocolBuffer transport.\n*\t*Serialization* of objects in both JSON and XML. In addition serialization of function descriptors as human-readable HTML.\n*\tA *handler* framework for Django, providing hooks to integrate Sharrock into a django app.\n*\tA Python *RPC Client* for Sharrock, making it easy to build client code against a Sharrock service by using the function descriptors.\n* An optional *REST* layer that allows functions to be rolled up into resources, and a ResourceClient in Python that allows for RESTful interaction.\n* An even more optional ResourceModel layer that binds the Resource functionality to a Django model. See \"Model Resources\" below for more info.\n\nRequirements\n------------\n\nSharrock requires the following libraries:\n\n* *[Django](http://www.djangoproject.com)* 1.2 or above\n* *[requests](http://docs.python-requests.org/en/latest/)* For the client libs.\n* *[Markdown](http://www.freewisdom.org/projects/python-markdown/)* for docstring parsing.\n\nInstallation\n------------\n\n* Use pip to install Sharrock:\n\n pip install -e git://github.com/Saaspire/sharrock.git#egg=Sharrock\n\n* Add \"sharrock\" to your INSTALLED_APPS.\n* In each of your apps that you with to use Sharrock, create a *descriptors.py* module.\n* In your root urls, add the following line to your urlpatterns:\n\n (r'^api/',include('sharrock.urls')), # The initial context \"api\" can be whatever you want.\n\n* Optional: if using the resource layer, mount the resource urls.\n\n (r'^resources/',include('sharrock.resource_urls')),\n\n\nDescriptors\n===========\n\nRemote procedures are created by defining *descriptors*. A descriptor is a declarative model of a remote procedure call (in the way that a Django model is a declarative model of a database table).\n\n from sharrock.descriptors import Descriptor, UnicodeParam\n\n class HelloWorld(Descriptor):\n \"\"\"\n Hello world!\n ============\n \"\"\"\n name = UnicodeParam('name',default=None,description='The name to address.')\n\n def execute(self,request,data,params):\n name = params['name']\n if name:\n return 'Hello %s!' % name\n else:\n return 'Hello world!'\n\nA simple function descriptor consists of a subclass of Descriptor. At minimum it must contain a docstring for the class, and an \"execute\" method. The execute method is called when the function is called remotely.\n\nDescriptor.execute\n------------------\n\nThe execute method should contain the business logic of the remote procedure. It will be passed 3 significant arguments:\n\n* *request*: The Django request object.\n* *data*: A deserialized data object (usually desesrialized from json). If there is a data object, there will be no params.\n* *params*: A dictionary of key/value params. If there are params there will be no data object.\n\nAny value the execute method returns should be something that can be serialized back into a response for the client.\n\nParameters\n----------\n\nAll parameters can be imported from *sharrock.descriptors*. There are several types of parameters available, each parameter type will attempt to cast incoming values to whatever is its preferred data type. Incoming values that cannot be cast to the data type will raise an exception. Parameter types include:\n\n* UnicodeParam\n* IntegerParam\n* FloatParam\n*\tBooleanParam\n* ListParam\n* DictParam\n*\tWildcardParam (any data is good)\n\nParameters must be instantiated with the first argument being the name of the parameter, and then with the following optional keyword arguments:\n\n* *required*: If True, this parameter is required. False by default. If a call is made on the function and a required parameter is missing, a ParamRequired exception will be raised.\n* *default*: The default value for the parameter, if it is not specified. Only makes sense for non-required parameters.\n* *description*: The description of the parameter, to be used in the automatically generated documentation.\n\nData Parsing\n------------\n\nFor descriptors meant to post serialized data (JSON, XML etc) instead of keyword arguments, set the `data_parsing` flag to `True` for the descriptor. This will alert Sharrock to apply the parameters to the deserialized data, and not keyward arguments. Obviously if you have required parameters for a descriptor set to data parsing and you post query parameters to it, it will fail with a ParamRequired exception.\n\nDescriptor Docstrings\n---------------------\n\nThe documentation system will automatically create documentation based on the descriptor docstring. It will read documentation in Markdown format and format it appropriately from that.\n\nDeprecating Descriptors\n-----------------------\n\nYou can deprecate descriptors by settings a deprecation message at the individual descriptor, at the resource or at the module level. Setting the deprecation message looks like this:\n\n\tdeprecated = 'You should stop using this function.'\n\t\nThe descriptor will be shown as deprecated in the API docs. Additionally, when it is called, the server will append a **Warning** response header to the response with a message indicating that the function is deprecated.\n\nDeprecation is inherited, so if a module is marked as depreated then all resources and descriptors within that module will be deprecated. Likewise if a resource is marked deprecated then all of its member descriptors will be deprecated.\n\nAPI Versions\n============\n\nThe version of your API can simply be defined by setting the following variable in your descriptors.py file:\n\nversion = \"1.0\"\n\nIf you do not define the version for your API, Sharrock will automatically define it as \"0.1dev\".\n\nMaintaining Multiple Versions of an API\n---------------------------------------\n\nSometimes it makes sense to maintain multiple versions of the same app's API. In this case, make descriptors a package (a folder with an __init__.py file). Within the package, create individual modules (files) for each version of the API you want to maintain. In each version module, make sure you define the *\"version\"* variable.\n\nIn the package's __init__.py file, make sure you include each version module in the __all__ variable.\n\nExecuting Functions\n===================\n\nFunctions may be executed with the following url pattern:\n\n (api mount point)/(app)/(version)/(function slug)\n\nSo for example, if you had an app called \"MyApp\", the version \"1.0\" and the function \"MyFunction\", and the mountpoint for Sharrock was \"/api/\" then the call would be:\n\n /api/myapp/1.0/myfunction/\n\nFunctions don't inheirantly expect any particular http method, although if they are expecting a data upload they'll only be able to get that through POST and PUT methods.\n\nAPI Documentation\n=================\n\nAPI documentation can be found at the \"/dir/\" context. For example:\n\n /api/dir/\n\nSpecific app and version documentation can be found by appending the app and version to the context:\n\n /api/dir/myapp/1.0/\n\nSpecific descriptors can be retrieved through the 'describe' context, in various formats (with HTML as default). For example:\n\n /api/describe/myapp/1.0/myfunction/\n\nor\n\n /api/describe/myapp/1.0/myfunction.json\n /api/describe/myapp/1.0/myfunction.xml\n\nThe API docs will show the full path to the function or resource call. You can set the root of the URL with the `SHARROCK_API_ROOT` and `SHARROCK_RESOURCE_ROOT` settings, respectively. This should match up to your domain URL and the mount point you used in your views. So for example:\n\n\tSHARROCK_API_ROOT = 'https://www.example.com/api'\n\tSHARROCK_RESOURCE_ROOT = 'https://www.example.com/api/resource'\n\nIf no roots are set, the API docs will display ellipsis (\"...\") in place of the roots.\n\nHttpClient\n==========\n\n*sharrock.client.HttpClient* is a simple RPC client class designed to consume Sharrock function descriptors and execute remote Sharrock procedure calls. It is inspired by the Python XML-RPC client.\n\nThe HttpClient will locally cache descriptors and, by default, perform local param checking on function calls. It uses JSON serialization to communicate with the server.\n\nHttpClient.__init__\n-------------------\n\n* *service_url*: The full URL to the server, including the API mount context. For example \"http://example.com/api\".\n* *app*: The app to address, for example \"myapp\".\n* *version*: The version of the API to use, for example \"1.0\".\n*\t*auth_user=USERNAME*: Optional. Will pass the username to basic auth.\n*\t*auth_password=PASSWORD*: Optional. Will pass the password to basic auth.\n\nTo use the HttpClient, simply execute method calls on it, with the slugified name of the function as the method name. All methods take the optional keyword argument \"data\" for data objects to be serialized and uploaded, and treat other keyword arguments as params.\n\nFor example, taking the \"HelloWorld\" descriptor from above:\n\n from sharrock.client import HttpClient\n\n c = HttpClient('http://example.com/api','myapp','1.0')\n c.helloworld(name='Loren')\n\nA Note About Basic Auth and the HttpClient\n------------------------------------------\n\nThe HttpClient (and ResourceClient) will accept the keyword args `auth_user` and `auth_password` which they'll use in Basic Auth: concatenating them together, base64 encoding them and appending them to an `Authorization: Basic` header.\n\nWhen working with the Axilent platform, the API token is used as the `auth_user`, with no password being set.\n\nThe same client example as above, but using basic auth:\n\n\tfrom sharrock.client import HttpClient\n\t\n\tc = HttpClient('http://example.com/api','myapp','1.0',auth_user='Loren',auth_password='MYSEKRIT')\n\tc.helloworld(name='Fred')\n\nCreating RESTful Services\n=========================\n\nIn Sharrock, REST is implemented as an optional layer on top of the basic function layer. This is based on the concept that while sometimes functionality is appropriately modeled as resources, sometimes its better to represent it as plain old procedure calls.\n\nResources are also defined in your descriptors.py file. Resources simply reference Descriptor objects and assign them to appropriate HTTP methods.\n\n from sharrock.descriptors import Descriptor, Resource\n\n class GetHello(Descriptor):\n \"\"\"\n Gets a big hello.\n \"\"\"\n def execute(self,request,data,params):\n return 'Why hello!'\n \n class Greeting(Resource):\n \"\"\"\n A resource for a greeting.\n \"\"\"\n get = GetHello()\n\nIn the above example, the GetHello function has been assigned to the \"get\" method of the Greeting resource. Resources may assign Descriptors to \"get\", \"post\", \"put\" and \"delete\" attributes.\n\nHiding Descriptors\n------------------\n\nWhen using Descriptors as resource methods, often its desirable to prevent the descriptors from being individually accessible as functions in the API. This can be done by setting their \"visible\" attribute as False.\n\n class MyGetter(Descriptor):\n \"\"\"\n Gets stuff.\n \"\"\"\n visible = False\n\n def execute(self,request,data,params):\n pass\n \n class MyResource(Resource):\n get = MyGetter()\n\nNow the MyGetter function will be available via the MyResource resource, but not as an individual function.\n\nExecuting Resources\n-------------------\n\nResources are executed via the following URL pattern:\n\n (resource mount point)/(app)/(version)/(resource slug)\n\nfor example:\n\n /resources/myapp/1.0/myresource\n\nSharrock will route the request to the appropriate descriptor, based on the http method of the request. If the incoming request uses a method that has not been defined in the resource the Sharrock will return a 403 (Method Not Allowed) error code.\n\nResource Client\n---------------\nSharrock supplies *sharrock.client.ResourceClient*, an HTTP client for REST-style operations. An instance of a ResourceClient represents a single resource, with the various HTTP method operations available for it.\n\n* `ResourceClient.__init__(service_url,app,version,resource_slug,auth_user='',auth_password='')`: Instantiates the client towards a single resource.\n\n* `ResourceClient.get(data=None,params=None,local_params_check=True)`\n* `ResourceClient.post(data=None,params=None,local_params_check=True)`\n* `ResourceClient.put(data=None,params=None,local_params_check=True)`\n* `ResourceClient.delete(data=None,params=None,local_params_check=True)`\n\nThe HTTP methods all have the same signature: Either a JSON object may be posted as data, or key/value params (but not both) and a flag that indicates params should be checked on the client (setting it to False supresses this function). If the resource descriptor does not define a method, the corresponding attribute will be None instead of a method. All of the HTTP methods will return a deserialized response from the server.\n\nExactly like the HttpClient, the ResourceClient will append an `Authorization: Basic` header to requests if the `auth_user` or `auth_password` keyword args are set.\n\nModel Resources\n===============\nA common case is to use the REST layer to directly manipulate Django models. While many REST frameworks assume this is the center case, I have purposefully packaged it as an add-on to the core REST functionality, which is itself an add-on to the basic RPC functionality. One could accomplish the same thing with a Resource implementation, so just think of this as a shortcut.\n\nModel Resources are easy to define:\n\n from sharrock.modelresource import ModelResource\n from myapp.models import MyModel\n\n class MyModelResource(ModelResource):\n \"\"\"Resource for my model.\"\"\"\n model = MyModel\n\nThat's about it. Your model resources are defined in the same descriptors.py file where you would put any other descriptors or ressource definitions. Model resources are mounted under the resource URL mount-point, the same as other resources.\n\nModel Resource Client\n---------------------\nSharrock provides a special client for model resources, sharrock.client.ModelResourceClient, to provide convenience methods for model CRUD operations. Usage is very similar to the ResourceClient.\n\n* ModelResourceClient.__init__(service_url,app,version,resource_slug)\n\n* ModelResourceClient.list(): Lists all of the models\n* ModelResourceClient.get(model_pk): Retrieves the model with the specified key.\n* ModelResourceClient.create(**attrs): Creates a new model with the specified attributes.\n* ModelResourceClient.update(model_pk,**attrs): Updates an existing model.\n* ModelResourceClient.delete(model_pk): Deletes the specified model resource client.\n\nNote: Added Table of Contents capabilities.\n\nConverting ObjectDoesNotExist exceptions to HTTP 404 Responses\n==============================================================\n\nFor APIs in which a specific object is addressed by some lookup parameter, the entire operation should fail if the object can't be located. Sharrock provides a shorthand to convert ObjectDoesNotExist exceptions into a 404 response to be sent back to the API client, by means of the `not_found_as_404` decorator.\n\nTo use, simply decorate the descriptor's `execute` method:\n\n\tclass MyDescriptor:\n\t\t...\n\t\t@not_found_as_404\n\t\tdef execute(self,request,data,params):\n\t\t\t# any code that raises ObjectDoesNotExist will trigger a 404 response\n\n", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/Axilent/sharrock", "keywords": null, "license": "BSD", "maintainer": null, "maintainer_email": null, "name": "Sharrock", "package_url": "https://pypi.org/project/Sharrock/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/Sharrock/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/Axilent/sharrock" }, "release_url": "https://pypi.org/project/Sharrock/0.7.4.1/", "requires_dist": null, "requires_python": null, "summary": "Python remote procedure call framework with server and client components. RESTful when you need it to be.", "version": "0.7.4.1" }, "last_serial": 1710961, "releases": { "0.6": [ { "comment_text": "", "digests": { "md5": "04e45a0c4ad5cef5220431e80bfb25a6", "sha256": "b7fd0ce01f4ac3f13d22ce029b9c324f2219f5c8ee4452fba7d197fa145139fa" }, "downloads": -1, "filename": "Sharrock-0.6.tar.gz", "has_sig": false, "md5_digest": "04e45a0c4ad5cef5220431e80bfb25a6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12908, "upload_time": "2013-04-11T15:10:27", "url": "https://files.pythonhosted.org/packages/3b/3e/6f73d108604a3f8299cf3343d29e7739d67cac6e18be1de1f66e02161e01/Sharrock-0.6.tar.gz" } ], "0.6.1": [ { "comment_text": "", "digests": { "md5": "13131361d9408881003e01804ca04431", "sha256": "d4714e8ce0a9033d7e84c0aaf71b012e036ee768aca704fff84bcc29a9f8052c" }, "downloads": -1, "filename": "Sharrock-0.6.1.tar.gz", "has_sig": false, "md5_digest": "13131361d9408881003e01804ca04431", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12137, "upload_time": "2013-04-11T15:18:15", "url": "https://files.pythonhosted.org/packages/ce/dc/6eecabbc0b8396b98db45598f0b9df4f41affcb2ea57dc1ec4d8ad209047/Sharrock-0.6.1.tar.gz" } ], "0.6.2": [ { "comment_text": "", "digests": { "md5": "c09628b2a2c7244bf306e102b9c41cec", "sha256": "3a3f8afca4e075a510ae38e2143d2ffffb31db3d73a21a129027718819bd7c2c" }, "downloads": -1, "filename": "Sharrock-0.6.2.tar.gz", "has_sig": false, "md5_digest": "c09628b2a2c7244bf306e102b9c41cec", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12274, "upload_time": "2013-04-20T17:58:52", "url": "https://files.pythonhosted.org/packages/23/f0/17ffb6f1cf6c6133ae62dd357fac46c2f54952b7b21a37da8bcd9aa0ed15/Sharrock-0.6.2.tar.gz" } ], "0.6.2.1": [ { "comment_text": "", "digests": { "md5": "aec63e45df1bbedd2419be0438dc00df", "sha256": "3e9496e807345634804aec35e57ec890e60c582f116e4eee162fcf9c2fb99a3c" }, "downloads": -1, "filename": "Sharrock-0.6.2.1.tar.gz", "has_sig": false, "md5_digest": "aec63e45df1bbedd2419be0438dc00df", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12373, "upload_time": "2013-04-20T20:56:04", "url": "https://files.pythonhosted.org/packages/bf/6c/b07f128a2bbd45cfcf8681991279a086104040ba1a914684d399b2af717a/Sharrock-0.6.2.1.tar.gz" } ], "0.6.2.2": [ { "comment_text": "", "digests": { "md5": "0ca63e1019d2421c453c5da2e48c9b03", "sha256": "81ccfd7a9809b6650838452023c88c177f545782f25fd724138c06448440fca9" }, "downloads": -1, "filename": "Sharrock-0.6.2.2.tar.gz", "has_sig": false, "md5_digest": "0ca63e1019d2421c453c5da2e48c9b03", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12448, "upload_time": "2013-04-20T21:34:15", "url": "https://files.pythonhosted.org/packages/97/4f/723e33caf24d3b7b29d8047ea3855de2cc3c999d8d1b4820960d8df7ff29/Sharrock-0.6.2.2.tar.gz" } ], "0.6.3": [ { "comment_text": "", "digests": { "md5": "485b110ccd46df46b45e0e10cf14e924", "sha256": "3b3d923e846961f9d93d9e5b22cf11afd7a5890b329e66e319e24d4c317b76a2" }, "downloads": -1, "filename": "Sharrock-0.6.3.tar.gz", "has_sig": false, "md5_digest": "485b110ccd46df46b45e0e10cf14e924", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21264, "upload_time": "2013-04-22T13:38:03", "url": "https://files.pythonhosted.org/packages/9e/54/7a5900d747013d073af935b9f3db59d308c55a0f4a5ec928cccd896f25b6/Sharrock-0.6.3.tar.gz" } ], "0.6.3.1": [ { "comment_text": "", "digests": { "md5": "170ea20f4b1a5720097f128cce0d61ab", "sha256": "7a4a38c584902e688b62fddea9cf083e633cd0761ee7ea5aef4bac93ff6d1ef0" }, "downloads": -1, "filename": "Sharrock-0.6.3.1.tar.gz", "has_sig": false, "md5_digest": "170ea20f4b1a5720097f128cce0d61ab", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21259, "upload_time": "2013-06-07T15:27:59", "url": "https://files.pythonhosted.org/packages/c8/8c/fc95bfb170ec70d516f1159c8784850bb79a9adc97838170abc752257cae/Sharrock-0.6.3.1.tar.gz" } ], "0.6.3.2": [ { "comment_text": "", "digests": { "md5": "72a024015c73a2e15c7ed428fde4d170", "sha256": "426c44668f00a6c227452fdf6839460238261bb9e9454b83224920f524a56f28" }, "downloads": -1, "filename": "Sharrock-0.6.3.2.tar.gz", "has_sig": false, "md5_digest": "72a024015c73a2e15c7ed428fde4d170", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21262, "upload_time": "2013-06-07T17:19:11", "url": "https://files.pythonhosted.org/packages/bb/e9/31a7a4c8adfd301b37c930ec18cfdf4688ef00857d010f545ad6772e60a5/Sharrock-0.6.3.2.tar.gz" } ], "0.6.3.3": [ { "comment_text": "", "digests": { "md5": "7261d9d06c08eac1996bfc4c760fb5a7", "sha256": "cd2ad5a7865b2a59d5a16b895fef617278ec780266d2c7fae0ac5682c5c9ad06" }, "downloads": -1, "filename": "Sharrock-0.6.3.3.tar.gz", "has_sig": false, "md5_digest": "7261d9d06c08eac1996bfc4c760fb5a7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21298, "upload_time": "2013-07-15T18:33:24", "url": "https://files.pythonhosted.org/packages/03/ba/afd02f9a0aa0b2ff2b3b89250d385200969a7a98893a07b5ebc51443fd68/Sharrock-0.6.3.3.tar.gz" } ], "0.6.3.4": [ { "comment_text": "", "digests": { "md5": "5a7dbd4a66e9fdffe109c8d6b293cf39", "sha256": "7e8638f0eb8d2f99db6cc6a426d3078da3c8be3a00214d7d0110e56bce5daa75" }, "downloads": -1, "filename": "Sharrock-0.6.3.4.tar.gz", "has_sig": false, "md5_digest": "5a7dbd4a66e9fdffe109c8d6b293cf39", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21295, "upload_time": "2013-07-15T18:44:54", "url": "https://files.pythonhosted.org/packages/68/d2/644e7d5be32dc2c6786c8ddfc93f25e40080fcbdbca20f401290bdc8af0c/Sharrock-0.6.3.4.tar.gz" } ], "0.6.3.5": [ { "comment_text": "", "digests": { "md5": "0c7c1f4e7fac23b750e8e0ba3e802ba7", "sha256": "d5b5169c4e0c30493123c8487c3abb448897aa5a29443cf52a1cc5b210196e40" }, "downloads": -1, "filename": "Sharrock-0.6.3.5.tar.gz", "has_sig": false, "md5_digest": "0c7c1f4e7fac23b750e8e0ba3e802ba7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21280, "upload_time": "2013-07-15T18:56:20", "url": "https://files.pythonhosted.org/packages/44/74/51fdac38a0874363c47aa2bbecd5b7f56524d7b528e63b62ba1e2b3e5853/Sharrock-0.6.3.5.tar.gz" } ], "0.6.3.6": [ { "comment_text": "", "digests": { "md5": "f297cf5f64b4f3b18cacd6dc576724db", "sha256": "62bfa2533a692f481290406c6f28b36843fc4a96ce8ef36b35f21de8e2cd5622" }, "downloads": -1, "filename": "Sharrock-0.6.3.6.tar.gz", "has_sig": false, "md5_digest": "f297cf5f64b4f3b18cacd6dc576724db", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21340, "upload_time": "2013-09-24T18:28:26", "url": "https://files.pythonhosted.org/packages/24/4c/aafbe7d2646a3f9f3722fd7d5dc88a42f7122edd527c80d4eb0ca1d08a0a/Sharrock-0.6.3.6.tar.gz" } ], "0.6.3.7": [ { "comment_text": "", "digests": { "md5": "0da5302f11adbfd8acc758dcd0b09996", "sha256": "254b368f627d813f34d9390e7abcd8e61880e8f2e674f8e0e840de6606c1e41c" }, "downloads": -1, "filename": "Sharrock-0.6.3.7.tar.gz", "has_sig": false, "md5_digest": "0da5302f11adbfd8acc758dcd0b09996", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21858, "upload_time": "2015-05-16T21:19:15", "url": "https://files.pythonhosted.org/packages/a1/6c/c2369cd8c01a540fc6166bbb1f645c62e5bef24ed1b26828cec771fbdea6/Sharrock-0.6.3.7.tar.gz" } ], "0.6.3.8": [ { "comment_text": "", "digests": { "md5": "76ffe7b069c359c32c0a42a9048da8be", "sha256": "f54e3d8eefbfa1d56fd4809fa3a46eaf8c11024ebc23c25ae5386fff942144c2" }, "downloads": -1, "filename": "Sharrock-0.6.3.8.tar.gz", "has_sig": false, "md5_digest": "76ffe7b069c359c32c0a42a9048da8be", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21923, "upload_time": "2015-08-02T17:37:01", "url": "https://files.pythonhosted.org/packages/16/84/ed2f979fc547fbfc09019987de9d1cb9b989c77c1f90303dc33c16bc56be/Sharrock-0.6.3.8.tar.gz" } ], "0.7.3": [ { "comment_text": "", "digests": { "md5": "72f467be68276ff7cf8967465f20b61e", "sha256": "032a24e35cdb2bd59ad46ae3e04ed99e1e87d12e44ed88ad45d0bc169e5c47e5" }, "downloads": -1, "filename": "Sharrock-0.7.3.tar.gz", "has_sig": false, "md5_digest": "72f467be68276ff7cf8967465f20b61e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21926, "upload_time": "2015-08-04T23:36:55", "url": "https://files.pythonhosted.org/packages/9a/d6/ca4247c70f611b35ab770ac788cbb4e072398b64c6baec4866fa3555530a/Sharrock-0.7.3.tar.gz" } ], "0.7.4": [ { "comment_text": "", "digests": { "md5": "69ff417835e8c9cca208a00e797b2a5d", "sha256": "7dad24b08d25db023903b7bcfa5fa28284e76f458d00e6295fa51d61f704dd24" }, "downloads": -1, "filename": "Sharrock-0.7.4.tar.gz", "has_sig": false, "md5_digest": "69ff417835e8c9cca208a00e797b2a5d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21925, "upload_time": "2015-09-01T19:47:53", "url": "https://files.pythonhosted.org/packages/94/e5/39e32275a97360e568551829f2503b353c3d7d7659ada35cf7ac173a9be7/Sharrock-0.7.4.tar.gz" } ], "0.7.4.1": [ { "comment_text": "", "digests": { "md5": "3099c78081c1dc4fa6dcf44a00434d6c", "sha256": "b62447841141d2af00a05c11d9e588f1ab63c8121d6fd8f398e04e4065812aef" }, "downloads": -1, "filename": "Sharrock-0.7.4.1.tar.gz", "has_sig": false, "md5_digest": "3099c78081c1dc4fa6dcf44a00434d6c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21929, "upload_time": "2015-09-07T01:44:16", "url": "https://files.pythonhosted.org/packages/38/33/3d15fc0ad4d8f3ac8d2db31aa140314b8615afa8ff80703741fc6e38dad6/Sharrock-0.7.4.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "3099c78081c1dc4fa6dcf44a00434d6c", "sha256": "b62447841141d2af00a05c11d9e588f1ab63c8121d6fd8f398e04e4065812aef" }, "downloads": -1, "filename": "Sharrock-0.7.4.1.tar.gz", "has_sig": false, "md5_digest": "3099c78081c1dc4fa6dcf44a00434d6c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21929, "upload_time": "2015-09-07T01:44:16", "url": "https://files.pythonhosted.org/packages/38/33/3d15fc0ad4d8f3ac8d2db31aa140314b8615afa8ff80703741fc6e38dad6/Sharrock-0.7.4.1.tar.gz" } ] }