log21 3.3.0__tar.gz → 3.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: log21
3
- Version: 3.3.0
3
+ Version: 3.3.2
4
4
  Summary: A simple logging package
5
5
  Keywords: python,log,colorize,color,logging,Python3,CodeWriter21
6
6
  Author: CodeWriter21(Mehrad Pooryoussof)
@@ -94,55 +94,65 @@ pip install git+https://github.com/MPCodeWriter21/log21
94
94
  Changelog
95
95
  ---------
96
96
 
97
- ### v3.3.0
97
+ ### v3.3.2
98
98
 
99
- Add `log21.helper_types` module.
99
+ Handle percent signs in arguments' help text.
100
100
 
101
- This module contains a collection of useful types meant for using with argument parser
102
- to parse CLI arguments to more usable formats.
101
+ In the older versions, if you had a percent sign in the help text of an argument, it
102
+ would cause an error when you try to show the help. This is because the argparse
103
+ module uses percent signs for string formatting, and it would try to format the help
104
+ text as a string, which would fail if there are any percent signs in it.
103
105
 
104
- + `FileSize`: Can take `str` and `int` values. Will convert human inputs such as "121 KB",
105
- "21MiB", or "4.56 GB" to bytes. Can also be used to represent bytes value in more
106
- human-readable formats.
106
+ The workaround for this issue was to escape the percent signs by doubling them, but it
107
+ was not a good solution. Now, in v3.3.2, log21 handles percent signs in arguments' help
108
+ text properly, so you can use percent signs without any issues.
107
109
 
108
- For even more control you can still define Logger, Handlers, and Formatters manually.
109
-
110
- #### Example
110
+ #### Example (works before and after v3.3.2)
111
111
 
112
112
  ```python
113
- from pathlib import Path
114
-
115
113
  import log21
116
- from log21.helper_types import FileSize
117
114
 
118
115
 
119
- def main(path: Path, min_size: FileSize, max_size: FileSize, /):
120
- log21.info(
121
- "Files that are smaller than %s or bigger than %s will be ignored.",
122
- args=(min_size, max_size),
123
- )
116
+ def show_percentage(a: float, b: float, /) -> None:
117
+ """Takes two numbers and returns the percentage of a in b. E.g. if a is 50 and b is
118
+ 200, the percentage would be 25.00%.
124
119
 
125
- for file in path.iterdir():
126
- if not file.is_file():
127
- continue
128
- if min_size <= (size := file.stat().st_size) <= max_size:
129
- log21.print(
130
- "`%s` is %s.",
131
- args=(file, FileSize(size).humanize(binary=False, fmt="%.4f")),
132
- )
120
+ :param a: The first number. (a %% b)
121
+ :param b: The second number. (a %% b)
122
+ :return: The percentage of a in b.
123
+ """
124
+ if b == 0:
125
+ raise log21.ArgumentError("b cannot be zero.")
126
+ percentage = (a / b) * 100
127
+ print(f"{a} is {percentage:.2f}% of {b}.")
133
128
 
134
129
 
135
130
  if __name__ == "__main__":
136
- log21.argumentify(main)
131
+ log21.argumentify(show_percentage)
137
132
  ```
138
133
 
