Metaprogrammierung, praktisch

                                   Andi Albrecht

                                       PyCon DE 2012


                               30. Oktober 2012




Hintergrund        Ein paar Konzepte                    Use-Cases                          Sinn oder Unsinn?
...                .....                                .....
                                                Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Andi Albrecht – @andialbrecht


              Erster Python-Kontakt vor etwa 10 Jahren als
              Studentische Hilfskraft bei der DFG
              Aktuell: Anwendungsentwickler für Webapplikationen bei
              ProUnix in Bonn
              Entwicklung und Pflege mittlerer und großer Systeme
              OpenSource: Rietveld Code Review Tool,
              python-sqlparse, CrunchyFrog, hgsvn, ...




Hintergrund              Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                      .....                       .....
                                             Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Übersicht

       Hintergrund


       Ein paar Konzepte


       Use-Cases


       Sinn oder Unsinn?




Hintergrund          Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                  .....                       .....
                                         Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Hintergrund
Was ist Metaprogrammierung?



              "Programmierung der Programmierung"
              "Programmcode erzeugt|untersucht|… Programmcode"
              "Programmcode wird zu Objekten von anderem
              (Meta-)Programmcode"




Hintergrund             Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                     .....                       .....
                                            Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Hintergrund
Was ist Metaprogrammierung?



              "Programmierung der Programmierung"
              "Programmcode erzeugt|untersucht|… Programmcode"
              "Programmcode wird zu Objekten von anderem
              (Meta-)Programmcode"
              mysterious, strange, weird, mind-blowing, …




Hintergrund              Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                      .....                       .....
                                             Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Hintergrund
Was ist Metaprogrammierung?


              "Programmierung der Programmierung"
              "Programmcode erzeugt|untersucht|… Programmcode"
              "Programmcode wird zu Objekten von anderem
              (Meta-)Programmcode"
              mysterious, strange, weird, mind-blowing, …
       Meta-: jenseits, dahinter liegend, …




Hintergrund              Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                      .....                       .....
                                             Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Hintergrund
Metaklassen in Python

              Wohl bekannteste Form der Metaprogrammierung in
              Python
              Möglichkeiten zur Modifikation von Klassen schon in 1995
              als C-Extension möglich (Don Beaudry Hook)
              Ab Python 1.5 auch ohne C-Extension∗
              Echter Support für Metaklassen mit New-Style-Classes in
              Python 2.2
       * dazu: Essay von GvR "Metaclasses in Python 1.5 (a.k.a. The Killer Joke)"
       http://www.python.org/doc/essays/metaclasses/
       http://python-history.blogspot.de/2009/04/metaclasses-and-extension-classes-aka.html




Hintergrund                 Ein paar Konzepte                Use-Cases                          Sinn oder Unsinn?
...                         .....                            .....
                                                     Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Hintergrund
Metaklassen in Python
       Python 1995: C-Extension                 Python 2.2
       Python 1.5
                                                class Foo(object):
       class Tracing:
                                                  __metaclass__ = MyMetaclass
         def __init__(self,
           name, bases, namespace):
         def __call__(self):                    Python 3
       class Instance:
         def __init__(self, klass):
         def __getattr__(self, name):
                                                class Foo(metaclass=MyMetaclass):
                                                  pass
       class BoundMethod:
         def __init__(self,
           function, instance):
         def __call__(self, *args):

       Trace = Tracing(’Trace’, (), )

       class MyTracedClass(Trace):
         def method1(self, a):



Hintergrund                 Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                         .....                       .....
                                                Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Konzepte
Metaprogrammierung in Python


              Types
              Metaklassen
              Dekoratoren
              Code-Generierung zur Laufzeit (synthetische
              Funktionen/Klassen)
              ...




Hintergrund             Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                     .....                       .....
                                            Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Konzepte
type()

              type(object) → liefert Typ des Objekts
              type(name, bases, namespace) → erzeugt einen
              neuen Typ

       > def my_func(self):
       .    return 42

       > Question = type(’Question’, (), {’answer’: my_func})
       > Question().answer()
       < 42




Hintergrund             Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                     .....                       .....
                                            Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Konzepte
