or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# rstr - Random String Generator

1

2

A comprehensive Python library for generating random strings from various alphabets and regular expressions. rstr provides both simple random string generation and advanced pattern-based string creation, supporting both secure (SystemRandom) and fast (Mersenne Twister) random number generation for different use cases from development testing to cryptographic applications.

3

4

## Package Information

5

6

- **Package Name**: rstr

7

- **Language**: Python

8

- **Installation**: `pip install rstr`

9

- **Python Compatibility**: 3.7+

10

11

## Core Imports

12

13

```python

14

import rstr

15

```

16

17

For class-based usage:

18

19

```python

20

from rstr import Rstr, RstrBase, SameCharacterError

21

# Note: Rstr is an alias for Xeger class

22

```

23

24

For direct imports:

25

26

```python

27

from rstr import rstr, xeger, letters, digits, uppercase, lowercase

28

# All alphabet functions are available for direct import

29

```

30

31

Complete available imports:

32

33

```python

34

from rstr import (

35

# Classes

36

Rstr, # Main class (alias for Xeger)

37

RstrBase, # Base class

38

SameCharacterError, # Exception class

39

40

# Core functions

41

rstr, xeger,

42

43

# Alphabet functions

44

printable, letters, uppercase, lowercase, digits, punctuation,

45

nondigits, nonletters, whitespace, nonwhitespace, normal, word,

46

nonword, unambiguous, postalsafe, urlsafe, domainsafe

47

)

48

```

49

50

## Basic Usage

51

52

Simple random string generation:

53

54

```python

55

import rstr

56

57

# Generate random string from custom alphabet

58

result = rstr.rstr('ABC') # Returns string like 'AACAACCB'

59

60

# Generate exact length

61

result = rstr.rstr('ABC', 4) # Returns 4-character string like 'ACBC'

62

63

# Generate regex-based string

64

postal_code = rstr.xeger(r'[A-Z]\d[A-Z] \d[A-Z]\d') # Returns 'R6M 1W5'

65

```

66

67

## Core Random String Generation

68

69

### Primary Function

70

71

```python { .api }

72

def rstr(

73

alphabet: Iterable[str],

74

start_range: Optional[int] = None,

75

end_range: Optional[int] = None,

76

include: Sequence[str] = '',

77

exclude: Sequence[str] = ''

78

) -> str

79

```

80

81

Generates random strings from the specified alphabet.

82

83

**Parameters:**

84

- `alphabet`: Characters to choose from (string, list, or tuple)

85

- `start_range`: Minimum length (default: 1, or exact length if end_range not specified)

86

- `end_range`: Maximum length (default: 10 if start_range not specified)

87

- `include`: Characters that must appear in the result

88

- `exclude`: Characters to exclude from alphabet

89

90

**Returns:** Random string meeting the specified criteria

91

92

**Example:**

93

```python

94

# Range of lengths

95

rstr.rstr('ABC', 5, 10) # 5-10 character string

96

97

# Include specific characters

98

rstr.rstr('ABC', include='&') # Will contain '&'

99

100

# Exclude characters

101

rstr.rstr(string.digits, exclude='5') # Digits except '5'

102

```

103

104

### Regex-based String Generation

105

106

```python { .api }

107

def xeger(string_or_regex: Union[str, Pattern[str]]) -> str

108

```

109

110

Generates random strings matching a regular expression pattern.

111

112

**Parameters:**

113

- `string_or_regex`: Regular expression pattern (string or compiled Pattern)

114

115

**Returns:** Random string matching the pattern

116

117

**Example:**

118

```python

119

# Canadian postal code

120

rstr.xeger(r'[A-Z]\d[A-Z] \d[A-Z]\d')

121

122

# Email-like pattern

123

rstr.xeger(r'[a-z]{3,8}@[a-z]{3,8}\.(com|org|net)')

124

```

125

126

## Predefined Alphabet Functions

127

128

All alphabet functions accept the same parameters as `rstr()`:

129

130

```python { .api }

131

def printable(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

132

def letters(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

133

def uppercase(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

134

def lowercase(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

135

def digits(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

136

def punctuation(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

137

def nondigits(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

138

def nonletters(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

139

def whitespace(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

140

def nonwhitespace(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

141

def normal(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

142

def word(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

143

def nonword(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

144

def unambiguous(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

145

def postalsafe(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

146

def urlsafe(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

147

def domainsafe(start_range: Optional[int] = None, end_range: Optional[int] = None, include: Sequence[str] = '', exclude: Sequence[str] = '') -> str

148

```

149

150

### Alphabet Descriptions

151

152

- **printable**: All printable characters (string.printable)

153

- **letters**: ASCII letters (a-z, A-Z)

154

- **uppercase**: Uppercase letters (A-Z)

155

- **lowercase**: Lowercase letters (a-z)

156

- **digits**: Numeric digits (0-9)

157

- **punctuation**: Punctuation marks (string.punctuation)

158

- **nondigits**: Letters + punctuation (excludes digits)

159

- **nonletters**: Digits + punctuation (excludes letters)

160

- **whitespace**: Whitespace characters (space, tab, newline, etc.)

161

