Skip to main content

Convert Case

Convert between string cases with built-in case inference.

Status

Source Shields
Project release license lines languages
Health readthedocs github_reviewcodacy codacy_coverage
Publishers pypi pypi_downloads
Repository issues issues_closed pulls pulls_closed
Activity contributors monthly_commits last_commit

Installing

Install the package from pypi:

pip install convert-case

To experiment with the source code locally, clone the repository:

git clone https://github.com/joellefkowitz/convert-case

To install linters, formatters and test runners:

pip install .[all]
npm install

Usage

from convert_case import camel_case

camel_case('camel case') # Inferred: lower -> camel
'camelCase'

camel_case('Camel Case') # Inferred: title -> camel
'camelCase'

camel_case('CamelCase') # Inferred: pascal -> camel
'camelCase'

Exports

def pascal_case(string: str) -> str:
    ...
def is_pascal_case(string: str) -> bool:
    ...

def camel_case(string: str) -> str:
    ...
def is_camel_case(string: str) -> bool:
    ...

def kebab_case(string: str) -> str:
    ...
def is_kebab_case(string: str) -> bool:
    ...

def sentence_case(string: str) -> str:
    ...
def is_sentence_case(string: str) -> bool:
    ...

def snake_case(string: str) -> str:
    ...
def is_snake_case(string: str) -> bool:
    ...

def title_case(string: str) -> str:
    ...
def is_title_case(string: str) -> bool:
    ...

def upper_case(string: str) -> str:
    ...
def is_upper_case(string: str) -> bool:
    ...

Definitions

LOWER = re.compile(r"^[a-z0-9\s]*$")
UPPER = re.compile(r"^[A-Z0-9\s]*$")

TITLE = re.compile(r"^(([A-Z0-9][a-z0-9]*)(\s[A-Z0-9][a-z0-9]*)*)?$")
SENTENCE = re.compile(r"^(([A-Z0-9][a-z0-9]*)(\s[a-z0-9]*)*)?$")

CAMEL = re.compile(r"^([a-z0-9][a-zA-Z0-9]*)?$")
PASCAL = re.compile(r"^([A-Z0-9]|([A-Z0-9][a-z0-9]+)*)?$")

SNAKE = re.compile(r"^([a-z0-9]+(_[a-z0-9]+)*)?$")
KEBAB = re.compile(r"^([a-z0-9]+(-[a-z0-9]+)*)?$")

Tests

To run unit tests:

grunt test

Test cases

test lower upper sentence title camel snake kebab pascal
a a A A A a a a A
A a A A A a a a A
abc abc ABC Abc Abc abc abc abc Abc
ab cd ab cd AB CD Ab cd Ab Cd abCd ab_cd ab-cd AbCd
Ab cd ab cd AB CD Ab cd Ab Cd abCd ab_cd ab-cd AbCd
Ab Cd ab cd AB CD Ab cd Ab Cd abCd ab_cd ab-cd AbCd
ab_cd ab cd AB CD Ab cd Ab Cd abCd ab_cd ab-cd AbCd
ab-cd ab cd AB CD Ab cd Ab Cd abCd ab_cd ab-cd AbCd
abCd ab cd AB CD Ab cd Ab Cd abCd ab_cd ab-cd AbCd
ABCD abcd ABCD Abcd Abcd abcd abcd abcd Abcd
AbCd ab cd AB CD Ab cd Ab Cd abCd ab_cd ab-cd AbCd
ab cd ef ab cd ef AB CD EF Ab cd ef Ab Cd Ef abCdEf ab_cd_ef ab-cd-ef AbCdEf
AbCdEf ab cd ef AB CD EF Ab cd ef Ab Cd Ef abCdEf ab_cd_ef ab-cd-ef AbCdEf
ab-cd-ef ab cd ef AB CD EF Ab cd ef Ab Cd Ef abCdEf ab_cd_ef ab-cd-ef AbCdEf
Ab cd ef ab cd ef AB CD EF Ab cd ef Ab Cd Ef abCdEf ab_cd_ef ab-cd-ef AbCdEf

Numbers

Numbers are treated as letters with no specific case.

test lower upper sentence title camel snake kebab pascal
1 1 1 1 1 1 1 1 1
1bc 1bc 1BC 1bc 1bc 1bc 1bc 1bc 1bc
a1c a1c A1C A1c A1c a1c a1c a1c A1c
ab1 ab1 AB1 Ab1 Ab1 ab1 ab1 ab1 Ab1
a1 c a1 c A1 C A1 c A1 C a1C a1_c a1-c A1C
a1-c a1 c A1 C A1 c A1 C a1C a1_c a1-c A1C

Advanced

A goal of this converter is that it is deterministic. If we consider the following examples we can see that this is not simple to achieve. How should we interpret the string 'ABC', is it in upper case or pascal case?

test upper pascal
abc ABC Abc
a b c A B C ABC

Our options are:

  • To consider strings with consecutive capitals like 'ABC' not to be pascal case. If in this case 'a b c' is parsed to 'Abc' it would clash with parsing 'abc' into pascal case.

  • To store some state that remembers the string's case before parsing. This would introduce too much complexity.

  • To prioritize parsing the string as one case unless told otherwise. We choose to pick upper case as the inferred case. The caveat here is that we will no longer be performing 'round trip' conversion.

Round trip conversion:

kebab_case('a b c')
'a-b-c'

lower_case('a-b-c')
'a b c'

Not round trip conversion:

pascal_case('a b c')
'ABC'

lower_case('ABC')
'abc'

Documentation

This repository's documentation is hosted on readthedocs.

Tooling

To run linters:

grunt lint

To run formatters:

grunt format

Continuous integration

This repository uses github actions to lint and test each commit. Formatting tasks and writing/generating documentation must be done before committing new code.

Versioning

This repository adheres to semantic versioning standards. For more information on semantic versioning visit SemVer.

Bump2version is used to version and tag changes. For example:

bump2version patch

Changelog

Please read this repository's changelog for details on changes that have been made.

Contributing

Please read this repository's guidelines on contributing for details on the process for submitting pull requests. Moreover, our code of conduct declares our collaboration standards.

Contributors

Buy Me A Coffee

Remarks

Lots of love to the open source community!

Be kind

Metadata

Release files for convert-case 1.2.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for convert-case 1.2.3
File Size Uploaded
convert-case-1.2.3.tar.gz 7.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for convert-case 1.2.3
File Interpreter ABI Platform
convert_case-1.2.3-py3-none-any.whl Python 3 none any Details

Total release size: 16.4 kB

Release files / convert-case-1.2.3.tar.gz

Download URL convert-case-1.2.3.tar.gz
Size 7.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a8c4329e47233a2b16cac3c5d020e8ba0305293efbe22a6d80f8ffddf049703f
BLAKE2b-256 checksum
How to use checksums
6cac22e9945f24acae18c43d1ff01f17ed792d4ba80b9d0757f2d18d23ce82ec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.11.3

Release files / convert_case-1.2.3-py3-none-any.whl

Download URL convert_case-1.2.3-py3-none-any.whl
Size 9.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ec8884050ca548e990666f82cba7ae2edfaa3c85dbead3042c2fd663b292373a
BLAKE2b-256 checksum
How to use checksums
f32e500ff29726ef207fdf6b625e62caf3839662c5d845897efc93bdf019192a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.11.3

Release history Release notifications | RSS feed

This release

1.2.3 This release

2 release files

1.2.2

2 release files

1.1.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page