types-Modul
       import types

       # Modul erzeugen
       my_mod = types.ModuleType(’foo’, ’doc string’)
       my_mod.foo = my_func
       sys.modules[’heyho’] = my_mod
       import heyho
       heyho.foo()

       # Methode erzeugen
       def answer(self):
           return 42
       class Foo(object):
           pass
       foo1 = Foo()
       foo2 = Foo()
       foo1.answer = types.MethodType(answer, foo1)
       foo1.answer() # gibt 42 zurück
       foo2.answer() # wirft einen AttributeError

Hintergrund            Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                    .....                       .....
                                           Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Konzepte
Metaklassen


              Metaklassen modifizieren Klassen
              Metaklassen können Meta-Funktionen haben
              Beispiel für Einsatzzwecke:
                  neue Typen von Klassen
                  neues Verhalten von Klassen
                  Automatisierungen
                  Registrierung von Klassen
                  Frameworks, ORMs
                  Introspektion, QA




Hintergrund             Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                     .....                       .....
                                            Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Konzepte
Metaklassen, Beispiel
       class PluginRegistry(type):

              registry = {}

              def __new__(mcls, name, bases, classdict):
                  return type.__new__(mcls, name, bases, classdict)

              def __init__(cls, name, bases, namespace):
                  PluginRegistry.register(cls)
                  return super(PluginRegistery, cls).__init__(name, bases, namespace)

              @classmethod
              def register(mcls, cls):
                  mcls.registry[cls.__name__] = cls

              @classmethod
              def get_all(cls):
                  return cls.registry

       class Foo(metaclass=PluginRegistry): pass
       class Bar(metaclass=PluginRegistry): pass

       PluginRegistry.get_all() # –> gibt {’Foo’: <class Foo>, ’Bar’: <class Bar>} zurück
       Foo.get_all()     # –> gibt {’Foo’: <class Foo>, ’Bar’: <class Bar>} zurück
       Foo().get_all()   # –> AttributeError


Hintergrund                    Ein paar Konzepte                Use-Cases                          Sinn oder Unsinn?
...                            .....                            .....
                                                        Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Konzepte
Klassendekoratoren, Definition zur Laufzeit, ...
              Klassendekoratoren                           Monkey-Patching

                                                           import amodule
              @my_classdecorator
              class Foo(object):                           def better_func():
                pass                                         print(’This is better!’)
                                                             return None
              Code-Generierung zur
              Laufzeit                                     amodule.func = better_func

              namespace = {}                               ...
              exec(”””def answer():
                return 42”””, namespace)
              namespace[’answer’]() # 42

              aber exec lieber vermeiden!




Hintergrund                          Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                                  .....                       .....
                                                         Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Use-Cases



              Enum-Implementierung mit type (Erstellung neuer Typen)
              ORM-API mit Metaklassen (Framework / ORM)
              Aufbau einer Testmatrix (Automatisierung)




Hintergrund              Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                      .....                       .....
                                             Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Use-Cases
Enums
       def enum(**enums):
           return type(’Enum’, (), enums)

       > Numbers = enum(ONE=1, TWO=2, THREE=’three’)
       > Numbers.ONE
       1
       > Numbers.TWO
       2
       > Numbers.THREE
       ’three’

       def enum(name, *sequential):
           enums = dict(x[::-1] for x in enumerate(sequential))
           return type(name, (), enums)
       > Colors = enum(’Colors’, ’RED’, ’GREEN’, ’BLUE’)
       > Colors.RED
       0

       Siehe http://stackoverflow.com/a/1695250/97167
Hintergrund            Ein paar Konzepte            Use-Cases                          Sinn oder Unsinn?
...                    .....                        .....
                                            Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Use-Cases
Django-Models


       from django.db import model

       class Book(model.Model):
           author = models.CharField(max_length=200)
           title = models.CharField(max_length=200)
           year = models.IntegerField()

              class Meta:
                  verbose_name_plural = u’Books’




Hintergrund               Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                       .....                       .....
                                              Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Use-Cases
Django-Models
       from django.db import model

       class Book(model.Model):
           author = models.CharField(max_length=200)
           title = models.CharField(max_length=200)
           year = models.IntegerField()

              class Meta:
                  verbose_name_plural = u’Books’

       ...und was Django's Metaklasse macht (unter anderem):
              verschiebt "Meta" nach "_meta" und erstellt eigenes Objekt
              fügt neue DoesNotExist/MultipleObjectsReturned-Attribute hinzu
              ergänzt einen Record-Manager als "objects"-Attribut
              wertet die gegebenen Attribute (Namespace) aus und macht sie fit zur
              Verwendung mit einer DB
              ...
