Comments (4)
@mjschock What behavior do you expect for humps.decamelize(humps.camelize('item_1entry'))
?
from humps.
@antonagestam hmm... i would expect the following:
>>> humps.camelize('item_1entry')
'item_1entry'
>>> humps.decamelize('item_1entry')
'item_1entry'
so
>>> humps.decamelize(humps.camelize('item_1entry'))
'item_1entry'
the general rules would be something like:
class IrreversibleProcessException(Exception):
pass
def camelize(chars, root=True):
camelized_chars = []
for i, char in enumerate(chars):
if char == '_':
continue
if i in (0, 1, len(chars) - 1):
camelized_chars.append(char)
continue
if chars[i-1] == '_' and char.isalpha() and char.islower():
camelized_chars.append(char.upper())
elif chars[i-1] == '_':
camelized_chars.append('_')
camelized_chars.append(char)
else:
camelized_chars.append(char)
camelized_chars_string = ''.join(camelized_chars)
if root and decamelize(camelized_chars_string, False) != chars:
raise IrreversibleProcessException
return camelized_chars_string
def decamelize(chars, root=True):
decamelized_chars = []
for i, char in enumerate(chars):
if i in (0, 1, len(chars) - 1):
decamelized_chars.append(char)
continue
if chars[i+1] == '_' or chars[i-1] == '_':
decamelized_chars.append(char)
elif (chars[i-1].isalpha() and chars[i-1].islower()) and char.isupper():
decamelized_chars.append('_')
decamelized_chars.append(char.lower())
elif not chars[i-1].isalpha() and char.isalpha() and char.isupper():
decamelized_chars.append('_')
decamelized_chars.append(char.lower())
else:
decamelized_chars.append(char)
decamelized_chars_string = ''.join(decamelized_chars)
if root and camelize(decamelized_chars_string, False) != chars:
raise IrreversibleProcessException
return decamelized_chars_string
assert camelize('item1_entry') == 'item1Entry'
assert camelize('N1_item') == 'N1Item'
assert camelize('n1_item') == 'n1Item'
assert camelize('item_1entry') == 'item_1entry'
assert camelize('ADVERTISED_1000baseT_Full') == 'ADVERTISED_1000baseT_Full'
assert decamelize('item1Entry') == 'item1_entry'
assert decamelize('item1entry') == 'item1entry'
assert decamelize('N1Item') == 'N1_item'
assert decamelize('N1item') == 'N1item'
assert decamelize('n1Item') == 'n1_item'
assert decamelize('item_1entry') == 'item_1entry'
assert decamelize('ADVERTISED_1000baseT_Full') == 'ADVERTISED_1000baseT_Full'
from humps.
I think this is the same issue as #168, I've added these examples in that issue.
# Inconsistent behaviour
>>> humps.camelize("ab")
'ab'
>>> humps.camelize("a_b")
'a_b'
>>> humps.camelize("a_be")
'a_be'
>>> humps.camelize("a_best")
'a_best'
>>> humps.camelize("ar_best")
'arBest'
# Incorrect roundtrip
>>> humps.decamelize(humps.camelize("area_b"))
'areab'
# Correct
>>> humps.decamelize(humps.camelize("aa_bb"))
'aa_bb'
# Wrong
>>> humps.decamelize(humps.camelize("aa_b"))
'aab'
# Correct
>>> humps.decamelize(humps.camelize("a_b"))
'a_b'
>>> humps.decamelize(humps.camelize("a_bb"))
'a_bb'
# Frist is wrong, second correct
>>> humps.camelize("a_b")
'a_b'
>>> humps.camelize("aa_ab")
'aaAb'
from humps.
I'd recommend using property based testing as this is a very classic round trip case.
Here's an example test that catches these type of failures.
import humps.main
from hypothesis import given
from hypothesis import strategies as st
@given(str_or_iter=st.text(min_size=1))
def test_roundtrip_camelize_decamelize(str_or_iter):
value0 = humps.main.camelize(str_or_iter=str_or_iter)
value1 = humps.main.decamelize(str_or_iter=value0)
assert str_or_iter == value1, (str_or_iter, value1)
Results:
===================================== FAILURES =====================================
________________________ test_roundtrip_camelize_decamelize ________________________
[gw0] darwin -- Python 3.9.0 ***
@given(str_or_iter=st.text(min_size=1))
> def test_roundtrip_camelize_decamelize(str_or_iter):
src/tests/schemas/test_query_params.py:28:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
str_or_iter = 'Aa'
@given(str_or_iter=st.text(min_size=1))
def test_roundtrip_camelize_decamelize(str_or_iter):
value0 = humps.main.camelize(str_or_iter=str_or_iter)
value1 = humps.main.decamelize(str_or_iter=value0)
> assert str_or_iter == value1, (str_or_iter, value1)
E AssertionError: ('Aa', 'aa')
E assert 'Aa' == 'aa'
E - aa
E + Aa
src/tests/...py:31: AssertionError
------------------------------------ Hypothesis ------------------------------------
Falsifying example: test_roundtrip_camelize_decamelize(
str_or_iter='Aa',
)
from humps.
Related Issues (20)
- ReadTheDocs build is failing after dropping Python 2.7
- Coveralls badge is not updating
- Support for Kebab case? HOT 6
- Add maximum depth option to all function to limit how deep to apply formatting
- Transition package manager from pipenv to poetry
- None and empty string input are not camelized correctly HOT 1
- decamelize incorrectly inserts _ after punctuation HOT 2
- Acronyms with inner digits do not decamelize correctly
- Add a conda-forge feedstock HOT 1
- An import issue after install and remove the 'humps' package. HOT 3
- [question] Abbreviation conversion assymetry workarounds HOT 3
- Add a humps jinja2 extension HOT 1
- Ability to build debian deb pkg HOT 2
- Complete transition into using poetry and more HOT 1
- Streamlit
- camelizeKeys only rather than the full dictionary (values and keys) HOT 3
- Kebabize string with spaces
- Wrong value for camelize and decamelize when using 1 or 2 characters key
- Support digits as tokens
- Release 3.9.0 didn't make it to PyPI HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from humps.