Skip to content

Commit c28dafe

Browse files
smartrandom v0.2.0 stable version.
1 parent 116f43a commit c28dafe

File tree

10 files changed

+220
-29
lines changed

10 files changed

+220
-29
lines changed

MANIFEST.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ include README.md
33
include requirements.txt
44
include setup.cfg
55
include setup.py
6-
global-exclude requirements/*
6+
global-exclude tests/*
7+
global-exclude data/*

README.md

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Author and developer: ___A.A. Suvorov.___
2323

2424
## What is news:
2525

26+
smartrandom 0.2.0 - new improved version of the library.
27+
2628
> WARNING! This version is not backward compatible with previous versions.
2729
2830
- Completely rewritten and improved code.
@@ -31,9 +33,10 @@ Author and developer: ___A.A. Suvorov.___
3133
- Generated passwords must now contain at least one digit, one lowercase letter, one uppercase letter and one symbol. Length is at least 4.
3234
- Random letter generation is now at least 2. At least 1 lowercase letter and one uppercase letter are required.
3335
- Improved UrandomGenerator default size=128.
34-
- Added TextRandomizer
35-
- Added StringAndNumberCodeGenerator
36-
- Added RandomDataMaster
36+
- Added TextRandomizer.
37+
- Added tests.
38+
- Test coverage 100%.
39+
- Added documentation.
3740

3841
***
3942

@@ -42,18 +45,17 @@ Author and developer: ___A.A. Suvorov.___
4245
`pip install smartrandom`
4346

4447
```python
45-
from smartrandom import RandomDataMaster
48+
from smartrandom import RandomDataGenerator
4649

47-
random_data_master = RandomDataMaster()
4850

49-
secret_code = random_data_master.letters.generate(6) # 'zREkjF'
50-
number_secret_code = random_data_master.numbers.generate(6) # '986741'
51-
symbols = random_data_master.symbols.generate(10) # '&&!@@&@!_!'
52-
hash_ = random_data_master.hash.generate('text') # '1798b0ae66b1ca6f3b88e00f9d17ce1470549e97687a1c97e26110bb8853ad41797e83831efe7eedbd29042a9a8991fd1adb4f7680946d57eed99b8b6e5502c4'
53-
urandom = random_data_master.urandom.generate(32) # '7b1dd304b42e79d9e26bfb9f839abf8d001fed2039bcc3c5bfd14c0b05cfcab2'
54-
text_randomizer = random_data_master.text_randomizer.randomize('{Salute|Hello|Good morning} {comrade|buddy|dear friend}!') # Good morning buddy!
55-
string_and_numeric_code = random_data_master.string_and_numeric_code.generate(10) # 'Fii3rbf7iS'
56-
password = random_data_master.password.generate(15) # 'b$L^#7rfIUzgY!2'
51+
secret_code = RandomDataGenerator.generate_secret_code(6) # 'zREkjF'
52+
number_secret_code = RandomDataGenerator.generate_random_numbers(6) # '986741'
53+
symbols = RandomDataGenerator.generate_random_symbols(10) # '&&!@@&@!_!'
54+
hash_ = RandomDataGenerator.generate_hash('text') # '1798b0ae66b1ca6f3b88e00f9d17ce1470549e97687a1c97e26110bb8853ad41797e83831efe7eedbd29042a9a8991fd1adb4f7680946d57eed99b8b6e5502c4'
55+
urandom_string = RandomDataGenerator.generate_random_hex_string(32) # '7b1dd304b42e79d9e26bfb9f839abf8d001fed2039bcc3c5bfd14c0b05cfcab2'
56+
urandom_bytes = RandomDataGenerator.generate_random_bytes(32) # b'f_@\x1bnP\xb4\xa8\xb7$a\xbf\x13\r#\x96\xe5\x07D\xa1N\xf5\xe9\x9a\x95\x91\xe4\xd0\x8fR"\''
57+
randomized_text = RandomDataGenerator.randomize_text('{Salute|Hello|Good morning} {comrade|buddy|dear friend}!') # Good morning buddy!
58+
password = RandomDataGenerator.generate_password(15) # 'b$L^#7rfIUzgY!2'
5759

5860

5961

@@ -100,13 +102,35 @@ Example of text randomization:
100102
```python
101103
from smartrandom import TextRandomizer
102104

103-
text_randomizer = TextRandomizer()
104-
105105
text = '{Salute|Hello|Good morning} {comrade|buddy|dear friend}!'
106-
randomized_text = text_randomizer.randomize(text)
106+
randomized_text = TextRandomizer.randomize(text)
107107
print(randomized_text) # Good morning buddy!
108108
```
109109

110+
---
111+
112+
### Test coverage:
113+
114+
#### Run tests:
115+
- `pip install pytest`
116+
- `pytest -v`
117+
118+
119+
#### __Test coverage 100%__
120+
121+
- `pip install pytest-coverage`
122+
- `pytest --cov`
123+
124+
![commandpack image](https://github.com/smartlegionlab/smartrandom/raw/master/data/images/coverage_report.png)
125+
126+
127+
#### Report html:
128+
129+
- `pytest --cov --cov-report=html`
130+
131+
***
132+
133+
110134
***
111135

112136
## Disclaimer of liability:

data/images/coverage_report.png

202 KB
Loading
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
setuptools
2+
wheel
3+
twine
4+
pytest
5+
pytest-cov

requirements/requirements-dev.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
# Copyright © 2018-2024, A.A. Suvorov
55
# All rights reserved.
66
# --------------------------------------------------------
7-
# https://github.com/smartlegionlab
7+
# https://github.com/smartlegionlab/
88
# --------------------------------------------------------
99
from setuptools import setup, find_packages
1010

1111
setup(
12-
packages=find_packages(),
12+
packages=find_packages(exclude=['tests', 'data']),
1313
)

smartrandom/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@
2222
TextRandomizer,
2323
PasswordGenerator,
2424
SecretCodeGenerator,
25-
RandomDataMaster,
25+
RandomDataGenerator,
2626
)
2727
__version__ = '0.2.0'

smartrandom/generators.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,22 @@ class TextRandomizer:
114114
@classmethod
115115
def randomize(cls, text: str) -> str:
116116
"""
117-
Randomizes text by replacing patterns enclosed in curly braces with random elements.
117+
Randomizes the input text by replacing patterns enclosed in curly braces with randomly selected elements.
118118
119-
:param text: Input text with patterns.
120-
:return: Randomized text.
119+
The method looks for patterns in the input text that are enclosed in curly braces `{}`.
120+
Inside the braces, multiple options can be provided, separated by a vertical bar `|`.
121+
For each occurrence of such a pattern, one of the options is randomly selected and
122+
replaces the entire pattern in the text.
123+
124+
For example:
125+
- Input: "Hello, {Alice|Bob|Charlie}!"
126+
- Output: "Hello, Bob!" (or "Hello, Alice!" or "Hello, Charlie!", randomly chosen)
127+
128+
:param text: The input text containing patterns to be randomized.
129+
:return: The randomized text with patterns replaced by randomly selected options.
121130
"""
122131
return re.sub(r"{(.+?)}", lambda x: secrets.choice(x.group(1).split("|")), text)
123132

124-
def __call__(self, message: str) -> str:
125-
return self.randomize(message)
126-
127133

128134
class SecretCodeGenerator:
129135
upper_letters = string.ascii_uppercase

tests/__init__.py

Whitespace-only changes.
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# --------------------------------------------------------
2+
# Licensed under the terms of the BSD 3-Clause License
3+
# (see LICENSE for details).
4+
# Copyright © 2018-2024, A.A. Suvorov
5+
# All rights reserved.
6+
# --------------------------------------------------------
7+
# https://github.com/smartlegionlab/
8+
# --------------------------------------------------------
9+
import pytest
10+
from smartrandom import (
11+
RandomLetterGenerator,
12+
RandomIntegerGenerator,
13+
RandomSymbolGenerator,
14+
HashGenerator,
15+
UrandomGenerator,
16+
TextRandomizer,
17+
SecretCodeGenerator,
18+
PasswordGenerator,
19+
RandomDataGenerator
20+
)
21+
22+
23+
def test_random_letter_generator():
24+
# Test valid length
25+
result = RandomLetterGenerator.generate(10)
26+
assert len(result) == 10
27+
assert any(c.isupper() for c in result)
28+
assert any(c.islower() for c in result)
29+
30+
# Test invalid length
31+
with pytest.raises(ValueError):
32+
RandomLetterGenerator.generate(1)
33+
34+
35+
def test_random_integer_generator():
36+
# Test valid length
37+
result = RandomIntegerGenerator.generate(5)
38+
assert len(result) == 5
39+
assert result.isdigit()
40+
41+
# Test invalid length
42+
with pytest.raises(ValueError):
43+
RandomIntegerGenerator.generate(0)
44+
45+
46+
def test_random_symbol_generator():
47+
# Test valid length
48+
result = RandomSymbolGenerator.generate(5)
49+
assert len(result) == 5
50+
assert all(c in RandomSymbolGenerator.symbols for c in result)
51+
52+
# Test invalid length
53+
with pytest.raises(ValueError):
54+
RandomSymbolGenerator.generate(0)
55+
56+
57+
def test_hash_generator():
58+
text = "test"
59+
result = HashGenerator.generate(text)
60+
assert isinstance(result, str)
61+
assert len(result) == 128 # SHA-3-512 produces a 128-character hex string
62+
63+
64+
def test_urandom_generator():
65+
# Test random bytes generation
66+
result = UrandomGenerator.generate(16)
67+
assert len(result) == 16
68+
assert isinstance(result, bytes)
69+
70+
# Test random hex string generation
71+
hex_result = UrandomGenerator.generate_string(16)
72+
assert len(hex_result) == 32 # 16 bytes = 32 hex characters
73+
74+
75+
def test_text_randomizer():
76+
text = "Hello {world|everyone}"
77+
result = TextRandomizer.randomize(text)
78+
assert result in ["Hello world", "Hello everyone"]
79+
80+
81+
def test_secret_code_generator():
82+
# Test valid length
83+
result = SecretCodeGenerator.generate(10)
84+
assert len(result) == 10
85+
assert any(c.isupper() for c in result)
86+
assert any(c.islower() for c in result)
87+
assert any(c.isdigit() for c in result)
88+
89+
# Test invalid length
90+
with pytest.raises(ValueError):
91+
SecretCodeGenerator.generate(2)
92+
93+
94+
def test_password_generator():
95+
# Test valid length
96+
result = PasswordGenerator.generate(12)
97+
assert len(result) == 12
98+
assert any(c.isupper() for c in result)
99+
assert any(c.islower() for c in result)
100+
assert any(c.isdigit() for c in result)
101+
assert any(c in PasswordGenerator.symbols for c in result)
102+
103+
# Test invalid length
104+
with pytest.raises(ValueError):
105+
PasswordGenerator.generate(3)
106+
107+
108+
def test_random_data_generator():
109+
# Test random letters
110+
letters = RandomDataGenerator.generate_random_letters(10)
111+
assert len(letters) == 10
112+
113+
# Test random numbers
114+
numbers = RandomDataGenerator.generate_random_numbers(5)
115+
assert len(numbers) == 5
116+
assert numbers.isdigit()
117+
118+
# Test random symbols
119+
symbols = RandomDataGenerator.generate_random_symbols(5)
120+
assert len(symbols) == 5
121+
assert all(c in RandomSymbolGenerator.symbols for c in symbols)
122+
123+
# Test hash generation
124+
hash_result = RandomDataGenerator.generate_hash("test")
125+
assert isinstance(hash_result, str)
126+
assert len(hash_result) == 128
127+
128+
# Test random bytes
129+
random_bytes = RandomDataGenerator.generate_random_bytes(16)
130+
assert len(random_bytes) == 16
131+
assert isinstance(random_bytes, bytes)
132+
133+
# Test random hex string
134+
hex_string = RandomDataGenerator.generate_random_hex_string(16)
135+
assert len(hex_string) == 32
136+
137+
# Test text randomization
138+
randomized_text = RandomDataGenerator.randomize_text("Hello {world|everyone}")
139+
assert randomized_text in ["Hello world", "Hello everyone"]
140+
141+
# Test password generation
142+
password = RandomDataGenerator.generate_password(12)
143+
assert len(password) == 12
144+
assert any(c.isupper() for c in password)
145+
assert any(c.islower() for c in password)
146+
assert any(c.isdigit() for c in password)
147+
assert any(c in PasswordGenerator.symbols for c in password)
148+
149+
# Test secret code generation
150+
secret_code = RandomDataGenerator.generate_secret_code(10)
151+
assert len(secret_code) == 10
152+
assert any(c.isupper() for c in secret_code)
153+
assert any(c.islower() for c in secret_code)
154+
assert any(c.isdigit() for c in secret_code)
155+
156+
157+
if __name__ == "__main__":
158+
pytest.main()

0 commit comments

Comments
 (0)