2015-12-11 8 views
6

Mi piacerebbe aggiungere suggerimenti di tipo Python 3.5 per gli attributi di oggetti generati dinamicamente, in modo che gli IDE li completino automaticamente. Qui con "dinamico" intendo che l'attributo non è presente durante la creazione della classe o in __init__ o in qualsiasi altro metodo.Attributi di istanza generati dinamicamente da Python 3.5

E.g. c'è un modo per aggiungere questi attraverso commenti o altri trucchi? In caso contrario, posso eseguire il fallback per aggiungere attributi di classe fittizi.

Esempio ::

class Request: 
     """Example HTTP request object. 

     We have `get_user()` but we do not declare it anyhere. 
     """ 

... 


# Pyramid's way of plugging in methods and properties to request, enabled addon capabilities for the framework 
# adds Request.user - done in different part of application lifecycle, not during class creation 
config.add_request_method(auth.get_user, 'user', reify=True) 

L'obiettivo è di fare questo lavoro in modo che PyCharm e altri IDE sarebbero completare questo attributo.

+0

Sospetto che ciò richiederà un grande sforzo per rendere questo lavoro ovunque ma nella libreria che aggiunge i metodi per voi. Se aggiunge metodi con annotazioni di tipo corrette, dovrebbe funzionare. Forse dovresti presentare un bug di richiesta di funzionalità su Pyramid? – Blckknght

risposta

1

In Python 3.6+ è possibile utilizzare i suggerimenti di tipo livello classe - il se non genererebbe attributi nella classe. Cioè

class Request(_Request): 
    user: Optional[User] 

Questo non creerebbe un attributo nella classe, solo un'annotazione.

>>> Request.user 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: type object 'Request' has no attribute 'user' 

>>> Request.__annotations__ 
{'user': typing.Union[foo.User, NoneType]} 

In Python 3.5 è possibile effettuare una funzione che restituisce un descrittore non di dati (cioè un descrittore senza__set__); questo sarebbe sovrascrivibile da un attributo di istanza ma viene fornito con un minimo di sovraccarico di runtime - il descrittore verrà recuperato da __dict__ e controllato se definisce lo slot __set__ - anche per tutte le letture. Si potrebbe quindi essere simile

class Request(_Request): 
    user = typed(User) 

dove il typed è definito come

def typed(type: Type[T]) -> T: 
    ... return a dummy non-data-descriptor... 

Questo dovrebbe essere sufficiente per PyCharm dedurre correttamente i tipi.

3
  • ho sottoclasse la classe vera

  • aggiungo finto __type_hinting__ metodo nella mia classe

  • Io uso questa classe al posto di quello reale come tipo di argomento suggerimento

    class Request(_Request): 
        """ 
        HTTP request class. 
        This is a Pyramid Request object augmented with type hinting information for Websauna-specific functionality. 
        To know more about request read also 
        * py:class:`pyramid.request.Request` documentation 
        * py:class:`webob.request.Request` documentation 
    
        Counterintuitively, this request is also available in non-HTTP applications like command line applications and timed tasks. 
        These applications do not get request URL from a front end HTTP webserver, but a faux request is constructed pointing to the website URL taken from ``websauna.site_url`` setting. 
        This is to allow similar design patterns and methodology to be applied in HTTP and non-HTTP applications. 
    
        By setting variables in ``__type_hinting__()`` based on arguments types allows IDEs to infer type information when you hint your views as:: 
    
         from websauna.system.http import Request 
    
         def hello_world(request: Request): 
          request. # <-- When typing, here autocompletion kicks in. 
    
        """ 
    
        def __type_hinting__(self, user: Optional[User], dbsession: Session, session: ISession, admin: Admin, registry: Registry): 
         """ 
         A dummy helper function to tell IDEs about reify'ed variables. 
         :param user: The logged in user. None if the visitor is anonymous. 
         :param dbsession: Current active SQLAlchemy session 
         :param session: Session data for anonymous and logged in users. 
         :param admin: The default admin interface of the site. Note that the site can have several admin interfaces for different purposes. 
         :param registry: Pyramid registry's. E.g. 
          :py:attr:`pyramid.registry.Registry.settings` for reading settings and :py:meth:`pyramid.registry.Registry.notify` for sending events. 
         """ 
         self.user = user 
         self.dbsession = dbsession 
         self.session = session 
         self.admin = admin 
         self.registry = registry 
    
Problemi correlati