or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

base-types.mdboolean-types.mddatetime-types.mddict-types.mdindex.mdinspection-types.mdnumeric-types.mdother-types.mdsequence-types.mdstring-types.md

string-types.mddocs/

0

# String Types

1

2

String and byte sequence validation with support for length constraints, case sensitivity, and regular expression matching. These types enable comprehensive validation of text and binary data with flexible pattern matching and formatting constraints.

3

4

## Capabilities

5

6

### IsAnyStr

7

8

Base class for string and bytes comparison providing common functionality for length constraints, case handling, and regular expression matching. Supports both string and bytes objects.

9

10

```python { .api }

11

class IsAnyStr(DirtyEquals):

12

"""

13

Base string/bytes comparison with configurable constraints.

14

15

Provides length validation, case handling, and regex matching

16

for both string and bytes objects.

17

"""

18

19

def __init__(

20

self,

21

*,

22

min_length: Optional[int] = None,

23

max_length: Optional[int] = None,

24

case: Optional[str] = None,

25

regex: Optional[Union[str, Pattern]] = None,

26

regex_flags: Optional[int] = None

27

):

28

"""

29

Initialize string/bytes validator.

30

31

Args:

32

min_length: Minimum string/bytes length

33

max_length: Maximum string/bytes length

34

case: Case constraint ('upper', 'lower', 'title', 'capitalize')

35

regex: Regular expression pattern to match

36

regex_flags: Regex flags (e.g., re.IGNORECASE, re.MULTILINE)

37

"""

38

39

expected_types: ClassVar[Tuple[type, ...]] = (str, bytes)

40

41

def equals(self, other: Any) -> bool:

42

"""

43

Check if value matches string/bytes constraints.

44

45

Args:

46

other: String or bytes value to validate

47

48

Returns:

49

bool: True if value satisfies all constraints

50

"""

51

```

52

53

#### Usage Examples

54

55

```python

56

from dirty_equals import IsAnyStr

57

import re

58

59

# Basic string or bytes validation

60

assert "hello" == IsAnyStr

61

assert b"hello" == IsAnyStr

62

63

# Length constraints

64

assert "hello world" == IsAnyStr(min_length=5, max_length=20)

65

assert b"data" == IsAnyStr(min_length=1, max_length=10)

66

67

# Case constraints

68

assert "HELLO" == IsAnyStr(case='upper')

69

assert "hello" == IsAnyStr(case='lower')

70

assert "Hello World" == IsAnyStr(case='title')

71

assert "Hello" == IsAnyStr(case='capitalize')

72

73

# Regex matching

74

assert "test@example.com" == IsAnyStr(regex=r'.+@.+\..+')

75

assert "123-456-7890" == IsAnyStr(regex=r'\d{3}-\d{3}-\d{4}')

76

77

# Regex with flags

78

assert "HELLO world" == IsAnyStr(

79

regex=r'hello world',

80

regex_flags=re.IGNORECASE

81

)

82

83

# Combined constraints

84

assert "Hello World!" == IsAnyStr(

85

min_length=5,

86

max_length=20,

87

regex=r'^[A-Za-z\s!]+$' # Letters, spaces, exclamation only

88

)

89

90

# API response validation

91

api_data = {

92

'username': 'john_doe',

93

'email': 'john@example.com',

94

'status': 'ACTIVE',

95

'description': b'binary data here'

96

}

97

98

assert api_data == {

99

'username': IsAnyStr(min_length=3, max_length=20),

100

'email': IsAnyStr(regex=r'.+@.+\..+'),

101

'status': IsAnyStr(case='upper'),

102

'description': IsAnyStr(min_length=1) # Any non-empty bytes

103

}

104

```

105

106

### IsStr

107

108

String-specific validation that inherits all functionality from IsAnyStr but restricts validation to string objects only, excluding bytes.

109

110

```python { .api }

111

class IsStr(IsAnyStr):

112

"""

113

String comparison with constraints (excludes bytes).

114

115

Inherits all functionality from IsAnyStr but only

116

accepts str objects, not bytes.

117

"""

118

119

expected_types: ClassVar[Tuple[type, ...]] = (str,)

120

```

121

122

#### Usage Examples

123

124

