Hear no evil, see no evil, patch no evil: Or, how to monkey-patch safely.

Graham Dumpleton
Graham DumpletonSoftware Developer
Hear no evil, see no evil,
patch no evil: Or, how to
monkey-patch safely.
Graham Dumpleton
@GrahamDumpleton
PyCon Australia - August 2016
Decorators are useful!
Decorators are easy to
implement?
Are you sure?
Typical decorator.
def function_wrapper(wrapped):
def _wrapper(*args, **kwargs):
return wrapped(*args, **kwargs)
return _wrapper
@function_wrapper
def function():
pass
This breaks
introspection.
__name__ and __doc__
attributes are not
preserved.
Doesn’t @functools.wraps() help?
import functools
def function_wrapper(wrapped):
@functools.wraps(wrapped)
def _wrapper(*args, **kwargs):
return wrapped(*args, **kwargs)
return _wrapper
@function_wrapper
def function():
pass
No, it doesn’t solve all
problems.
Still issues with: introspection,
wrapping decorators
implemented using descriptors,
and more.
http://blog.dscpl.com.au
Quick Link: Decorators and monkey patching.
Complicated details removed ….
Get all the details at:
Please try not to
implement decorators
yourself.
What is the solution?
Use ‘wrapt’.
Basic decorator.
import wrapt
@wrapt.decorator
def pass_through(wrapped, instance, args, kwargs):
return wrapped(*args, **kwargs)
@pass_through
def function():
pass
Universal decorator.
import wrapt
import inspect
@wrapt.decorator
def universal(wrapped, instance, args, kwargs):
if instance is None:
if inspect.isclass(wrapped):
# Decorator was applied to a class.
return wrapped(*args, **kwargs)
else:
# Decorator was applied to a function or staticmethod.
return wrapped(*args, **kwargs)
else:
if inspect.isclass(instance):
# Decorator was applied to a classmethod.
return wrapped(*args, **kwargs)
else:
# Decorator was applied to an instancemethod.
return wrapped(*args, **kwargs)
Bonus feature of wrapt
if using multithreading.
Synchronise function calls.
from wrapt import synchronized
@synchronized # lock bound to function1
def function1():
pass
@synchronized # lock bound to function2
def function2():
pass
Methods of classes as well.
from wrapt import synchronized
class Class(object):
@synchronized # lock bound to instance of Class
def function_im(self):
pass
@synchronized # lock bound to Class
@classmethod
def function_cm(cls):
pass
@synchronized # lock bound to function_sm
@staticmethod
def function_sm():
pass
Synchronise block of code.
from wrapt import synchronized
class Object(object):
@synchronized
def function_im_1(self):
pass
def function_im_2(self):
with synchronized(self):
pass
def function_im_3(self):
with synchronized(Object):
pass
Don’t trust me when I say
you should use wrapt?
Potential candidate for being
included in the Python
standard library.
So it must be awesome.
Primary purpose of the
wrapt package wasn’t as
way to build decorators.
Primary reason for
existence of wrapt was to
help with monkey patching.
Decorators rely on similar
principles to monkey
patching.
Before decorators.
# python 2.4+
@function_wrapper
def function():
pass
# python 2.3
def function():
pass
function = function_wrapper(function)
Decorators are applied
when code is defined.
Monkey patching is
performed after the fact,
… and can’t use the
decorator syntax
Why monkey patch?
• Fix bugs in code you can’t modify.
• Replace/mock out code for testing.
• Add instrumentation for monitoring.
Monkey patching with wrapt.
# example.py
class Example(object):
def name(self):
return 'name'
# patches.py
import wrapt
def wrapper(wrapped, instance, args, kwargs):
return wrapped(*args, **kwargs)
from example import Example
wrapt.wrap_function_wrapper(Example, 'name', wrapper)
Don’t patch it yourself.
# patches.py
import wrapt
@wrapt.decorator
def wrapper(wrapped, instance, args, kwargs):
return wrapped(*args, **kwargs)
from example import Example
# DON’T DO THIS.
Example.name = wrapper(Example.name)
Direct patching of
methods breaks in
certain corner cases.
Let wrapt apply the
wrapper for you.
Avoiding imports.
# patches.py
import wrapt
@wrapt.patch_function_wrapper('example', 'Example.name')
def wrapper(wrapped, instance, args, kwargs):
return wrapped(*args, **kwargs)
What about testing,
where we do not want
permanent patches?
Mock alternative.
# example.py
class Storage(object):
def lookup(self, key):
return 'value'
def clear(self):
pass
# tests.py
import wrapt
@wrapt.transient_function_wrapper('example', 'Storage.lookup')
def validate_storage_lookup(wrapped, instance, args, kwargs):
assert len(args) == 1 and not kwargs
return wrapped(*args, **kwargs)
@validate_storage_lookup
def test_method():
storage = Storage()
result = storage.lookup('key')
storage.clear()
What if we need to
intercept access to single
instance of an object?
Transparent object proxy.
# tests.py
import wrapt
class StorageProxy(wrapt.ObjectProxy):
def lookup(self, key):
assert isinstance(key, str)
return self.__wrapped__.lookup(key)
def test_method():
storage = StorageProxy(Storage())
result = storage.lookup(‘key')
storage.clear()
Beware though of
ordering problems when
applying monkey patches.
Import from module.
# example.py
def function():
pass
# module.py
from example import function
# patches.py
import wrapt
@wrapt.patch_function_wrapper('example', 'function')
def wrapper(wrapped, instance, args, kwargs):
return wrapped(*args, **kwargs)
Plus importing and patching
of modules that the
application doesn’t need.
Post import hooks (PEP 369).
# patches.py
import wrapt
def wrapper(wrapped, instance, args, kwargs):
return wrapped(*args, **kwargs)
@wrapt.when_imported('example')
def apply_patches(module):
wrapt.wrap_function_wrapper(module, 'Example.name', wrapper)
Better, but still requires
patches module to be
imported before anything
else in the main
application script.
Need a way to trigger
monkey patches without
modifying application code.
The autowrapt package.
pip install autowrapt
Bundle patches as module.
from setuptools import setup
PATCHES = [
'wsgiref.simple_server = wrapt_wsgiref_debugging:apply_patches'
]
setup(
name = 'wrapt_wsgiref_debugging',
version = '0.1',
py_modules = ['wrapt_wsgiref_debugging'],
entry_points = {‘wrapt_wsgiref_debugging': PATCHES}
)
Patch to time functions.
from __future__ import print_function
from wrapt import wrap_function_wrapper
from timeit import default_timer
def timed_function(wrapped, instance, args, kwargs):
start = default_timer()
print('start', wrapped.__name__)
try:
return wrapped(*args, **kwargs)
finally:
duration = default_timer() - start
print('finish %s %.3fms' % (
wrapped.__name__, duration*1000.0))
def apply_patches(module):
print('patching', module.__name__)
wrap_function_wrapper(module,
'WSGIRequestHandler.handle', timed_function)
Enabling patches.
$ AUTOWRAPT_BOOTSTRAP=wrapt_wsgiref_debugging
$ export AUTOWRAPT_BOOTSTRAP
$ python app.py
patching wsgiref.simple_server
start handle
127.0.0.1 - - [14/Jul/2016 10:18:46] "GET / HTTP/1.1" 200 12
finish handle 1.018ms
Packaging of patches means
they could technically be
shared via PyPi.
Eg: instrumentation for
monitoring.
Reasons to use wrapt.
• Create better decorators.
• Awesome thread synchronisation decorator.
• Safer mechanisms for monkey patching.
Graham.Dumpleton@gmail.com
@GrahamDumpleton
wrapt.readthedocs.io
blog.dscpl.com.au
1 de 50

Recomendados

BYD automobile social media campaign. por
BYD automobile social media campaign.BYD automobile social media campaign.
BYD automobile social media campaign.Enas Alsumairi
562 visualizações15 slides
Jupyterの機能を拡張してみた por
Jupyterの機能を拡張してみたJupyterの機能を拡張してみた
Jupyterの機能を拡張してみたtaka400k
281 visualizações29 slides
Data analytics in the cloud with Jupyter notebooks. por
Data analytics in the cloud with Jupyter notebooks.Data analytics in the cloud with Jupyter notebooks.
Data analytics in the cloud with Jupyter notebooks.Graham Dumpleton
1.5K visualizações54 slides
Days on Jupyter por
Days on JupyterDays on Jupyter
Days on JupyterYen-lung Tsai
805 visualizações84 slides
HadoopCon 2016 - 用 Jupyter Notebook Hold 住一個上線 Spark Machine Learning 專案實戰 por
HadoopCon 2016  - 用 Jupyter Notebook Hold 住一個上線 Spark  Machine Learning 專案實戰HadoopCon 2016  - 用 Jupyter Notebook Hold 住一個上線 Spark  Machine Learning 專案實戰
HadoopCon 2016 - 用 Jupyter Notebook Hold 住一個上線 Spark Machine Learning 專案實戰Wayne Chen
771 visualizações33 slides
Introduction to IPython & Jupyter Notebooks por
Introduction to IPython & Jupyter NotebooksIntroduction to IPython & Jupyter Notebooks
Introduction to IPython & Jupyter NotebooksEueung Mulyana
6.3K visualizações34 slides

Mais conteúdo relacionado

Destaque

D3 in Jupyter : PyData NYC 2015 por
D3 in Jupyter : PyData NYC 2015D3 in Jupyter : PyData NYC 2015
D3 in Jupyter : PyData NYC 2015Brian Coffey
18.7K visualizações23 slides
Data science apps: beyond notebooks por
Data science apps: beyond notebooksData science apps: beyond notebooks
Data science apps: beyond notebooksNatalino Busa
762 visualizações34 slides
Jupyter NotebookとChainerで楽々Deep Learning por
Jupyter NotebookとChainerで楽々Deep LearningJupyter NotebookとChainerで楽々Deep Learning
Jupyter NotebookとChainerで楽々Deep LearningJun-ya Norimatsu
14.2K visualizações54 slides
Jupyter for Education: Beyond Gutenberg and Erasmus por
Jupyter for Education: Beyond Gutenberg and ErasmusJupyter for Education: Beyond Gutenberg and Erasmus
Jupyter for Education: Beyond Gutenberg and ErasmusPaco Nathan
10.5K visualizações44 slides
Clean Code in Jupyter notebook por
Clean Code in Jupyter notebookClean Code in Jupyter notebook
Clean Code in Jupyter notebookVolodymyr Kazantsev
6.2K visualizações43 slides
Jupyter Kernel: How to Speak in Another Language por
Jupyter Kernel: How to Speak in Another LanguageJupyter Kernel: How to Speak in Another Language
Jupyter Kernel: How to Speak in Another LanguageWey-Han Liaw
2.4K visualizações60 slides

Destaque(9)

D3 in Jupyter : PyData NYC 2015 por Brian Coffey
D3 in Jupyter : PyData NYC 2015D3 in Jupyter : PyData NYC 2015
D3 in Jupyter : PyData NYC 2015
Brian Coffey18.7K visualizações
Data science apps: beyond notebooks por Natalino Busa
Data science apps: beyond notebooksData science apps: beyond notebooks
Data science apps: beyond notebooks
Natalino Busa762 visualizações
Jupyter NotebookとChainerで楽々Deep Learning por Jun-ya Norimatsu
Jupyter NotebookとChainerで楽々Deep LearningJupyter NotebookとChainerで楽々Deep Learning
Jupyter NotebookとChainerで楽々Deep Learning
Jun-ya Norimatsu14.2K visualizações
Jupyter for Education: Beyond Gutenberg and Erasmus por Paco Nathan
Jupyter for Education: Beyond Gutenberg and ErasmusJupyter for Education: Beyond Gutenberg and Erasmus
Jupyter for Education: Beyond Gutenberg and Erasmus
Paco Nathan10.5K visualizações
Clean Code in Jupyter notebook por Volodymyr Kazantsev
Clean Code in Jupyter notebookClean Code in Jupyter notebook
Clean Code in Jupyter notebook
Volodymyr Kazantsev6.2K visualizações
Jupyter Kernel: How to Speak in Another Language por Wey-Han Liaw
Jupyter Kernel: How to Speak in Another LanguageJupyter Kernel: How to Speak in Another Language
Jupyter Kernel: How to Speak in Another Language
Wey-Han Liaw2.4K visualizações
APACHE TOREE: A JUPYTER KERNEL FOR SPARK by Marius van Niekerk por Spark Summit
APACHE TOREE: A JUPYTER KERNEL FOR SPARK by Marius van NiekerkAPACHE TOREE: A JUPYTER KERNEL FOR SPARK by Marius van Niekerk
APACHE TOREE: A JUPYTER KERNEL FOR SPARK by Marius van Niekerk
Spark Summit3K visualizações
QGIS第三講—地圖展示與匯出 por Chengtao Lin
QGIS第三講—地圖展示與匯出QGIS第三講—地圖展示與匯出
QGIS第三講—地圖展示與匯出
Chengtao Lin25.4K visualizações
Jupyter 簡介—互動式的筆記本系統 por Chengtao Lin
Jupyter 簡介—互動式的筆記本系統Jupyter 簡介—互動式的筆記本系統
Jupyter 簡介—互動式的筆記本系統
Chengtao Lin22.9K visualizações

Similar a Hear no evil, see no evil, patch no evil: Or, how to monkey-patch safely.

PyCon NZ 2013 - Advanced Methods For Creating Decorators por
PyCon NZ 2013 - Advanced Methods For Creating DecoratorsPyCon NZ 2013 - Advanced Methods For Creating Decorators
PyCon NZ 2013 - Advanced Methods For Creating DecoratorsGraham Dumpleton
3.2K visualizações55 slides
Andy On Closures por
Andy On ClosuresAndy On Closures
Andy On Closuresmelbournepatterns
1.2K visualizações55 slides
Python mocking intro por
Python mocking introPython mocking intro
Python mocking introHans Jones
13 visualizações33 slides
Python and You Series por
Python and You SeriesPython and You Series
Python and You SeriesKarthik Prakash
1.5K visualizações49 slides
Advance python por
Advance pythonAdvance python
Advance pythonpulkit agrawal
174 visualizações40 slides
обзор Python por
обзор Pythonобзор Python
обзор PythonYehor Nazarkin
725 visualizações34 slides

Similar a Hear no evil, see no evil, patch no evil: Or, how to monkey-patch safely.(20)

PyCon NZ 2013 - Advanced Methods For Creating Decorators por Graham Dumpleton
PyCon NZ 2013 - Advanced Methods For Creating DecoratorsPyCon NZ 2013 - Advanced Methods For Creating Decorators
PyCon NZ 2013 - Advanced Methods For Creating Decorators
Graham Dumpleton3.2K visualizações
Andy On Closures por melbournepatterns
Andy On ClosuresAndy On Closures
Andy On Closures
melbournepatterns1.2K visualizações
Python mocking intro por Hans Jones
Python mocking introPython mocking intro
Python mocking intro
Hans Jones13 visualizações
Python and You Series por Karthik Prakash
Python and You SeriesPython and You Series
Python and You Series
Karthik Prakash1.5K visualizações
Advance python por pulkit agrawal
Advance pythonAdvance python
Advance python
pulkit agrawal174 visualizações
обзор Python por Yehor Nazarkin
обзор Pythonобзор Python
обзор Python
Yehor Nazarkin725 visualizações
What's New In Python 2.5 por Richard Jones
What's New In Python 2.5What's New In Python 2.5
What's New In Python 2.5
Richard Jones1.7K visualizações
The Naked Bundle - Symfony Live London 2014 por Matthias Noback
The Naked Bundle - Symfony Live London 2014The Naked Bundle - Symfony Live London 2014
The Naked Bundle - Symfony Live London 2014
Matthias Noback4K visualizações
iPhone Seminar Part 2 por NAILBITER
iPhone Seminar Part 2iPhone Seminar Part 2
iPhone Seminar Part 2
NAILBITER582 visualizações
DjangoCon US 2011 - Monkeying around at New Relic por Graham Dumpleton
DjangoCon US 2011 - Monkeying around at New RelicDjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New Relic
Graham Dumpleton1.7K visualizações
Djangocon11: Monkeying around at New Relic por New Relic
Djangocon11: Monkeying around at New RelicDjangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New Relic
New Relic2.1K visualizações
Control structures functions and modules in python programming por Srinivas Narasegouda
Control structures functions and modules in python programmingControl structures functions and modules in python programming
Control structures functions and modules in python programming
Srinivas Narasegouda220 visualizações
Django Good Practices por Solution4Future
Django Good PracticesDjango Good Practices
Django Good Practices
Solution4Future4.3K visualizações
Metaprogramming Rails por Justus Eapen
Metaprogramming RailsMetaprogramming Rails
Metaprogramming Rails
Justus Eapen1.5K visualizações
The Naked Bundle - Symfony Usergroup Belgium por Matthias Noback
The Naked Bundle - Symfony Usergroup BelgiumThe Naked Bundle - Symfony Usergroup Belgium
The Naked Bundle - Symfony Usergroup Belgium
Matthias Noback1.1K visualizações
Effective testing with pytest por Hector Canto
Effective testing with pytestEffective testing with pytest
Effective testing with pytest
Hector Canto627 visualizações
Javascript Design Patterns por Subramanyan Murali
Javascript Design PatternsJavascript Design Patterns
Javascript Design Patterns
Subramanyan Murali18.7K visualizações
Bring the fun back to java por ciklum_ods
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
ciklum_ods640 visualizações
Functions2.pdf por prasnt1
Functions2.pdfFunctions2.pdf
Functions2.pdf
prasnt12 visualizações
Scala - core features por Łukasz Wójcik
Scala - core featuresScala - core features
Scala - core features
Łukasz Wójcik2.6K visualizações

Mais de Graham Dumpleton

Implementing a decorator for thread synchronisation. por
Implementing a decorator for thread synchronisation.Implementing a decorator for thread synchronisation.
Implementing a decorator for thread synchronisation.Graham Dumpleton
2.1K visualizações41 slides
Not Tom Eastman por
Not Tom EastmanNot Tom Eastman
Not Tom EastmanGraham Dumpleton
577 visualizações16 slides
“warpdrive”, making Python web application deployment magically easy. por
“warpdrive”, making Python web application deployment magically easy.“warpdrive”, making Python web application deployment magically easy.
“warpdrive”, making Python web application deployment magically easy.Graham Dumpleton
1.1K visualizações54 slides
OpenShift, Docker, Kubernetes: The next generation of PaaS por
OpenShift, Docker, Kubernetes: The next generation of PaaSOpenShift, Docker, Kubernetes: The next generation of PaaS
OpenShift, Docker, Kubernetes: The next generation of PaaSGraham Dumpleton
1.9K visualizações41 slides
Automated Image Builds in OpenShift and Kubernetes por
Automated Image Builds in OpenShift and KubernetesAutomated Image Builds in OpenShift and Kubernetes
Automated Image Builds in OpenShift and KubernetesGraham Dumpleton
5.1K visualizações43 slides
PyCon HK 2015 - Monitoring the performance of python web applications por
PyCon HK 2015 -  Monitoring the performance of python web applicationsPyCon HK 2015 -  Monitoring the performance of python web applications
PyCon HK 2015 - Monitoring the performance of python web applicationsGraham Dumpleton
901 visualizações42 slides

Mais de Graham Dumpleton(12)

Implementing a decorator for thread synchronisation. por Graham Dumpleton
Implementing a decorator for thread synchronisation.Implementing a decorator for thread synchronisation.
Implementing a decorator for thread synchronisation.
Graham Dumpleton2.1K visualizações
Not Tom Eastman por Graham Dumpleton
Not Tom EastmanNot Tom Eastman
Not Tom Eastman
Graham Dumpleton577 visualizações
“warpdrive”, making Python web application deployment magically easy. por Graham Dumpleton
“warpdrive”, making Python web application deployment magically easy.“warpdrive”, making Python web application deployment magically easy.
“warpdrive”, making Python web application deployment magically easy.
Graham Dumpleton1.1K visualizações
OpenShift, Docker, Kubernetes: The next generation of PaaS por Graham Dumpleton
OpenShift, Docker, Kubernetes: The next generation of PaaSOpenShift, Docker, Kubernetes: The next generation of PaaS
OpenShift, Docker, Kubernetes: The next generation of PaaS
Graham Dumpleton1.9K visualizações
Automated Image Builds in OpenShift and Kubernetes por Graham Dumpleton
Automated Image Builds in OpenShift and KubernetesAutomated Image Builds in OpenShift and Kubernetes
Automated Image Builds in OpenShift and Kubernetes
Graham Dumpleton5.1K visualizações
PyCon HK 2015 - Monitoring the performance of python web applications por Graham Dumpleton
PyCon HK 2015 -  Monitoring the performance of python web applicationsPyCon HK 2015 -  Monitoring the performance of python web applications
PyCon HK 2015 - Monitoring the performance of python web applications
Graham Dumpleton901 visualizações
PyCon AU 2015 - Using benchmarks to understand how wsgi servers work por Graham Dumpleton
PyCon AU 2015  - Using benchmarks to understand how wsgi servers workPyCon AU 2015  - Using benchmarks to understand how wsgi servers work
PyCon AU 2015 - Using benchmarks to understand how wsgi servers work
Graham Dumpleton833 visualizações
PyCon US 2013 Making Apache suck less for hosting Python web applications por Graham Dumpleton
PyCon US 2013 Making Apache suck less for hosting Python web applicationsPyCon US 2013 Making Apache suck less for hosting Python web applications
PyCon US 2013 Making Apache suck less for hosting Python web applications
Graham Dumpleton8.4K visualizações
PyCon AU 2010 - Getting Started With Apache/mod_wsgi. por Graham Dumpleton
PyCon AU 2010 - Getting Started With Apache/mod_wsgi.PyCon AU 2010 - Getting Started With Apache/mod_wsgi.
PyCon AU 2010 - Getting Started With Apache/mod_wsgi.
Graham Dumpleton9.7K visualizações
PyCon US 2012 - State of WSGI 2 por Graham Dumpleton
PyCon US 2012 - State of WSGI 2PyCon US 2012 - State of WSGI 2
PyCon US 2012 - State of WSGI 2
Graham Dumpleton2K visualizações
PyCon AU 2012 - Debugging Live Python Web Applications por Graham Dumpleton
PyCon AU 2012 - Debugging Live Python Web ApplicationsPyCon AU 2012 - Debugging Live Python Web Applications
PyCon AU 2012 - Debugging Live Python Web Applications
Graham Dumpleton11.4K visualizações
PyCon US 2012 - Web Server Bottlenecks and Performance Tuning por Graham Dumpleton
PyCon US 2012 - Web Server Bottlenecks and Performance TuningPyCon US 2012 - Web Server Bottlenecks and Performance Tuning
PyCon US 2012 - Web Server Bottlenecks and Performance Tuning
Graham Dumpleton8.8K visualizações

Último

20231129 - Platform @ localhost 2023 - Application-driven infrastructure with... por
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...sparkfabrik
5 visualizações46 slides
Navigating container technology for enhanced security by Niklas Saari por
Navigating container technology for enhanced security by Niklas SaariNavigating container technology for enhanced security by Niklas Saari
Navigating container technology for enhanced security by Niklas SaariMetosin Oy
13 visualizações34 slides
A first look at MariaDB 11.x features and ideas on how to use them por
A first look at MariaDB 11.x features and ideas on how to use themA first look at MariaDB 11.x features and ideas on how to use them
A first look at MariaDB 11.x features and ideas on how to use themFederico Razzoli
45 visualizações36 slides
DSD-INT 2023 European Digital Twin Ocean and Delft3D FM - Dols por
DSD-INT 2023 European Digital Twin Ocean and Delft3D FM - DolsDSD-INT 2023 European Digital Twin Ocean and Delft3D FM - Dols
DSD-INT 2023 European Digital Twin Ocean and Delft3D FM - DolsDeltares
7 visualizações23 slides
DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t... por
DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t...DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t...
DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t...Deltares
9 visualizações26 slides
Fleet Management Software in India por
Fleet Management Software in India Fleet Management Software in India
Fleet Management Software in India Fleetable
11 visualizações1 slide

Último(20)

20231129 - Platform @ localhost 2023 - Application-driven infrastructure with... por sparkfabrik
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...
sparkfabrik5 visualizações
Navigating container technology for enhanced security by Niklas Saari por Metosin Oy
Navigating container technology for enhanced security by Niklas SaariNavigating container technology for enhanced security by Niklas Saari
Navigating container technology for enhanced security by Niklas Saari
Metosin Oy13 visualizações
A first look at MariaDB 11.x features and ideas on how to use them por Federico Razzoli
A first look at MariaDB 11.x features and ideas on how to use themA first look at MariaDB 11.x features and ideas on how to use them
A first look at MariaDB 11.x features and ideas on how to use them
Federico Razzoli45 visualizações
DSD-INT 2023 European Digital Twin Ocean and Delft3D FM - Dols por Deltares
DSD-INT 2023 European Digital Twin Ocean and Delft3D FM - DolsDSD-INT 2023 European Digital Twin Ocean and Delft3D FM - Dols
DSD-INT 2023 European Digital Twin Ocean and Delft3D FM - Dols
Deltares7 visualizações
DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t... por Deltares
DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t...DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t...
DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t...
Deltares9 visualizações
Fleet Management Software in India por Fleetable
Fleet Management Software in India Fleet Management Software in India
Fleet Management Software in India
Fleetable11 visualizações
Agile 101 por John Valentino
Agile 101Agile 101
Agile 101
John Valentino7 visualizações
Software testing company in India.pptx por SakshiPatel82
Software testing company in India.pptxSoftware testing company in India.pptx
Software testing company in India.pptx
SakshiPatel827 visualizações
HarshithAkkapelli_Presentation.pdf por harshithakkapelli
HarshithAkkapelli_Presentation.pdfHarshithAkkapelli_Presentation.pdf
HarshithAkkapelli_Presentation.pdf
harshithakkapelli11 visualizações
Unleash The Monkeys por Jacob Duijzer
Unleash The MonkeysUnleash The Monkeys
Unleash The Monkeys
Jacob Duijzer7 visualizações
The Era of Large Language Models.pptx por AbdulVahedShaik
The Era of Large Language Models.pptxThe Era of Large Language Models.pptx
The Era of Large Language Models.pptx
AbdulVahedShaik5 visualizações
Generic or specific? Making sensible software design decisions por Bert Jan Schrijver
Generic or specific? Making sensible software design decisionsGeneric or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisions
Bert Jan Schrijver6 visualizações
DevsRank por devsrank786
DevsRankDevsRank
DevsRank
devsrank78611 visualizações
Gen Apps on Google Cloud PaLM2 and Codey APIs in Action por Márton Kodok
Gen Apps on Google Cloud PaLM2 and Codey APIs in ActionGen Apps on Google Cloud PaLM2 and Codey APIs in Action
Gen Apps on Google Cloud PaLM2 and Codey APIs in Action
Márton Kodok5 visualizações
SUGCON ANZ Presentation V2.1 Final.pptx por Jack Spektor
SUGCON ANZ Presentation V2.1 Final.pptxSUGCON ANZ Presentation V2.1 Final.pptx
SUGCON ANZ Presentation V2.1 Final.pptx
Jack Spektor22 visualizações
WebAssembly por Jens Siebert
WebAssemblyWebAssembly
WebAssembly
Jens Siebert37 visualizações
DSD-INT 2023 Simulating a falling apron in Delft3D 4 - Engineering Practice -... por Deltares
DSD-INT 2023 Simulating a falling apron in Delft3D 4 - Engineering Practice -...DSD-INT 2023 Simulating a falling apron in Delft3D 4 - Engineering Practice -...
DSD-INT 2023 Simulating a falling apron in Delft3D 4 - Engineering Practice -...
Deltares6 visualizações
MariaDB stored procedures and why they should be improved por Federico Razzoli
MariaDB stored procedures and why they should be improvedMariaDB stored procedures and why they should be improved
MariaDB stored procedures and why they should be improved
Federico Razzoli8 visualizações
Copilot Prompting Toolkit_All Resources.pdf por Riccardo Zamana
Copilot Prompting Toolkit_All Resources.pdfCopilot Prompting Toolkit_All Resources.pdf
Copilot Prompting Toolkit_All Resources.pdf
Riccardo Zamana8 visualizações
DSD-INT 2023 The Danube Hazardous Substances Model - Kovacs por Deltares
DSD-INT 2023 The Danube Hazardous Substances Model - KovacsDSD-INT 2023 The Danube Hazardous Substances Model - Kovacs
DSD-INT 2023 The Danube Hazardous Substances Model - Kovacs
Deltares8 visualizações

Hear no evil, see no evil, patch no evil: Or, how to monkey-patch safely.

  • 1. Hear no evil, see no evil, patch no evil: Or, how to monkey-patch safely. Graham Dumpleton @GrahamDumpleton PyCon Australia - August 2016
  • 3. Decorators are easy to implement?
  • 5. Typical decorator. def function_wrapper(wrapped): def _wrapper(*args, **kwargs): return wrapped(*args, **kwargs) return _wrapper @function_wrapper def function(): pass
  • 7. __name__ and __doc__ attributes are not preserved.
  • 8. Doesn’t @functools.wraps() help? import functools def function_wrapper(wrapped): @functools.wraps(wrapped) def _wrapper(*args, **kwargs): return wrapped(*args, **kwargs) return _wrapper @function_wrapper def function(): pass
  • 9. No, it doesn’t solve all problems.
  • 10. Still issues with: introspection, wrapping decorators implemented using descriptors, and more.
  • 11. http://blog.dscpl.com.au Quick Link: Decorators and monkey patching. Complicated details removed …. Get all the details at:
  • 12. Please try not to implement decorators yourself.
  • 13. What is the solution?
  • 15. Basic decorator. import wrapt @wrapt.decorator def pass_through(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) @pass_through def function(): pass
  • 16. Universal decorator. import wrapt import inspect @wrapt.decorator def universal(wrapped, instance, args, kwargs): if instance is None: if inspect.isclass(wrapped): # Decorator was applied to a class. return wrapped(*args, **kwargs) else: # Decorator was applied to a function or staticmethod. return wrapped(*args, **kwargs) else: if inspect.isclass(instance): # Decorator was applied to a classmethod. return wrapped(*args, **kwargs) else: # Decorator was applied to an instancemethod. return wrapped(*args, **kwargs)
  • 17. Bonus feature of wrapt if using multithreading.
  • 18. Synchronise function calls. from wrapt import synchronized @synchronized # lock bound to function1 def function1(): pass @synchronized # lock bound to function2 def function2(): pass
  • 19. Methods of classes as well. from wrapt import synchronized class Class(object): @synchronized # lock bound to instance of Class def function_im(self): pass @synchronized # lock bound to Class @classmethod def function_cm(cls): pass @synchronized # lock bound to function_sm @staticmethod def function_sm(): pass
  • 20. Synchronise block of code. from wrapt import synchronized class Object(object): @synchronized def function_im_1(self): pass def function_im_2(self): with synchronized(self): pass def function_im_3(self): with synchronized(Object): pass
  • 21. Don’t trust me when I say you should use wrapt?
  • 22. Potential candidate for being included in the Python standard library. So it must be awesome.
  • 23. Primary purpose of the wrapt package wasn’t as way to build decorators.
  • 24. Primary reason for existence of wrapt was to help with monkey patching.
  • 25. Decorators rely on similar principles to monkey patching.
  • 26. Before decorators. # python 2.4+ @function_wrapper def function(): pass # python 2.3 def function(): pass function = function_wrapper(function)
  • 27. Decorators are applied when code is defined.
  • 28. Monkey patching is performed after the fact, … and can’t use the decorator syntax
  • 29. Why monkey patch? • Fix bugs in code you can’t modify. • Replace/mock out code for testing. • Add instrumentation for monitoring.
  • 30. Monkey patching with wrapt. # example.py class Example(object): def name(self): return 'name' # patches.py import wrapt def wrapper(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) from example import Example wrapt.wrap_function_wrapper(Example, 'name', wrapper)
  • 31. Don’t patch it yourself. # patches.py import wrapt @wrapt.decorator def wrapper(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) from example import Example # DON’T DO THIS. Example.name = wrapper(Example.name)
  • 32. Direct patching of methods breaks in certain corner cases. Let wrapt apply the wrapper for you.
  • 33. Avoiding imports. # patches.py import wrapt @wrapt.patch_function_wrapper('example', 'Example.name') def wrapper(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs)
  • 34. What about testing, where we do not want permanent patches?
  • 35. Mock alternative. # example.py class Storage(object): def lookup(self, key): return 'value' def clear(self): pass # tests.py import wrapt @wrapt.transient_function_wrapper('example', 'Storage.lookup') def validate_storage_lookup(wrapped, instance, args, kwargs): assert len(args) == 1 and not kwargs return wrapped(*args, **kwargs) @validate_storage_lookup def test_method(): storage = Storage() result = storage.lookup('key') storage.clear()
  • 36. What if we need to intercept access to single instance of an object?
  • 37. Transparent object proxy. # tests.py import wrapt class StorageProxy(wrapt.ObjectProxy): def lookup(self, key): assert isinstance(key, str) return self.__wrapped__.lookup(key) def test_method(): storage = StorageProxy(Storage()) result = storage.lookup(‘key') storage.clear()
  • 38. Beware though of ordering problems when applying monkey patches.
  • 39. Import from module. # example.py def function(): pass # module.py from example import function # patches.py import wrapt @wrapt.patch_function_wrapper('example', 'function') def wrapper(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs)
  • 40. Plus importing and patching of modules that the application doesn’t need.
  • 41. Post import hooks (PEP 369). # patches.py import wrapt def wrapper(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) @wrapt.when_imported('example') def apply_patches(module): wrapt.wrap_function_wrapper(module, 'Example.name', wrapper)
  • 42. Better, but still requires patches module to be imported before anything else in the main application script.
  • 43. Need a way to trigger monkey patches without modifying application code.
  • 44. The autowrapt package. pip install autowrapt
  • 45. Bundle patches as module. from setuptools import setup PATCHES = [ 'wsgiref.simple_server = wrapt_wsgiref_debugging:apply_patches' ] setup( name = 'wrapt_wsgiref_debugging', version = '0.1', py_modules = ['wrapt_wsgiref_debugging'], entry_points = {‘wrapt_wsgiref_debugging': PATCHES} )
  • 46. Patch to time functions. from __future__ import print_function from wrapt import wrap_function_wrapper from timeit import default_timer def timed_function(wrapped, instance, args, kwargs): start = default_timer() print('start', wrapped.__name__) try: return wrapped(*args, **kwargs) finally: duration = default_timer() - start print('finish %s %.3fms' % ( wrapped.__name__, duration*1000.0)) def apply_patches(module): print('patching', module.__name__) wrap_function_wrapper(module, 'WSGIRequestHandler.handle', timed_function)
  • 47. Enabling patches. $ AUTOWRAPT_BOOTSTRAP=wrapt_wsgiref_debugging $ export AUTOWRAPT_BOOTSTRAP $ python app.py patching wsgiref.simple_server start handle 127.0.0.1 - - [14/Jul/2016 10:18:46] "GET / HTTP/1.1" 200 12 finish handle 1.018ms
  • 48. Packaging of patches means they could technically be shared via PyPi. Eg: instrumentation for monitoring.
  • 49. Reasons to use wrapt. • Create better decorators. • Awesome thread synchronisation decorator. • Safer mechanisms for monkey patching.