From dd47055b88a2ed08cd5d044c44f2dc46f8049495 Mon Sep 17 00:00:00 2001 From: Lincoln Puzey <18750802+LincolnPuzey@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:43:03 +0800 Subject: [PATCH 1/3] #1655 Vendor the stringcase library which appears to unmaintained --- frictionless/vendors/stringcase.py | 275 +++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 frictionless/vendors/stringcase.py diff --git a/frictionless/vendors/stringcase.py b/frictionless/vendors/stringcase.py new file mode 100644 index 0000000000..44d03d4c27 --- /dev/null +++ b/frictionless/vendors/stringcase.py @@ -0,0 +1,275 @@ +""" +String convert functions + +The MIT License (MIT) + +Copyright (c) 2015 Taka Okunishi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +# The "stringcase" package appears to unmaintained +# https://github.com/okunishinishi/python-stringcase/issues/42 +# It has been vendored here so we can fix warnings that will eventually become errors +# Code here was copied from the 1.2.0 version uploaded to PyPI +# https://pypi.org/project/stringcase/1.2.0/ + +import re + + +def camelcase(string): + """ Convert string into camel case. + + Args: + string: String to convert. + + Returns: + string: Camel case string. + + """ + + string = re.sub(r"\w[\s\W]+\w", '', str(string)) + if not string: + return string + return lowercase(string[0]) + re.sub(r"[\-_\.\s]([a-z])", lambda matched: uppercase(matched.group(1)), string[1:]) + + +def capitalcase(string): + """Convert string into capital case. + First letters will be uppercase. + + Args: + string: String to convert. + + Returns: + string: Capital case string. + + """ + + string = str(string) + if not string: + return string + return uppercase(string[0]) + string[1:] + + +def constcase(string): + """Convert string into upper snake case. + Join punctuation with underscore and convert letters into uppercase. + + Args: + string: String to convert. + + Returns: + string: Const cased string. + + """ + + return uppercase(snakecase(string)) + + +def lowercase(string): + """Convert string into lower case. + + Args: + string: String to convert. + + Returns: + string: Lowercase case string. + + """ + + return str(string).lower() + + +def pascalcase(string): + """Convert string into pascal case. + + Args: + string: String to convert. + + Returns: + string: Pascal case string. + + """ + + return capitalcase(camelcase(string)) + + +def pathcase(string): + """Convert string into path case. + Join punctuation with slash. + + Args: + string: String to convert. + + Returns: + string: Path cased string. + + """ + string = snakecase(string) + if not string: + return string + return re.sub(r"_", "/", string) + + +def backslashcase(string): + """Convert string into spinal case. + Join punctuation with backslash. + + Args: + string: String to convert. + + Returns: + string: Spinal cased string. + + """ + str1 = re.sub(r"_", r"\\", snakecase(string)) + + return str1 + # return re.sub(r"\\n", "", str1)) # TODO: make regex fot \t ... + + +def sentencecase(string): + """Convert string into sentence case. + First letter capped and each punctuations are joined with space. + + Args: + string: String to convert. + + Returns: + string: Sentence cased string. + + """ + joiner = ' ' + string = re.sub(r"[\-_\.\s]", joiner, str(string)) + if not string: + return string + return capitalcase(trimcase( + re.sub(r"[A-Z]", lambda matched: joiner + + lowercase(matched.group(0)), string) + )) + + +def snakecase(string): + """Convert string into snake case. + Join punctuation with underscore + + Args: + string: String to convert. + + Returns: + string: Snake cased string. + + """ + + string = re.sub(r"[\-\.\s]", '_', str(string)) + if not string: + return string + return lowercase(string[0]) + re.sub(r"[A-Z]", lambda matched: '_' + lowercase(matched.group(0)), string[1:]) + + +def spinalcase(string): + """Convert string into spinal case. + Join punctuation with hyphen. + + Args: + string: String to convert. + + Returns: + string: Spinal cased string. + + """ + + return re.sub(r"_", "-", snakecase(string)) + + +def dotcase(string): + + """Convert string into dot case. + Join punctuation with dot. + + Args: + string: String to convert. + + Returns: + string: Dot cased string. + + """ + + return re.sub(r"_", ".", snakecase(string)) + + +def titlecase(string): + """Convert string into sentence case. + First letter capped while each punctuations is capitalsed + and joined with space. + + Args: + string: String to convert. + + Returns: + string: Title cased string. + + """ + + return ' '.join( + [capitalcase(word) for word in snakecase(string).split("_")] + ) + + +def trimcase(string): + """Convert string into trimmed string. + + Args: + string: String to convert. + + Returns: + string: Trimmed case string + """ + + return str(string).strip() + + +def uppercase(string): + """Convert string into upper case. + + Args: + string: String to convert. + + Returns: + string: Uppercase case string. + + """ + + return str(string).upper() + + +def alphanumcase(string): + """Cuts all non-alphanumeric symbols, + i.e. cuts all expect except 0-9, a-z and A-Z. + + Args: + string: String to convert. + + Returns: + string: String with cutted non-alphanumeric symbols. + + """ + # return filter(str.isalnum, str(string)) + return re.sub("\W+", "", string) \ No newline at end of file From e9bad0017d3571ac6b1e397f7fb2c5e7d430e66c Mon Sep 17 00:00:00 2001 From: Lincoln Puzey <18750802+LincolnPuzey@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:46:03 +0800 Subject: [PATCH 2/3] #1655 Make string raw string to fix Deprecation warning --- frictionless/vendors/stringcase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frictionless/vendors/stringcase.py b/frictionless/vendors/stringcase.py index 44d03d4c27..ab2c0b7350 100644 --- a/frictionless/vendors/stringcase.py +++ b/frictionless/vendors/stringcase.py @@ -272,4 +272,4 @@ def alphanumcase(string): """ # return filter(str.isalnum, str(string)) - return re.sub("\W+", "", string) \ No newline at end of file + return re.sub(r"\W+", "", string) \ No newline at end of file From 50e71854186646d148f48ea3a04d6d93ed216364 Mon Sep 17 00:00:00 2001 From: Lincoln Puzey <18750802+LincolnPuzey@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:50:20 +0800 Subject: [PATCH 3/3] #1655 Swap stringcase dependency for the vendored package --- frictionless/helpers/general.py | 2 +- frictionless/metadata/metadata.py | 2 +- pyproject.toml | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/frictionless/helpers/general.py b/frictionless/helpers/general.py index 45e27ce5b7..5f0a11804a 100644 --- a/frictionless/helpers/general.py +++ b/frictionless/helpers/general.py @@ -17,7 +17,7 @@ from typing import Any, Dict, Iterator, List, Optional, Tuple, Type, TypeVar, Union from urllib.parse import parse_qs, urlparse -import stringcase # type: ignore +from ..vendors import stringcase # type: ignore # General diff --git a/frictionless/metadata/metadata.py b/frictionless/metadata/metadata.py index dbf9e572df..829b231828 100644 --- a/frictionless/metadata/metadata.py +++ b/frictionless/metadata/metadata.py @@ -21,12 +21,12 @@ Union, ) -import stringcase # type: ignore from typing_extensions import Self from .. import helpers from ..exception import FrictionlessException from ..platform import platform +from ..vendors import stringcase # type: ignore if TYPE_CHECKING: from .. import types diff --git a/pyproject.toml b/pyproject.toml index fbe068da06..82b131cbcd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,6 @@ dependencies = [ "tabulate>=0.8.10", "jsonschema>=4.20", "simpleeval>=0.9.11", - "stringcase>=1.2", "typer>=0.12", "validators>=0.18", "python-slugify>=1.2",