- **nonwhitespace**: Printable characters except whitespace

162

- **normal**: Letters + digits + space

163

- **word**: Letters + digits + underscore (regex \\w equivalent)

164

- **nonword**: Characters not in word set (regex \\W equivalent)

165

- **unambiguous**: Letters + digits excluding similar characters (0, O, 1, l, I)

166

- **postalsafe**: Characters safe for postal addresses (letters, digits, space, ., #, -, /)

167

- **urlsafe**: URL-safe unreserved characters (letters, digits, -, ., _, ~)

168

- **domainsafe**: Domain name safe characters (letters, digits, -)

169

170

**Example:**

171

```python

172

# Generate random email username

173

username = rstr.letters(5, 12)

174

175

# Generate unambiguous identifier

176

id_code = rstr.unambiguous(8)

177

178

# Generate domain-safe string

179

domain = rstr.domainsafe(3, 15)

180

```

181

182

## Class-based Usage

183

184

### RstrBase Class

185

186

```python { .api }

187

class RstrBase:

188

def __init__(self, _random: Random, **custom_alphabets: str) -> None

189

```

190

191

Base class for random string generation functionality.

192

193

**Parameters:**

194

- `_random`: Random number generator instance (required)

195

- `**custom_alphabets`: Custom alphabet definitions as keyword arguments

196

197

### Xeger Class

198

199

```python { .api }

200

class Xeger(RstrBase):

201

def __init__(self, _random: Random = random, **custom_alphabets: str) -> None

202

```

203

204

Main class implementing random string generation from regular expressions and alphabets.

205

206

**Parameters:**

207

- `_random`: Random number generator instance (default: standard random module)

208

- `**custom_alphabets`: Custom alphabet definitions as keyword arguments

209

210

### Rstr Class

211

212

```python { .api }

213

Rstr = Xeger # Alias for Xeger class

214

```

215

216

`Rstr` is an alias for the `Xeger` class. Use either name interchangeably.

217

218

**Parameters:**

219

- `_random`: Random number generator instance (default: standard random module)

220

- `**custom_alphabets`: Custom alphabet definitions as keyword arguments

221

222

**Examples:**

223

224

```python

225

from random import SystemRandom

226

from rstr import Rstr, RstrBase

227

228

# Using RstrBase (requires explicit random instance)

229

base_rstr = RstrBase(SystemRandom())

230

231

# Using Xeger/Rstr with default random

232

default_rstr = Rstr() # Uses standard random module

233

234

# Cryptographically secure instance

235

secure_rstr = Rstr(SystemRandom())

236

237

# Instance with custom alphabets

238

custom_rstr = Rstr(vowels='AEIOU', consonants='BCDFGHJKLMNPQRSTVWXYZ')

239

240

# RstrBase with custom alphabets (explicit random required)

241

secure_base = RstrBase(SystemRandom(), hex_chars='0123456789abcdef')

242

```

243

244

### Class Methods

245

246

```python { .api }

247

def add_alphabet(self, alpha_name: str, characters: str) -> None

248

```

249

250

Adds a custom alphabet to the instance and makes it available as a method.

251

252

**Parameters:**

253

- `alpha_name`: Name for the new alphabet method

254

- `characters`: String of characters for the alphabet

255

256

**Implementation Note:**

257

The `add_alphabet` method works with the class's `__getattr__` implementation to dynamically create methods. When you call a method name that matches an alphabet name, it automatically calls `rstr()` with that alphabet.

258

259

**Example:**

260

```python

261

rs = Rstr()

262

rs.add_alphabet('odds', '13579')

263

result = rs.odds(5) # 5-character string from odd digits

264

265

# This is equivalent to:

266

result = rs.rstr('13579', 5)

267

268

# You can also add alphabets during instantiation:

269

rs = Rstr(evens='02468', odds='13579')

270

even_result = rs.evens(3) # Uses '02468' alphabet

271

```

272

273

```python { .api }

274

def sample_wr(self, population: Sequence[str], k: int) -> List[str]

275

```

276

277

Samples k random elements with replacement from a population.

278

279

**Parameters:**

280

- `population`: Sequence of strings to sample from

281

- `k`: Number of elements to sample

282

283

**Returns:** List of k randomly selected elements (with replacement)

284

285

**Example:**

286

```python

287

rs = Rstr()

288

samples = rs.sample_wr(['A', 'B', 'C'], 5) # e.g., ['A', 'C', 'A', 'B', 'A']

289

```

290

291

All alphabet methods are available on class instances with the same signatures as package-level functions.

292

293

### Module-Level Functions Implementation

294

295

All module-level functions (`rstr`, `xeger`, alphabet functions) are actually methods of a default `Rstr()` instance:

296

297

```python { .api }

298

# Internal implementation (from rstr.__init__)

299

_default_instance = Rstr()

300

rstr = _default_instance.rstr

301

xeger = _default_instance.xeger

302

letters = _default_instance.letters

303

# ... all other alphabet functions

304

```

305

306

This means that all module-level functions share the same random state and use the standard `random` module by default.

307

308

### Exception Handling

309

310

```python { .api }

311

class SameCharacterError(ValueError):

312

pass

313

```

314

315

Raised when `include` and `exclude` parameters contain the same character(s) in any `rstr()` call.

316

317

**When raised:**

318

- Calling `rstr()` or any alphabet function with overlapping `include` and `exclude` characters

319

- Error message includes the conflicting character(s)

320

- Inherits from `ValueError` for standard exception handling patterns

321

322

**Examples:**

323

```python

324

import rstr

325

326

try:

327

# Single conflicting character

328

result = rstr.rstr('ABC', include='A', exclude='A')

329

except rstr.SameCharacterError as e:

330

print(f"Error: {e}")

331

# Output: "include and exclude parameters contain same character (A)"

332

333

try:

334

# Multiple conflicting characters

335

result = rstr.letters(include='XY', exclude='YZ')

336

except rstr.SameCharacterError as e:

337

print(f"Error: {e}")

338

# Output: "include and exclude parameters contain same characters (Y)"

339

```

340

341

## Advanced Usage Examples

342

343

### Secure Random Strings

344

345

For cryptographic applications, use SystemRandom:

346

347

```python

348

from random import SystemRandom

349

from rstr import Rstr

350

351

# Create secure instance

352

secure_rstr = Rstr(SystemRandom())

353

354

# Generate secure password

355

password = secure_rstr.unambiguous(16)

356

```

357

358

### Complex String Templates

359

360

Combine rstr with string formatting:

361

362

```python

363

# Generate email address

364

email = '{0}@{1}.{2}'.format(

365

rstr.nonwhitespace(exclude='@'),

366

rstr.domainsafe(),

367

rstr.letters(3)

368

)

369

370

# Generate URL

371

url = 'https://{0}.{1}/{2}?{3}'.format(

372

rstr.domainsafe(),

373

rstr.letters(3),

374

rstr.urlsafe(),

375

rstr.urlsafe()

376

)

377

378

# Generate postal address

379

address = """{0} {1}

380

{2} {3}

381

{4}, {5} {6}""".format(

382

rstr.letters(4, 8).title(),

383

rstr.letters(4, 8).title(),

384

rstr.digits(3, 5),

385

rstr.letters(4, 10).title(),

386

rstr.letters(4, 15).title(),

387

rstr.uppercase(2),

388

rstr.digits(5)

389

)

390

```

391

392

### Custom Alphabets

393

394

```python

395

# Instance with custom alphabets

396

rs = Rstr(

397

vowels='AEIOU',

398

consonants='BCDFGHJKLMNPQRSTVWXYZ',

399

hex_lower='0123456789abcdef'

400

)

401

402

# Use custom alphabets

403

vowel_string = rs.vowels(5)

404

consonant_string = rs.consonants(10)

405

hex_id = rs.hex_lower(8)

406

```

407

408

## Type Definitions

409

410

```python { .api }

411

from typing import Iterable, List, Mapping, Optional, Sequence, Union, Pattern

412

from random import Random

413

414

# Core function signature types

415

AlphabetType = Iterable[str]

416

IncludeExcludeType = Sequence[str]

417

RegexInputType = Union[str, Pattern[str]]

418

419

# Internal type definitions (available but not typically needed)

420

from typing import TypeVar, Protocol

421

_T = TypeVar('_T')

422

423

class _PartialRstrFunc(Protocol):

424

"""Type definition for dynamically created alphabet methods"""

425

def __call__(

426

self,

427

start_range: Optional[int] = ...,

428

end_range: Optional[int] = ...,

429

include: str = ...,

430

exclude: str = ...,

431

) -> str: ...

432

```

433

434

## Constants

435

436

```python { .api }

437

# From rstr.rstr_base

438

from rstr.rstr_base import ALPHABETS

439

ALPHABETS: Mapping[str, str] # Predefined alphabet mappings

440

441

# From rstr.xeger

442

from rstr.xeger import STAR_PLUS_LIMIT

443

STAR_PLUS_LIMIT: int = 100 # Maximum repeats for regex * and +

444

```

445

446

## Installation and Requirements

447

448

```bash

449

pip install rstr

450

```

451

452

- **Python**: 3.7+

453

- **Dependencies**: None (standard library only)

454

- **Optional**: SystemRandom for cryptographic applications

455

456

## Common Patterns

457

458

### Testing and Fuzz Testing

459

460

```python

461

# Generate test data with specific constraints

462

test_usernames = [rstr.letters(3, 20) for _ in range(100)]

463

test_emails = [f"{rstr.letters(5)}@{rstr.domainsafe()}.com" for _ in range(50)]

464

465

# Fuzz testing with problematic characters

466

fuzz_inputs = [rstr.rstr(string.printable, include=char) for char in '<>&"\'']

467

```

468

469

### Dummy Data Generation

470

471

```python

472

# Generate realistic-looking dummy data

473

names = [rstr.letters(4, 12).title() for _ in range(100)]

474

phone_numbers = [rstr.xeger(r'\(\d{3}\) \d{3}-\d{4}') for _ in range(50)]

475

social_security = [rstr.xeger(r'\d{3}-\d{2}-\d{4}') for _ in range(25)]

476

```