Coder Social home page Coder Social logo

Camelize/decamelize asymmetries about humps HOT 4 CLOSED

nficano avatar nficano commented on June 15, 2024 3
Camelize/decamelize asymmetries

from humps.

Comments (4)

antonagestam avatar antonagestam commented on June 15, 2024

@mjschock What behavior do you expect for humps.decamelize(humps.camelize('item_1entry'))?

from humps.

mjschock avatar mjschock commented on June 15, 2024

@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.

Hultner avatar Hultner commented on June 15, 2024

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.

Hultner avatar Hultner commented on June 15, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.