139
- Example usage and output:
134
+ #### Example (Works only after v3.3.2)
135
+
136
+ ```python
137
+ import log21
138
+
139
+
140
+ def show_percentage(a: float, b: float, /) -> None:
141
+ """Takes two numbers and returns the percentage of a in b. E.g. if a is 50 and b is
142
+ 200, the percentage would be 25.00%.
143
+
144
+ :param a: The first number. (a % b)
145
+ :param b: The second number. (a % b)
146
+ :return: The percentage of a in b.
147
+ """
148
+ if b == 0:
149
+ raise log21.ArgumentError("b cannot be zero.")
150
+ percentage = (a / b) * 100
151
+ print(f"{a} is {percentage:.2f}% of {b}.")
140
152
 
141
- ```shell
142
- $ uv run test.py . "1.23MiB" "0.5 GB"
143
- [21:21:21] [INFO] Files that are smaller than 1.23 MiB or bigger than 476.84 MiB will be
144
- ignored.
145
- `myfile21.zip` is 35.1856 MB.
153
+
154
+ if __name__ == "__main__":
155
+ log21.argumentify(show_percentage)
146
156
  ```
147
157
 
148
158
  [Full CHANGELOG](https://github.com/MPCodeWriter21/log21/blob/master/CHANGELOG.md)
@@ -69,55 +69,65 @@ pip install git+https://github.com/MPCodeWriter21/log21
69
69
  Changelog
70
70
  ---------
71
71
 
72
- ### v3.3.0
72
+ ### v3.3.2
73
73
 
74
- Add `log21.helper_types` module.
74
+ Handle percent signs in arguments' help text.
75
75
 
76
- This module contains a collection of useful types meant for using with argument parser
77
- to parse CLI arguments to more usable formats.
76
+ In the older versions, if you had a percent sign in the help text of an argument, it
77
+ would cause an error when you try to show the help. This is because the argparse
78
+ module uses percent signs for string formatting, and it would try to format the help
79
+ text as a string, which would fail if there are any percent signs in it.
78
80
 
79
- + `FileSize`: Can take `str` and `int` values. Will convert human inputs such as "121 KB",
80
- "21MiB", or "4.56 GB" to bytes. Can also be used to represent bytes value in more
81
- human-readable formats.
81
+ The workaround for this issue was to escape the percent signs by doubling them, but it
82
+ was not a good solution. Now, in v3.3.2, log21 handles percent signs in arguments' help
83
+ text properly, so you can use percent signs without any issues.
82
84
 
83
- For even more control you can still define Logger, Handlers, and Formatters manually.
84
-
85
- #### Example
85
+ #### Example (works before and after v3.3.2)
86
86
 
87
87
  ```python
88
- from pathlib import Path
89
-
90
88
  import log21
91
- from log21.helper_types import FileSize
92
89
 
93
90
 
94
- def main(path: Path, min_size: FileSize, max_size: FileSize, /):
95
- log21.info(
96
- "Files that are smaller than %s or bigger than %s will be ignored.",
97
- args=(min_size, max_size),
98
- )
91
+ def show_percentage(a: float, b: float, /) -> None:
92
+ """Takes two numbers and returns the percentage of a in b. E.g. if a is 50 and b is
93
+ 200, the percentage would be 25.00%.
99
94
 
100
- for file in path.iterdir():
101
- if not file.is_file():
102
- continue
103
- if min_size <= (size := file.stat().st_size) <= max_size:
104
- log21.print(
105
- "`%s` is %s.",
106
- args=(file, FileSize(size).humanize(binary=False, fmt="%.4f")),
107
- )
95
+ :param a: The first number. (a %% b)
96
+ :param b: The second number. (a %% b)
97
+ :return: The percentage of a in b.
98
+ """
99
+ if b == 0:
100
+ raise log21.ArgumentError("b cannot be zero.")
101
+ percentage = (a / b) * 100
102
+ print(f"{a} is {percentage:.2f}% of {b}.")
108
103
 
109
104
 
110
105
  if __name__ == "__main__":
111
- log21.argumentify(main)
106
+ log21.argumentify(show_percentage)
112
107
  ```
113
108
 
114
- Example usage and output:
109
+ #### Example (Works only after v3.3.2)
110
+
111
+ ```python
112
+ import log21
113
+
114
+
115
+ def show_percentage(a: float, b: float, /) -> None:
116
+ """Takes two numbers and returns the percentage of a in b. E.g. if a is 50 and b is
117
+ 200, the percentage would be 25.00%.
118
+
119
+ :param a: The first number. (a % b)
120
+ :param b: The second number. (a % b)
121
+ :return: The percentage of a in b.
122
+ """
123
+ if b == 0:
124
+ raise log21.ArgumentError("b cannot be zero.")
125
+ percentage = (a / b) * 100
126
+ print(f"{a} is {percentage:.2f}% of {b}.")
115
127
 
