PyramidのViewでPython3の関数アノテーションを使う

Pyramidの現在の最新安定版であるバージョン1.5.7は、ViewでPython3の関数アノテーションに対応していません。

この例では、hello関数の戻り値の型がdictであることを関数アノテーションで表しています。

@view_config(route_name='hello', renderer='json')
def hello(request) -> dict:
    return {
        'greeting': 'Hello'
    }

これでPyramidを起動してアクセスするとエラーになります。スタックトレースは長いので、この記事の一番最後に書きます。

現在はまだアルファ版ですが、1.6系を使用することで対応できます。PyPIには上がっていませんが、pipを使用してGitHubから直接インストールします。

$ pip3 install git+https://github.com/Pylons/pyramid.git@1.6a1 -U

これで完了です。

デバッグ

pyramid.config.utilのtakes_one_arg関数の中でinspect.getargspecが呼ばれています。この関数はPython3.0から非推奨になっており、関数アノテーションに対応していません。Python3の場合にのみ、代わりにinspect.getargfullspecを呼ぶことで解決できます。ちなみにPython2にはinspect.getargfullspecは存在しません。

スタックトレース

Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/__init__.py", line 1059, in execute_actions
    callable(*args, **kw)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 1239, in register
    derived_view = deriver(view)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 162, in __call__
    view)))))))))
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 106, in inner
    wrapper_view = wrapper(self, view)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 174, in mapped_view
    mapped_view = mapper(**self.kw)(view)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 427, in __call__
    view = self.map_nonclass(view)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 445, in map_nonclass
    ronly = requestonly(view, self.attr)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 516, in requestonly
    return takes_one_arg(view, attr=attr, argname='request')
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/util.py", line 204, in takes_one_arg
    argspec = inspect.getargspec(fn)
  File "/usr/lib/python3.4/inspect.py", line 930, in getargspec
    raise ValueError("Function has keyword-only arguments or annotations"
ValueError: Function has keyword-only arguments or annotations, use getfullargspec() API which can support them

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/paste/deploy/loadwsgi.py", line 247, in loadapp
    return loadobj(APP, uri, name=name, **kw)
  File "/usr/local/lib/python3.4/dist-packages/paste/deploy/loadwsgi.py", line 272, in loadobj
    return context.create()
  File "/usr/local/lib/python3.4/dist-packages/paste/deploy/loadwsgi.py", line 710, in create
    return self.object_type.invoke(self)
  File "/usr/local/lib/python3.4/dist-packages/paste/deploy/loadwsgi.py", line 146, in invoke
    return fix_call(context.object, context.global_conf, **context.local_conf)
  File "/usr/local/lib/python3.4/dist-packages/paste/deploy/util.py", line 55, in fix_call
    val = callable(*args, **kw)
  File "./appname/__init__.py", line 13, in main
    return config.make_wsgi_app()
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/__init__.py", line 939, in make_wsgi_app
    self.commit()
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/__init__.py", line 610, in commit
    self.action_state.execute_actions(introspector=self.introspector)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/__init__.py", line 1067, in execute_actions
    tb)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/compat.py", line 131, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/__init__.py", line 1059, in execute_actions
    callable(*args, **kw)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 1239, in register
    derived_view = deriver(view)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 162, in __call__
    view)))))))))
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 106, in inner
    wrapper_view = wrapper(self, view)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 174, in mapped_view
    mapped_view = mapper(**self.kw)(view)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 427, in __call__
    view = self.map_nonclass(view)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 445, in map_nonclass
    ronly = requestonly(view, self.attr)
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/views.py", line 516, in requestonly
    return takes_one_arg(view, attr=attr, argname='request')
  File "/usr/local/lib/python3.4/dist-packages/pyramid/config/util.py", line 204, in takes_one_arg
    argspec = inspect.getargspec(fn)
  File "/usr/lib/python3.4/inspect.py", line 930, in getargspec
    raise ValueError("Function has keyword-only arguments or annotations"
pyramid.exceptions.ConfigurationExecutionError: <class 'ValueError'>: Function has keyword-only arguments or annotations, use getfullargspec() API which can support them
  in:
  Line 10 of file ./appname/views.py:
    def hello(request) -> dict:

コメント

2015 - 2017 (c) 成瀬基樹