Coverage for pyyc/mod.py: 84%

44 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-10-09 18:58 +0200

1""" 

2Documentation for module `mod`. 

3""" 

4 

5__all__ = ["version"] # limits the content of "import *" 

6 

7version = "top-level module" 

8print(f"Initialization {__name__!r}: {version}") # NO PRINT in a true module! 

9 

10#################################################### 

11 

12import os, sys # pylint: disable=wrong-import-position,multiple-imports 

13 

14 

15def addition(*args): 

16 r""" 

17 Addition function (undefined type). 

18 

19 Arguments should support mutual addition: 

20 

21 .. math:: 

22 

23 \mathrm{out} = \sum_i \mathrm{arg}_i 

24 

25 :param args: parameters 

26 :return: python addition of args 

27 :raises TypeError: arguments cannot be summed together 

28 

29 >>> addition(1, 2, 3) 

30 6 

31 >>> addition("abc", "def") 

32 'abcdef' 

33 >>> addition([1], [2, 3], [4, 5, 6]) 

34 [1, 2, 3, 4, 5, 6] 

35 >>> addition(1, "abc") 

36 Traceback (most recent call last): 

37 ... 

38 TypeError: unsupported operand type(s) for +=: 'int' and 'str' 

39 """ 

40 

41 out = args[0] 

42 for arg in args[1:]: 

43 out += arg 

44 

45 return out 

46 

47 

48def addition_int(*args): 

49 """ 

50 Addition function for integers (includes cast to integer). 

51 

52 :param int args: arguments to be casted to integer 

53 :return: integer addition of args 

54 :rtype: int 

55 :raise ValueError: if arguments cannot be casted to integer. 

56 

57 >>> addition_int(1, 2, 3) 

58 6 

59 >>> addition_int('1', 2) 

60 3 

61 >>> addition_int("abc", "def") 

62 Traceback (most recent call last): 

63 ... 

64 ValueError: Arguments must cast to integer. 

65 """ 

66 

67 try: 

68 iargs = [int(arg) for arg in args] 

69 except ValueError as exc: 

70 raise ValueError("Arguments must cast to integer.") from exc 

71 

72 return sum(iargs) 

73 

74 

75if sys.version_info[:2] >= (3, 10): 

76 from importlib.resources import files # Python 3.10+ 

77else: 

78 from importlib_resources import files # External 

79 

80PYYC_PATH = files("pyyc.config") #: Path to pyyc configuration file. 

81 

82 

83def read_config(cfgname="default.cfg"): 

84 """ 

85 Get config from configuration file. 

86 

87 If the input filename does not specifically include a path, it will be 

88 looked for in the default :const:`PYYC_PATH` directory. 

89 

90 :param str cfgname: configuration file name 

91 :return: configuration object 

92 :rtype: configparser.ConfigParser 

93 

94 >>> cfg = read_config() # doctest: +ELLIPSIS 

95 Reading configuration from ... 

96 >>> cfg['DEFAULT']['version'] 

97 'cfg-1.0' 

98 """ 

99 

100 from configparser import ConfigParser # pylint: disable=import-outside-toplevel 

101 

102 if os.path.dirname(cfgname): # cfgname includes a path (e.g. `./path/to/file`) 

103 fname = cfgname 

104 else: # use PYYC_PATH as default 

105 fname = PYYC_PATH.joinpath(cfgname) 

106 print(f"Reading configuration from {fname!s}...") 

107 

108 cfg = ConfigParser() 

109 if not cfg.read(fname): # It silently failed 

110 raise IOError(f"Could not find or parse {fname!s}") 

111 

112 return cfg 

113 

114 

115def format_pkg_tree(node, max_depth=2, printout=False, depth=0): 

116 """ 

117 Format the package architecture. 

118 

119 :param module node: name of the top-level module 

120 :param int max_depth: maximum depth of recursion 

121 :param bool printout: print out the resulting string 

122 :param int depth: depth level (used for recursion) 

123 :return: structure as a list of strings (without newlines) 

124 :rtype: list 

125 

126 >>> import pyyc 

127 >>> format_pkg_tree(pyyc, max_depth=1) # doctest: +NORMALIZE_WHITESPACE 

128 ['pyyc', 

129 ' pyyc.config', 

130 ' pyyc.mod', 

131 ' pyyc.subpkgA', 

132 ' pyyc.subpkgB'] 

133 """ 

134 

135 if depth > max_depth: 

136 return [] 

137 

138 s = [] 

139 if hasattr(node, "__name__"): 

140 s.append(" " * depth + node.__name__) 

141 for name in dir(node): 

142 if not name.startswith("_"): 

143 s.extend( 

144 format_pkg_tree( 

145 getattr(node, name), max_depth=max_depth, depth=depth + 1 

146 ) 

147 ) 

148 

149 if printout: 

150 print("\n".join(s)) # Intentionally not tested (for coverage) 

151 

152 return s 

153 

154 

155def greetings(): 

156 """ 

157 Stupid function, to illustrate tests on stdin/stdout. 

158 """ 

159 

160 name = input("What's you name? ") 

161 print(f"Hello, {name}!")