Skip to content

Commit 8c7a25e

Browse files
committed
[GR-11899] str.title function is not implemented.
1 parent 3f9c1b4 commit 8c7a25e

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_string.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,30 @@ def test_isprintable(self):
685685
# self.assertFalse('\U000E0020'.isprintable())
686686

687687

688+
def test_title(self):
689+
self.checkequal(' Hello ', ' hello ', 'title')
690+
self.checkequal('Hello ', 'hello ', 'title')
691+
self.checkequal('Hello ', 'Hello ', 'title')
692+
self.checkequal('Format This As Title String', "fOrMaT thIs aS titLe String", 'title')
693+
self.checkequal('Format,This-As*Title;String', "fOrMaT,thIs-aS*titLe;String", 'title', )
694+
self.checkequal('Getint', "getInt", 'title')
695+
self.checkraises(TypeError, 'hello', 'title', 42)
696+
697+
def test_title_uni(self):
698+
self.assertEqual('\U0001044F'.title(), '\U00010427')
699+
self.assertEqual('\U0001044F\U0001044F'.title(),
700+
'\U00010427\U0001044F')
701+
self.assertEqual('\U0001044F\U0001044F \U0001044F\U0001044F'.title(),
702+
'\U00010427\U0001044F \U00010427\U0001044F')
703+
self.assertEqual('\U00010427\U0001044F \U00010427\U0001044F'.title(),
704+
'\U00010427\U0001044F \U00010427\U0001044F')
705+
self.assertEqual('\U0001044F\U00010427 \U0001044F\U00010427'.title(),
706+
'\U00010427\U0001044F \U00010427\U0001044F')
707+
self.assertEqual('X\U00010427x\U0001044F X\U00010427x\U0001044F'.title(),
708+
'X\U0001044Fx\U0001044F X\U0001044Fx\U0001044F')
709+
self.assertEqual('fiNNISH'.title(), 'Finnish')
710+
self.assertEqual('A\u03a3A'.title(), 'A\u03c3a')
711+
688712
def test_same_id():
689713
empty_ids = set([id(str()) for i in range(100)])
690714
assert len(empty_ids) == 1

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/StringBuiltins.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,6 +1539,71 @@ boolean doString(String self) {
15391539
}
15401540
}
15411541

1542+
@Builtin(name = "title", fixedNumOfPositionalArgs = 1)
1543+
@GenerateNodeFactory
1544+
@TypeSystemReference(PythonArithmeticTypes.class)
1545+
abstract static class TitleNode extends PythonUnaryBuiltinNode {
1546+
1547+
@Specialization
1548+
@TruffleBoundary
1549+
public String doTitle(String self) {
1550+
int[] codePoints = self.codePoints().toArray();
1551+
int len = codePoints.length;
1552+
boolean shouldBeLowerCase = false;
1553+
boolean translated;
1554+
StringBuilder converted = new StringBuilder();
1555+
for (int i = 0; i < len; i++) {
1556+
int ch = codePoints[i];
1557+
translated = false;
1558+
if (Character.isAlphabetic(ch)) {
1559+
if (shouldBeLowerCase) {
1560+
// Should be lower case
1561+
if (Character.isUpperCase(ch)) {
1562+
translated = true;
1563+
if (ch < 256) {
1564+
converted.append((char) Character.toLowerCase(ch));
1565+
} else {
1566+
String origPart = new String(Character.toChars(ch));
1567+
String changedPart = origPart.toLowerCase();
1568+
converted.append(changedPart);
1569+
}
1570+
}
1571+
} else {
1572+
// Should be upper case
1573+
if (Character.isLowerCase(ch)) {
1574+
translated = true;
1575+
if (ch < 256) {
1576+
converted.append((char) Character.toUpperCase(ch));
1577+
} else {
1578+
String origPart = new String(Character.toChars(ch));
1579+
String changedPart = origPart.toUpperCase();
1580+
if (origPart.length() < changedPart.length()) {
1581+
// the original char was mapped to more chars ->
1582+
// we need to make upper case just the first one
1583+
changedPart = doTitle(changedPart);
1584+
}
1585+
converted.append(changedPart);
1586+
}
1587+
}
1588+
}
1589+
// And this was a letter
1590+
shouldBeLowerCase = true;
1591+
} else {
1592+
// This was not a letter
1593+
shouldBeLowerCase = false;
1594+
}
1595+
if (!translated) {
1596+
if (ch < 256) {
1597+
converted.append((char) ch);
1598+
} else {
1599+
converted.append(Character.toChars(ch));
1600+
}
1601+
}
1602+
}
1603+
return converted.toString();
1604+
}
1605+
}
1606+
15421607
@Builtin(name = __GETITEM__, fixedNumOfPositionalArgs = 2)
15431608
@GenerateNodeFactory
15441609
@TypeSystemReference(PythonArithmeticTypes.class)

0 commit comments

Comments
 (0)