From fc5f0ed8982e0be9d3996510b4b06b441f3a58cd Mon Sep 17 00:00:00 2001 From: ObjectsCountries Date: Mon, 2 Jun 2025 12:34:16 -0700 Subject: [PATCH 1/4] Fix edge cases for utils.py --- python_mermaid/utils.py | 23 ++++++--- python_mermaid/utils_unit_tests.py | 77 ++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 7 deletions(-) create mode 100755 python_mermaid/utils_unit_tests.py diff --git a/python_mermaid/utils.py b/python_mermaid/utils.py index 41db7cc..566ba49 100644 --- a/python_mermaid/utils.py +++ b/python_mermaid/utils.py @@ -2,13 +2,22 @@ from unidecode import unidecode -def snake_case(s): +def snake_case(s: str): s = unidecode(s) - s = '_'.join( - sub( - '([A-Z][a-z]+)', r' \1', - sub('([A-Z]+)', r' \1', s.replace('-', ' ')) - ).split() - ).lower() + + s = s.replace("-", " ") + s = s.replace("_", " ") + + s = sub(" ([A-Z]+)", r"_\1", s) # All caps word + + s = sub(" ([A-Z][a-z]+)", r"_\1", s) # Capitalized word + + s = sub("([a-z])([A-Z])", r"\1_\2", s) # Camel Case word + + s = sub("([A-Z])([A-Z])([a-z]+)", r"\1_\2\3", s) # words such as THESEWords + + s = sub("( )", r"__", s) # Multiple spaces + + s = "_".join(s.split()).lower() return s diff --git a/python_mermaid/utils_unit_tests.py b/python_mermaid/utils_unit_tests.py new file mode 100755 index 0000000..3721ef4 --- /dev/null +++ b/python_mermaid/utils_unit_tests.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 + +import unittest + +from utils import snake_case + + +class SnakeCaseUnitTests(unittest.TestCase): + def test_one_lowercase_letter(self): + self.assertEqual(snake_case("a"), "a") + + def test_one_capital_letter(self): + self.assertEqual(snake_case("A"), "a") + + def test_one_word(self): + self.assertEqual(snake_case("testing"), "testing") + + def test_one_word_all_caps(self): + self.assertEqual(snake_case("TESTING"), "testing") + + def test_already_snake_case(self): + self.assertEqual(snake_case("already_snake_case"), "already_snake_case") + + def test_already_snake_case__fully_all_caps(self): + self.assertEqual(snake_case("ALL_CAPS_SNAKE_CASE"), "all_caps_snake_case") + + def test_camel_case(self): + self.assertEqual(snake_case("camelCaseInput"), "camel_case_input") + + def test_mixed_cases(self): + self.assertEqual( + snake_case("MIXEDCases mixedCases mixed_cases"), + "mixed_cases_mixed_cases_mixed_cases", + ) + + def test_capitalized_word(self): + self.assertEqual(snake_case("Capitalized"), "capitalized") + + def test_mix_of_hyphens_underscores_spaces(self): + self.assertEqual( + snake_case("hyphenated-words spaced apart SNAKE_CASE_CONSTANT"), + "hyphenated_words_spaced_apart_snake_case_constant", + ) + + def test_capital_letter_after_hyphen(self): + self.assertEqual(snake_case("Capital-After-Hyphen"), "capital_after_hyphen") + + def test_capital_letter_after_space(self): + self.assertEqual(snake_case("Capital After Space"), "capital_after_space") + + def test_capital_letter_after_underscore(self): + self.assertEqual( + snake_case("Capital_After_Underscore"), "capital_after_underscore" + ) + + def test_already_snake_case__partially_all_caps(self): + self.assertEqual( + snake_case("ALLCAPS_SURROUNDED_BY_UNDERSCORES_lowercase"), + "allcaps_surrounded_by_underscores_lowercase", + ) + + def test_capitalized_mix_of_hyphens_underscores_spaces(self): + self.assertEqual( + snake_case( + "Capitalized-Hyphenated Capitalized Spaced Capitalized_Underscores" + ), + "capitalized_hyphenated_capitalized_spaced_capitalized_underscores", + ) + + def test_multiple_underscores_in_a_row(self): + self.assertEqual(snake_case("multiple__underscores"), "multiple__underscores") + + def test_multiple_underscores_in_a_row__capital_after_underscore(self): + self.assertEqual(snake_case("multiple__Underscores"), "multiple__underscores") + +if __name__ == "__main__": + unittest.main() From 053667e994e61b50aad29ac2d5dfc258d097c506 Mon Sep 17 00:00:00 2001 From: ObjectsCountries Date: Wed, 4 Jun 2025 12:43:09 -0700 Subject: [PATCH 2/4] Rewrite unit tests for snake_case method --- python_mermaid/utils_unit_tests.py | 77 ------------------------------ tests/snakeCase/__init__.py | 0 tests/snakeCase/test_snake_case.py | 55 +++++++++++++++++++++ 3 files changed, 55 insertions(+), 77 deletions(-) delete mode 100755 python_mermaid/utils_unit_tests.py create mode 100644 tests/snakeCase/__init__.py create mode 100755 tests/snakeCase/test_snake_case.py diff --git a/python_mermaid/utils_unit_tests.py b/python_mermaid/utils_unit_tests.py deleted file mode 100755 index 3721ef4..0000000 --- a/python_mermaid/utils_unit_tests.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python3 - -import unittest - -from utils import snake_case - - -class SnakeCaseUnitTests(unittest.TestCase): - def test_one_lowercase_letter(self): - self.assertEqual(snake_case("a"), "a") - - def test_one_capital_letter(self): - self.assertEqual(snake_case("A"), "a") - - def test_one_word(self): - self.assertEqual(snake_case("testing"), "testing") - - def test_one_word_all_caps(self): - self.assertEqual(snake_case("TESTING"), "testing") - - def test_already_snake_case(self): - self.assertEqual(snake_case("already_snake_case"), "already_snake_case") - - def test_already_snake_case__fully_all_caps(self): - self.assertEqual(snake_case("ALL_CAPS_SNAKE_CASE"), "all_caps_snake_case") - - def test_camel_case(self): - self.assertEqual(snake_case("camelCaseInput"), "camel_case_input") - - def test_mixed_cases(self): - self.assertEqual( - snake_case("MIXEDCases mixedCases mixed_cases"), - "mixed_cases_mixed_cases_mixed_cases", - ) - - def test_capitalized_word(self): - self.assertEqual(snake_case("Capitalized"), "capitalized") - - def test_mix_of_hyphens_underscores_spaces(self): - self.assertEqual( - snake_case("hyphenated-words spaced apart SNAKE_CASE_CONSTANT"), - "hyphenated_words_spaced_apart_snake_case_constant", - ) - - def test_capital_letter_after_hyphen(self): - self.assertEqual(snake_case("Capital-After-Hyphen"), "capital_after_hyphen") - - def test_capital_letter_after_space(self): - self.assertEqual(snake_case("Capital After Space"), "capital_after_space") - - def test_capital_letter_after_underscore(self): - self.assertEqual( - snake_case("Capital_After_Underscore"), "capital_after_underscore" - ) - - def test_already_snake_case__partially_all_caps(self): - self.assertEqual( - snake_case("ALLCAPS_SURROUNDED_BY_UNDERSCORES_lowercase"), - "allcaps_surrounded_by_underscores_lowercase", - ) - - def test_capitalized_mix_of_hyphens_underscores_spaces(self): - self.assertEqual( - snake_case( - "Capitalized-Hyphenated Capitalized Spaced Capitalized_Underscores" - ), - "capitalized_hyphenated_capitalized_spaced_capitalized_underscores", - ) - - def test_multiple_underscores_in_a_row(self): - self.assertEqual(snake_case("multiple__underscores"), "multiple__underscores") - - def test_multiple_underscores_in_a_row__capital_after_underscore(self): - self.assertEqual(snake_case("multiple__Underscores"), "multiple__underscores") - -if __name__ == "__main__": - unittest.main() diff --git a/tests/snakeCase/__init__.py b/tests/snakeCase/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/snakeCase/test_snake_case.py b/tests/snakeCase/test_snake_case.py new file mode 100755 index 0000000..2ff21af --- /dev/null +++ b/tests/snakeCase/test_snake_case.py @@ -0,0 +1,55 @@ +import pytest + +from python_mermaid.utils import snake_case + + +def test_one_lowercase_letter(): + assert snake_case("a") == "a" + +def test_one_capital_letter(): + assert snake_case("A") == "a" + +def test_one_word(): + assert snake_case("testing") == "testing" + +def test_one_word_all_caps(): + assert snake_case("TESTING") == "testing" + +def test_already_snake_case(): + assert snake_case("already_snake_case") == "already_snake_case" + +def test_already_snake_case__fully_all_caps(): + assert snake_case("ALL_CAPS_SNAKE_CASE") == "all_caps_snake_case" + +def test_camel_case(): + assert snake_case("camelCaseInput") == "camel_case_input" + +def test_mixed_cases(): + assert snake_case("MIXEDCases mixedCases mixed_cases") == "mixed_cases_mixed_cases_mixed_cases" + +def test_capitalized_word(): + assert snake_case("Capitalized") == "capitalized" + +def test_mix_of_hyphens_underscores_spaces(): + assert snake_case("hyphenated-words spaced apart SNAKE_CASE_CONSTANT") == "hyphenated_words_spaced_apart_snake_case_constant" + +def test_capital_letter_after_hyphen(): + assert snake_case("Capital-After-Hyphen") == "capital_after_hyphen" + +def test_capital_letter_after_space(): + assert snake_case("Capital After Space") == "capital_after_space" + +def test_capital_letter_after_underscore(): + assert snake_case("Capital_After_Underscore") == "capital_after_underscore" + +def test_already_snake_case__partially_all_caps(): + assert snake_case("ALLCAPS_SURROUNDED_BY_UNDERSCORES_lowercase") == "allcaps_surrounded_by_underscores_lowercase" + +def test_capitalized_mix_of_hyphens_underscores_spaces(): + assert snake_case("Capitalized-Hyphenated Capitalized Spaced Capitalized_Underscores") == "capitalized_hyphenated_capitalized_spaced_capitalized_underscores" + +def test_multiple_underscores_in_a_row(): + assert snake_case("multiple__underscores") == "multiple__underscores" + +def test_multiple_underscores_in_a_row__capital_after_underscore(): + assert snake_case("multiple__Underscores") == "multiple__underscores" From 04fdde8896ba1adb0e458e33acf34bcfb0ba7768 Mon Sep 17 00:00:00 2001 From: Dynnammo Date: Sun, 8 Jun 2025 15:29:02 +0200 Subject: [PATCH 3/4] Update to 0.1.6 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bdf6c9e..f72f8ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "python_mermaid" -version = "0.1.5" +version = "0.1.6" description = "A (quite) simple that helps creating on-the-fly Mermaid diagrams" authors = ["Dynnammo "] readme = "README.md" From 03042290e3e286088d43b51719c0ad1505f5be30 Mon Sep 17 00:00:00 2001 From: Dynnammo Date: Sun, 8 Jun 2025 15:36:40 +0200 Subject: [PATCH 4/4] Update README --- README.md | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 3e25208..53570b0 100644 --- a/README.md +++ b/README.md @@ -74,29 +74,12 @@ robert_march ---> amy which results can be seen [here](https://mermaid.live/edit#pako:eNptj8FOw0AMRH9l5XPzA3tAAnFC9AIHpOIKuYlJUmo72jqHqOq_46zEiZzGbzzS2DdorWPI0DQNqo9-4ZxeRw9NHyasqHXTF5qGhCrcfyLsuUc4op4t4MXqfGIfgp5CKpMsgY-yVCp24uJfQqVdU28V037Ff_sUjQ8pmrbss225a_mWH0fADoSL0NjFlzfUlBB8YGGEHGNH5QcB9R45mt3eF20he5l5B_PUkfPzSPG9QP6myzXcifRg9sf3X1ADb2E) ## Roadmap -### October 2023 -1-to-1 implementation of [flowchart](https://mermaid.js.org/syntax/flowchart.html#flowcharts-basic-syntax) -- [ ] All features of flowchart - - [x] Chart title - - [x] Nodes shapes - - [x] Links between nodes - - [x] Subgraph - - [ ] Links between nodes with subgraphs - - [ ] Directions ([#24](https://github.com/Dynnammo/python_mermaid/issues/24)) - - [ ] Interaction - - [ ] Styling and classes ([#19](https://github.com/Dynnammo/python_mermaid/issues/19) and [#20](https://github.com/Dynnammo/python_mermaid/issues/20)) - - [ ] Basic support for fontawesome ([#23](https://github.com/Dynnammo/python_mermaid/issues/23)) - -### November 2023 -- [ ] Main Features of stateflow-v2 - - [x] Nodes - - [x] Notes - - [x] Start and End nodes - - [x] Named links between nodes - - [ ] Graph configuration - -### End 2023 -- [ ] Architecture improvements for easing diagram creation +### Available features +- [x] Create basic [flowcharts](https://mermaid.js.org/syntax/flowchart.html) and [statecharts](https://mermaid.js.org/syntax/stateDiagram.html) + +### Roadmap +See [issues](https://github.com/Dynnammo/python_mermaid/issues) + ## Development - Requirements: install [Poetry](https://python-poetry.org). Here is the official method below. ⚠️ Please consider getting a look at Poetry's documentation if it doesn't work. ⚠️ ```shell