55import  attr 
66from  attr .validators  import  deep_iterable , instance_of , matches_re , optional 
77
8+ #: Pattern used to match URL items. 
9+ URL_PATTERN : str  =  r".+://.*" 
10+ 
811
912class  FileItem (str ):
1013    """A document path in a toctree list. 
1114
12-     This should be in Posix format (folders split by ``/``), 
13-     relative to the source directory, 
14-     and can be with or without extension. 
15+     This should be in POSIX format (folders split by ``/``), relative to the 
16+     source directory, and can be with or without an extension. 
1517    """ 
1618
1719
@@ -24,7 +26,7 @@ class UrlItem:
2426    """A URL in a toctree.""" 
2527
2628    # regex should match sphinx.util.url_re 
27-     url : str  =  attr .ib (validator = [instance_of (str ), matches_re (r".+://.*" )])
29+     url : str  =  attr .ib (validator = [instance_of (str ), matches_re (URL_PATTERN )])
2830    title : Optional [str ] =  attr .ib (None , validator = optional (instance_of (str )))
2931
3032
@@ -39,40 +41,55 @@ class TocTree:
3941        )
4042    )
4143    caption : Optional [str ] =  attr .ib (
42-         None , kw_only = True , validator = optional (instance_of (str ))
44+         default = None , kw_only = True , validator = optional (instance_of (str ))
4345    )
44-     hidden : bool  =  attr .ib (True , kw_only = True , validator = instance_of (bool ))
45-     maxdepth : int  =  attr .ib (- 1 , kw_only = True , validator = instance_of (int ))
46+     hidden : bool  =  attr .ib (default = True , kw_only = True , validator = instance_of (bool ))
47+     maxdepth : int  =  attr .ib (default = - 1 , kw_only = True , validator = instance_of (int ))
4648    numbered : Union [bool , int ] =  attr .ib (
47-         False , kw_only = True , validator = instance_of ((bool , int ))
49+         default = False , kw_only = True , validator = instance_of ((bool , int ))
4850    )
49-     reversed : bool  =  attr .ib (False , kw_only = True , validator = instance_of (bool ))
50-     titlesonly : bool  =  attr .ib (False , kw_only = True , validator = instance_of (bool ))
51+     reversed : bool  =  attr .ib (default = False , kw_only = True , validator = instance_of (bool ))
52+     titlesonly : bool  =  attr .ib (default = False , kw_only = True , validator = instance_of (bool ))
5153
5254    def  files (self ) ->  List [str ]:
55+         """Returns a list of file items included in this ToC tree. 
56+ 
57+         :return: file items 
58+         """ 
5359        return  [str (item ) for  item  in  self .items  if  isinstance (item , FileItem )]
5460
5561    def  globs (self ) ->  List [str ]:
62+         """Returns a list of glob items included in this ToC tree. 
63+ 
64+         :return: glob items 
65+         """ 
5666        return  [str (item ) for  item  in  self .items  if  isinstance (item , GlobItem )]
5767
5868
5969@attr .s (slots = True ) 
6070class  Document :
6171    """A document in the site map.""" 
6272
63-     docname : str  =  attr .ib (validator = instance_of (str ))
64-     title : Optional [str ] =  attr .ib (None , validator = optional (instance_of (str )))
6573    # TODO validate uniqueness of docnames across all parts (and none should be the docname) 
74+     docname : str  =  attr .ib (validator = instance_of (str ))
6675    subtrees : List [TocTree ] =  attr .ib (
67-         factory = list , validator = deep_iterable (instance_of (TocTree ), instance_of (list ))
76+         factory = list ,
77+         validator = deep_iterable (instance_of (TocTree ), instance_of (list )),
6878    )
79+     title : Optional [str ] =  attr .ib (default = None , validator = optional (instance_of (str )))
6980
7081    def  child_files (self ) ->  List [str ]:
71-         """Return all children files.""" 
82+         """Return all children files. 
83+ 
84+         :return: child files 
85+         """ 
7286        return  [name  for  tree  in  self .subtrees  for  name  in  tree .files ()]
7387
7488    def  child_globs (self ) ->  List [str ]:
75-         """Return all children globs.""" 
89+         """Return all children globs. 
90+ 
91+         :return: child globs 
92+         """ 
7693        return  [name  for  tree  in  self .subtrees  for  name  in  tree .globs ()]
7794
7895
@@ -93,17 +110,26 @@ def __init__(
93110
94111    @property  
95112    def  root (self ) ->  Document :
96-         """Return the root document.""" 
113+         """Return the root document of the ToC tree. 
114+ 
115+         :return: root document 
116+         """ 
97117        return  self ._root 
98118
99119    @property  
100120    def  meta (self ) ->  Dict [str , Any ]:
101-         """Return the site-map metadata.""" 
121+         """Return the site-map metadata. 
122+ 
123+         :return: metadata dictionary 
124+         """ 
102125        return  self ._meta 
103126
104127    @property  
105128    def  file_format (self ) ->  Optional [str ]:
106-         """Return the format of the file to write to.""" 
129+         """Return the format of the file to write to. 
130+ 
131+         :return: output file format 
132+         """ 
107133        return  self ._file_format 
108134
109135    @file_format .setter  
@@ -116,21 +142,45 @@ def globs(self) -> Set[str]:
116142        return  {glob  for  item  in  self ._docs .values () for  glob  in  item .child_globs ()}
117143
118144    def  __getitem__ (self , docname : str ) ->  Document :
145+         """Enable retrieving a document by name using the indexing operator. 
146+ 
147+         :param docname: document name 
148+         :return: document instance 
149+         """ 
119150        return  self ._docs [docname ]
120151
121152    def  __setitem__ (self , docname : str , item : Document ) ->  None :
153+         """Enable setting a document by name using the indexing operator. 
154+ 
155+         :param docname: document name 
156+         :param item: document instance 
157+         """ 
122158        assert  item .docname  ==  docname 
123159        self ._docs [docname ] =  item 
124160
125-     def  __delitem__ (self , docname : str ):
161+     def  __delitem__ (self , docname : str ) ->  None :
162+         """Enable removing a document by name. 
163+ 
164+         :param docname: document name 
165+         """ 
126166        assert  docname  !=  self ._root .docname , "cannot delete root doc item" 
127167        del  self ._docs [docname ]
128168
129169    def  __iter__ (self ) ->  Iterator [str ]:
170+         """Enable iterating the names of the documents the site map is composed 
171+         of. 
172+ 
173+         :yield: document name 
174+         """ 
130175        for  docname  in  self ._docs :
131176            yield  docname 
132177
133178    def  __len__ (self ) ->  int :
179+         """Enable using Python's built-in `len()` function to return the number 
180+         of documents contained in a site map. 
181+ 
182+         :return: number of documents in this site map 
183+         """ 
134184        return  len (self ._docs )
135185
136186    @staticmethod  
@@ -151,15 +201,19 @@ def as_json(self) -> Dict[str, Any]:
151201            else  self ._docs [k ]
152202            for  k  in  sorted (self ._docs )
153203        }
154-         data  =  {"root" : self .root .docname , "documents" : doc_dict , "meta" : self .meta }
204+         data  =  {
205+             "root" : self .root .docname ,
206+             "documents" : doc_dict ,
207+             "meta" : self .meta ,
208+         }
155209        if  self .file_format :
156210            data ["file_format" ] =  self .file_format 
157211        return  data 
158212
159213    def  get_changed (self , previous : "SiteMap" ) ->  Set [str ]:
160214        """Compare this sitemap to another and return a list of changed documents. 
161215
162-         Note:  for sphinx , file extensions should be removed to get docnames 
216+         .. note::  for Sphinx , file extensions should be removed to get docnames.  
163217        """ 
164218        changed_docs  =  set ()
165219        # check if the root document has changed 
0 commit comments