From ce8a93c405c55dcdb18531369ad610f5e7ef0b3f Mon Sep 17 00:00:00 2001 From: Adam Donahue Date: Sat, 24 Jun 2017 15:43:54 -0400 Subject: [PATCH 1/4] master: Update to_camel_case to handle leading and double-underscores. --- graphene/utils/str_converters.py | 33 +++++++++++++++++---- graphene/utils/tests/test_str_converters.py | 6 +++- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/graphene/utils/str_converters.py b/graphene/utils/str_converters.py index ae8ceffe..6616fc04 100644 --- a/graphene/utils/str_converters.py +++ b/graphene/utils/str_converters.py @@ -1,14 +1,35 @@ import re -# From this response in Stackoverflow -# http://stackoverflow.com/a/19053800/1072990 def to_camel_case(snake_str): - components = snake_str.split('_') - # We capitalize the first letter of each component except the first one - # with the 'title' method and join them together. - return components[0] + "".join(x.title() if x else '_' for x in components[1:]) + """ + Return a camel-cased version of a snake-cased string. + + Leading underscores and multiple-underscores are kept + intact. + + :param snake_str: A snake-cased string. + :return: A camel-cased string. + """ + # Find all subcomponents in a snake-cased string, including + # any trailing underscores, which are treated as + snake_case_sub_strings = re.findall(r'(_*[a-zA-Z]+|_+$)', snake_str) + # The first variable is unchanged case wise. + camel_case_sub_strings = [snake_case_sub_strings[0]] + + for s in snake_case_sub_strings[1:]: + # We reset the camel casing algorithm if more than one + # underscore is encountered, and do nothing for trailing + # unscores at the end of the snake-cased variable. + if s.startswith('__') or s.endswith('_'): + camel_case_sub_strings.append(s) + continue + + # Otherwise replace '_name' with 'Name', for example. + camel_case_sub_strings.append(s[1:].title()) + + return ''.join(camel_case_sub_strings) # From this response in Stackoverflow # http://stackoverflow.com/a/1176023/1072990 diff --git a/graphene/utils/tests/test_str_converters.py b/graphene/utils/tests/test_str_converters.py index 2ee7d7a5..62eed4ad 100644 --- a/graphene/utils/tests/test_str_converters.py +++ b/graphene/utils/tests/test_str_converters.py @@ -14,8 +14,12 @@ def test_snake_case(): def test_camel_case(): assert to_camel_case('snakes_on_a_plane') == 'snakesOnAPlane' - assert to_camel_case('snakes_on_a__plane') == 'snakesOnA_Plane' + assert to_camel_case('snakes_on_a__plane') == 'snakesOnA__plane' assert to_camel_case('i_phone_hysteria') == 'iPhoneHysteria' + assert to_camel_case('i_phone_hysteria_') == 'iPhoneHysteria_' + assert to_camel_case('_i_phone_hysteria') == '_iPhoneHysteria' + assert to_camel_case('__i_phone_hysteria') == '__iPhoneHysteria' + assert to_camel_case('__all__') == '__all__' def test_to_const(): From 9e408b385aaf28c0c7f03a1066108be56f3bbab7 Mon Sep 17 00:00:00 2001 From: Adam Donahue Date: Sat, 24 Jun 2017 15:53:32 -0400 Subject: [PATCH 2/4] Fix up comments. --- graphene/utils/str_converters.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/graphene/utils/str_converters.py b/graphene/utils/str_converters.py index 6616fc04..72c4cbf1 100644 --- a/graphene/utils/str_converters.py +++ b/graphene/utils/str_converters.py @@ -12,16 +12,19 @@ def to_camel_case(snake_str): :return: A camel-cased string. """ # Find all subcomponents in a snake-cased string, including - # any trailing underscores, which are treated as + # any trailing underscores, which are treated as a separate + # component. snake_case_sub_strings = re.findall(r'(_*[a-zA-Z]+|_+$)', snake_str) - # The first variable is unchanged case wise. + # The first variable is unchanged case wise (and leading + # underscores preserved as-is). camel_case_sub_strings = [snake_case_sub_strings[0]] for s in snake_case_sub_strings[1:]: # We reset the camel casing algorithm if more than one - # underscore is encountered, and do nothing for trailing - # unscores at the end of the snake-cased variable. + # underscore is encountered. The endwiths handles any + # trailing underscores in the original snake-cased + # variable. if s.startswith('__') or s.endswith('_'): camel_case_sub_strings.append(s) continue From c012c48866b307345935401b02e0b6de542d5d83 Mon Sep 17 00:00:00 2001 From: Adam Donahue Date: Sat, 24 Jun 2017 16:45:13 -0400 Subject: [PATCH 3/4] Address pylint issues. --- graphene/utils/str_converters.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/graphene/utils/str_converters.py b/graphene/utils/str_converters.py index 72c4cbf1..5d3d2fad 100644 --- a/graphene/utils/str_converters.py +++ b/graphene/utils/str_converters.py @@ -4,10 +4,10 @@ import re def to_camel_case(snake_str): """ Return a camel-cased version of a snake-cased string. - + Leading underscores and multiple-underscores are kept intact. - + :param snake_str: A snake-cased string. :return: A camel-cased string. """ @@ -29,11 +29,12 @@ def to_camel_case(snake_str): camel_case_sub_strings.append(s) continue - # Otherwise replace '_name' with 'Name', for example. + # Otherwise we replace '_name' with 'Name', for example. camel_case_sub_strings.append(s[1:].title()) return ''.join(camel_case_sub_strings) + # From this response in Stackoverflow # http://stackoverflow.com/a/1176023/1072990 def to_snake_case(name): From faf8a41118555c715c3a56b8371ab33b654fe9ab Mon Sep 17 00:00:00 2001 From: Adam Donahue Date: Tue, 27 Jun 2017 18:22:22 -0400 Subject: [PATCH 4/4] Fix to comments. --- graphene/utils/str_converters.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/graphene/utils/str_converters.py b/graphene/utils/str_converters.py index 5d3d2fad..0b1bb28d 100644 --- a/graphene/utils/str_converters.py +++ b/graphene/utils/str_converters.py @@ -5,7 +5,7 @@ def to_camel_case(snake_str): """ Return a camel-cased version of a snake-cased string. - Leading underscores and multiple-underscores are kept + Leading underscores and multiple consecutive underscores are kept intact. :param snake_str: A snake-cased string. @@ -16,13 +16,13 @@ def to_camel_case(snake_str): # component. snake_case_sub_strings = re.findall(r'(_*[a-zA-Z]+|_+$)', snake_str) - # The first variable is unchanged case wise (and leading + # The first variable is unchanged case-wise (and leading # underscores preserved as-is). camel_case_sub_strings = [snake_case_sub_strings[0]] for s in snake_case_sub_strings[1:]: # We reset the camel casing algorithm if more than one - # underscore is encountered. The endwiths handles any + # underscore is encountered. The endswith handles any # trailing underscores in the original snake-cased # variable. if s.startswith('__') or s.endswith('_'):