116
- ```shell
117
- $ uv run test.py . "1.23MiB" "0.5 GB"
118
- [21:21:21] [INFO] Files that are smaller than 1.23 MiB or bigger than 476.84 MiB will be
119
- ignored.
120
- `myfile21.zip` is 35.1856 MB.
128
+
129
+ if __name__ == "__main__":
130
+ log21.argumentify(show_percentage)
121
131
  ```
122
132
 
123
133
  [Full CHANGELOG](https://github.com/MPCodeWriter21/log21/blob/master/CHANGELOG.md)
@@ -23,7 +23,7 @@ dependencies = [
23
23
  "webcolors",
24
24
  "docstring-parser"
25
25
  ]
26
- version = "3.3.0"
26
+ version = "3.3.2"
27
27
 
28
28
  [build-system]
29
29
  requires = ["uv_build>=0.8.15,<0.9.0"]
@@ -33,7 +33,7 @@ from .stream_handler import StreamHandler, ColorizingStreamHandler
33
33
  # yapf: enable
34
34
 
35
35
  __author__ = 'CodeWriter21 (Mehrad Pooryoussof)'
36
- __version__ = '3.3.0'
36
+ __version__ = '3.3.2'
37
37
  __github__ = 'https://GitHub.com/MPCodeWriter21/log21'
38
38
  __all__ = [
39
39
  'ColorizingStreamHandler', 'DecolorizingFileHandler', 'ColorizingFormatter',
@@ -171,8 +171,10 @@ class ColorizingHelpFormatter(_argparse.HelpFormatter):
171
171
  # collect the pieces of the action help
172
172
  parts = [action_header]
173
173
 
174
+ percent_pattern = _re.compile(r'([%]{2}|[%])')
174
175
  # if there was help for the action, add lines of help text
175
176
  if action.help:
177
+ action.help = percent_pattern.sub("%%", action.help)
176
178
  help_text = _gc(self.colors['help']) + self._expand_help(action)
177
179
  help_lines = self._split_lines(help_text, help_width)
178
180
  parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
@@ -784,7 +786,8 @@ class ColorizingArgumentParser(_argparse.ArgumentParser, _ActionsContainer):
784
786
  else:
785
787
  exception = ValueError()
786
788
  for type_ in func_type:
787
- name = getattr(type_, '__name__', repr(type_))
789
+ if type_ is not type(None):
790
+ name = getattr(type_, '__name__', repr(type_))
788
791
  try:
789
792
  result = type_(arg_string)
790
793
  break
@@ -451,7 +451,7 @@ def _argumentify(functions: _Dict[str, Callable]) -> None:
451
451
  args = []
452
452
  kwargs = {}
453
453
  info = None
454
- for name, (function, info) in functions_info.items(): # noqa: B007
454
+ for _name, (function, info) in functions_info.items(): # noqa: B007
455
455
  if function == cli_args.func:
456
456
  break
457
457
  else:
@@ -475,7 +475,7 @@ def _argumentify(functions: _Dict[str, Callable]) -> None:
475
475
 
476
476
  def argumentify(
477
477
  entry_point: _Union[Callable, _List[Callable], _Dict[str, Callable]]
478
- ) -> _Callable:
478
+ ) -> _Union[Callable, _List[Callable], _Dict[str, Callable]]:
479
479
  """This function argumentifies one or more functions as the entry point of the
480
480
  script.
481
481
 
@@ -493,7 +493,7 @@ def argumentify(
493
493
  12 if __name__ == '__main__':
494
494
  13 argumentify(main)
495
495
 
496
- $ python argumentified.py Ahmad Ahmadi --age 20
496
+ $ python argumentified.py Ahmad Mohammadi --age 20
497
497
  Ahmad Ahmadi is 20 years old.
498
498
  $ python argumentified.py Mehrad Pooryoussof
499
499
  Mehrad Pooryoussof is not yet born.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes