diff --git a/integration_tests/test_str_attributes.py b/integration_tests/test_str_attributes.py index 2124e38026..d7b70730b4 100755 --- a/integration_tests/test_str_attributes.py +++ b/integration_tests/test_str_attributes.py @@ -21,6 +21,7 @@ def lower(): assert "DDd12Vv" .lower() == "ddd12vv" assert "".lower() == "" + def upper(): s: str s = "AaaaAABBbbbbBB!@12223BN" @@ -28,6 +29,7 @@ def upper(): assert "DDd12Vv".upper() == "DDD12VV" assert "".upper() == "" + def strip(): s: str s = " AASAsaSas " @@ -88,14 +90,15 @@ def startswith(): assert s.startswith("sdd") == False assert "".startswith("ok") == False + def endswith(): # The following test suite fulfils the control flow graph coverage # in terms of Statement Coverage and Branch Coverage associated with endwith() functionality. - # Case 1: When string is constant and suffix is also constant + # Case 1: When string is constant and suffix is also constant assert "".endswith("") == True - assert "".endswith(" ") == False + assert "".endswith(" ") == False assert "".endswith("%") == False assert "".endswith("a1234PT#$") == False assert "".endswith("blah blah") == False @@ -105,13 +108,12 @@ def endswith(): assert " rendezvous 5:30 ".endswith("apple") == False assert "two plus".endswith("longer than string") == False - # Case 2: When string is constant and suffix is variable suffix: str suffix = "" assert "".endswith(suffix) == True suffix = " " - assert "".endswith(suffix) == False + assert "".endswith(suffix) == False suffix = "5:30 " assert " rendezvous 5:30 ".endswith(suffix) == True suffix = "" @@ -138,13 +140,14 @@ def endswith(): suffix = "apple" assert s.endswith(suffix) == False + def partition(): - - # Note: Both string or seperator cannot be empty - # Case 1: When string is constant and seperator is also constant - assert " ".partition(" ") == (""," "," ") - assert "apple mango".partition(" ") == ("apple"," ","mango") - assert "applemango".partition("afdnjkfsn") == ("applemango","","") + + # Note: Both string or seperator cannot be empty + # Case 1: When string is constant and seperator is also constant + assert " ".partition(" ") == ("", " ", " ") + assert "apple mango".partition(" ") == ("apple", " ", "mango") + assert "applemango".partition("afdnjkfsn") == ("applemango", "", "") assert "applemango".partition("an") == ("applem", "an", "go") assert "applemango".partition("mango") == ("apple", "mango", "") assert "applemango".partition("applemango") == ("", "applemango", "") @@ -154,15 +157,17 @@ def partition(): # Case 2: When string is constant and seperator is variable seperator: str seperator = " " - assert " ".partition(seperator) == (""," "," ") + assert " ".partition(seperator) == ("", " ", " ") seperator = " " - assert "apple mango".partition(seperator) == ("apple"," ","mango") + assert "apple mango".partition(seperator) == ("apple", " ", "mango") seperator = "5:30 " - assert " rendezvous 5:30 ".partition(seperator) == (" rendezvous ", "5:30 ", "") + assert " rendezvous 5:30 ".partition( + seperator) == (" rendezvous ", "5:30 ", "") seperator = "^&" assert "@#$%^&*()#!".partition(seperator) == ("@#$%", "^&", "*()#!") seperator = "daddada " - assert " rendezvous 5:30 ".partition(seperator) == (" rendezvous 5:30 ", "", "") + assert " rendezvous 5:30 ".partition( + seperator) == (" rendezvous 5:30 ", "", "") seperator = "longer than string" assert "two plus".partition(seperator) == ("two plus", "", "") @@ -182,6 +187,7 @@ def partition(): seperator = "apple" assert s.partition(seperator) == ("rendezvous 5", "", "") + def is_lower(): # Case 1: When constant string is present assert "".islower() == False @@ -204,8 +210,9 @@ def is_lower(): s = "apple is a fruit" assert s.islower() == True + def is_upper(): - # Case 1: When constant string is present + # Case 1: When constant string is present assert "".isupper() == False assert "apple".isupper() == False assert "4432632479".isupper() == False @@ -226,6 +233,7 @@ def is_upper(): s = "APPLE IS A FRUIT" assert s.isupper() == True + def is_decimal(): # Case 1: When constant string is present assert "".isdecimal() == False @@ -251,6 +259,7 @@ def is_decimal(): s = "12 34" assert s.isdecimal() == False + def is_ascii(): # Case 1: When constant string is present assert "".isascii() == True @@ -280,12 +289,16 @@ def is_ascii(): def is_space(): assert "\n".isspace() == True assert " ".isspace() == True - assert "\r".isspace() == True + assert "\r".isspace() == True + assert "".isspace() == False - s:str = " " - assert s.isspace() == True + s: str = " " + assert s.isspace() == True s = "a" assert s.isspace() == False + s = "" + assert s.isspace() == False + def check(): capitalize() @@ -303,4 +316,5 @@ def check(): is_ascii() is_space() + check() diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 8487a4ac54..e75028c9e7 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -7107,18 +7107,18 @@ class BodyVisitor : public CommonVisitor { Return True if all cased characters in the string are uppercase and there is at least one cased character, False otherwise. */ bool is_cased_present = false; - bool is_lower = true; + bool is_upper = true; for (auto &i : s_var) { if ((i >= 'A' && i <= 'Z') || (i >= 'a' && i <= 'z')) { is_cased_present = true; if(!(i >= 'A' && i <= 'Z')) { - is_lower = false; + is_upper = false; break; } } } - is_lower = is_lower && is_cased_present; - tmp = ASR::make_LogicalConstant_t(al, loc, is_lower, + is_upper = is_upper && is_cased_present; + tmp = ASR::make_LogicalConstant_t(al, loc, is_upper, ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4))); return; } else if(attr_name == "isdecimal") { @@ -7160,13 +7160,13 @@ characters, as defined by CPython. Return false otherwise. For now we use the std::isspace function, but if we later discover that it differs from CPython, we will have to use something else. */ - bool is_space = true; - for (char i : s_var) { - if (!std::isspace(static_cast(i))) { - is_space = false; - break; - } + bool is_space = (s_var.size() != 0); + for (char i : s_var) { + if (!std::isspace(static_cast(i))) { + is_space = false; + break; } + } tmp = ASR::make_LogicalConstant_t(al, loc, is_space, ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4))); return; diff --git a/src/runtime/lpython_builtin.py b/src/runtime/lpython_builtin.py index 1ac93fbfa9..46b758c725 100644 --- a/src/runtime/lpython_builtin.py +++ b/src/runtime/lpython_builtin.py @@ -955,7 +955,7 @@ def _lpython_str_isdecimal(s: str) -> bool: @overload def _lpython_str_isascii(s: str) -> bool: - if(len(s) == 0): + if len(s) == 0: return True i: str for i in s: @@ -964,6 +964,8 @@ def _lpython_str_isascii(s: str) -> bool: return True def _lpython_str_isspace(s:str) -> bool: + if len(s) == 0: + return False ch: str for ch in s: if ch != ' ' and ch != '\t' and ch != '\n' and ch != '\r' and ch != '\f' and ch != '\v':