1616# from os import glob
1717
1818from .categories import Category , parse as parse_categories
19+ from .fs import Fs , PathFs
1920from .metadata import (
2021 Example ,
2122 DocFilenames ,
@@ -55,6 +56,7 @@ class DocGenMergeWarning(MetadataError):
5556class DocGen :
5657 root : Path
5758 errors : MetadataErrors
59+ fs : Fs = field (default_factory = PathFs )
5860 entities : Dict [str , str ] = field (default_factory = dict )
5961 prefix : Optional [str ] = None
6062 validation : ValidationConfig = field (default_factory = ValidationConfig )
@@ -171,8 +173,12 @@ def extend_examples(self, examples: Iterable[Example], errors: MetadataErrors):
171173 self .examples [id ] = example
172174
173175 @classmethod
174- def empty (cls , validation : ValidationConfig = ValidationConfig ()) -> "DocGen" :
175- return DocGen (root = Path ("/" ), errors = MetadataErrors (), validation = validation )
176+ def empty (
177+ cls , validation : ValidationConfig = ValidationConfig (), fs : Fs = PathFs ()
178+ ) -> "DocGen" :
179+ return DocGen (
180+ root = Path ("/" ), errors = MetadataErrors (), validation = validation , fs = fs
181+ )
176182
177183 @classmethod
178184 def default (cls ) -> "DocGen" :
@@ -190,6 +196,7 @@ def clone(self) -> "DocGen":
190196 snippet_files = set (),
191197 cross_blocks = set (),
192198 examples = {},
199+ fs = self .fs ,
193200 )
194201
195202 def for_root (
@@ -199,7 +206,7 @@ def for_root(
199206
200207 config = config or Path (__file__ ).parent / "config"
201208
202- doc_gen = DocGen .empty ()
209+ doc_gen = DocGen .empty (fs = self . fs )
203210 parse_config (doc_gen , root , config , self .validation .strict_titles )
204211 self .merge (doc_gen )
205212
@@ -209,31 +216,31 @@ def for_root(
209216 return self
210217
211218 def find_and_process_metadata (self , metadata_path : Path ):
212- for path in metadata_path . glob ("*_metadata.yaml" ):
219+ for path in self . fs . glob (metadata_path , "*_metadata.yaml" ):
213220 self .process_metadata (path )
214221
215222 def process_metadata (self , path : Path ) -> "DocGen" :
216223 if path in self ._loaded :
217224 return self
218225 try :
219- with open (path ) as file :
220- examples , errs = parse_examples (
221- path ,
222- yaml .safe_load (file ),
223- self .sdks ,
224- self .services ,
225- self .standard_categories ,
226- self .cross_blocks ,
227- self .validation ,
228- )
229- self .extend_examples (examples , self .errors )
230- self .errors .extend (errs )
231- for example in examples :
232- for lang in example .languages :
233- language = example .languages [lang ]
234- for version in language .versions :
235- for excerpt in version .excerpts :
236- self .snippet_files .update (excerpt .snippet_files )
226+ content = self . fs . read (path )
227+ examples , errs = parse_examples (
228+ path ,
229+ yaml .safe_load (content ),
230+ self .sdks ,
231+ self .services ,
232+ self .standard_categories ,
233+ self .cross_blocks ,
234+ self .validation ,
235+ )
236+ self .extend_examples (examples , self .errors )
237+ self .errors .extend (errs )
238+ for example in examples :
239+ for lang in example .languages :
240+ language = example .languages [lang ]
241+ for version in language .versions :
242+ for excerpt in version .excerpts :
243+ self .snippet_files .update (excerpt .snippet_files )
237244 self ._loaded .add (path )
238245 except ParserError as e :
239246 self .errors .append (YamlParseError (file = path , parser_error = str (e )))
@@ -246,8 +253,9 @@ def from_root(
246253 config : Optional [Path ] = None ,
247254 validation : ValidationConfig = ValidationConfig (),
248255 incremental : bool = False ,
256+ fs : Fs = PathFs (),
249257 ) -> "DocGen" :
250- return DocGen .empty (validation = validation ).for_root (
258+ return DocGen .empty (validation = validation , fs = fs ).for_root (
251259 root , config , incremental = incremental
252260 )
253261
@@ -348,6 +356,10 @@ def default(self, obj):
348356 "__entity_errors__" : [{error .entity : error .message ()} for error in obj ]
349357 }
350358
359+ if isinstance (obj , Fs ):
360+ # Don't serialize filesystem objects for security
361+ return {}
362+
351363 if isinstance (obj , set ):
352364 return {"__set__" : list (obj )}
353365
@@ -356,64 +368,63 @@ def default(self, obj):
356368
357369def parse_config (doc_gen : DocGen , root : Path , config : Path , strict : bool ):
358370 try :
359- with open (root / ".doc_gen" / "validation.yaml" , encoding = "utf-8" ) as file :
360- validation = yaml .safe_load (file )
361- validation = validation or {}
362- doc_gen .validation .allow_list .update (validation .get ("allow_list" , []))
363- doc_gen .validation .sample_files .update (validation .get ("sample_files" , []))
371+ content = doc_gen . fs . read (root / ".doc_gen" / "validation.yaml" )
372+ validation = yaml .safe_load (content )
373+ validation = validation or {}
374+ doc_gen .validation .allow_list .update (validation .get ("allow_list" , []))
375+ doc_gen .validation .sample_files .update (validation .get ("sample_files" , []))
364376 except Exception :
365377 pass
366378
367379 try :
368380 sdk_path = config / "sdks.yaml"
369- with sdk_path . open ( encoding = "utf-8" ) as file :
370- meta = yaml .safe_load (file )
371- sdks , errs = parse_sdks (sdk_path , meta , strict )
372- doc_gen .sdks = sdks
373- doc_gen .errors .extend (errs )
381+ content = doc_gen . fs . read ( sdk_path )
382+ meta = yaml .safe_load (content )
383+ sdks , errs = parse_sdks (sdk_path , meta , strict )
384+ doc_gen .sdks = sdks
385+ doc_gen .errors .extend (errs )
374386 except Exception :
375387 pass
376388
377389 try :
378390 services_path = config / "services.yaml"
379- with services_path . open ( encoding = "utf-8" ) as file :
380- meta = yaml .safe_load (file )
381- services , service_errors = parse_services (services_path , meta )
382- doc_gen .services = services
383- for service in doc_gen .services .values ():
384- if service .expanded :
385- doc_gen .entities [service .long ] = service .expanded .long
386- doc_gen .entities [service .short ] = service .expanded .short
387- doc_gen .errors .extend (service_errors )
391+ content = doc_gen . fs . read ( services_path )
392+ meta = yaml .safe_load (content )
393+ services , service_errors = parse_services (services_path , meta )
394+ doc_gen .services = services
395+ for service in doc_gen .services .values ():
396+ if service .expanded :
397+ doc_gen .entities [service .long ] = service .expanded .long
398+ doc_gen .entities [service .short ] = service .expanded .short
399+ doc_gen .errors .extend (service_errors )
388400 except Exception :
389401 pass
390402
391403 try :
392404 categories_path = config / "categories.yaml"
393- with categories_path .open (encoding = "utf-8" ) as file :
394- meta = yaml .safe_load (file )
395- standard_categories , categories , errs = parse_categories (
396- categories_path , meta
397- )
398- doc_gen .standard_categories = standard_categories
399- doc_gen .categories = categories
400- doc_gen .errors .extend (errs )
405+ content = doc_gen .fs .read (categories_path )
406+ meta = yaml .safe_load (content )
407+ standard_categories , categories , errs = parse_categories (categories_path , meta )
408+ doc_gen .standard_categories = standard_categories
409+ doc_gen .categories = categories
410+ doc_gen .errors .extend (errs )
401411 except Exception :
402412 pass
403413
404414 try :
405415 entities_config_path = config / "entities.yaml"
406- with entities_config_path . open ( encoding = "utf-8" ) as file :
407- entities_config = yaml .safe_load (file )
416+ content = doc_gen . fs . read ( entities_config_path )
417+ entities_config = yaml .safe_load (content )
408418 for entity , expanded in entities_config ["expanded_override" ].items ():
409419 doc_gen .entities [entity ] = expanded
410420 except Exception :
411421 pass
412422
413423 metadata = root / ".doc_gen/metadata"
414424 try :
425+ cross_content_path = metadata .parent / "cross-content"
415426 doc_gen .cross_blocks = set (
416- [path .name for path in ( metadata . parent / "cross-content" ) .glob ("*.xml" )]
427+ [path .name for path in doc_gen . fs .glob (cross_content_path , "*.xml" )]
417428 )
418429 except Exception :
419430 pass
0 commit comments