@@ -37,18 +37,40 @@ class NodeInfo(NamedTuple):
3737types_dict : dict [str , set [str ]] = {}
3838log_file = None
3939
40- NTP_MIN_VERSION = (3 , 0 )
40+ BLENDER_3_MAX_VERSION = 6
41+ BLENDER_4_MAX_VERSION = 5
42+ BLENDER_5_MAX_VERSION = 0
43+
44+ NTP_MIN_VERSION = Version (3 , 0 )
45+
46+ BLENDER_VERSIONS = [Version (3 , i ) for i in range (0 , BLENDER_3_MAX_VERSION + 1 )]
47+ BLENDER_VERSIONS += [Version (4 , i ) for i in range (0 , BLENDER_4_MAX_VERSION + 1 )]
48+ BLENDER_VERSIONS += [Version (5 , i ) for i in range (0 , BLENDER_5_MAX_VERSION + 1 )]
49+
50+ def log (message : str ):
51+ if log_file is None :
52+ raise RuntimeError ("Log file was null!" )
53+ with log_mutex :
54+ log_file .write (message )
4155
4256def process_attr (attr , section , node : str , version : Version ) -> None :
57+ # Get name
4358 name_section = attr .find (["code" , "span" ], class_ = "sig-name descname" )
44-
4559 if not name_section :
4660 raise ValueError (f"{ version .tuple_str ()} { node } : Couldn't find name section in\n \t { section } " )
4761 name = name_section .text
62+
63+ # Check for deprecation
64+ if "Deprecated" in str (attr ):
65+ log (f"WARNING: { version .tuple_str ()} Attribute { node } .{ name } "
66+ f"was marked deprecated, returning\n " )
67+ return
4868
69+ # Get type
4970 type_section = attr .find ("dd" , class_ = "field-odd" )
5071 if not type_section :
51- raise ValueError (f"{ version .tuple_str ()} { node } .{ name } : Couldn't find type section in\n \t { section } " )
72+ raise ValueError (f"{ version .tuple_str ()} { node } .{ name } : "
73+ f"Couldn't find type section in\n \t { section } " )
5274 type_text = type_section .text
5375
5476 with mutex :
@@ -61,8 +83,8 @@ def process_attr(attr, section, node: str, version: Version) -> None:
6183 ntp_type = types_utils .get_NTP_type (type_text )
6284 if ntp_type is None :
6385 # Read-only attribute, don't add to attribute list
64- with log_mutex :
65- log_file . write ( f"WARNING: { version . tuple_str () } { node } . { name } 's type is being ignored:\n \t { type_text .strip ()} \n " )
86+ log ( f"WARNING: { version . tuple_str () } { node } . { name } 's "
87+ f" type is being ignored:\n \t { type_text .strip ()} \n " )
6688 return
6789
6890 ntp_setting = NTPNodeSetting (name , ntp_type )
@@ -114,7 +136,7 @@ def download_file(filepath: str, version: Version, local_path: str) -> bool:
114136
115137
116138def get_subclasses (current : str , parent : str , root_path : str ,
117- version : Version ) -> list [ str ] :
139+ version : Version ) -> None :
118140 relative_path = f"bpy.types.{ current } .html"
119141 current_path = os .path .join (root_path , relative_path )
120142
@@ -132,12 +154,14 @@ def get_subclasses(current: str, parent: str, root_path: str,
132154 main_id = f"{ current .lower ()} -{ parent .lower ()} "
133155 sections = soup .find_all (id = main_id )
134156 if not sections :
135- raise ValueError (f"{ version .tuple_str ()} { current } : Couldn't find main section with id { main_id } " )
157+ raise ValueError (f"{ version .tuple_str ()} { current } : "
158+ f"Couldn't find main section with id { main_id } " )
136159
137160 section = sections [0 ]
138161 paragraphs = section .find_all ("p" )
139162 if len (paragraphs ) < 2 :
140- raise ValueError (f"{ version .tuple_str ()} { current } : Couldn't find subclass section" )
163+ raise ValueError (f"{ version .tuple_str ()} { current } : "
164+ f"Couldn't find subclass section" )
141165
142166 subclasses_paragraph = paragraphs [1 ]
143167 if not subclasses_paragraph .text .strip ().startswith ("subclasses —" ):
@@ -147,7 +171,8 @@ def get_subclasses(current: str, parent: str, root_path: str,
147171
148172 subclass_anchors = subclasses_paragraph .find_all ("a" )
149173 if not subclass_anchors :
150- raise ValueError (f"{ version .tuple_str ()} { current } No anchors in subclasses paragraph" )
174+ raise ValueError (f"{ version .tuple_str ()} { current } "
175+ f"No anchors in subclasses paragraph" )
151176
152177 subclass_types = [anchor .get ("title" ) for anchor in subclass_anchors ]
153178 threads : list [Thread ] = []
@@ -156,13 +181,15 @@ def get_subclasses(current: str, parent: str, root_path: str,
156181 raise ValueError (f"{ version .tuple_str ()} { current } Type was invalid" )
157182 is_matching = re .match (r"bpy\.types\.(.*)" , type )
158183 if not is_matching :
159- raise ValueError (f"{ version .tuple_str ()} { current } : Type { type } was not of the form \" bpy.types.x\" " )
184+ raise ValueError (f"{ version .tuple_str ()} { current } : "
185+ f"Type { type } was not of the form \" bpy.types.x\" " )
160186 pure_type = is_matching .group (1 )
161187 if (pure_type == "TextureNode" ):
162188 # unsupported
163189 continue
164190
165- thread = Thread (target = get_subclasses , args = (pure_type , current , root_path , version ))
191+ thread = Thread (target = get_subclasses ,
192+ args = (pure_type , current , root_path , version ))
166193 threads .append (thread )
167194 thread .start ()
168195
@@ -180,24 +207,21 @@ def process_bpy_version(version: Version) -> None:
180207 get_subclasses (current , parent , root_path , version )
181208
182209def generate_versions (max_version_inc : Version ) -> list [Version ]:
183- BLENDER_3_MAX_VERSION = 6
184- BLENDER_4_MAX_VERSION = 5
210+ versions = BLENDER_VERSIONS .copy ()
185211
186- versions = [Version (3 , i ) for i in range (0 , BLENDER_3_MAX_VERSION + 1 )]
187- versions += [Version (4 , i ) for i in range (0 , BLENDER_4_MAX_VERSION + 1 )]
188- versions += [Version (5 , i ) for i in range (0 , max_version_inc .minor_ + 1 )]
189-
190- #lazy max version check
212+ # lazy version bounds check
191213 for version in versions [::- 1 ]:
192214 if version > max_version_inc :
193215 versions .remove (version )
216+ if version < NTP_MIN_VERSION :
217+ versions .remove (version )
194218
195219 return versions
196220
197221def subminor (version : Version ) -> tuple :
198222 return (version [0 ], version [1 ], 0 )
199223
200- def get_min_version (versions : list [Version ]) -> Version :
224+ def get_min_version (versions : list [Version ]) -> Version | None :
201225 min_version = min (versions )
202226
203227 if min_version != NTP_MIN_VERSION :
@@ -206,7 +230,7 @@ def get_min_version(versions: list[Version]) -> Version:
206230 return None
207231
208232def get_max_version (versions : list [Version ], blender_versions : list [Version ]
209- ) -> Version :
233+ ) -> Version | None :
210234 max_v_inclusive = max (versions )
211235 max_v_inclusive_index = blender_versions .index (max_v_inclusive )
212236 max_v_exclusive = blender_versions [max_v_inclusive_index + 1 ]
@@ -246,7 +270,8 @@ def write_node_info_class(file: TextIOWrapper):
246270 file .write ("\n " )
247271
248272def write_ntp_node_settings (node_info : NodeInfo , file : TextIOWrapper ,
249- node_min_v : Version , node_max_v : Version ):
273+ node_min_v : Version | None ,
274+ node_max_v : Version | None ) -> None :
250275 attr_dict = node_info .attributes_
251276 file .write ("\n \t \t [" )
252277 attrs_exist = len (attr_dict .items ()) > 0
@@ -286,6 +311,14 @@ def write_node(name: str, node_info: NodeInfo, file: TextIOWrapper):
286311
287312 file .write ("\n \t ),\n \n " )
288313
314+ def get_max_version_exc (max_version_inc : Version ) -> Version :
315+ idx = BLENDER_VERSIONS .index (max_version_inc )
316+ exc_idx = idx + 1
317+ if exc_idx < len (BLENDER_VERSIONS ):
318+ return BLENDER_VERSIONS [exc_idx ]
319+ else :
320+ return Version (max_version_inc .major_ , max_version_inc .minor_ + 1 )
321+
289322if __name__ == "__main__" :
290323 parser = argparse .ArgumentParser ()
291324 parser .add_argument ('max_major_version' , type = int ,
@@ -312,7 +345,8 @@ def write_node(name: str, node_info: NodeInfo, file: TextIOWrapper):
312345 for version in versions :
313346 process_bpy_version (version )
314347
315- NTP_MAX_VERSION_EXC = (NTP_MAX_VERSION_INC [0 ], NTP_MAX_VERSION_INC [1 ] + 1 )
348+ NTP_MAX_VERSION_EXC = get_max_version_exc (NTP_MAX_VERSION_INC )
349+
316350 versions .append (NTP_MAX_VERSION_EXC )
317351
318352 sorted_nodes = dict (sorted (nodes_dict .items ()))
@@ -340,8 +374,8 @@ def write_node(name: str, node_info: NodeInfo, file: TextIOWrapper):
340374 print ("Successfully finished" )
341375
342376 sorted_types = dict (sorted (types_dict .items ()))
343- log_file . write ("\n Types encountered:\n " )
377+ log ("\n Types encountered:\n " )
344378 for key , value in types_dict .items ():
345- log_file . write (f"{ key } \n " )
379+ log (f"{ key } \n " )
346380 for string in value :
347- log_file . write (f"\t { string } \n " )
381+ log (f"\t { string } \n " )
0 commit comments