Skip to content

Instantly share code, notes, and snippets.

@aericson
Created February 5, 2015 17:36
Show Gist options
  • Save aericson/0a456a725d1f16ad1146 to your computer and use it in GitHub Desktop.
Save aericson/0a456a725d1f16ad1146 to your computer and use it in GitHub Desktop.
Exemplo de uso de metaclass
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": "",
"signature": "sha256:ae2acf626e9dee6ea411b000dd488b72ceb7f7f0c5f76c6372d11a497de63669"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"O que a gente quer \u00e9 ter um `__doc__` gerado automaticamente"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A implementa\u00e7\u00e3o mais simples seria:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class A(object):\n",
" \n",
" def __init__(self, resource=None):\n",
" self.resource = resource\n",
" \n",
" def _get_doc(self):\n",
" return self.resource\n",
"\n",
" __doc__ = property(_get_doc)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 1
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a = A(resource='doc of method x in api')"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a.__doc__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 3,
"text": [
"'doc of method x in api'"
]
}
],
"prompt_number": 3
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Mas e se A n\u00e3o tiver self.resource?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a = A()\n",
"print a.__doc__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"None\n"
]
}
],
"prompt_number": 4
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class A(object):\n",
" \n",
" def __init__(self, resource=None):\n",
" self.resource = resource\n",
" \n",
" def _get_doc(self):\n",
" if self.resource:\n",
" return self.resource\n",
" else:\n",
" return ''\n",
" __doc__ = property(_get_doc)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a = A()\n",
"print a.__doc__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
}
],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Seria legal se `__doc__` tivesse alguma coisa interessante caso n\u00e3o tivesse resource.\n",
"Seria bom se ele retornasse a `__doc__` da class que \u00e9 o comportamento padr\u00e3o do `__doc__`"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class A(object):\n",
" \"\"\"This is a doc string\"\"\""
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a = A()\n",
"a.__doc__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 8,
"text": [
"'This is a doc string'"
]
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Seguindo nossa implementa\u00e7\u00e3o anterior:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class A(object):\n",
" \"\"\"This is a docstring\"\"\"\n",
" \n",
" def __init__(self, resource=None):\n",
" self.resource = resource\n",
" \n",
" def _get_doc(self):\n",
" if self.resource:\n",
" return self.resource\n",
" else:\n",
" return A.__doc__\n",
"\n",
" __doc__ = property(_get_doc)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 9
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a = A()\n",
"print a.__doc__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"<property object at 0x7f2a8cb9cfc8>\n"
]
}
],
"prompt_number": 10
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"O problema \u00e9 que quando criamos a property pra `__doc__` o docstring original se perde.\n",
"A \u00fanica solu\u00e7\u00e3o que encontrei foi guardar o conteudo da docstring no momento de cria\u00e7\u00e3o da class."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class KeepDocMetaClass(type):\n",
"\n",
" def __new__(cls, name, bases, attrs):\n",
" def _get_doc(self):\n",
" if self.resource:\n",
" return self.resource\n",
" # attrs['__doc__'] vai ter o valor da docstring\n",
" return attrs.get('__doc__')\n",
" new_attrs = attrs.copy()\n",
" new_attrs['__doc__'] = property(_get_doc)\n",
"\n",
" return super(KeepDocMetaClass, cls).__new__(cls, name, bases, new_attrs)\n",
"\n",
"\n",
"class SimpleTapiocaClient(object):\n",
" \"\"\"This has a doc string and will make sphinx happy :)\"\"\"\n",
" __metaclass__ = KeepDocMetaClass\n",
" \n",
" def __init__(self, resource=None):\n",
" self.resource = resource"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 11
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a = SimpleTapiocaClient(resource='a new docstring!')\n",
"a.__doc__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 12,
"text": [
"'a new docstring!'"
]
}
],
"prompt_number": 12
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a = SimpleTapiocaClient()\n",
"a.__doc__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 13,
"text": [
"'This has a doc string and will make sphinx happy :)'"
]
}
],
"prompt_number": 13
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 13
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment