{ "info": { "author": "Eyal Posener", "author_email": "eyal@stratoscale.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 2.7", "Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware" ], "description": "# hammock\nA good place to REST.\nHammock provides a friendly approach to develop resources for a REST server.\ncurrently supports falcon.\n\n## General\n\nYour REST server might have resources.\n\n1. Make a resources package somewhere in your project (with __init__.py and so on).\n2. Add your resources to that package (see below).\n3. Add the resources to the falcon API (see below).\n4. Use the auto-generated client.\n\n## Creating a resource\nA resource defined by its URL prefix.\nA resource is a class with name of its module, capitalized, and inherits from the `hammock.Resource`. Resource class:\nLets create an helloworld resource, in resources/helloworld.py:\n```python\nimport hammock\n\nclass Helloworld(hammock.Resource):\n @hammock.get()\n def say(self):\n return \"hello world\"\n```\n\nThis class definition will add a resource in the URL `/helloworld`. The `hammock.get` decorator\ndefines the say method as a rest method for `GET /helloworld`.\n\n## Adding resources package to falcon API\nSimply use this code:\n```python\nimport hammock\nfrom somewhere.in.your.project import resources\n\nhammock.Hammock('falcon', resources)\n```\n\n## REST methods\nAs explained above, adding a rest method is done by adding a method to the resource class with an\nappropriate decorator.\nYou can use one decorators: `hammock.get`, `hammock.post`, `hammock.put`, `hammock.patch` or `hammock.delete`.\nThe developer may write a method that gets arguments, or keyword arguments, and returns\nsomething, usually an object that can be converted to JSON format in the response body. The arguments\nwill be parsed automatically from the request URL query or JSON body (depending on the method used), and the return\nvalue will be written to the response message.\n\n### The decorators may get some arguments:\n- path (default: \"\"): representing a path in the resource. This path may include variables,\nsurrounded by curly braces, same as you would have done in falcon.\n- success_code (default: 200): the code that will be returned with the HTTP response,\nin case that no error was raised.\n- result_content_type (default \"application/json\"): the content type that will be in the header of the response.\n- rule_name: see [Policy](#policy), below.\n\n## Route argument types\n\nYou may add types for the route method's arguments.\nThe types are given in the docstring of the method and also influence the CLI.\nTo document an argument, add line/lines to the docstring:\n```python\n\"\"\"\n:param [] : \n\"\"\"\n```\nThe you define an argument type, the argument will be converted to the proper type\nbefore entering your method. If an error occurs during the conversion, an HTTP 400 (Bad Request)\nwill be raised. Special cases:\n\n- If a type is `list`, and a single item will be given, the item will be converted to a list with one item.\n- The value `None` won't be converted and it will be passed as is. In the case of type `list`, an empty list\n will be passed to the method.\n\n### Special arguments\nNaming the method's argument in a special way, might result in a different behaviour:\n- `_headers`: the argument that will be passed to the method is the headers of the request.\n- `_file`: This method expects \"application/octet-stream\" as content-type of the request, and the stream\nwill be delivered to the `_file` argument. Notice that this method must be \"PUT\" or \"POST\".\nOther arguments will be passed through the URL query parameters.\n- `_list`: when JSON body is a list (and not a dict) the body will go to this variable.\n\n## URLs\nThe URL of your resource is created using the python packages and class name.\nFor example, if your Echo class is in `your.project.resources.tools.echo.Echo`,\nand you add the package `your.project.resources` to the rest.Rest class, the resource URL will be:\n`/tools/echo`, since its class name is Echo and it is in subpackage tools.\n\n### Overriding URLs\n- For packages: if you want the URL component of a package to differ from its name,\nyou can add to the package `__init__.py` file: `PATH = \"some-other-name\"`. This will replace the package\nname with `some-other-name` in the URL.\n- For classes: adding PATH class member\n```python\nclass SomeResource(hammock.Resource):\n PATH = \"some-other-name\"\n```\n\n## Client Methods:\n\nIn case you want that one route method will be expand to different \nmethods in the generated client. you can use the route `client_methods`\nargument, and map a method name to kwargs that will be enforced as part\nof the client's request.\n\nYou can see this [example](./tests/client_methods.py).\n\n## Policy\n\nDefine routing policies using a policy JSON file.\nA policy rule is according to [oslo.policy](http://docs.openstack.org/developer/oslo.policy).\nTo use the policy file, instantiate the Hammock instance with\nthe policy_file keyword argument.\nA rule has a name and a Boolean expression that is evaluated\nusing the headers and target resource parameters.\n- The rule name is combined of rule-group and rule-name\n - The rule group is by default the resource class name, lowercase,\n and can be overridden using the `POLICY_GROUP_NAME` class member. Setting this\n member to `False` will result in no policy enforcement on the class.\n - The rule name is the route method name, and can be overridden using the\n `rule_name` keyword argument in the route decorator.\n - The full name is `{rule-group}:{rule-name}`\n- The headers are converted to a credentials dict,\n by default using the [Credentials](./hammock/types/credentials.py) class,\n but can be customized using credentials_class parameter.\n- The request is converted to a dict using hammock engine, and passed to oslo.policy as\n the target field.\n- Evaluating the expression:\n the expression is key:value tuple. The key might be:\n * `rule`: then the target is reference to another rule.\n * `role`: then the value is looked up in a list stored in a key 'roles' in the credentials dict.\n * project_id/user_id/domain_id: the credential's project_id/user_id/domain_id.\n * other: the key is searched in the credentials rules, and then the value is compared after\n evaluating the python expression: value % target\n * [reference](http://docs.openstack.org/developer/oslo.policy/api/oslo_policy.html#policy-rule-expressions).\n * Example:\n rule is 'credentials_entry:%(target_entry)s', then\n if credentials are {'credentials_entry': 'x'} and target is {'target_entry': 'x'},\n then the rule is evaluated to True.\n- The expression might have and/or parentheses.\n\n### Enforcement in the route method context\n\nNot all policies can be enforced in the route method entry level.\nThe credentials dict might be injected to the route method, using\nthe `_credentials` keyword argument. For example:\n\n```python\nimport hammock\nimport manager\n\nclass MySecuredResource(hammock.Resource):\n @hammock.get()\n def get(self, _credentials, resource_id):\n resource = manager.get(resource_id)\n \u00a0\u00a0\u00a0\u00a0if resource['project_id'] != _credentials['project_id']:\n \u00a0\u00a0\u00a0 raise exceptions.Unauthorized('Get secured resource {}'.format(resource_id))\n return vm\n```\n\n## CLI\n\nA CLI for a hammock auto-generated client can be initiated using The `hammock.cli.app.App` class.\nYou can inherit it in your project, to override the prompt, description, version or proprties.\nYou initiate it using a list of hammock client classes. Notice that it expects classes and not instances. All the clients are merged into a one CLI.\n\n### Command names\n\nThe CLI is populated with commands and sub commands using the client Class.\nA Resource class in the client will be converted into a command, containing all its routing methods, or resource nested classes as sub commands (recursively). The name of the resource and routing methods will be conveted into a command name (no caps, dashes, etc...) automatically, but you can override this name as follows:\n\nFor resources package, add `CLI_COMMAND_NAME` variable in the `__init__.py` file of the package, for a resource class: add a `CLI_COMMAND_NAME` attribute, for a route method, use the `cli_command_name` parameter when you define it. The effect will be as follows:\n\n- `None` will have no effect and the command name will be converted from the package/class/method name.\n- `False` will remove the package/class/method from the CLI (and all its nested dependencies).\n- any other string will be used as the command name.\n\n### Command arguments\n\n- The arguments for a command are taken from the route method it represents.\n- `args` are converted to positional arguments. `kwargs` are converted to optional arguments.\n- Type and documentation strings are taken from the method doc string: if the doc string contains a line(s): `:param [] : `.\n * The type can be `str`, `bool`, `int` of `float` to specify type.\n * `list` will define a CLI argparser `nargs='*'`.\n * `bool[False]` or `bool[True]` will use the `action='store_true'` or `action='store_false'` respectively, and type bool.\n- Return value of a method can be defined using the doc string line(s): `:return : `, The return value affects the command as follows:\n * `dict`: means the return value is an item, the CLI will print a table with dict keys and values. The CLI will add option `-f` that can change the output format (JSON, YAML, etc...).\n * `list`: means the return value is a list of items. The CLI will print a table of the values for each item, will add the `-f` flag that can define the format, `-c` to select specific columns and more. It is best practice to return a list of dicts, containing the same keys. If a list of other types is returned, the CLI will convert it to a list of dicts containing one key `value`.\n * other types will be printed to the stdout of the CLI.\n\n\n- The documentation string for the command is taken from the route method doc string.\n\n## Examples:\n\n* Look at the resources test [package](./tests/resources).\n* Look at the example [project](./examples/phoenix)", "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/stratoscale/hammock.git", "keywords": "REST", "license": "Apache License 2.0", "maintainer": "Eyal Posener", "maintainer_email": "eyal@stratoscale.com", "name": "hammock-rest", "package_url": "https://pypi.org/project/hammock-rest/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/hammock-rest/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/stratoscale/hammock.git" }, "release_url": "https://pypi.org/project/hammock-rest/0.0.1/", "requires_dist": null, "requires_python": null, "summary": "A good place to REST", "version": "0.0.1" }, "last_serial": 2127370, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "0a18cc0a2b68f05fb825729ca66931b2", "sha256": "8b02ef3d3ec424fba0777662fba5cefd59a2f16d21810b1c0110e83e1dbfd333" }, "downloads": -1, "filename": "hammock-rest-0.0.1.tar.gz", "has_sig": false, "md5_digest": "0a18cc0a2b68f05fb825729ca66931b2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 43103, "upload_time": "2016-05-19T19:21:00", "url": "https://files.pythonhosted.org/packages/69/3e/d80de0477a5eb95566683f405dc154ae9d0c6c0a779f555def52d62b5d62/hammock-rest-0.0.1.tar.gz" } ], "v0.0.1": [] }, "urls": [ { "comment_text": "", "digests": { "md5": "0a18cc0a2b68f05fb825729ca66931b2", "sha256": "8b02ef3d3ec424fba0777662fba5cefd59a2f16d21810b1c0110e83e1dbfd333" }, "downloads": -1, "filename": "hammock-rest-0.0.1.tar.gz", "has_sig": false, "md5_digest": "0a18cc0a2b68f05fb825729ca66931b2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 43103, "upload_time": "2016-05-19T19:21:00", "url": "https://files.pythonhosted.org/packages/69/3e/d80de0477a5eb95566683f405dc154ae9d0c6c0a779f555def52d62b5d62/hammock-rest-0.0.1.tar.gz" } ] }