[MediaWiki-commits] [Gerrit] Simplify getattr/setattr magic - change (thumbor/proxy-engine)
jenkins-bot has submitted this change and it was merged. Change subject: Simplify getattr/setattr magic .. Simplify getattr/setattr magic By whitelisting local attributes, code is a lot less verbose Bug: T120566 Change-Id: I7b49b76d48896f8708665e3ef6abac6e224e1504 --- M wikimedia_thumbor_proxy_engine/__init__.py 1 file changed, 44 insertions(+), 31 deletions(-) Approvals: Ori.livneh: Looks good to me, approved jenkins-bot: Verified diff --git a/wikimedia_thumbor_proxy_engine/__init__.py b/wikimedia_thumbor_proxy_engine/__init__.py index 5c30b80..dc52da4 100644 --- a/wikimedia_thumbor_proxy_engine/__init__.py +++ b/wikimedia_thumbor_proxy_engine/__init__.py @@ -22,8 +22,13 @@ def __init__(self, context): engines = context.config.PROXY_ENGINE_ENGINES -object.__setattr__(self, 'context', context) -object.__setattr__(self, 'engines', engines) +# Create an object that will store local values +# Setting it this way avoids hitting the __setattr__ +# proxying +super(Engine, self).__setattr__('lcl', {}) + +self.lcl['context'] = context +self.lcl['engines'] = engines for engine in engines: self.init_engine(context, engine) @@ -31,17 +36,17 @@ def init_engine(self, context, module): mod = importlib.import_module(module) klass = getattr(mod, 'Engine') -object.__setattr__(self, module, klass(context)) + +self.lcl[module] = klass(context) def select_engine(self): -buffer = object.__getattribute__(self, 'buffer') -extension = object.__getattribute__(self, 'extension') -engines = object.__getattribute__(self, 'engines') - -for enginename in engines: -engine = object.__getattribute__(self, enginename) +for enginename in self.lcl['engines']: +engine = self.lcl[enginename] try: -if engine.should_run(extension, buffer): +if engine.should_run( +self.lcl['extension'], +self.lcl['buffer'] +): return enginename # Not implementing should_run means that the engine @@ -51,39 +56,40 @@ except AttributeError: return enginename -raise Exception('Unable to find a suitable engine, tried %r' % engines) +raise Exception( +'Unable to find a suitable engine, tried %r' % self.lcl['engines'] +) # This is our entry point for the proxy, it's the first call to the engine def load(self, buffer, extension): -object.__setattr__(self, 'start', datetime.datetime.now()) +self.lcl['start'] = datetime.datetime.now() # buffer and extension are needed by select_engine -object.__setattr__(self, 'extension', extension) -object.__setattr__(self, 'buffer', buffer) +self.lcl['extension'] = extension +self.lcl['buffer'] = buffer # Now that we'll select the right engine, let's initialize it -context = object.__getattribute__(self, 'context') -engine = getattr(self, 'select_engine')() -context.request_handler.set_header('Engine', engine) +self.lcl['context'].request_handler.set_header( +'Engine', +self.select_engine() +) -super(Engine, self).__init__(context) +super(Engine, self).__init__(self.lcl['context']) super(Engine, self).load(buffer, extension) def __getattr__(self, name): -engine = getattr(self, 'select_engine')() - -return getattr(object.__getattribute__(self, engine), name) +return getattr(self.lcl[self.select_engine()], name) def __delattr__(self, name): -engine = self.select_engine() -return delattr(object.__getattribute__(self, engine), name) +return delattr(self.lcl[self.select_engine()], name) def __setattr__(self, name, value): -engine = self.select_engine() -return setattr(object.__getattribute__(self, engine), name, value) +return setattr(self.lcl[self.select_engine()], name, value) # The following have to be redefined because their fallbacks in BaseEngine # don't have the right amount of parameters +# They call __getattr__ because the calls still need to be proxied +# (otherwise they would just loop back to their own definition right here) def create_image(self, buffer): return self.__getattr__('create_image')(buffer) @@ -99,13 +105,20 @@ ret = self.__getattr__('read')(extension, quality) finish = datetime.datetime.now() -start = object.__getattribute__(self, 'start') -context = object.__getattribute__(self, 'context') -engine = getattr(self, 'select_engine')() -duration = (finish - start).total_seconds()
[MediaWiki-commits] [Gerrit] Simplify getattr/setattr magic - change (thumbor/proxy-engine)
Gilles has uploaded a new change for review. https://gerrit.wikimedia.org/r/257189 Change subject: Simplify getattr/setattr magic .. Simplify getattr/setattr magic By whitelisting local attributes, code is a lot less verbose Bug: T120566 Change-Id: I7b49b76d48896f8708665e3ef6abac6e224e1504 --- M wikimedia_thumbor_proxy_engine/__init__.py 1 file changed, 57 insertions(+), 37 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/thumbor/proxy-engine refs/changes/89/257189/1 diff --git a/wikimedia_thumbor_proxy_engine/__init__.py b/wikimedia_thumbor_proxy_engine/__init__.py index 5c30b80..01e4b75 100644 --- a/wikimedia_thumbor_proxy_engine/__init__.py +++ b/wikimedia_thumbor_proxy_engine/__init__.py @@ -17,13 +17,22 @@ from thumbor.engines import BaseEngine +# These attributes aren't to be proxied, they are local to the class +LOCAL_ATTRIBUTES = [ +'buffer', +'context', +'engines', +'extension', +'start' +] + class Engine(BaseEngine): def __init__(self, context): engines = context.config.PROXY_ENGINE_ENGINES -object.__setattr__(self, 'context', context) -object.__setattr__(self, 'engines', engines) +self.context = context +self.engines = engines for engine in engines: self.init_engine(context, engine) @@ -31,17 +40,15 @@ def init_engine(self, context, module): mod = importlib.import_module(module) klass = getattr(mod, 'Engine') -object.__setattr__(self, module, klass(context)) +LOCAL_ATTRIBUTES.append(module) + +setattr(self, module, klass(context)) def select_engine(self): -buffer = object.__getattribute__(self, 'buffer') -extension = object.__getattribute__(self, 'extension') -engines = object.__getattribute__(self, 'engines') - -for enginename in engines: -engine = object.__getattribute__(self, enginename) +for enginename in self.engines: +engine = getattr(self, enginename) try: -if engine.should_run(extension, buffer): +if engine.should_run(self.extension, self.buffer): return enginename # Not implementing should_run means that the engine @@ -51,72 +58,85 @@ except AttributeError: return enginename -raise Exception('Unable to find a suitable engine, tried %r' % engines) +raise Exception( +'Unable to find a suitable engine, tried %r' % self.engines +) # This is our entry point for the proxy, it's the first call to the engine def load(self, buffer, extension): -object.__setattr__(self, 'start', datetime.datetime.now()) +self.start = datetime.datetime.now() # buffer and extension are needed by select_engine -object.__setattr__(self, 'extension', extension) -object.__setattr__(self, 'buffer', buffer) +self.extension = extension +self.buffer = buffer # Now that we'll select the right engine, let's initialize it -context = object.__getattribute__(self, 'context') -engine = getattr(self, 'select_engine')() -context.request_handler.set_header('Engine', engine) +self.context.request_handler.set_header('Engine', self.select_engine()) -super(Engine, self).__init__(context) +super(Engine, self).__init__(self.context) super(Engine, self).load(buffer, extension) def __getattr__(self, name): -engine = getattr(self, 'select_engine')() +# These attributes need to be local to the proxy +if (name in LOCAL_ATTRIBUTES): +return super(Engine, self).__getattr__(name) -return getattr(object.__getattribute__(self, engine), name) +# Any other attributes are to be proxied +return self.proxy(name) + +def proxy(self, name): +return getattr(getattr(self, self.select_engine()), name) def __delattr__(self, name): -engine = self.select_engine() -return delattr(object.__getattribute__(self, engine), name) +# These attributes need to be local to the proxy +if (name in LOCAL_ATTRIBUTES): +return super(Engine, self).__delattr__(name) + +# Any other attributes are to be proxied +return delattr(getattr(self, self.select_engine()), name) def __setattr__(self, name, value): -engine = self.select_engine() -return setattr(object.__getattribute__(self, engine), name, value) +# These attributes need to be local to the proxy +if (name in LOCAL_ATTRIBUTES): +return super(Engine, self).__setattr__(name, value) + +# Any other attributes are to be proxied +return setattr(getattr(self, self.select_engine()), name, value) # The following have to be redefined