2013-04-09 41 views
10

Tôi có mô-đun cần có số @property, tôi đã giải quyết điều này bằng cách đặt lớp làm mô-đun. Tôi có ý tưởng từ câu trả lời này: Lazy module variables--can it be done?Đặc tính mô-đun tài liệu Sphinx

Tôi muốn điều này có thể lặp lại và dễ sử dụng vì vậy tôi đã thực hiện một metaclass cho nó. Công việc này như một cái duyên vậy.

Vấn đề là khi sử dụng Nhân sư để tạo thuộc tính tài liệu không được ghi nhận. Mọi thứ khác được ghi lại như mong đợi. Tôi không có ý tưởng làm thế nào để sửa lỗi này, có lẽ đây là một vấn đề với Sphinx?

Module:

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 

Và một copy-paste để tạo/xem tài liệu hướng dẫn Sphinx:

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

Phần quan trọng nhất là để ghi lại các thuộc tính lớp. Điểm thưởng cũng là tài liệu thành viên mô-đun ban đầu.

CHỈNH SỬA: Lớp phải được ghi lại là mô-đun. Lớp này được sử dụng theo cách này và do đó sẽ xuất hiện theo cách này trong Sphinx.

Ví dụ về đầu ra mong muốn:

Module Foo 
    TestClass docstring. 

    some_property 
     Property docstring. 

    meth() 
     meth doc 

EDIT 2: tôi tìm thấy một cái gì đó mà có thể hỗ trợ trong việc tìm kiếm một giải pháp. Khi có một module thường xuyên foo với nội dung sau:

#: Property of foo 
prop = 'test' 

Sphinx tài liệu này như:

foo.prop = 'test' 
    Property of foo 

Các công trình tương tự nếu prop là một thuộc tính của một lớp. Tôi đã không tìm ra lý do tại sao nó không hoạt động trong trường hợp đặc biệt của tôi.

+0

Mã của bạn không hoạt động. 'ModMeta' không được xác định. Bạn có thể vui lòng đăng mã làm việc không? – jterrace

+0

@jterrace Sao chép-dán không thành công. Bây giờ là cố định ;-) – siebz0r

+0

Đã xóa câu trả lời của tôi vì mã ban đầu của bạn có '__metaclass_' thay vì' __metaclass__', khiến nó không hoạt động. – jterrace

Trả lời

1

Đây là sự hiểu biết của tôi.

Lý thuyết là: làm cho đột biến hoạt động lớp học của bạn giống như mô-đun này (bit chút hacky) khiến nhân sư nghĩ rằng mình không cần (phân tích) thuộc tính từ mô-đun (vì đó là mô hình cấp lớp). Vì vậy, đối với nhân sư, TestClass là một mô-đun.

Trước hết, để đảm bảo rằng thủ phạm là mã để thực hiện một hành động lớp như một module - chúng ta hãy loại bỏ nó:

class ClassAsModule(type): 
    pass 

chúng ta sẽ thấy trong tài liệu:

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. 

Như bạn thấy, nhân sư đọc tài sản mà không gặp bất kỳ vấn đề gì. Không có gì đặc biệt ở đây.


giải pháp khả thi cho vấn đề của bạn là để tránh sử dụng @property trang trí và thay thế bằng gọi property constructor lớp. Ví dụ.:

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 

Đối với mã nhân sư này tạo ra:

package Package 
    script Module 
     TestClass docstring. 

      package.script.get_some_property(self) 
       Property docstring. 

      package.script.meth(self) 
       meth doc 

Có thể câu trả lời là một mảnh vô nghĩa, nhưng tôi hy vọng nó sẽ chỉ cho bạn đi đúng hướng.

+0

Rất tiếc, điều này thiếu điểm sử dụng thuộc tính và tài liệu được đồng bộ hóa. – siebz0r

+0

Vâng, nhưng, điều quan trọng là phải hiểu rằng trang trí '' property' chỉ là một đường cú pháp. Xác định các thuộc tính thông qua instantiating lớp 'property' như tôi đã đề xuất hoạt động thực sự giống như cách sử dụng trang trí. Nhưng, chắc chắn, trong trường hợp này, tài liệu cho thấy một chút hình ảnh khác nhau một chút. – alecxe

+0

Tôi đang trao cho bạn tiền thưởng vì không ai sẽ nhận được những điểm đó. Tôi sẽ không nhận được tiền hoàn lại và tôi không mong đợi câu trả lời được chấp nhận sớm nên có vẻ như điều 'tốt nhất' cần làm. – siebz0r

0

Con đường tôi đã tìm thấy phù hợp nhất là để giữ cho nội dung tập tin giống như nếu bạn đang viết một module thường xuyên, sau đó ở cuối thay thế các mô-đun phôi trong 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__) 

tài liệu Tiêu đề :

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

Module docstring. 

mymod.meth() 

    meth doc 

mymod.some_property = None 

    Property docstring. 

Đối với phiên bản của Sphinx tôi đang sử dụng (v1.1.3), có vẻ như bạn cần phải áp dụng các nhà xây dựng bất động sản một cách rõ ràng (bạn không thể sử dụng nó như một trang trí), và docstring có để đi vào tệp ở cấp cao nhất, trên dòng sau khi xây dựng hoặc gọi tạo ra thuộc tính (nó không hoạt động như một chuỗi bên trong thuộc tính getter). Nguồn vẫn còn khá dễ đọc, mặc dù.