testsAndMisc/python_pkg/randomize_numbers/random_digits.py
Krzysztof kuhy Rudnicki 0e73b27d50 fix: address all pylint warnings
- R0914 (too many locals): Extract helper functions in generate_jpeg.py,
  engine.py, lichess_api.py, main.py
- R0902 (too many instance attributes): Use dataclasses in keyboard_coop
- W0621 (redefined outer name): Rename parameters/variables to avoid shadowing
- W0201 (attribute outside init): Initialize all attrs in __init__
- R1705 (no-else-return): Remove unnecessary else after return
- C1805 (implicit booleaness): Use implicit boolean checks
- R1732 (consider-using-with): Use context manager for subprocess.Popen
- E0401 (import-error): Add pylint disable for optional deps (selenium, mitmproxy)
- Clean up pyproject.toml: update comments, remove redundant settings

Pylint score: 10.00/10
2025-12-01 16:11:15 +01:00

111 lines
3.5 KiB
Python

"""Randomize numbers by applying a random percentage variation."""
import contextlib
import logging
import re
import secrets
import sys
_logger = logging.getLogger(__name__)
# Use cryptographically secure random number generator
_rng = secrets.SystemRandom()
DEFAULT_MIN_PERCENTAGE = 1
DEFAULT_MAX_PERCENTAGE = 20
def randomize_numbers(
nums: list[float],
min_pct: float = DEFAULT_MIN_PERCENTAGE,
max_pct: float = DEFAULT_MAX_PERCENTAGE,
) -> list[float]:
"""Apply random percentage variation to a list of numbers."""
result = []
for number in nums:
percentage = _rng.uniform(min_pct, max_pct) / 100
if _rng.choice([True, False]):
new_number = number + (number * percentage)
else:
new_number = number - (number * percentage)
result.append(new_number)
return result
def parse_input(text: str) -> tuple[list[float], list[int]]:
"""Parse a string of numbers and return floats with decimal counts."""
# Replace commas with dots and remove non-numeric characters
# except dots, commas, and digits
cleaned_input = re.sub(r"[^\d.,\s]", "", text).replace(",", ".")
# Split the cleaned input into individual numbers
number_strings = cleaned_input.split()
# Convert the number strings to floats
nums: list[float] = []
decimals: list[int] = []
for num_str in number_strings:
parsed = _parse_single_number(num_str)
if parsed is not None:
float_num, digits_count = parsed
nums.append(float_num)
decimals.append(digits_count)
return nums, decimals
def _parse_single_number(num_str: str) -> tuple[float, int] | None:
"""Parse a single number string into float and decimal count.
Args:
num_str: The number string to parse.
Returns:
Tuple of (float value, decimal count) or None if invalid.
"""
try:
float_num = float(num_str)
digits_count = len(num_str.split(".")[-1]) if "." in num_str else 0
except ValueError:
return None
return float_num, digits_count
MIN_ARGS = 2
if __name__ == "__main__":
if len(sys.argv) < MIN_ARGS:
_logger.info(
"Usage: python random_digits.py <number1> <number2> ... "
"[min_percentage max_percentage]"
)
sys.exit(1)
input_string = " ".join(sys.argv[1:])
numbers, decimal_counts = parse_input(input_string)
if not numbers:
_logger.error("No valid numbers provided.")
sys.exit(1)
min_percentage = DEFAULT_MIN_PERCENTAGE
max_percentage = DEFAULT_MAX_PERCENTAGE
try:
if len(sys.argv) > len(numbers) + 1:
with contextlib.suppress(ValueError):
min_percentage = float(sys.argv[len(numbers) + 1])
if len(sys.argv) > len(numbers) + 2:
with contextlib.suppress(ValueError):
max_percentage = float(sys.argv[len(numbers) + 2])
randomized_numbers = randomize_numbers(numbers, min_percentage, max_percentage)
formatted_numbers = []
for i, num in enumerate(randomized_numbers):
format_str = f".{decimal_counts[i]}f"
formatted_numbers.append(float(format(num, format_str)))
_logger.info("Original numbers: %s", numbers)
_logger.info("Randomized numbers: %s", formatted_numbers)
except ValueError:
_logger.exception("Error processing numbers")
_logger.exception("Please provide valid numbers and percentages.")
sys.exit(1)