2013-04-09 14 views
10

Ho un modulo che dovrebbe avere un @property, ho risolto questo impostando una classe come modulo. Ho avuto l'idea da questa risposta: Lazy module variables--can it be done?Proprietà modulo documento Sfinge

Volevo che fosse ripetibile e facile da usare, quindi ho creato un metaclasse per questo. Funziona come un fascino.

Il problema è che quando si utilizza Sphinx per generare proprietà della documentazione non viene documentato. Tutto il resto è documentato come previsto. Non ho idea di come risolvere questo problema, forse questo è un problema con Sphinx?

Il modulo:

import sys 
import types 

class ClassAsModule(type): 
    def __new__(cls, name, bases, attrs): 
     # Make sure the name of the class is the module name. 
     name = attrs.pop('__module__') 
     # Create a class. 
     cls = type.__new__(cls, name, bases, attrs) 
     # Instantiate the class and register it. 
     sys.modules[name] = cls = cls(name) 
     # Update the dict so dir works properly 
     cls.__dict__.update(attrs) 

class TestClass(types.ModuleType): 
    """TestClass docstring.""" 
    __metaclass__ = ClassAsModule 
    @property 
    def some_property(self): 
     """Property docstring.""" 
     pass 
    def meth(): 
     """meth doc""" 
     pass 

E un copia-incolla per generare/visualizzare la documentazione Sfinge:

sphinx-apidoc . -o doc --full 
sphinx-build doc html 
xdg-open html/module.html 

La parte più essenziale è quello di documentare le proprietà della classe. Punti bonus per documentare anche i membri del modulo originale.

MODIFICA: La classe deve essere documentata come il modulo in cui si trova. La classe viene utilizzata in questo modo e dovrebbe quindi apparire in questo modo in Sfinge.

Esempio di output desiderato:

Module Foo 
    TestClass docstring. 

    some_property 
     Property docstring. 

    meth() 
     meth doc 

EDIT 2: ho trovato qualcosa che può aiutare a trovare una soluzione. Quando avere un modulo di regolare foo con il seguente contenuto:

#: Property of foo 
prop = 'test' 

documenti Sphinx questo come:

foo.prop = 'test' 
    Property of foo 

Le stesse opere se prop è un attributo di una classe. Non ho capito perché non funziona nel mio caso particolare.

+0

Il tuo codice non funziona. 'ModMeta' non è definito. Potresti per favore postare codice funzionante? – jterrace

+0

@jterrace Copia-incolla fallita. È stato risolto ora ;-) – siebz0r

+0

Ho eliminato la mia risposta perché il codice originale aveva '__metaclass_' invece di' __metaclass__', causandone il non funzionamento. – jterrace

risposta

1

Ecco la mia comprensione.

La teoria è: fare un mutante la classe si comportano come un modulo di questo (un po 'hacky) modo rende sfinge pensare che egli non ha bisogno (per analizzare) oggetti di moduli (perché è un paradigma a livello di classe). Quindi, per la sfinge, TestClass è un modulo.

Prima di tutto, per assicurarsi che il colpevole è il codice per fare un atto di classe come un modulo - cerchiamo di rimuoverlo:

class ClassAsModule(type): 
    pass 

vedremo nei documenti:

package Package 
    script Module 

    class package.script.ClassAsModule 
     Bases: type 

    class package.script.TestClass 
     Bases: module 

     TestClass docstring. 

     meth() 
      meth doc 

     some_property 
      Property docstring. 

Come vedi, la sfinge ha letto la proprietà senza problemi. Niente di speciale qui.


possibile soluzione per il vostro problema è quello di evitare l'uso di @property decoratore e sostituirlo con chiamando property costruttore di classe. Per esempio.:

import sys 
import types 

class ClassAsModule(type): 
    def __new__(cls, name, bases, attrs): 
     # Make sure the name of the class is the module name. 
     name = attrs.pop('__module__') 
     # Create a class. 
     cls = type.__new__(cls, name, bases, attrs) 
     # Instantiate the class and register it. 
     sys.modules[name] = cls = cls(name) 
     # Update the dict so dir works properly 
     cls.__dict__.update(attrs) 


class TestClass(types.ModuleType): 
    """TestClass docstring.""" 
    __metaclass__ = ClassAsModule 

    def get_some_property(self): 
     """Property docstring.""" 
     pass 

    some_property = property(get_some_property) 

    def meth(self): 
     """meth doc""" 
     pass 

Per questo codice sfinge genera:

package Package 
    script Module 
     TestClass docstring. 

      package.script.get_some_property(self) 
       Property docstring. 

      package.script.meth(self) 
       meth doc 

può essere la risposta è un pezzo di sciocchezze, ma spero che sarà punto è nella giusta direzione.

+0

Purtroppo questo non ha il senso di avere l'uso delle proprietà e della documentazione in sincrono. – siebz0r

+0

Sì, ma è importante capire che decoratore di '@ property' è solo uno zucchero di sintassi. Definire le proprietà tramite l'istanziazione della classe 'property', come ho suggerito, funziona esattamente allo stesso modo dell'utilizzo del decoratore. Ma, certo, in questo caso la documentazione mostra un'immagine un po 'diversa. – alecxe

+0

Ti assegnerò la taglia perché altrimenti nessuno riceverà quei punti. Non riceverò un rimborso e non mi aspetto una risposta accettata al più presto, quindi mi è sembrata la cosa "migliore" da fare. – siebz0r

0

Il modo che ho trovato che funziona meglio è quello di mantenere il contenuto del file lo stesso come se si stesse scrivendo un modulo regolare, poi alla fine sostituire il modulo embrionale sys.modules:

"""Module docstring. """ 

import sys 
import types 

def _some_property(self): 
    pass 
some_property = property(_some_property) 
"""Property docstring.""" 

def meth(): 
    """meth doc""" 
    pass 

def _make_class_module(name): 
    mod = sys.modules[name] 
    cls = type('ClassModule', (types.ModuleType,), mod.__dict__) 
    clsmod = cls(name) 
    clsmod.__dict__.update(mod.__dict__) 
    clsmod.__wrapped__ = mod 
    sys.modules[name] = clsmod 
_make_class_module(__name__) 

documentazione Testo :

mymod Module 
************ 

Module docstring. 

mymod.meth() 

    meth doc 

mymod.some_property = None 

    Property docstring. 

per la versione di Sfinge sto usando (v1.1.3), sembra che si deve applicare il costruttore di proprietà in modo esplicito (non è possibile utilizzarlo come decoratore), e il docstring ha per andare nel file al livello più alto, sulla linea dopo il costrutto o chiamata che crea la proprietà (non funziona come docstring all'interno del getter della proprietà). La fonte è ancora abbastanza leggibile, però.

Problemi correlati