├── .coveragerc ├── .gitchangelog.rc ├── .gitignore ├── .travis.yml ├── CHANGELOG ├── LICENSE ├── MANIFEST.in ├── README.rst ├── aiohttp_transmute ├── __init__.py ├── handler.py ├── requirements.txt ├── route.py ├── swagger.py ├── tests │ ├── __init__.py │ ├── conftest.py │ ├── example.py │ ├── test_full.py │ ├── test_handler.py │ ├── test_parsing.py │ ├── test_urldispatcher.py │ └── utils.py └── url_dispatcher.py ├── conda.yml ├── docs ├── Makefile ├── changelog.rst ├── conf.py ├── index.rst └── make.bat ├── readthedocs.yml ├── setup.py ├── ubuild.py └── uranium /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | omit = aiohttp_transmute/tests/* -------------------------------------------------------------------------------- /.gitchangelog.rc: -------------------------------------------------------------------------------- 1 | ## 2 | ## Format 3 | ## 4 | ## ACTION: [AUDIENCE:] COMMIT_MSG [!TAG ...] 5 | ## 6 | ## Description 7 | ## 8 | ## ACTION is one of 'chg', 'fix', 'new' 9 | ## 10 | ## Is WHAT the change is about. 11 | ## 12 | ## 'chg' is for refactor, small improvement, cosmetic changes... 13 | ## 'fix' is for bug fixes 14 | ## 'new' is for new features, big improvement 15 | ## 16 | ## AUDIENCE is optional and one of 'dev', 'usr', 'pkg', 'test', 'doc' 17 | ## 18 | ## Is WHO is concerned by the change. 19 | ## 20 | ## 'dev' is for developpers (API changes, refactors...) 21 | ## 'usr' is for final users (UI changes) 22 | ## 'pkg' is for packagers (packaging changes) 23 | ## 'test' is for testers (test only related changes) 24 | ## 'doc' is for doc guys (doc only changes) 25 | ## 26 | ## COMMIT_MSG is ... well ... the commit message itself. 27 | ## 28 | ## TAGs are additionnal adjective as 'refactor' 'minor' 'cosmetic' 29 | ## 30 | ## They are preceded with a '!' or a '@' (prefer the former, as the 31 | ## latter is wrongly interpreted in github.) Commonly used tags are: 32 | ## 33 | ## 'refactor' is obviously for refactoring code only 34 | ## 'minor' is for a very meaningless change (a typo, adding a comment) 35 | ## 'cosmetic' is for cosmetic driven change (re-indentation, 80-col...) 36 | ## 'wip' is for partial functionality but complete subfunctionality. 37 | ## 38 | ## Example: 39 | ## 40 | ## new: usr: support of bazaar implemented 41 | ## chg: re-indentend some lines !cosmetic 42 | ## new: dev: updated code to be compatible with last version of killer lib. 43 | ## fix: pkg: updated year of licence coverage. 44 | ## new: test: added a bunch of test around user usability of feature X. 45 | ## fix: typo in spelling my name in comment. !minor 46 | ## 47 | ## Please note that multi-line commit message are supported, and only the 48 | ## first line will be considered as the "summary" of the commit message. So 49 | ## tags, and other rules only applies to the summary. The body of the commit 50 | ## message will be displayed in the changelog without reformatting. 51 | 52 | 53 | ## 54 | ## ``ignore_regexps`` is a line of regexps 55 | ## 56 | ## Any commit having its full commit message matching any regexp listed here 57 | ## will be ignored and won't be reported in the changelog. 58 | ## 59 | ignore_regexps = [ 60 | r'release', r'v0', 61 | r'@minor', r'!minor', 62 | r'@cosmetic', r'!cosmetic', 63 | r'@refactor', r'!refactor', 64 | r'@wip', r'!wip', 65 | r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[p|P]kg:', 66 | r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[d|D]ev:', 67 | r'^(.{3,3}\s*:)?\s*[fF]irst commit.?\s*$', 68 | ] 69 | 70 | 71 | ## ``section_regexps`` is a list of 2-tuples associating a string label and a 72 | ## list of regexp 73 | ## 74 | ## Commit messages will be classified in sections thanks to this. Section 75 | ## titles are the label, and a commit is classified under this section if any 76 | ## of the regexps associated is matching. 77 | ## 78 | ## Please note that ``section_regexps`` will only classify commits and won't 79 | ## make any changes to the contents. So you'll probably want to go check 80 | ## ``subject_process`` (or ``body_process``) to do some changes to the subject, 81 | ## whenever you are tweaking this variable. 82 | ## 83 | section_regexps = [ 84 | ('New', [ 85 | r'^[nN]ew\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', 86 | ]), 87 | ('Changes', [ 88 | r'^[cC]hg\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', 89 | ]), 90 | ('Fix', [ 91 | r'^[fF]ix\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', 92 | ]), 93 | ('Deprecation', [ 94 | r'^[dD]ep' 95 | ]), 96 | ('Other', None ## Match all lines 97 | ), 98 | 99 | ] 100 | 101 | 102 | ## ``body_process`` is a callable 103 | ## 104 | ## This callable will be given the original body and result will 105 | ## be used in the changelog. 106 | ## 107 | ## Available constructs are: 108 | ## 109 | ## - any python callable that take one txt argument and return txt argument. 110 | ## 111 | ## - ReSub(pattern, replacement): will apply regexp substitution. 112 | ## 113 | ## - Indent(chars=" "): will indent the text with the prefix 114 | ## Please remember that template engines gets also to modify the text and 115 | ## will usually indent themselves the text if needed. 116 | ## 117 | ## - Wrap(regexp=r"\n\n"): re-wrap text in separate paragraph to fill 80-Columns 118 | ## 119 | ## - noop: do nothing 120 | ## 121 | ## - ucfirst: ensure the first letter is uppercase. 122 | ## (usually used in the ``subject_process`` pipeline) 123 | ## 124 | ## - final_dot: ensure text finishes with a dot 125 | ## (usually used in the ``subject_process`` pipeline) 126 | ## 127 | ## - strip: remove any spaces before or after the content of the string 128 | ## 129 | ## Additionally, you can `pipe` the provided filters, for instance: 130 | #body_process = Wrap(regexp=r'\n(?=\w+\s*:)') | Indent(chars=" ") 131 | #body_process = Wrap(regexp=r'\n(?=\w+\s*:)') 132 | #body_process = noop 133 | body_process = ReSub(r'((^|\n)[A-Z]\w+(-\w+)*: .*(\n\s+.*)*)+$', r'') | strip 134 | 135 | 136 | ## ``subject_process`` is a callable 137 | ## 138 | ## This callable will be given the original subject and result will 139 | ## be used in the changelog. 140 | ## 141 | ## Available constructs are those listed in ``body_process`` doc. 142 | subject_process = (strip | 143 | ReSub(r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n@]*)(@[a-z]+\s+)*$', r'\4') | 144 | ucfirst | final_dot) 145 | 146 | 147 | ## ``tag_filter_regexp`` is a regexp 148 | ## 149 | ## Tags that will be used for the changelog must match this regexp. 150 | ## 151 | tag_filter_regexp = r'^v[0-9]+\.[0-9]+(\.[0-9]+)?$' 152 | 153 | 154 | ## ``unreleased_version_label`` is a string 155 | ## 156 | ## This label will be used as the changelog Title of the last set of changes 157 | ## between last valid tag and HEAD if any. 158 | unreleased_version_label = "%%version%% (unreleased)" 159 | 160 | 161 | ## ``output_engine`` is a callable 162 | ## 163 | ## This will change the output format of the generated changelog file 164 | ## 165 | ## Available choices are: 166 | ## 167 | ## - rest_py 168 | ## 169 | ## Legacy pure python engine, outputs ReSTructured text. 170 | ## This is the default. 171 | ## 172 | ## - mustache() 173 | ## 174 | ## Template name could be any of the available templates in 175 | ## ``templates/mustache/*.tpl``. 176 | ## Requires python package ``pystache``. 177 | ## Examples: 178 | ## - mustache("markdown") 179 | ## - mustache("restructuredtext") 180 | ## 181 | ## - makotemplate() 182 | ## 183 | ## Template name could be any of the available templates in 184 | ## ``templates/mako/*.tpl``. 185 | ## Requires python package ``mako``. 186 | ## Examples: 187 | ## - makotemplate("restructuredtext") 188 | ## 189 | output_engine = rest_py 190 | #output_engine = mustache("restructuredtext") 191 | #output_engine = mustache("markdown") 192 | #output_engine = makotemplate("restructuredtext") 193 | 194 | 195 | ## ``include_merge`` is a boolean 196 | ## 197 | ## This option tells git-log whether to include merge commits in the log. 198 | ## The default is to include them. 199 | include_merge = False 200 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | #Ipython Notebook 62 | .ipynb_checkpoints 63 | bin 64 | include 65 | .uranium 66 | VERSION 67 | pip-selfcheck.json 68 | .pytest_cache 69 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: python 3 | python: 4 | - "3.5" 5 | install: 6 | - pip install coveralls 7 | script: "./uranium test" 8 | after_success: 9 | coveralls 10 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | v0.2.13 (2016-11-11) 5 | -------------------- 6 | 7 | Fix 8 | ~~~ 9 | 10 | - Compatible with version 1.1.3+ of aiohttp. [Yusuke Tsutsumi] 11 | 12 | Other 13 | ~~~~~ 14 | 15 | - Adding changelogs. [Yusuke Tsutsumi] 16 | 17 | v0.2.12 (2016-11-01) 18 | -------------------- 19 | 20 | - Adding content types for swagger. [Yusuke Tsutsumi] 21 | 22 | - Fixing up readme. [Yusuke Tsutsumi] 23 | 24 | - Adding coveralls support. [Yusuke Tsutsumi] 25 | 26 | - Adding travis testing, fixing up readme. [Yusuke Tsutsumi] 27 | 28 | - Make example work. [Michael Flaxman] 29 | 30 | Syntax was invalid and swagger docs endpoint didn't work 31 | 32 | - Fixing issues with content-type not set in the response header. 33 | [Yusuke Tsutsumi] 34 | 35 | - Fix missing "@" from decarator. [Vladimir Rutsky] 36 | 37 | - Adding some examples of optional values. [Yusuke Tsutsumi] 38 | 39 | - Fixing an issue with parsing get arguments which accept multiple 40 | values. [Yusuke Tsutsumi] 41 | 42 | - Adding a new way to add aiohttp_transmute routes. [Yusuke Tsutsumi] 43 | 44 | - Adding route documentation. [Yusuke Tsutsumi] 45 | 46 | - Fixing up unit tests. [Yusuke Tsutsumi] 47 | 48 | v0.2.1 (2016-05-17) 49 | ------------------- 50 | 51 | - Accomodating new changes to transmute-core. [Yusuke Tsutsumi] 52 | 53 | - Adding tests for swagger and basic serialization. [Yusuke Tsutsumi] 54 | 55 | - Proof of concept of shared utility functions for aiohttp. [Yusuke 56 | Tsutsumi] 57 | 58 | - Have aiohttp documented pretty well. [Yusuke Tsutsumi] 59 | 60 | - Styling up the docs. [Yusuke Tsutsumi] 61 | 62 | - Added a pretty complete set of documentation. [Yusuke Tsutsumi] 63 | 64 | - Adding some docs. [Yusuke Tsutsumi] 65 | 66 | - Fixing a bug. [Yusuke Tsutsumi] 67 | 68 | - Working on some unit tests. [Yusuke Tsutsumi] 69 | 70 | - Adding compatability with new transmute-core. [Yusuke Tsutsumi] 71 | 72 | - New version, compatible with transmute-core. [Yusuke Tsutsumi] 73 | 74 | v0.0.7 (2016-04-17) 75 | ------------------- 76 | 77 | - Honoring path parameters, reflecting changes in APIException. [Yusuke 78 | Tsutsumi] 79 | 80 | - Using new web-transmute code. [Yusuke Tsutsumi] 81 | 82 | - Promoted 0.0.4, onto 0.0.5. [Yusuke Tsutsumi] 83 | 84 | v0.0.4 (2016-04-04) 85 | ------------------- 86 | 87 | - Using changes from new web-transmute. [Yusuke Tsutsumi] 88 | 89 | - Adding json as the default content type, support for the 'request' 90 | parameter. [Yusuke Tsutsumi] 91 | 92 | - Omitting the request parameter. [Yusuke Tsutsumi] 93 | 94 | - Upping version. [Yusuke Tsutsumi] 95 | 96 | - Added a POC for swagger. [Yusuke Tsutsumi] 97 | 98 | - Have basic GET routing. [Yusuke Tsutsumi] 99 | 100 | - Close to working example. [Yusuke Tsutsumi] 101 | 102 | - Starting work on a transmute library for aiohttp. [Yusuke Tsutsumi] 103 | 104 | - Initial commit. [Yusuke Tsutsumi] 105 | 106 | 107 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Yusuke Tsutsumi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include VERSION -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | aiohttp-transmute 3 | ================= 4 | 5 | **NOTE: this library is now deprecated, with transute-core supporting aiohttp directly. See https://transmute-core.readthedocs.io/** -------------------------------------------------------------------------------- /aiohttp_transmute/__init__.py: -------------------------------------------------------------------------------- 1 | from transmute_core import * 2 | from transmute_core.frameworks.aiohttp import * 3 | route = add_route -------------------------------------------------------------------------------- /aiohttp_transmute/handler.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | from aiohttp.web import HTTPException 3 | from transmute_core.exceptions import APIException, NoSerializerFound 4 | from transmute_core.function.signature import NoDefault 5 | from transmute_core import ParamExtractor, NoArgument 6 | from aiohttp import web 7 | 8 | 9 | def create_handler(transmute_func, context): 10 | 11 | @wraps(transmute_func.raw_func) 12 | async def handler(request): 13 | exc, result = None, None 14 | try: 15 | args, kwargs = await extract_params(request, context, 16 | transmute_func) 17 | result = await transmute_func.raw_func(*args, **kwargs) 18 | except HTTPException as hpe: 19 | code = hpe.status_code or 400 20 | exc = APIException(code=code, message=str(hpe)) 21 | except Exception as e: 22 | exc = e 23 | if isinstance(result, web.Response): 24 | return result 25 | else: 26 | response = transmute_func.process_result( 27 | context, result, exc, request.content_type 28 | ) 29 | return web.Response( 30 | body=response["body"], status=response["code"], 31 | content_type=response["content-type"], 32 | headers=response["headers"] 33 | ) 34 | 35 | handler.transmute_func = transmute_func 36 | return handler 37 | 38 | 39 | async def extract_params(request, context, transmute_func): 40 | body = await request.content.read() 41 | content_type = request.content_type 42 | extractor = ParamExtractorAIOHTTP(request, body) 43 | return extractor.extract_params( 44 | context, transmute_func, content_type 45 | ) 46 | 47 | 48 | class ParamExtractorAIOHTTP(ParamExtractor): 49 | 50 | def __init__(self, request, body): 51 | self._request = request 52 | self._body = body 53 | 54 | def _get_framework_args(self): 55 | return {"request": self._request} 56 | 57 | @property 58 | def body(self): 59 | return self._body 60 | 61 | def _query_argument(self, key, is_list): 62 | if key not in self._request.query: 63 | return NoArgument 64 | if is_list: 65 | return self._request.query.getall(key) 66 | else: 67 | return self._request.query[key] 68 | 69 | def _header_argument(self, key): 70 | return self._request.headers.get(key, NoArgument) 71 | 72 | def _path_argument(self, key): 73 | return self._request.match_info.get(key, NoArgument) 74 | -------------------------------------------------------------------------------- /aiohttp_transmute/requirements.txt: -------------------------------------------------------------------------------- 1 | # for readthedocs 2 | -e . 3 | -------------------------------------------------------------------------------- /aiohttp_transmute/route.py: -------------------------------------------------------------------------------- 1 | from transmute_core import TransmuteFunction, default_context 2 | from .handler import create_handler 3 | from .swagger import get_swagger_spec 4 | 5 | 6 | def add_route(app, fn, context=default_context): 7 | """ 8 | a decorator that adds a transmute route to the application. 9 | """ 10 | transmute_func = TransmuteFunction( 11 | fn, 12 | args_not_from_request=["request"] 13 | ) 14 | handler = create_handler(transmute_func, context=context) 15 | get_swagger_spec(app).add_func(transmute_func, context) 16 | 17 | for p in transmute_func.paths: 18 | aiohttp_path = _convert_to_aiohttp_path(p) 19 | resource = app.router.add_resource(aiohttp_path) 20 | for method in transmute_func.methods: 21 | resource.add_route(method, handler) 22 | 23 | 24 | def _convert_to_aiohttp_path(path): 25 | """ convert a transmute path to one supported by aiohttp. """ 26 | return path 27 | -------------------------------------------------------------------------------- /aiohttp_transmute/swagger.py: -------------------------------------------------------------------------------- 1 | import json 2 | from aiohttp import web 3 | 4 | from transmute_core.swagger import ( 5 | generate_swagger_html, 6 | get_swagger_static_root, 7 | SwaggerSpec 8 | ) 9 | 10 | STATIC_ROOT = "/_swagger/static" 11 | APP_KEY = "_aiohttp_transmute_swagger" 12 | 13 | 14 | def get_swagger_spec(app): 15 | if APP_KEY not in app: 16 | app[APP_KEY] = SwaggerSpec() 17 | return app[APP_KEY] 18 | 19 | 20 | def add_swagger(app, json_route, html_route): 21 | """ 22 | a convenience method for both adding a swagger.json route, 23 | as well as adding a page showing the html documentation 24 | """ 25 | app.router.add_route('GET', json_route, create_swagger_json_handler(app)) 26 | add_swagger_api_route(app, html_route, json_route) 27 | 28 | 29 | def add_swagger_api_route(app, target_route, swagger_json_route): 30 | """ 31 | mount a swagger statics page. 32 | 33 | app: the aiohttp app object 34 | target_route: the path to mount the statics page. 35 | swagger_json_route: the path where the swagger json definitions is 36 | expected to be. 37 | """ 38 | static_root = get_swagger_static_root() 39 | swagger_body = generate_swagger_html( 40 | STATIC_ROOT, swagger_json_route 41 | ).encode("utf-8") 42 | 43 | async def swagger_ui(request): 44 | return web.Response(body=swagger_body, content_type="text/html") 45 | 46 | app.router.add_route("GET", target_route, swagger_ui) 47 | app.router.add_static(STATIC_ROOT, static_root) 48 | 49 | 50 | def create_swagger_json_handler(app, **kwargs): 51 | """ 52 | Create a handler that returns the swagger definition 53 | for an application. 54 | 55 | This method assumes the application is using the 56 | TransmuteUrlDispatcher as the router. 57 | """ 58 | 59 | spec = get_swagger_spec(app).swagger_definition(**kwargs) 60 | encoded_spec = json.dumps(spec).encode("UTF-8") 61 | 62 | async def swagger(request): 63 | return web.Response( 64 | # we allow CORS, so this can be requested at swagger.io 65 | headers={ 66 | "Access-Control-Allow-Origin": "*" 67 | }, 68 | body=encoded_spec, 69 | content_type="application/json", 70 | ) 71 | 72 | return swagger 73 | -------------------------------------------------------------------------------- /aiohttp_transmute/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toumorokoshi/aiohttp-transmute/6d887fe41738602e25a4b0c277e90ba89240013f/aiohttp_transmute/tests/__init__.py -------------------------------------------------------------------------------- /aiohttp_transmute/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from .example import create_app 3 | 4 | 5 | @pytest.fixture 6 | def app(loop): 7 | return create_app(loop) 8 | 9 | 10 | @pytest.fixture 11 | def cli(app, loop, test_client): 12 | return loop.run_until_complete(test_client(app)) 13 | -------------------------------------------------------------------------------- /aiohttp_transmute/tests/example.py: -------------------------------------------------------------------------------- 1 | from aiohttp import web 2 | import aiohttp_transmute 3 | from aiohttp_transmute import ( 4 | describe, add_swagger, add_route, route, 5 | APIException, Response 6 | ) 7 | from aiohttp.web import HTTPForbidden 8 | from .utils import User 9 | 10 | 11 | async def handle(request): 12 | text = "Hello, can you hear me?" 13 | return web.Response(body=text.encode('utf-8')) 14 | 15 | 16 | @aiohttp_transmute.describe(paths="/multiply") 17 | async def multiply(request, left: int, right: int) -> int: 18 | return left * right 19 | 20 | 21 | @aiohttp_transmute.describe(paths="/id/{my_id}") 22 | async def get_id(request, my_id: str) -> str: 23 | return "your id is: " + my_id 24 | 25 | 26 | @aiohttp_transmute.describe(paths="/optional") 27 | async def get_optional(request, include_foo: bool=False) -> bool: 28 | return include_foo 29 | 30 | 31 | @describe(paths="/headers/", 32 | response_types={ 33 | 200: { 34 | "type": str, 35 | "description": "success", 36 | "headers": { 37 | "location": { 38 | "description": "url to the location", 39 | "type": str 40 | } 41 | } 42 | } 43 | }) 44 | async def header_response(request): 45 | return Response("foo", headers={ 46 | "location": "boo" 47 | }) 48 | 49 | 50 | @aiohttp_transmute.describe(paths="/aiohttp_error") 51 | async def error(request): 52 | raise HTTPForbidden(reason="unauthorized") 53 | 54 | 55 | @aiohttp_transmute.describe(paths="/api_exception") 56 | async def api_exception(request) -> User: 57 | raise APIException("nope") 58 | 59 | 60 | @aiohttp_transmute.describe( 61 | paths="/body_and_header", 62 | methods="POST", 63 | body_parameters=["body"], 64 | header_parameters=["header"] 65 | ) 66 | async def body_and_header(request, body: str, header: str) -> bool: 67 | return body == header 68 | 69 | 70 | @aiohttp_transmute.describe(paths="/config") 71 | async def config(request): 72 | return request.app["config"] 73 | 74 | 75 | @aiohttp_transmute.describe(paths="/multiple_query_params") 76 | async def multiple_query_params(tag: [str]) -> str: 77 | return ",".join(tag) 78 | 79 | 80 | def create_app(loop): 81 | app = web.Application(loop=loop) 82 | app["config"] = {"test": "foo"} 83 | app.router.add_route('GET', '/', handle) 84 | add_route(app, multiple_query_params) 85 | add_route(app, multiply) 86 | add_route(app, get_id) 87 | add_route(app, header_response) 88 | route(app, config) 89 | route(app, get_optional) 90 | route(app, body_and_header) 91 | route(app, error) 92 | route(app, api_exception) 93 | # this should be at the end, to ensure all routes are considered when 94 | # constructing the handler. 95 | add_swagger(app, "/swagger.json", "/swagger") 96 | return app 97 | -------------------------------------------------------------------------------- /aiohttp_transmute/tests/test_full.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import json 3 | 4 | 5 | @pytest.mark.asyncio 6 | async def test_content_type_in_response(cli): 7 | """ the content type should be specified in the response. """ 8 | resp = await cli.get('/optional') 9 | assert 200 == resp.status 10 | assert resp.headers['Content-Type'] == 'application/json' 11 | 12 | 13 | @pytest.mark.asyncio 14 | async def test_headers(cli): 15 | """ the content type should be specified in the response. """ 16 | resp = await cli.get('/headers/') 17 | assert "boo" == resp.headers["location"] 18 | 19 | 20 | @pytest.mark.asyncio 21 | async def test_multiply(cli): 22 | resp = await cli.get('/multiply?left=5&right=10') 23 | assert 200 == resp.status 24 | text = await resp.text() 25 | assert json.loads(text) == 50 26 | 27 | 28 | @pytest.mark.asyncio 29 | async def test_multiply_bad_int(cli): 30 | resp = await cli.get('/multiply?left=foo&right=0x00') 31 | assert 400 == resp.status 32 | 33 | 34 | @pytest.mark.asyncio 35 | async def test_error(cli): 36 | """ HTTPProcessingErrors should be honored. """ 37 | resp = await cli.get('/aiohttp_error') 38 | assert 403 == resp.status 39 | text = await resp.text() 40 | assert "unauthorized" in json.loads(text)["result"] 41 | 42 | 43 | @pytest.mark.asyncio 44 | async def test_api_exception(cli): 45 | """ APIException should be honored. """ 46 | resp = await cli.get('/api_exception') 47 | assert 400 == resp.status 48 | text = await resp.text() 49 | assert "nope" in json.loads(text)["result"] 50 | 51 | 52 | @pytest.mark.asyncio 53 | async def test_optional(cli): 54 | resp = await cli.get('/optional') 55 | assert 200 == resp.status 56 | ret_value = await resp.json() 57 | assert ret_value is False 58 | 59 | 60 | @pytest.mark.asyncio 61 | async def test_optional_with_value(cli): 62 | resp = await cli.get('/optional?include_foo=true') 63 | assert 200 == resp.status 64 | ret_value = await resp.json() 65 | assert ret_value is True 66 | 67 | 68 | @pytest.mark.asyncio 69 | async def test_body_and_header(cli): 70 | resp = await cli.post('/body_and_header', 71 | data=json.dumps({"body": "body"}), 72 | headers={ 73 | "content-type": "application/json", 74 | "header": "header" 75 | }) 76 | assert 200 == resp.status 77 | ret_value = await resp.json() 78 | assert ret_value is False 79 | 80 | 81 | @pytest.mark.asyncio 82 | async def test_get_id(cli): 83 | resp = await cli.get('/id/10') 84 | assert 200 == resp.status 85 | text = await resp.text() 86 | assert json.loads(text) == "your id is: 10" 87 | 88 | 89 | @pytest.mark.asyncio 90 | async def test_config(cli): 91 | resp = await cli.get('/config') 92 | assert 200 == resp.status 93 | text = await resp.text() 94 | assert json.loads(text) == {"test": "foo"} 95 | 96 | 97 | @pytest.mark.asyncio 98 | async def test_swagger(cli): 99 | resp = await cli.get('/swagger.json') 100 | assert 200 == resp.status 101 | assert "application/json" == resp.headers["Content-Type"] 102 | text = await resp.text() 103 | assert json.loads(text)["paths"]["/multiply"]["get"]["responses"] == { 104 | "200": { 105 | "schema": {"type": "integer"}, 106 | "description": "success" 107 | }, 108 | "400": { 109 | "schema": { 110 | "title": "FailureObject", 111 | "type": "object", 112 | "required": ["success", "result"], 113 | "properties": { 114 | "result": {"type": "string"}, 115 | "success": {"type": "boolean"} 116 | } 117 | }, 118 | "description": "invalid input received"} 119 | } 120 | 121 | 122 | @pytest.mark.asyncio 123 | async def test_swagger_page(cli): 124 | resp = await cli.get('/swagger') 125 | assert 200 == resp.status 126 | assert "text/html" == resp.headers["Content-Type"] 127 | -------------------------------------------------------------------------------- /aiohttp_transmute/tests/test_handler.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toumorokoshi/aiohttp-transmute/6d887fe41738602e25a4b0c277e90ba89240013f/aiohttp_transmute/tests/test_handler.py -------------------------------------------------------------------------------- /aiohttp_transmute/tests/test_parsing.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.mark.asyncio 5 | async def test_parsing_multiiple_query_params(cli): 6 | resp = await cli.get('/multiple_query_params?tag=foo&tag=bar') 7 | ret_value = await resp.json() 8 | assert 200 == resp.status 9 | assert ret_value == "foo,bar" 10 | 11 | 12 | @pytest.mark.asyncio 13 | async def test_parsing_multiple_query_params_single_tag(cli): 14 | resp = await cli.get('/multiple_query_params?tag=foo') 15 | ret_value = await resp.json() 16 | assert 200 == resp.status 17 | assert ret_value == "foo" 18 | -------------------------------------------------------------------------------- /aiohttp_transmute/tests/test_urldispatcher.py: -------------------------------------------------------------------------------- 1 | """ 2 | tests for legacy url dispatcher. 3 | """ 4 | import pytest 5 | from aiohttp_transmute.url_dispatcher import TransmuteUrlDispatcher 6 | from aiohttp_transmute.swagger import get_swagger_spec 7 | from aiohttp_transmute import describe 8 | from unittest.mock import patch 9 | 10 | 11 | async def describe_later() -> str: 12 | return "foo" 13 | 14 | 15 | @describe(paths="/describe_now") 16 | async def describe_now() -> str: 17 | return "foo" 18 | 19 | 20 | @pytest.fixture 21 | def url_dispatcher(app): 22 | dispatcher = TransmuteUrlDispatcher() 23 | dispatcher.post_init(app) 24 | return dispatcher 25 | 26 | 27 | def test_urldispatcher_exception_invalid_argcount(url_dispatcher): 28 | with pytest.raises(ValueError): 29 | url_dispatcher.add_transmute_route(1, 2, 3, 4) 30 | 31 | 32 | def test_urldispatcher_adds_route(app, url_dispatcher): 33 | with patch("aiohttp_transmute.url_dispatcher.add_route") as add_route: 34 | url_dispatcher.add_transmute_route("GET", "/describe_later", describe_later) 35 | assert "GET" in describe_later.transmute.methods 36 | assert "/describe_later" in describe_later.transmute.paths 37 | add_route.assert_called_with( 38 | app, describe_later, context=url_dispatcher._transmute_context 39 | ) 40 | 41 | 42 | def test_urldispatcher_adds_route_one_arg(app, url_dispatcher): 43 | with patch("aiohttp_transmute.url_dispatcher.add_route") as add_route: 44 | url_dispatcher.add_transmute_route(describe_now) 45 | add_route.assert_called_with( 46 | app, describe_now, context=url_dispatcher._transmute_context 47 | ) 48 | -------------------------------------------------------------------------------- /aiohttp_transmute/tests/utils.py: -------------------------------------------------------------------------------- 1 | from schematics.models import Model 2 | from schematics.types import IntType 3 | 4 | 5 | class User(Model): 6 | points = IntType() 7 | -------------------------------------------------------------------------------- /aiohttp_transmute/url_dispatcher.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from aiohttp.web import UrlDispatcher 3 | from collections import OrderedDict 4 | from transmute_core import default_context, describe 5 | from transmute_core.function import TransmuteFunction 6 | from transmute_core.swagger import SwaggerSpec 7 | from .route import add_route 8 | 9 | 10 | class TransmuteUrlDispatcher(UrlDispatcher): 11 | """ 12 | .. warning:: The TransmuteUrlDispatcher is deprecated. 13 | please use aiohttp_transmute.add_route instead. 14 | 15 | A UrlDispatcher which instruments the add_route function to 16 | collect swagger spec data from transmuted functions. 17 | """ 18 | 19 | def __init__(self, *args, context=default_context, **kwargs): 20 | warnings.warn(("TransmuteUrlDispatch has been deprecated. " 21 | " And will be removed in a future version. " 22 | " Please use aiohttp_transmute.add_route instead. "), 23 | DeprecationWarning, stacklevel=2) 24 | super().__init__() 25 | self._transmute_context = context 26 | 27 | def post_init(self, app): 28 | """ 29 | this must be called after dispatcher creation, to ensure proper operability. 30 | """ 31 | self._app = app 32 | 33 | def add_transmute_route(self, *args): 34 | """ 35 | two formats are accepted, for transmute routes. One allows 36 | for a more traditional aiohttp syntax, while the other 37 | allows for a flask-like variant. 38 | 39 | .. code-block:: python 40 | 41 | # if the path and method are not added in describe. 42 | add_transmute_route("GET", "/route", fn) 43 | 44 | # if the path and method are already added in describe 45 | add_transmute_route(fn) 46 | """ 47 | if len(args) == 1: 48 | fn = args[0] 49 | elif len(args) == 3: 50 | methods, paths, fn = args 51 | fn = describe(methods=methods, paths=paths)(fn) 52 | else: 53 | raise ValueError( 54 | "expected one or three arguments for add_transmute_route!" 55 | ) 56 | 57 | add_route(self._app, fn, context=self._transmute_context) 58 | -------------------------------------------------------------------------------- /conda.yml: -------------------------------------------------------------------------------- 1 | name: py35 2 | dependencies: 3 | - python=3.5.1=0 4 | - pip: 5 | - . 6 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help 23 | help: 24 | @echo "Please use \`make ' where is one of" 25 | @echo " html to make standalone HTML files" 26 | @echo " dirhtml to make HTML files named index.html in directories" 27 | @echo " singlehtml to make a single large HTML file" 28 | @echo " pickle to make pickle files" 29 | @echo " json to make JSON files" 30 | @echo " htmlhelp to make HTML files and a HTML help project" 31 | @echo " qthelp to make HTML files and a qthelp project" 32 | @echo " applehelp to make an Apple Help Book" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " epub3 to make an epub3" 36 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 37 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 38 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 39 | @echo " text to make text files" 40 | @echo " man to make manual pages" 41 | @echo " texinfo to make Texinfo files" 42 | @echo " info to make Texinfo files and run them through makeinfo" 43 | @echo " gettext to make PO message catalogs" 44 | @echo " changes to make an overview of all changed/added/deprecated items" 45 | @echo " xml to make Docutils-native XML files" 46 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 47 | @echo " linkcheck to check all external links for integrity" 48 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 49 | @echo " coverage to run coverage check of the documentation (if enabled)" 50 | @echo " dummy to check syntax errors of document sources" 51 | 52 | .PHONY: clean 53 | clean: 54 | rm -rf $(BUILDDIR)/* 55 | 56 | .PHONY: html 57 | html: 58 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 61 | 62 | .PHONY: dirhtml 63 | dirhtml: 64 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 65 | @echo 66 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 67 | 68 | .PHONY: singlehtml 69 | singlehtml: 70 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 71 | @echo 72 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 73 | 74 | .PHONY: pickle 75 | pickle: 76 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 77 | @echo 78 | @echo "Build finished; now you can process the pickle files." 79 | 80 | .PHONY: json 81 | json: 82 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 83 | @echo 84 | @echo "Build finished; now you can process the JSON files." 85 | 86 | .PHONY: htmlhelp 87 | htmlhelp: 88 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 89 | @echo 90 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 91 | ".hhp project file in $(BUILDDIR)/htmlhelp." 92 | 93 | .PHONY: qthelp 94 | qthelp: 95 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 96 | @echo 97 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 98 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 99 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/aiohttp-transmute.qhcp" 100 | @echo "To view the help file:" 101 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/aiohttp-transmute.qhc" 102 | 103 | .PHONY: applehelp 104 | applehelp: 105 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 106 | @echo 107 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 108 | @echo "N.B. You won't be able to view it unless you put it in" \ 109 | "~/Library/Documentation/Help or install it in your application" \ 110 | "bundle." 111 | 112 | .PHONY: devhelp 113 | devhelp: 114 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 115 | @echo 116 | @echo "Build finished." 117 | @echo "To view the help file:" 118 | @echo "# mkdir -p $$HOME/.local/share/devhelp/aiohttp-transmute" 119 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/aiohttp-transmute" 120 | @echo "# devhelp" 121 | 122 | .PHONY: epub 123 | epub: 124 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 125 | @echo 126 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 127 | 128 | .PHONY: epub3 129 | epub3: 130 | $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 131 | @echo 132 | @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." 133 | 134 | .PHONY: latex 135 | latex: 136 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 137 | @echo 138 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 139 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 140 | "(use \`make latexpdf' here to do that automatically)." 141 | 142 | .PHONY: latexpdf 143 | latexpdf: 144 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 145 | @echo "Running LaTeX files through pdflatex..." 146 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 147 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 148 | 149 | .PHONY: latexpdfja 150 | latexpdfja: 151 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 152 | @echo "Running LaTeX files through platex and dvipdfmx..." 153 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 154 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 155 | 156 | .PHONY: text 157 | text: 158 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 159 | @echo 160 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 161 | 162 | .PHONY: man 163 | man: 164 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 165 | @echo 166 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 167 | 168 | .PHONY: texinfo 169 | texinfo: 170 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 171 | @echo 172 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 173 | @echo "Run \`make' in that directory to run these through makeinfo" \ 174 | "(use \`make info' here to do that automatically)." 175 | 176 | .PHONY: info 177 | info: 178 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 179 | @echo "Running Texinfo files through makeinfo..." 180 | make -C $(BUILDDIR)/texinfo info 181 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 182 | 183 | .PHONY: gettext 184 | gettext: 185 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 186 | @echo 187 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 188 | 189 | .PHONY: changes 190 | changes: 191 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 192 | @echo 193 | @echo "The overview file is in $(BUILDDIR)/changes." 194 | 195 | .PHONY: linkcheck 196 | linkcheck: 197 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 198 | @echo 199 | @echo "Link check complete; look for any errors in the above output " \ 200 | "or in $(BUILDDIR)/linkcheck/output.txt." 201 | 202 | .PHONY: doctest 203 | doctest: 204 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 205 | @echo "Testing of doctests in the sources finished, look at the " \ 206 | "results in $(BUILDDIR)/doctest/output.txt." 207 | 208 | .PHONY: coverage 209 | coverage: 210 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 211 | @echo "Testing of coverage in the sources finished, look at the " \ 212 | "results in $(BUILDDIR)/coverage/python.txt." 213 | 214 | .PHONY: xml 215 | xml: 216 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 217 | @echo 218 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 219 | 220 | .PHONY: pseudoxml 221 | pseudoxml: 222 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 223 | @echo 224 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 225 | 226 | .PHONY: dummy 227 | dummy: 228 | $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy 229 | @echo 230 | @echo "Build finished. Dummy builder generates no files." 231 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | Changelog 3 | ========= 4 | 5 | ------------------------------ 6 | Backwards incompatible changes 7 | ------------------------------ 8 | 9 | 0.6.0 10 | ===== 11 | 12 | To be released March 1st, 2017. TransmuteUrlDispatcher will be removed. 13 | 14 | 0.5.0 15 | ===== 16 | 17 | The legacy pattern of TransmuteUrlDispatcher now requires manual execution of 18 | post_init, due to a change in aiohttp (https://github.com/KeepSafe/aiohttp/issues/1373) : 19 | 20 | .. code:: python 21 | 22 | router = TransmuteUrlDispatcher() 23 | app = web.Application( 24 | loop=loop, 25 | router=router 26 | middlewares=[db_connection_factory] 27 | ) 28 | router.post_init(app) 29 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # aiohttp-transmute documentation build configuration file, created by 5 | # sphinx-quickstart on Mon May 9 23:13:22 2016. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | import alabaster 17 | import sys 18 | import os 19 | 20 | # If extensions (or modules to document with autodoc) are in another directory, 21 | # add these directories to sys.path here. If the directory is relative to the 22 | # documentation root, use os.path.abspath to make it absolute, like shown here. 23 | #sys.path.insert(0, os.path.abspath('.')) 24 | 25 | # -- General configuration ------------------------------------------------ 26 | 27 | # If your documentation needs a minimal Sphinx version, state it here. 28 | #needs_sphinx = '1.0' 29 | 30 | # Add any Sphinx extension module names here, as strings. They can be 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 32 | # ones. 33 | extensions = [ 34 | 'sphinx.ext.autodoc', 35 | 'sphinx.ext.intersphinx' 36 | ] 37 | 38 | intersphinx_mapping = { 39 | 'core': ('http://transmute-core.readthedocs.io/en/latest/', None), 40 | } 41 | 42 | 43 | # Add any paths that contain templates here, relative to this directory. 44 | templates_path = ['_templates'] 45 | 46 | # The suffix(es) of source filenames. 47 | # You can specify multiple suffix as a list of string: 48 | # source_suffix = ['.rst', '.md'] 49 | source_suffix = '.rst' 50 | 51 | # The encoding of source files. 52 | #source_encoding = 'utf-8-sig' 53 | 54 | # The master toctree document. 55 | master_doc = 'index' 56 | 57 | # General information about the project. 58 | project = 'aiohttp-transmute' 59 | copyright = '2016, Yusuke Tsutsumi' 60 | author = 'Yusuke Tsutsumi' 61 | 62 | # The version info for the project you're documenting, acts as replacement for 63 | # |version| and |release|, also used in various other places throughout the 64 | # built documents. 65 | # 66 | # The short X.Y version. 67 | version = '0.1' 68 | # The full version, including alpha/beta/rc tags. 69 | release = '0.1' 70 | 71 | # The language for content autogenerated by Sphinx. Refer to documentation 72 | # for a list of supported languages. 73 | # 74 | # This is also used if you do content translation via gettext catalogs. 75 | # Usually you set "language" from the command line for these cases. 76 | language = None 77 | 78 | # There are two options for replacing |today|: either, you set today to some 79 | # non-false value, then it is used: 80 | #today = '' 81 | # Else, today_fmt is used as the format for a strftime call. 82 | #today_fmt = '%B %d, %Y' 83 | 84 | # List of patterns, relative to source directory, that match files and 85 | # directories to ignore when looking for source files. 86 | # This patterns also effect to html_static_path and html_extra_path 87 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 88 | 89 | # The reST default role (used for this markup: `text`) to use for all 90 | # documents. 91 | #default_role = None 92 | 93 | # If true, '()' will be appended to :func: etc. cross-reference text. 94 | #add_function_parentheses = True 95 | 96 | # If true, the current module name will be prepended to all description 97 | # unit titles (such as .. function::). 98 | #add_module_names = True 99 | 100 | # If true, sectionauthor and moduleauthor directives will be shown in the 101 | # output. They are ignored by default. 102 | #show_authors = False 103 | 104 | # The name of the Pygments (syntax highlighting) style to use. 105 | pygments_style = 'sphinx' 106 | 107 | # A list of ignored prefixes for module index sorting. 108 | #modindex_common_prefix = [] 109 | 110 | # If true, keep warnings as "system message" paragraphs in the built documents. 111 | #keep_warnings = False 112 | 113 | # If true, `todo` and `todoList` produce output, else they produce nothing. 114 | todo_include_todos = False 115 | 116 | 117 | # -- Options for HTML output ---------------------------------------------- 118 | 119 | # The theme to use for HTML and HTML Help pages. See the documentation for 120 | # a list of builtin themes. 121 | html_theme = 'alabaster' 122 | 123 | # Theme options are theme-specific and customize the look and feel of a theme 124 | # further. For a list of options available for each theme, see the 125 | # documentation. 126 | #html_theme_options = {} 127 | html_theme_options = { 128 | 'description': 'transmute for aiohttp', 129 | 'github_user': 'toumorokoshi', 130 | 'github_repo': 'aiohttp-transmute', 131 | 'github_button': True, 132 | 'github_banner': True, 133 | } 134 | 135 | # Add any paths that contain custom themes here, relative to this directory. 136 | #html_theme_path = [] 137 | html_theme_path = [alabaster.get_path()] 138 | 139 | # The name for this set of Sphinx documents. 140 | # " v documentation" by default. 141 | #html_title = 'aiohttp-transmute v0.1' 142 | 143 | # A shorter title for the navigation bar. Default is the same as html_title. 144 | #html_short_title = None 145 | 146 | # The name of an image file (relative to this directory) to place at the top 147 | # of the sidebar. 148 | #html_logo = None 149 | 150 | # The name of an image file (relative to this directory) to use as a favicon of 151 | # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 152 | # pixels large. 153 | #html_favicon = None 154 | 155 | # Add any paths that contain custom static files (such as style sheets) here, 156 | # relative to this directory. They are copied after the builtin static files, 157 | # so a file named "default.css" will overwrite the builtin "default.css". 158 | html_static_path = ['_static'] 159 | 160 | # Add any extra paths that contain custom files (such as robots.txt or 161 | # .htaccess) here, relative to this directory. These files are copied 162 | # directly to the root of the documentation. 163 | #html_extra_path = [] 164 | 165 | # If not None, a 'Last updated on:' timestamp is inserted at every page 166 | # bottom, using the given strftime format. 167 | # The empty string is equivalent to '%b %d, %Y'. 168 | #html_last_updated_fmt = None 169 | 170 | # If true, SmartyPants will be used to convert quotes and dashes to 171 | # typographically correct entities. 172 | #html_use_smartypants = True 173 | 174 | # Custom sidebar templates, maps document names to template names. 175 | #html_sidebars = {} 176 | html_sidebars = { 177 | '**': [ 178 | 'about.html', 'navigation.html', 'searchbox.html', 179 | ] 180 | } 181 | 182 | # Additional templates that should be rendered to pages, maps page names to 183 | # template names. 184 | #html_additional_pages = {} 185 | 186 | # If false, no module index is generated. 187 | #html_domain_indices = True 188 | 189 | # If false, no index is generated. 190 | #html_use_index = True 191 | 192 | # If true, the index is split into individual pages for each letter. 193 | #html_split_index = False 194 | 195 | # If true, links to the reST sources are added to the pages. 196 | #html_show_sourcelink = True 197 | 198 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 199 | #html_show_sphinx = True 200 | 201 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 202 | #html_show_copyright = True 203 | 204 | # If true, an OpenSearch description file will be output, and all pages will 205 | # contain a tag referring to it. The value of this option must be the 206 | # base URL from which the finished HTML is served. 207 | #html_use_opensearch = '' 208 | 209 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 210 | #html_file_suffix = None 211 | 212 | # Language to be used for generating the HTML full-text search index. 213 | # Sphinx supports the following languages: 214 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' 215 | # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr', 'zh' 216 | #html_search_language = 'en' 217 | 218 | # A dictionary with options for the search language support, empty by default. 219 | # 'ja' uses this config value. 220 | # 'zh' user can custom change `jieba` dictionary path. 221 | #html_search_options = {'type': 'default'} 222 | 223 | # The name of a javascript file (relative to the configuration directory) that 224 | # implements a search results scorer. If empty, the default will be used. 225 | #html_search_scorer = 'scorer.js' 226 | 227 | # Output file base name for HTML help builder. 228 | htmlhelp_basename = 'aiohttp-transmutedoc' 229 | 230 | # -- Options for LaTeX output --------------------------------------------- 231 | 232 | #latex_elements = { 233 | # The paper size ('letterpaper' or 'a4paper'). 234 | #'papersize': 'letterpaper', 235 | 236 | # The font size ('10pt', '11pt' or '12pt'). 237 | #'pointsize': '10pt', 238 | 239 | # Additional stuff for the LaTeX preamble. 240 | #'preamble': '', 241 | 242 | # Latex figure (float) alignment 243 | #'figure_align': 'htbp', 244 | # } 245 | 246 | # Grouping the document tree into LaTeX files. List of tuples 247 | # (source start file, target name, title, 248 | # author, documentclass [howto, manual, or own class]). 249 | latex_documents = [ 250 | (master_doc, 'aiohttp-transmute.tex', 'aiohttp-transmute Documentation', 251 | 'Yusuke Tsutsumi', 'manual'), 252 | ] 253 | 254 | # The name of an image file (relative to this directory) to place at the top of 255 | # the title page. 256 | #latex_logo = None 257 | 258 | # For "manual" documents, if this is true, then toplevel headings are parts, 259 | # not chapters. 260 | #latex_use_parts = False 261 | 262 | # If true, show page references after internal links. 263 | #latex_show_pagerefs = False 264 | 265 | # If true, show URL addresses after external links. 266 | #latex_show_urls = False 267 | 268 | # Documents to append as an appendix to all manuals. 269 | #latex_appendices = [] 270 | 271 | # If false, no module index is generated. 272 | #latex_domain_indices = True 273 | 274 | 275 | # -- Options for manual page output --------------------------------------- 276 | 277 | # One entry per manual page. List of tuples 278 | # (source start file, name, description, authors, manual section). 279 | man_pages = [ 280 | (master_doc, 'aiohttp-transmute', 'aiohttp-transmute Documentation', 281 | [author], 1) 282 | ] 283 | 284 | # If true, show URL addresses after external links. 285 | #man_show_urls = False 286 | 287 | 288 | # -- Options for Texinfo output ------------------------------------------- 289 | 290 | # Grouping the document tree into Texinfo files. List of tuples 291 | # (source start file, target name, title, author, 292 | # dir menu entry, description, category) 293 | texinfo_documents = [ 294 | (master_doc, 'aiohttp-transmute', 'aiohttp-transmute Documentation', 295 | author, 'aiohttp-transmute', 'One line description of project.', 296 | 'Miscellaneous'), 297 | ] 298 | 299 | # Documents to append as an appendix to all manuals. 300 | #texinfo_appendices = [] 301 | 302 | # If false, no module index is generated. 303 | #texinfo_domain_indices = True 304 | 305 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 306 | #texinfo_show_urls = 'footnote' 307 | 308 | # If true, do not generate a @detailmenu in the "Top" node's menu. 309 | #texinfo_no_detailmenu = False 310 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. aiohttp-transmute documentation master file, created by 2 | sphinx-quickstart on Mon May 9 23:13:22 2016. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | aiohttp-transmute 7 | ================= 8 | 9 | A `transmute 10 | `_ 11 | framework for `aiohttp `_. This 12 | framework provides: 13 | 14 | * declarative generation of http handler interfaces by parsing function annotations 15 | * validation and serialization to and from a variety of content types (e.g. json or yaml). 16 | * validation and serialization to and from native python objects, using `schematics `_. 17 | * autodocumentation of all handlers generated this way, via `swagger `_. 18 | 19 | As of February 2019, this library is deprecated in favor of using transmute-core directly. See https://transmute-core.readthedocs.io/en/latest/ -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. epub3 to make an epub3 31 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 32 | echo. text to make text files 33 | echo. man to make manual pages 34 | echo. texinfo to make Texinfo files 35 | echo. gettext to make PO message catalogs 36 | echo. changes to make an overview over all changed/added/deprecated items 37 | echo. xml to make Docutils-native XML files 38 | echo. pseudoxml to make pseudoxml-XML files for display purposes 39 | echo. linkcheck to check all external links for integrity 40 | echo. doctest to run all doctests embedded in the documentation if enabled 41 | echo. coverage to run coverage check of the documentation if enabled 42 | echo. dummy to check syntax errors of document sources 43 | goto end 44 | ) 45 | 46 | if "%1" == "clean" ( 47 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 48 | del /q /s %BUILDDIR%\* 49 | goto end 50 | ) 51 | 52 | 53 | REM Check if sphinx-build is available and fallback to Python version if any 54 | %SPHINXBUILD% 1>NUL 2>NUL 55 | if errorlevel 9009 goto sphinx_python 56 | goto sphinx_ok 57 | 58 | :sphinx_python 59 | 60 | set SPHINXBUILD=python -m sphinx.__init__ 61 | %SPHINXBUILD% 2> nul 62 | if errorlevel 9009 ( 63 | echo. 64 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 65 | echo.installed, then set the SPHINXBUILD environment variable to point 66 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 67 | echo.may add the Sphinx directory to PATH. 68 | echo. 69 | echo.If you don't have Sphinx installed, grab it from 70 | echo.http://sphinx-doc.org/ 71 | exit /b 1 72 | ) 73 | 74 | :sphinx_ok 75 | 76 | 77 | if "%1" == "html" ( 78 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 79 | if errorlevel 1 exit /b 1 80 | echo. 81 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 82 | goto end 83 | ) 84 | 85 | if "%1" == "dirhtml" ( 86 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 87 | if errorlevel 1 exit /b 1 88 | echo. 89 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 90 | goto end 91 | ) 92 | 93 | if "%1" == "singlehtml" ( 94 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 95 | if errorlevel 1 exit /b 1 96 | echo. 97 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 98 | goto end 99 | ) 100 | 101 | if "%1" == "pickle" ( 102 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 103 | if errorlevel 1 exit /b 1 104 | echo. 105 | echo.Build finished; now you can process the pickle files. 106 | goto end 107 | ) 108 | 109 | if "%1" == "json" ( 110 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 111 | if errorlevel 1 exit /b 1 112 | echo. 113 | echo.Build finished; now you can process the JSON files. 114 | goto end 115 | ) 116 | 117 | if "%1" == "htmlhelp" ( 118 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 119 | if errorlevel 1 exit /b 1 120 | echo. 121 | echo.Build finished; now you can run HTML Help Workshop with the ^ 122 | .hhp project file in %BUILDDIR%/htmlhelp. 123 | goto end 124 | ) 125 | 126 | if "%1" == "qthelp" ( 127 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 128 | if errorlevel 1 exit /b 1 129 | echo. 130 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 131 | .qhcp project file in %BUILDDIR%/qthelp, like this: 132 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\aiohttp-transmute.qhcp 133 | echo.To view the help file: 134 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\aiohttp-transmute.ghc 135 | goto end 136 | ) 137 | 138 | if "%1" == "devhelp" ( 139 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 140 | if errorlevel 1 exit /b 1 141 | echo. 142 | echo.Build finished. 143 | goto end 144 | ) 145 | 146 | if "%1" == "epub" ( 147 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 148 | if errorlevel 1 exit /b 1 149 | echo. 150 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 151 | goto end 152 | ) 153 | 154 | if "%1" == "epub3" ( 155 | %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3 156 | if errorlevel 1 exit /b 1 157 | echo. 158 | echo.Build finished. The epub3 file is in %BUILDDIR%/epub3. 159 | goto end 160 | ) 161 | 162 | if "%1" == "latex" ( 163 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 164 | if errorlevel 1 exit /b 1 165 | echo. 166 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 167 | goto end 168 | ) 169 | 170 | if "%1" == "latexpdf" ( 171 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 172 | cd %BUILDDIR%/latex 173 | make all-pdf 174 | cd %~dp0 175 | echo. 176 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 177 | goto end 178 | ) 179 | 180 | if "%1" == "latexpdfja" ( 181 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 182 | cd %BUILDDIR%/latex 183 | make all-pdf-ja 184 | cd %~dp0 185 | echo. 186 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 187 | goto end 188 | ) 189 | 190 | if "%1" == "text" ( 191 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 192 | if errorlevel 1 exit /b 1 193 | echo. 194 | echo.Build finished. The text files are in %BUILDDIR%/text. 195 | goto end 196 | ) 197 | 198 | if "%1" == "man" ( 199 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 200 | if errorlevel 1 exit /b 1 201 | echo. 202 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 203 | goto end 204 | ) 205 | 206 | if "%1" == "texinfo" ( 207 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 208 | if errorlevel 1 exit /b 1 209 | echo. 210 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 211 | goto end 212 | ) 213 | 214 | if "%1" == "gettext" ( 215 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 216 | if errorlevel 1 exit /b 1 217 | echo. 218 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 219 | goto end 220 | ) 221 | 222 | if "%1" == "changes" ( 223 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 224 | if errorlevel 1 exit /b 1 225 | echo. 226 | echo.The overview file is in %BUILDDIR%/changes. 227 | goto end 228 | ) 229 | 230 | if "%1" == "linkcheck" ( 231 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 232 | if errorlevel 1 exit /b 1 233 | echo. 234 | echo.Link check complete; look for any errors in the above output ^ 235 | or in %BUILDDIR%/linkcheck/output.txt. 236 | goto end 237 | ) 238 | 239 | if "%1" == "doctest" ( 240 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 241 | if errorlevel 1 exit /b 1 242 | echo. 243 | echo.Testing of doctests in the sources finished, look at the ^ 244 | results in %BUILDDIR%/doctest/output.txt. 245 | goto end 246 | ) 247 | 248 | if "%1" == "coverage" ( 249 | %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage 250 | if errorlevel 1 exit /b 1 251 | echo. 252 | echo.Testing of coverage in the sources finished, look at the ^ 253 | results in %BUILDDIR%/coverage/python.txt. 254 | goto end 255 | ) 256 | 257 | if "%1" == "xml" ( 258 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml 259 | if errorlevel 1 exit /b 1 260 | echo. 261 | echo.Build finished. The XML files are in %BUILDDIR%/xml. 262 | goto end 263 | ) 264 | 265 | if "%1" == "pseudoxml" ( 266 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml 267 | if errorlevel 1 exit /b 1 268 | echo. 269 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. 270 | goto end 271 | ) 272 | 273 | if "%1" == "dummy" ( 274 | %SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy 275 | if errorlevel 1 exit /b 1 276 | echo. 277 | echo.Build finished. Dummy builder generates no files. 278 | goto end 279 | ) 280 | 281 | :end 282 | -------------------------------------------------------------------------------- /readthedocs.yml: -------------------------------------------------------------------------------- 1 | conda: 2 | file: conda.yml 3 | python: 4 | pip_install: true 5 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | from setuptools import setup, find_packages 5 | 6 | base = os.path.dirname(os.path.abspath(__file__)) 7 | README_PATH = os.path.join(base, "README.rst") 8 | 9 | is_release = False 10 | if "--release" in sys.argv: 11 | is_release = True 12 | sys.argv.remove("--release") 13 | 14 | install_requires = [ 15 | 'transmute-core>=1.11.0', 16 | 'aiohttp>=2.3.8' 17 | ] 18 | 19 | tests_require = [] 20 | 21 | setup(name='aiohttp-transmute', 22 | setup_requires=["vcver"], 23 | vcver={ 24 | "is_release": is_release, 25 | "path": base 26 | }, 27 | description='a toolset to generate routes from functions for aiohttp.', 28 | long_description=open(README_PATH).read(), 29 | author='Yusuke Tsutsumi', 30 | author_email='yusuke@tsutsumi.io', 31 | url='', 32 | packages=find_packages(), 33 | install_requires=install_requires, 34 | classifiers=[ 35 | 'Development Status :: 5 - Production/Stable', 36 | 'Operating System :: MacOS', 37 | 'Operating System :: POSIX :: Linux', 38 | 'Topic :: System :: Software Distribution', 39 | 'License :: OSI Approved :: MIT License', 40 | 'Programming Language :: Python', 41 | 'Programming Language :: Python :: 3', 42 | 'Programming Language :: Python :: 3.5', 43 | ], 44 | tests_require=tests_require 45 | ) 46 | -------------------------------------------------------------------------------- /ubuild.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | 4 | 5 | def main(build): 6 | build.packages.install(".", develop=True) 7 | 8 | 9 | def test(build): 10 | main(build) 11 | build.packages.install("jedi") 12 | build.packages.install("pytest") 13 | build.packages.install("pytest-cov") 14 | build.packages.install("pytest-aiohttp") 15 | pytest = os.path.join(build.root, "bin", "py.test") 16 | subprocess.call([ 17 | pytest, "--cov", "aiohttp_transmute", 18 | "aiohttp_transmute/tests", 19 | "--cov-report", "term-missing" 20 | ] + build.options.args) 21 | 22 | 23 | def publish(build): 24 | """ distribute the uranium package """ 25 | build.packages.install("wheel") 26 | build.executables.run([ 27 | "python", "setup.py", 28 | "sdist", "bdist_wheel", "--universal", "upload", "--release" 29 | ]) 30 | 31 | 32 | def stamp(build): 33 | """ after a distribution, stamp the current build. """ 34 | build.packages.install("gitchangelog") 35 | changelog_text = subprocess.check_output(["gitchangelog"]) 36 | with open(os.path.join(build.root, "CHANGELOG"), "wb+") as fh: 37 | fh.write(changelog_text) 38 | 39 | 40 | def build_docs(build): 41 | build.packages.install("sphinx") 42 | return subprocess.call( 43 | ["make", "html"], cwd=os.path.join(build.root, "docs") 44 | ) 45 | -------------------------------------------------------------------------------- /uranium: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # warmup should be added into everyone's root level repository. warmup will: 3 | # * download and set up a virtualenv 4 | # * install uranium 5 | # * run uranium 6 | import os 7 | 8 | ROOT = os.path.dirname(__file__) 9 | URANIUM_PATH = os.getenv('URANIUM_PATH', None) 10 | URANIUM_GITHUB_ACCOUNT = os.getenv('URANIUM_GITHUB_ACCOUNT', 'toumorokoshi') 11 | URANIUM_GITHUB_BRANCH = os.getenv('URANIUM_GITHUB_BRANCH', 'master') 12 | URANIUM_STANDALONE_URL = "https://raw.githubusercontent.com/{account}/uranium/{branch}/uranium/scripts/uranium_standalone".format(account=URANIUM_GITHUB_ACCOUNT, branch=URANIUM_GITHUB_BRANCH) 13 | CACHE_DIRECTORY = os.path.join(ROOT, ".uranium") 14 | CACHED_URANIUM_STANDALONE = os.path.join(CACHE_DIRECTORY, "uranium_standalone") 15 | 16 | 17 | def get_cached_standalone(): 18 | if not os.path.isfile(CACHED_URANIUM_STANDALONE): 19 | return None 20 | with open(CACHED_URANIUM_STANDALONE) as fh: 21 | return fh.read() 22 | 23 | 24 | def store_cached_standalone(body): 25 | if not os.path.exists(CACHE_DIRECTORY): 26 | os.makedirs(CACHE_DIRECTORY) 27 | with open(CACHED_URANIUM_STANDALONE, "wb+") as fh: 28 | fh.write(body) 29 | 30 | cached_standalone = get_cached_standalone() 31 | 32 | if URANIUM_PATH is not None: 33 | print("Executing uranium from " + URANIUM_PATH) 34 | execfile(os.path.realpath(URANIUM_PATH)) 35 | elif cached_standalone is not None: 36 | exec(cached_standalone) 37 | else: 38 | print("Downloading uranium from " + URANIUM_STANDALONE_URL) 39 | try: 40 | from urllib2 import urlopen as urlopen 41 | except: 42 | from urllib.request import urlopen as urlopen 43 | 44 | print("loading uranium bootstrapper...") 45 | body = urlopen(URANIUM_STANDALONE_URL).read() 46 | print("caching standalone uranium script...") 47 | store_cached_standalone(body) 48 | exec(body) 49 | --------------------------------------------------------------------------------