Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/graphviz/saving.py: 80%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

44 statements  

1"""Save DOT source lines to a file.""" 

2 

3import logging 

4import os 

5 

6from . import _defaults 

7from . import _tools 

8from . import base 

9from . import encoding 

10 

11__all__ = ['Save'] 

12 

13log = logging.getLogger(__name__) 

14 

15 

16class Save(encoding.Encoding, base.Base): 

17 """Save DOT source lines to file.""" 

18 

19 directory: str = '' 

20 

21 _default_extension = _defaults.DEFAULT_SOURCE_EXTENSION 

22 

23 _mkdirs = staticmethod(_tools.mkdirs) 

24 

25 def __init__(self, *, 

26 filename: os.PathLike[str] | str | None, 

27 directory: os.PathLike[str] | str | None = None, 

28 **kwargs) -> None: 

29 super().__init__(**kwargs) 

30 

31 if filename is None: 

32 filename = f'{self.__class__.__name__}.{self._default_extension}' 

33 

34 self.filename = os.fspath(filename) 

35 """str: Target file name for saving the DOT source file.""" 

36 

37 if directory is not None: 

38 self.directory = os.fspath(directory) 

39 

40 def _copy_kwargs(self, **kwargs): 

41 """Return the kwargs to create a copy of the instance.""" 

42 assert 'directory' not in kwargs 

43 if 'directory' in self.__dict__: 

44 kwargs['directory'] = self.directory 

45 return super()._copy_kwargs(filename=self.filename, **kwargs) 

46 

47 @property 

48 def filepath(self) -> str: 

49 """The target path for saving the DOT source file.""" 

50 return os.path.join(self.directory, self.filename) 

51 

52 @_tools.deprecate_positional_args(supported_number=1, ignore_arg='self') 

53 def save(self, filename: os.PathLike[str] | str | None = None, 

54 directory: os.PathLike[str] | str | None = None, *, 

55 skip_existing: bool | None = False) -> str: 

56 """Save the DOT source to file. Ensure the file ends with a newline. 

57 

58 Args: 

59 filename: Filename for saving the source (defaults to ``name`` + ``'.gv'``) 

60 directory: (Sub)directory for source saving and rendering. 

61 skip_existing: Skip write if file exists (default: ``False``). 

62 

63 Returns: 

64 The (possibly relative) path of the saved source file. 

65 """ 

66 if filename is not None: 

67 self.filename = os.fspath(filename) 

68 if directory is not None: 

69 self.directory = os.fspath(directory) 

70 

71 filepath = self.filepath 

72 if skip_existing and os.path.exists(filepath): 

73 return filepath 

74 

75 self._mkdirs(filepath) 

76 

77 log.debug('write lines to %r', filepath) 

78 with open(filepath, 'w', encoding=self.encoding) as fd: 

79 for uline in self: 

80 fd.write(uline) 

81 

82 return filepath