Elegant Python Function to Convert Camelcase to Snake_Case

Elegant Python function to convert CamelCase to snake_case?

Camel case to snake case

import re

name = 'CamelCaseName'
name = re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()
print(name) # camel_case_name

If you do this many times and the above is slow, compile the regex beforehand:

pattern = re.compile(r'(?<!^)(?=[A-Z])')
name = pattern.sub('_', name).lower()

To handle more advanced cases specially (this is not reversible anymore):

def camel_to_snake(name):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()

print(camel_to_snake('camel2_camel2_case')) # camel2_camel2_case
print(camel_to_snake('getHTTPResponseCode')) # get_http_response_code
print(camel_to_snake('HTTPResponseCodeXYZ')) # http_response_code_xyz

To add also cases with two underscores or more:

def to_snake_case(name):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
name = re.sub('__([A-Z])', r'_\1', name)
name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name)
return name.lower()

Snake case to pascal case

name = 'snake_case_name'
name = ''.join(word.title() for word in name.split('_'))
print(name) # SnakeCaseName

Convert camelCase to snakeCase

data = {
'firstName': 'abc',
'lastName': 'xyz',
'favoriteMovies': ['Star Wars', 'The lone ranger'],
'favoriteCountries': [
{'country': 'China', 'capitalCity': 'Beiging'},
{'country': 'India', 'capitalCity': 'New Delhi'}
]
}

new_data = {}
for key, value in data.items():
new_key_list = ['_' + x.lower() if x.isupper() else x for x in key]
new_key = ''.join(new_key_list)
if isinstance(value[0],dict):
new_value = []
for item in value:
temp_dict = {}
for key2, value2 in item.items():
new_key_list = ['_' + x.lower() if x.isupper() else x for x in key2]
new_key = ''.join(new_key_list)
temp_dict[new_key] = value2
new_value.append(temp_dict)
new_data[new_key] = new_value
else:
new_data[new_key] = value

Output:

{'first_name': 'abc', 'last_name': 'xyz', 'favorite_movies': ['Star Wars', 'The lone ranger'], 'capital_city': [{'country': 'China', 'capital_city': 'Beiging'}, {'country': 'India', 'capital_city': 'New Delhi'}]}

python function to convert camel case to snake case

To answer your second question first, this seems like a perfectly reasonable way to accomplish this task but it might not be as maintainable as other approaches since it can be kind of difficult to figure out how it works.

Here is a breakdown of what each line does:

  • string = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', string)
    Adds an underscore immediately before every single uppercase character that is followed by one or more lowercase character, except at the beginning of the string.

  • string = re.sub('(.)([0-9]+)', r'\1_\2', string)
    Adds an underscore immediately before any group of consecutive digits, except at the beginning of the string.

  • return re.sub('([a-z0-9])([A-Z])', r'\1_\2', string).lower()
    Adds an underscore immediately before any uppercase character that has a lowercase character or digit before it, and converts the whole string to lowercase and returns.

How to convert snippet placeholder from CamelCase to snake_case

"camelToSnakeCase": {
"prefix": "test",
"body": [

"${1} -> ${1/([A-Z][a-z]+$)|([A-Z][a-z]+)/${1:/downcase}${2:/downcase}${2:+_}/g}"
],
"description": "transform from CamelCase to snake_case"
}

In order to differentiate between some last capture group like Abcd and the preceding capture groups, I used an alternation:

([A-Z][a-z]+$)|([A-Z][a-z]+) must be in this order

so group 1 will be at the end of the input because of the $ indicator and group 2 will not be at the end. And group 2s will always have at least one more group after them. Then, using the conditional ${2:+_} only insert an underscore if there is a group 2 - because there must be a following group 1.


This keybinding version also works if you have a different workflow:

{
"key": "alt+3", // whatever keybinding you wish
"command": "extension.multiCommand.execute",
"args": {
"sequence": [
"cursorWordLeftSelect",
"editor.action.transformToSnakecase",
"editor.action.transformToLowercase",
// "cursorLineEnd" // if you want this
]
},
"when": "editorTextFocus && !editorHasSelection"
}

Type your word and trigger the keybinding. Uses the macro extension multi-command.

Python + Flask REST API, how to convert data keys between camelcase and snakecase?

You don't convert your keys, because you don't need to. Data is not code, the keys in JSON are not variables. They are not subject to PEP8 and you don't convert them.

If you have a convention for your JSON object keys, stick to it everywhere, in your front end and back end. Then use the Marshmallow 3.x data_key argument for a field to set the key name in the JSON document when loading and dumping.

E.g.

class UserSchema(Schema):
first_name = fields.String(data_key="firstName")
last_name = fields.Email(data_key='lastName')

If you want to automate this for all your fields, you could provide your own Schema.on_bind_field() implementation to generate a data_key value from the field name:

import re
from functools import partial

from marshmallow import Schema

_snake_case = re.compile(r"(?<=\w)_(\w)")
_to_camel_case = partial(_snake_case.sub, lambda m: m[1].upper())

class CamelCasedSchema(Schema):
"""Gives fields a camelCased data key"""
def on_bind_field(self, field_name, field_obj, _cc=_to_camel_case):
field_obj.data_key = _cc(field_name.lower())

Demo:

>>> from marshmallow import fields
>>> class UserSchema(CamelCasedSchema):
... first_name = fields.String()
... last_name = fields.String()
...
>>> schema = UserSchema()
>>> schema.load({"firstName": "Eric", "lastName": "Idle"})
{'first_name': 'Eric', 'last_name': 'Idle'}
>>> schema.dump({"first_name": "John", "last_name": "Cleese"})
{'firstName': 'John', 'lastName': 'Cleese'}

The examples section of the Marshmallow documentation has a similar recipe.

If you are using Marshmallow 2.x, then there are two arguments to set: load_from and dump_to.

Convert snake_case to camelCase in Python GraphQL resolver using Ariadne

Well, after reading this Ariadne discussion, I figured out that, I just had not to pass Ariadne snake_case_fallback_resolvers while creating Ariadne executable GraphQL schema.

So, basically, what I had done was -

from ariadne import load_schema_from_path, make_executable_schema, snake_case_fallback_resolvers, graphql_sync, ObjectType

type_defs = load_schema_from_path("./schema.graphql")
schema = make_executable_schema(type_defs, query, snake_case_fallback_resolvers)

What I did to fix this issue of not being able to map attributes in camelCase back to GraphQL response:

schema = make_executable_schema(type_defs, query)
# Just removed snake_case_fallback_resolvers from the function parameters

Also, I removed @snake_case_fallback_resolvers from the resolver function, to get attributes if any passed as input to the resolver in camelCase.



Related Topics



Leave a reply



Submit