Skip to content

Commit cd3c672

Browse files
Fix breaking change in to_snake from v2.7 -> v2.8 (#9812)
1 parent 7a70051 commit cd3c672

File tree

3 files changed

+18
-9
lines changed

3 files changed

+18
-9
lines changed

pydantic/alias_generators.py

+10-9
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,14 @@ def to_snake(camel: str) -> str:
4949
Returns:
5050
The converted string in snake_case.
5151
"""
52-
# `(?<=[a-zA-Z])(?=[0-9])` matches the space between a letter and a digit
53-
# `(?<=[a-z0-9])(?=[A-Z])` matches the space between a lowercase letter / digit and uppercase letter
54-
# `(?<=[A-Z])(?=[A-Z][a-z])` matches the space between two uppercase letters when the latter is followed by a lowercase letter
55-
# `-` matches a hyphen in order to convert kebab case strings
56-
snake = re.sub(
57-
r'(?<=[a-zA-Z])(?=[0-9])|(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|-',
58-
'_',
59-
camel,
60-
)
52+
# Handle the sequence of uppercase letters followed by a lowercase letter
53+
snake = re.sub(r'([A-Z]+)([A-Z][a-z])', lambda m: f'{m.group(1)}_{m.group(2)}', camel)
54+
# Insert an underscore between a lowercase letter and an uppercase letter
55+
snake = re.sub(r'([a-z])([A-Z])', lambda m: f'{m.group(1)}_{m.group(2)}', snake)
56+
# Insert an underscore between a digit and an uppercase letter
57+
snake = re.sub(r'([0-9])([A-Z])', lambda m: f'{m.group(1)}_{m.group(2)}', snake)
58+
# Insert an underscore between a lowercase letter and a digit
59+
snake = re.sub(r'([a-z])([0-9])', lambda m: f'{m.group(1)}_{m.group(2)}', snake)
60+
# Replace hyphens with underscores to handle kebab-case
61+
snake = snake.replace('-', '_')
6162
return snake.lower()

pyproject.toml

+7
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,10 @@ skip = '.git,env*,pydantic/v1/*'
246246
# `ser` - abbreviation for "ser"ialisation
247247
# `crate` - a rust crate
248248
ignore-words-list = 'gir,ser,crate'
249+
250+
[tool.codeflash]
251+
module-root = "pydantic"
252+
tests-root = "tests"
253+
test-framework = "pytest"
254+
ignore-paths = []
255+
formatter-cmd = ["ruff check --exit-zero --fix $file", "ruff format $file"]

tests/test_utils.py

+1
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ def test_snake2pascal(value: str, result: str) -> None:
542542
('Kebab-Snake', 'kebab_snake'),
543543
('PascalToSnake', 'pascal_to_snake'),
544544
('snake_to_snake', 'snake_to_snake'),
545+
('snakeV2', 'snake_v2'),
545546
],
546547
)
547548
def test_to_snake(value: str, result: str) -> None:

0 commit comments

Comments
 (0)