Coverage for pyyc/mod.py: 50%
44 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-10-11 23:51 +0200
« prev ^ index » next coverage.py v7.2.7, created at 2023-10-11 23:51 +0200
1"""
2Documentation for module `mod`.
3"""
5__all__ = ['version'] # limits the content of "import *"
7version = "top-level module"
8print("Initialization", version) # NO PRINT in a true module!
10####################################################
12import os, sys # pylint: disable=wrong-import-position,multiple-imports
14def addition(*args):
15 r"""
16 Addition function (undefined type).
18 Arguments should support mutual addition:
20 .. math::
22 \mathrm{out} = \sum_i \mathrm{arg}_i
24 :param args: parameters
25 :return: python addition of args
26 :raises TypeError: arguments cannot be summed together
28 >>> addition(1, 2, 3)
29 6
30 >>> addition("abc", "def")
31 'abcdef'
32 >>> addition([1], [2, 3], [4, 5, 6])
33 [1, 2, 3, 4, 5, 6]
34 >>> addition(1, "abc")
35 Traceback (most recent call last):
36 ...
37 TypeError: unsupported operand type(s) for +=: 'int' and 'str'
38 """
40 out = args[0]
41 for arg in args[1:]:
42 out += arg
44 return out
47def addition_int(*args):
48 """
49 Addition function for integers (includes cast to integer).
51 :param int args: arguments to be casted to integer
52 :return: integer addition of args
53 :rtype: int
54 :raise ValueError: if arguments cannot be casted to integer.
56 >>> addition_int(1, 2, 3)
57 6
58 >>> addition_int('1', 2)
59 3
60 >>> addition_int("abc", "def")
61 Traceback (most recent call last):
62 ...
63 ValueError: Arguments must cast to integer.
64 """
66 try:
67 iargs = [ int(arg) for arg in args ]
68 except ValueError as exc:
69 raise ValueError("Arguments must cast to integer.") from exc
71 return sum(iargs)
74if sys.version_info[:2] >= (3, 10):
75 from importlib.resources import files # Python 3.10+
76else:
77 from importlib_resources import files # External
79PYYC_PATH = files("pyyc.config") #: Path to pyyc configuration file.
82def read_config(cfgname="default.cfg"):
83 """
84 Get config from configuration file.
86 If the input filename does not specifically include a path, it will be
87 looked for in the default :const:`PYYC_PATH` directory.
89 :param str cfgname: configuration file name
90 :return: configuration object
91 :rtype: configparser.ConfigParser
93 >>> cfg = read_config() # doctest: +ELLIPSIS
94 Reading configuration from ...
95 >>> cfg['DEFAULT']['version']
96 'cfg-1.0'
97 """
99 from configparser import ConfigParser # pylint: disable=import-outside-toplevel
101 if os.path.dirname(cfgname): # cfgname includes a path (e.g. `./path/to/file`)
102 fname = cfgname
103 else: # use PYYC_PATH as default
104 fname = PYYC_PATH.joinpath(cfgname)
105 print(f"Reading configuration from {fname!s}...")
107 cfg = ConfigParser()
108 if not cfg.read(fname): # It silently failed
109 raise IOError(f"Could not find or parse {fname!s}")
111 return cfg
114def format_pkg_tree(node, max_depth=2, printout=False, depth=0):
115 """
116 Format the package architecture.
118 :param module node: name of the top-level module
119 :param int max_depth: maximum depth of recursion
120 :param bool printout: print out the resulting string
121 :param int depth: depth level (used for recursion)
122 :return: structure as a list of strings (without newlines)
123 :rtype: list
125 >>> import pyyc
126 >>> format_pkg_tree(pyyc, max_depth=1) # doctest: +NORMALIZE_WHITESPACE
127 ['pyyc',
128 ' pyyc.config',
129 ' pyyc.mod',
130 ' pyyc.subpkgA',
131 ' pyyc.subpkgB']
132 """
134 if depth > max_depth:
135 return []
137 s = []
138 if hasattr(node, '__name__'):
139 s.append(' ' * depth + node.__name__)
140 for name in dir(node):
141 if not name.startswith('_'):
142 s.extend(format_pkg_tree(getattr(node, name),
143 max_depth=max_depth,
144 depth=depth + 1))
146 if printout:
147 print('\n'.join(s))
149 return s
152def greetings():
153 """
154 Stupid function, to illustrate tests on stdin/stdout.
155 """
157 name = input("What's you name? ")
158 print(f"Hello, {name}!")