Hintergrund                Ein paar Konzepte             Use-Cases                          Sinn oder Unsinn?
...                        .....                         .....
                                                 Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Use-Cases
Test-Matrix
       class ApiTestCase(unittest.TestCase, metaclass=TestMatrixMeta):
           apicalls = (
               (’/user/1’, ’GET’, {’name’: ’foo’}),
               (’/user/1/locations’, ’GET’, [’Leipzig’,]),
           )


       python3 testmatrix.py -v
       test__user_1_json (__main__.test__user_1_locations_xml) ... ok
       test__user_1_locations_json (__main__.test__user_1_locations_xml) ... ok
       test__user_1_locations_xml (__main__.test__user_1_locations_xml) ... FAIL
       test__user_1_xml (__main__.test__user_1_locations_xml) ... ok

       ======================================================================
       FAIL: test__user_1_locations_xml (__main__.test__user_1_locations_xml)
       ———————————————————————-
       Traceback (most recent call last):
         File ”testmatrix.py”, line 17, in test_wrapper
           self.assertFalse(u==’/user/1/locations’ and c == ’xml’)
       AssertionError: True is not false

       ———————————————————————-
       Ran 4 tests in 0.001s

       FAILED (failures=1)


Hintergrund                  Ein paar Konzepte               Use-Cases                          Sinn oder Unsinn?
...                          .....                           .....
                                                     Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Use-Cases
Test-Matrix
       class TestMatrixMeta(type):

              def __new__(mcls, name, bases, attrs):
                  apicalls = attrs.pop(’apicalls’, [])
                  for url, method, expected in apicalls:
                      for ctype in (’json’, ’xml’):
                          name = ’test_%s_%s’ % (url.replace(’/’, ’_’), ctype)
                          attrs[name] = mcls.build_test(name, url, method, expected, ctype)
                  new_cls = type.__new__(mcls, name, bases, attrs)
                  return new_cls

              @classmethod
              def build_test(cls, name, url, method, expected, ctype):
                  def test_wrapper(self, u=url, m=method, e=expected, c=ctype):
                      self.assertFalse(u==’/user/1/locations’ and c == ’xml’)
                  test_wrapper.__name__ = name
                  return test_wrapper

       class ApiTestCase(unittest.TestCase, metaclass=TestMatrixMeta):
           apicalls = (
               (’/user/1’, ’GET’, {’name’: ’foo’}),
               (’/user/1/locations’, ’GET’, [’Leipzig’,]),
           )



Hintergrund                    Ein paar Konzepte                Use-Cases                          Sinn oder Unsinn?
...                            .....                            .....
                                                        Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Sinn oder Unsinn?

              Für (fast) alles gibt es auch einen andere Lösung
              Debugging wird teils schwieriger, Fehlverhalten nicht
              immer transparent

              Verwendung des Codes wird für End-Entwickler eleganter
              Leichte Erweiterung der Sprache um spezielle
              Paradigmen, Funktionen, Verhalten, Qualitätsrichtlinien, …

       → Metaprogrammierung gezielt einsetzen
       → Einsatz transparent machen



Hintergrund              Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                      .....                       .....
                                             Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Danke!

              E-Mail albrecht@prounix.de
                     albrecht.andi@gmail.com

              Twitter @andialbrecht

        Homepage http://andialbrecht.de

                     http://www.prounix.de/unternehmen/jobs/python/
                     prounix.de




Hintergrund             Ein paar Konzepte           Use-Cases                          Sinn oder Unsinn?
...                     .....                       .....
                                            Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012

