Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions utils.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import re

_CLASS_FINDER = re.compile(r'^class ([A-Z].*)\(ABC\)')
_CLASS_FINDER = re.compile(r'^\s*class\s+([A-Z][a-zA-Z0-9_]*)\s*\((?:ABC|object)\)\s*:\s*')


def guess_classname(code: str) -> str:
if match := _CLASS_FINDER.search(code):
return match.group(1)
for line in code.splitlines():
if match := _CLASS_FINDER.search(line):
return match.group(1)
raise ValueError('Cannot find classname in code. Expected a class definition like `class ClassName(ABC):`')


def camel_to_snake(input: str) -> str:
return re.sub(r'(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[a-z])(?=[A-Z]{2,})', '_', input).lower()
s1 = re.sub(r'(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])', '_', input)
s2 = re.sub(r'([a-zA-Z])([0-9])', r'\1\2', s1)
return re.sub(r'([0-9])([A-Z])', r'\1_\2', s2).lower()
22 changes: 22 additions & 0 deletions utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ def test_guess_classname_edge_case_lowercase(self):
with self.assertRaises(ValueError):
guess_classname(code)

def test_guess_classname_with_extra_whitespace(self):
code = "class MyClass (ABC) : pass"
self.assertEqual(guess_classname(code), "MyClass")

def test_guess_classname_with_multiple_classes(self):
code = "class FirstClass(ABC): pass\nclass SecondClass(ABC): pass"
self.assertEqual(guess_classname(code), "FirstClass")

def test_guess_classname_with_complex_class_definition(self):
code = "class MyComplexClass(object, metaclass=MyMeta): pass"
with self.assertRaises(ValueError):
guess_classname(code)

def test_camel_to_snake_edge_case(self):
self.assertEqual(camel_to_snake(""), "")
self.assertEqual(camel_to_snake("A"), "a")
Expand All @@ -30,3 +43,12 @@ def test_camel_to_snake_with_acronyms(self):
self.assertEqual(camel_to_snake("MyID"), "my_id")
self.assertEqual(camel_to_snake("SimpleXMLParser"), "simple_xml_parser")
self.assertEqual(camel_to_snake("APIFlagsSet"), "api_flags_set")

def test_camel_to_snake_with_numbers(self):
self.assertEqual(camel_to_snake("MyClass1"), "my_class1")
self.assertEqual(camel_to_snake("MyClass123"), "my_class123")
self.assertEqual(camel_to_snake("Class123Name"), "class123_name")

def test_camel_to_snake_single_word(self):
self.assertEqual(camel_to_snake("hello"), "hello")
self.assertEqual(camel_to_snake("WORLD"), "world")