```python

125

from dirty_equals import IsStr

126

import re

127

128

# Basic string validation

129

assert "hello world" == IsStr

130

assert "12345" == IsStr

131

132

# Bytes won't match

133

# assert b"hello" == IsStr # Would fail

134

135

# Length validation

136

assert "username" == IsStr(min_length=3, max_length=20)

137

assert "short" == IsStr(min_length=1, max_length=10)

138

139

# Case validation

140

assert "HELLO" == IsStr(case='upper')

141

assert "hello" == IsStr(case='lower')

142

assert "Hello World" == IsStr(case='title')

143

assert "Hello" == IsStr(case='capitalize')

144

145

# Pattern matching

146

assert "john@example.com" == IsStr(regex=r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')

147

assert "+1-555-123-4567" == IsStr(regex=r'^\+\d{1,3}-\d{3}-\d{3}-\d{4}$')

148

149

# URL validation

150

assert "https://www.example.com/path" == IsStr(regex=r'^https?://.+')

151

152

# Username validation

153

assert "user_name123" == IsStr(

154

min_length=3,

155

max_length=20,

156

regex=r'^[a-zA-Z0-9_]+$' # Alphanumeric and underscore only

157

)

158

159

# Password strength validation

160

assert "MyPassword123!" == IsStr(

161

min_length=8,

162

regex=r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).*$'

163

)

164

165

# Form data validation

166

form_input = {

167

'first_name': 'John',

168

'last_name': 'Doe',

169

'email': 'john.doe@company.com',

170

'phone': '555-0123',

171

'zip_code': '12345',

172

'country': 'US'

173

}

174

175

assert form_input == {

176

'first_name': IsStr(min_length=1, max_length=50, case='capitalize'),

177

'last_name': IsStr(min_length=1, max_length=50, case='capitalize'),

178

'email': IsStr(regex=r'^[^@]+@[^@]+\.[^@]+$'),

179

'phone': IsStr(regex=r'^\d{3}-\d{4}$'),

180

'zip_code': IsStr(regex=r'^\d{5}$'),

181

'country': IsStr(case='upper', min_length=2, max_length=2)

182

}

183

184

# Configuration validation

185

config = {

186

'app_name': 'MyApplication',

187

'environment': 'production',

188

'log_level': 'INFO',

189

'secret_key': 'abc123def456ghi789'

190

}

191

192

assert config == {

193

'app_name': IsStr(min_length=1),

194

'environment': IsStr(regex=r'^(development|staging|production)$'),

195

'log_level': IsStr(regex=r'^(DEBUG|INFO|WARNING|ERROR|CRITICAL)$'),

196

'secret_key': IsStr(min_length=16)

197

}

198

199

# File path validation

200

file_paths = {

201

'config_file': '/etc/myapp/config.json',

202

'log_file': '/var/log/myapp.log',

203

'temp_dir': '/tmp/myapp/'

204

}

205

206

assert file_paths == {

207

'config_file': IsStr(regex=r'^/.+\.json$'),

208

'log_file': IsStr(regex=r'^/.+\.log$'),

209

'temp_dir': IsStr(regex=r'^/.+/$') # Ends with slash

210

}

211

212

# Social media validation

213

social_handles = {

214

'twitter': '@johndoe',

215

'instagram': 'john.doe.photography',

216

'linkedin': 'john-doe-engineer'

217

}

218

219

assert social_handles == {

220

'twitter': IsStr(regex=r'^@[a-zA-Z0-9_]{1,15}$'),

221

'instagram': IsStr(regex=r'^[a-zA-Z0-9_.]{1,30}$'),

222

'linkedin': IsStr(regex=r'^[a-zA-Z0-9-]{3,100}$')

223

}

224

225

# API token validation

226

tokens = {

227

'api_key': 'sk-1234567890abcdef1234567890abcdef',

228

'session_token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',

229

'refresh_token': 'rt_1234567890abcdef'

230

}

231

232

assert tokens == {

233

'api_key': IsStr(regex=r'^sk-[a-f0-9]{32}$'),

234

'session_token': IsStr(min_length=100), # JWT tokens are long

235

'refresh_token': IsStr(regex=r'^rt_[a-f0-9]{16}$')

236

}

237

```

238

239

### IsBytes

240

241

Bytes-specific validation that inherits all functionality from IsAnyStr but restricts validation to bytes objects only, excluding strings.

242

243

```python { .api }

244

class IsBytes(IsAnyStr):

245

"""

246

Bytes comparison with constraints (excludes strings).

247

248

Inherits all functionality from IsAnyStr but only

249

accepts bytes objects, not strings.

250

"""

251

252

expected_types: ClassVar[Tuple[type, ...]] = (bytes,)

253

```

254

255

#### Usage Examples

256

257

