21

現在、EndpointsModel を使用して、AppEngine 上のすべてのモデル用の RESTful API を作成しています。RESTful であるため、これらの API には繰り返しのコードが多くあり、これを回避したいと考えています。

例えば:

class Reducer(EndpointsModel):
    name = ndb.StringProperty(indexed=False)

@endpoints.api(
    name="bigdata",
    version="v1",
    description="""The BigData API""",
    allowed_client_ids=ALLOWED_CLIENT_IDS,
)
class BigDataApi(remote.Service):
    @Reducer.method(
        path="reducer",
        http_method="POST",
        name="reducer.insert",
        user_required=True,
    )
    def ReducerInsert(self, obj):
        pass

    ## and GET, POST, PUT, DELETE
    ## REPEATED for each model

それらをジェネリックにしたい。だから私はクラスにメソッドを動的に追加しようとします。私がこれまでに試したこと:

from functools import partial, wraps

def GenericInsert(self, obj, cls):
    obj.owner = endpoints.get_current_user()
    obj.put()
    return obj

# Ignore GenericDelete, GenericGet, GenericUpdate ...

import types
from functools import partial

def register_rest_api(api_server, endpoint_cls):
    name = endpoint_cls.__name__

    # create list method 
    query_method = types.MethodType(
    endpoint_cls.query_method(
        query_fields=('limit', 'pageToken'),
        path="%ss" % name,
        http_method="GET",
        name="%s.list" % name,
        user_required=True
    )(partial(GenericList, cls=endpoint_cls)))

    setattr(api_server, "%sList", query_method)

    # create insert method
    # ...

register_rest_api(BigDataApi, Reducer)

しかし、のデコレータとパーシャルの'functools.partial' object has no attribute '__module__' exception. 間にいくつかの競合があるためだと思います。endpoints.methodしかし、それを回避する方法がわかりません。

Traceback (most recent call last):
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/wsgi.py", line 239, in Handle
    handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/wsgi.py", line 298, in _LoadHandler
    handler, path, err = LoadObject(self._handler)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/wsgi.py", line 84, in LoadObject
    obj = __import__(path[0])
  File "/Users/Sylvia/gcdc2013/apis.py", line 795, in <module>
    register_rest_api(BigDataApi, Reducer)
  File "/Users/Sylvia/gcdc2013/apis.py", line 788, in register_rest_api
    )(partial(GenericList, cls=endpoint_cls)))
  File "/Users/Sylvia/gcdc2013/endpoints_proto_datastore/ndb/model.py", line 1544, in RequestToQueryDecorator
    @functools.wraps(api_method)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/functools.py", line 33, in update_wrapper
    setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'functools.partial' object has no attribute '__module__'

関連記事:

4

7 に答える 7

2

functools の「ラップ」の問題が原因である場合、ラップを呼び出さない独自のパーシャルを作成することを妨げるものは何もありません。Python のドキュメントによると、これはパーシャルの有効な実装です。

def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc
于 2014-07-22T20:48:27.647 に答える
0

私たちの場合、functools.partial をサブクラス化することでこれを解決しました。

class WrappablePartial(functools.partial):

    @property
    def __module__(self):
        return self.func.__module__

    @property
    def __name__(self):
        return "functools.partial({}, *{}, **{})".format(
            self.func.__name__,
            self.args,
            self.keywords
        )

    @property
    def __doc__(self):
        return self.func.__doc__

NB __getattr__ を使用してクエリをリダイレクトすることもできますが、実際には読みにくいと思いました (そして、__name__ のように有用なメタデータを挿入するのがより困難になります)。

于 2015-10-16T14:37:05.200 に答える
-2

この問題は Python 2.7.11 で修正されています (どのリリースで修正されたかは不明です)。2.7.11functools.wrapsのオブジェクトで実行できます。functools.partial

于 2016-08-29T23:20:56.433 に答える