Skip to content

Commit a9470b5

Browse files
committed
Enforce strict CamelCase for Table subclasses
Per @dimitri-yatsenko suggestion.
1 parent f9adfb3 commit a9470b5

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

datajoint/utils.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,33 @@ def get_master(full_table_name: str) -> str:
5353
return match["master"] + "`" if match else ""
5454

5555

56+
def contains_non_ascii_char(s):
57+
"""
58+
Check if a string contains non-ASCII characters.
59+
60+
:param s: string to check
61+
:returns: True if the string contains any non-ASCII characters, False otherwise
62+
Example:
63+
>>> contains_non_ascii_char("Hello") # returns False
64+
>>> contains_non_ascii_char("HelloΣ") # returns True
65+
"""
66+
return any(ord(c) > 127 for c in s)
67+
68+
69+
def is_camel_case(s):
70+
"""
71+
Check if a string is in CamelCase notation.
72+
73+
:param s: string to check
74+
:returns: True if the string is in CamelCase notation, False otherwise
75+
Example:
76+
>>> is_camel_case("TableName") # returns True
77+
>>> is_camel_case("table_name") # returns False
78+
"""
79+
# return re.match(r"^[A-Z][a-z0-9]+(?:[A-Z][a-z0-9]+)*$", s) is not None
80+
return re.match(r"[A-Z][a-zA-Z0-9]*", s) is not None and not contains_non_ascii_char(s)
81+
82+
5683
def to_camel_case(s):
5784
"""
5885
Convert names with under score (_) separation into camel case names.
@@ -82,7 +109,7 @@ def from_camel_case(s):
82109
def convert(match):
83110
return ("_" if match.groups()[0] else "") + match.group(0).lower()
84111

85-
if not re.match(r"[A-Z][a-zA-Z0-9]*", s):
112+
if not is_camel_case(s):
86113
raise DataJointError(
87114
"ClassName must be alphanumeric in CamelCase, begin with a capital letter"
88115
)

tests/test_utils.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,23 @@
33
"""
44

55
from datajoint import DataJointError
6-
from datajoint.utils import from_camel_case, to_camel_case
6+
from datajoint.utils import from_camel_case, to_camel_case, is_camel_case, contains_non_ascii_char
77
import pytest
88

99

10+
def test_is_camel_case():
11+
assert is_camel_case("AllGroups")
12+
assert not is_camel_case("allGroups")
13+
assert not is_camel_case("repNames")
14+
assert not is_camel_case("10_all")
15+
assert not is_camel_case("hello world")
16+
assert not is_camel_case("#baisc_names")
17+
assert not is_camel_case("alphaBeta")
18+
non_ascii_class_name = "TestΣ"
19+
assert contains_non_ascii_char(non_ascii_class_name)
20+
assert not is_camel_case(non_ascii_class_name)
21+
22+
1023
def test_from_camel_case():
1124
assert from_camel_case("AllGroups") == "all_groups"
1225
with pytest.raises(DataJointError):

0 commit comments

Comments
 (0)