```python

258

from dirty_equals import IsBytes

259

import re

260

261

# Basic bytes validation

262

assert b"hello world" == IsBytes

263

assert b"\x00\x01\x02\x03" == IsBytes

264

265

# Strings won't match

266

# assert "hello" == IsBytes # Would fail

267

268

# Length validation

269

assert b"binary_data" == IsBytes(min_length=5, max_length=50)

270

assert b"short" == IsBytes(min_length=1, max_length=10)

271

272

# Pattern matching on bytes

273

assert b"Content-Type: application/json" == IsBytes(regex=rb'Content-Type: \w+/\w+')

274

assert b"HTTP/1.1 200 OK" == IsBytes(regex=rb'HTTP/\d\.\d \d{3} \w+')

275

276

# File signature validation (magic numbers)

277

png_header = b'\x89PNG\r\n\x1a\n'

278

jpeg_header = b'\xff\xd8\xff'

279

pdf_header = b'%PDF-'

280

281

assert png_header == IsBytes(regex=rb'^\x89PNG\r\n\x1a\n')

282

assert jpeg_header == IsBytes(regex=rb'^\xff\xd8\xff')

283

assert pdf_header == IsBytes(regex=rb'^%PDF-')

284

285

# Network packet validation

286

http_request = b'GET /api/users HTTP/1.1\r\nHost: example.com\r\n\r\n'

287

assert http_request == IsBytes(

288

regex=rb'^GET .+ HTTP/\d\.\d\r\n.*Host: .+\r\n\r\n$'

289

)

290

291

# Binary protocol validation

292

protocol_message = b'\x02\x00\x10Hello World!\x03' # STX + length + data + ETX

293

assert protocol_message == IsBytes(

294

min_length=4, # At least header + footer

295

regex=rb'^\x02.+\x03$' # Starts with STX, ends with ETX

296

)

297

298

# Cryptographic data validation

299

encrypted_data = {

300

'iv': b'\x12\x34\x56\x78' * 4, # 16 bytes IV

301

'ciphertext': b'encrypted_payload_here_with_padding',

302

'tag': b'\xaa\xbb\xcc\xdd' * 4 # 16 bytes auth tag

303

}

304

305

assert encrypted_data == {

306

'iv': IsBytes(min_length=16, max_length=16), # Exactly 16 bytes

307

'ciphertext': IsBytes(min_length=1), # Non-empty

308

'tag': IsBytes(min_length=16, max_length=16) # Exactly 16 bytes

309

}

310

311

# File content validation

312

file_data = {

313

'image': b'\x89PNG\r\n\x1a\n' + b'image_data_here',

314

'document': b'%PDF-1.4\n' + b'pdf_content_here',

315

'archive': b'PK\x03\x04' + b'zip_content_here'

316

}

317

318

assert file_data == {

319

'image': IsBytes(regex=rb'^\x89PNG'), # PNG file

320

'document': IsBytes(regex=rb'^%PDF-'), # PDF file

321

'archive': IsBytes(regex=rb'^PK\x03\x04') # ZIP file

322

}

323

324

# Database blob validation

325

blob_data = {

326

'profile_picture': b'binary_image_data_here',

327

'document_content': b'binary_document_data',

328

'metadata': b'{"created": "2023-01-01"}'

329

}

330

331

assert blob_data == {

332

'profile_picture': IsBytes(min_length=1, max_length=5*1024*1024), # Max 5MB

333

'document_content': IsBytes(min_length=1),

334

'metadata': IsBytes(regex=rb'^\{.*\}$') # JSON-like structure

335

}

336

337

# Message queue payloads

338

queue_messages = [

339

b'{"type": "user_created", "data": {...}}',

340

b'{"type": "order_processed", "data": {...}}',

341

b'{"type": "email_sent", "data": {...}}'

342

]

343

344

message_pattern = IsBytes(regex=rb'^\{"type": "\w+", "data": .*\}$')

345

for message in queue_messages:

346

assert message == message_pattern

347

348

# Network response validation

349

api_response_bytes = b'{"status": "success", "data": [...]}'

350

assert api_response_bytes == IsBytes(

351

min_length=10, # Minimum JSON structure

352

regex=rb'^\{.*"status".*\}$' # Contains status field

353

)

354

355

# Base64 encoded data (still bytes before decoding)

356

base64_data = b'SGVsbG8gV29ybGQh' # "Hello World!" encoded

357

assert base64_data == IsBytes(regex=rb'^[A-Za-z0-9+/]+=*$')

358

359

# Binary log entries

360

log_entry = b'\x00\x00\x00\x20' + b'2023-01-01 12:00:00 INFO: App started'

361

assert log_entry == IsBytes(

362

min_length=8, # Header + some content

363

regex=rb'^\x00\x00\x00.+INFO:' # Starts with header, contains INFO

364

)

365

```

366

367

## Type Definitions

368

369

```python { .api }

370

from typing import ClassVar, Optional, Pattern, Tuple, Union

371

import re

372

373

# All string types inherit from IsAnyStr which inherits from DirtyEquals

374

# They work with Python's standard str and bytes types

375

376

# Common regex flags that can be used with regex_flags parameter:

377

# re.IGNORECASE, re.MULTILINE, re.DOTALL, re.VERBOSE, etc.

378

```