Coverage for pyyc/mod.py: 84%
44 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-09 18:58 +0200
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-09 18:58 +0200
1"""
2Documentation for module `mod`.
3"""
5__all__ = ["version"] # limits the content of "import *"
7version = "top-level module"
8print(f"Initialization {__name__!r}: {version}") # NO PRINT in a true module!
10####################################################
12import os, sys # pylint: disable=wrong-import-position,multiple-imports
15def addition(*args):
16 r"""
17 Addition function (undefined type).
19 Arguments should support mutual addition:
21 .. math::
23 \mathrm{out} = \sum_i \mathrm{arg}_i
25 :param args: parameters
26 :return: python addition of args
27 :raises TypeError: arguments cannot be summed together
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 """
41 out = args[0]
42 for arg in args[1:]:
43 out += arg
45 return out
48def addition_int(*args):
49 """
50 Addition function for integers (includes cast to integer).
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.
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 """
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
72 return sum(iargs)
75if sys.version_info[:2] >= (3, 10):
76 from importlib.resources import files # Python 3.10+
77else:
78 from importlib_resources import files # External
80PYYC_PATH = files("pyyc.config") #: Path to pyyc configuration file.
83def read_config(cfgname="default.cfg"):
84 """
85 Get config from configuration file.
87 If the input filename does not specifically include a path, it will be
88 looked for in the default :const:`PYYC_PATH` directory.
90 :param str cfgname: configuration file name
91 :return: configuration object
92 :rtype: configparser.ConfigParser
94 >>> cfg = read_config() # doctest: +ELLIPSIS
95 Reading configuration from ...
96 >>> cfg['DEFAULT']['version']
97 'cfg-1.0'
98 """
100 from configparser import ConfigParser # pylint: disable=import-outside-toplevel
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}...")
108 cfg = ConfigParser()
109 if not cfg.read(fname): # It silently failed
110 raise IOError(f"Could not find or parse {fname!s}")
112 return cfg
115def format_pkg_tree(node, max_depth=2, printout=False, depth=0):
116 """
117 Format the package architecture.
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
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 """
135 if depth > max_depth:
136 return []
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 )
149 if printout:
150 print("\n".join(s)) # Intentionally not tested (for coverage)
152 return s
155def greetings():
156 """
157 Stupid function, to illustrate tests on stdin/stdout.
158 """
160 name = input("What's you name? ")
161 print(f"Hello, {name}!")