Metaprogrammierung, praktisch

  • 1.
    Metaprogrammierung, praktisch Andi Albrecht PyCon DE 2012 30. Oktober 2012 Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 2.
    Andi Albrecht –@andialbrecht Erster Python-Kontakt vor etwa 10 Jahren als Studentische Hilfskraft bei der DFG Aktuell: Anwendungsentwickler für Webapplikationen bei ProUnix in Bonn Entwicklung und Pflege mittlerer und großer Systeme OpenSource: Rietveld Code Review Tool, python-sqlparse, CrunchyFrog, hgsvn, ... Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 3.
    Übersicht Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 4.
    Hintergrund Was ist Metaprogrammierung? "Programmierung der Programmierung" "Programmcode erzeugt|untersucht|… Programmcode" "Programmcode wird zu Objekten von anderem (Meta-)Programmcode" Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 5.
    Hintergrund Was ist Metaprogrammierung? "Programmierung der Programmierung" "Programmcode erzeugt|untersucht|… Programmcode" "Programmcode wird zu Objekten von anderem (Meta-)Programmcode" mysterious, strange, weird, mind-blowing, … Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 6.
    Hintergrund Was ist Metaprogrammierung? "Programmierung der Programmierung" "Programmcode erzeugt|untersucht|… Programmcode" "Programmcode wird zu Objekten von anderem (Meta-)Programmcode" mysterious, strange, weird, mind-blowing, … Meta-: jenseits, dahinter liegend, … Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 7.
    Hintergrund Metaklassen in Python Wohl bekannteste Form der Metaprogrammierung in Python Möglichkeiten zur Modifikation von Klassen schon in 1995 als C-Extension möglich (Don Beaudry Hook) Ab Python 1.5 auch ohne C-Extension∗ Echter Support für Metaklassen mit New-Style-Classes in Python 2.2 * dazu: Essay von GvR "Metaclasses in Python 1.5 (a.k.a. The Killer Joke)" http://www.python.org/doc/essays/metaclasses/ http://python-history.blogspot.de/2009/04/metaclasses-and-extension-classes-aka.html Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 8.
    Hintergrund Metaklassen in Python Python 1995: C-Extension Python 2.2 Python 1.5 class Foo(object): class Tracing: __metaclass__ = MyMetaclass def __init__(self, name, bases, namespace): def __call__(self): Python 3 class Instance: def __init__(self, klass): def __getattr__(self, name): class Foo(metaclass=MyMetaclass): pass class BoundMethod: def __init__(self, function, instance): def __call__(self, *args): Trace = Tracing(’Trace’, (), ) class MyTracedClass(Trace): def method1(self, a): Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 9.
    Konzepte Metaprogrammierung in Python Types Metaklassen Dekoratoren Code-Generierung zur Laufzeit (synthetische Funktionen/Klassen) ... Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 10.
    Konzepte type() type(object) → liefert Typ des Objekts type(name, bases, namespace) → erzeugt einen neuen Typ > def my_func(self): . return 42 > Question = type(’Question’, (), {’answer’: my_func}) > Question().answer() < 42 Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 11.
    Konzepte types-Modul import types # Modul erzeugen my_mod = types.ModuleType(’foo’, ’doc string’) my_mod.foo = my_func sys.modules[’heyho’] = my_mod import heyho heyho.foo() # Methode erzeugen def answer(self): return 42 class Foo(object): pass foo1 = Foo() foo2 = Foo() foo1.answer = types.MethodType(answer, foo1) foo1.answer() # gibt 42 zurück foo2.answer() # wirft einen AttributeError Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 12.
    Konzepte Metaklassen Metaklassen modifizieren Klassen Metaklassen können Meta-Funktionen haben Beispiel für Einsatzzwecke: neue Typen von Klassen neues Verhalten von Klassen Automatisierungen Registrierung von Klassen Frameworks, ORMs Introspektion, QA Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 13.
    Konzepte Metaklassen, Beispiel class PluginRegistry(type): registry = {} def __new__(mcls, name, bases, classdict): return type.__new__(mcls, name, bases, classdict) def __init__(cls, name, bases, namespace): PluginRegistry.register(cls) return super(PluginRegistery, cls).__init__(name, bases, namespace) @classmethod def register(mcls, cls): mcls.registry[cls.__name__] = cls @classmethod def get_all(cls): return cls.registry class Foo(metaclass=PluginRegistry): pass class Bar(metaclass=PluginRegistry): pass PluginRegistry.get_all() # –> gibt {’Foo’: <class Foo>, ’Bar’: <class Bar>} zurück Foo.get_all() # –> gibt {’Foo’: <class Foo>, ’Bar’: <class Bar>} zurück Foo().get_all() # –> AttributeError Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 14.
    Konzepte Klassendekoratoren, Definition zurLaufzeit, ... Klassendekoratoren Monkey-Patching import amodule @my_classdecorator class Foo(object): def better_func(): pass print(’This is better!’) return None Code-Generierung zur Laufzeit amodule.func = better_func namespace = {} ... exec(”””def answer(): return 42”””, namespace) namespace[’answer’]() # 42 aber exec lieber vermeiden! Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 15.
    Use-Cases Enum-Implementierung mit type (Erstellung neuer Typen) ORM-API mit Metaklassen (Framework / ORM) Aufbau einer Testmatrix (Automatisierung) Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 16.
    Use-Cases Enums def enum(**enums): return type(’Enum’, (), enums) > Numbers = enum(ONE=1, TWO=2, THREE=’three’) > Numbers.ONE 1 > Numbers.TWO 2 > Numbers.THREE ’three’ def enum(name, *sequential): enums = dict(x[::-1] for x in enumerate(sequential)) return type(name, (), enums) > Colors = enum(’Colors’, ’RED’, ’GREEN’, ’BLUE’) > Colors.RED 0 Siehe http://stackoverflow.com/a/1695250/97167 Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 17.
    Use-Cases Django-Models from django.db import model class Book(model.Model): author = models.CharField(max_length=200) title = models.CharField(max_length=200) year = models.IntegerField() class Meta: verbose_name_plural = u’Books’ Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 18.
    Use-Cases Django-Models from django.db import model class Book(model.Model): author = models.CharField(max_length=200) title = models.CharField(max_length=200) year = models.IntegerField() class Meta: verbose_name_plural = u’Books’ ...und was Django's Metaklasse macht (unter anderem): verschiebt "Meta" nach "_meta" und erstellt eigenes Objekt fügt neue DoesNotExist/MultipleObjectsReturned-Attribute hinzu ergänzt einen Record-Manager als "objects"-Attribut wertet die gegebenen Attribute (Namespace) aus und macht sie fit zur Verwendung mit einer DB ... Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 19.
    Use-Cases Test-Matrix class ApiTestCase(unittest.TestCase, metaclass=TestMatrixMeta): apicalls = ( (’/user/1’, ’GET’, {’name’: ’foo’}), (’/user/1/locations’, ’GET’, [’Leipzig’,]), ) python3 testmatrix.py -v test__user_1_json (__main__.test__user_1_locations_xml) ... ok test__user_1_locations_json (__main__.test__user_1_locations_xml) ... ok test__user_1_locations_xml (__main__.test__user_1_locations_xml) ... FAIL test__user_1_xml (__main__.test__user_1_locations_xml) ... ok ====================================================================== FAIL: test__user_1_locations_xml (__main__.test__user_1_locations_xml) ———————————————————————- Traceback (most recent call last): File ”testmatrix.py”, line 17, in test_wrapper self.assertFalse(u==’/user/1/locations’ and c == ’xml’) AssertionError: True is not false ———————————————————————- Ran 4 tests in 0.001s FAILED (failures=1) Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 20.
    Use-Cases Test-Matrix class TestMatrixMeta(type): def __new__(mcls, name, bases, attrs): apicalls = attrs.pop(’apicalls’, []) for url, method, expected in apicalls: for ctype in (’json’, ’xml’): name = ’test_%s_%s’ % (url.replace(’/’, ’_’), ctype) attrs[name] = mcls.build_test(name, url, method, expected, ctype) new_cls = type.__new__(mcls, name, bases, attrs) return new_cls @classmethod def build_test(cls, name, url, method, expected, ctype): def test_wrapper(self, u=url, m=method, e=expected, c=ctype): self.assertFalse(u==’/user/1/locations’ and c == ’xml’) test_wrapper.__name__ = name return test_wrapper class ApiTestCase(unittest.TestCase, metaclass=TestMatrixMeta): apicalls = ( (’/user/1’, ’GET’, {’name’: ’foo’}), (’/user/1/locations’, ’GET’, [’Leipzig’,]), ) Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 21.
    Sinn oder Unsinn? Für (fast) alles gibt es auch einen andere Lösung Debugging wird teils schwieriger, Fehlverhalten nicht immer transparent Verwendung des Codes wird für End-Entwickler eleganter Leichte Erweiterung der Sprache um spezielle Paradigmen, Funktionen, Verhalten, Qualitätsrichtlinien, … → Metaprogrammierung gezielt einsetzen → Einsatz transparent machen Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  • 22.
    Danke! E-Mail albrecht@prounix.de albrecht.andi@gmail.com Twitter @andialbrecht Homepage http://andialbrecht.de http://www.prounix.de/unternehmen/jobs/python/ prounix.de Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn? ... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012