Diff
Modified: trunk/Tools/ChangeLog (264714 => 264715)
--- trunk/Tools/ChangeLog 2020-07-22 18:28:32 UTC (rev 264714)
+++ trunk/Tools/ChangeLog 2020-07-22 18:35:42 UTC (rev 264715)
@@ -1,3 +1,27 @@
+2020-07-22 Jonathan Bedard <[email protected]>
+
+ [webkitcorepy] Add string_utils (Part 1)
+ https://bugs.webkit.org/show_bug.cgi?id=214405
+
+ Reviewed by Dewei Zhu.
+
+ Centralize handling of unicode encoding/decoding along with various tools
+ for printing strings.
+
+ * Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py:
+ * Scripts/libraries/webkitcorepy/webkitcorepy/string_utils.py: Added.
+ (encode): Encode a string as bytes.
+ (decode): Decode a bytes as a string.
+ (ordinal): Convert a number to 1st, 2nd, 3rd, 4th, ect.
+ (pluralize): Convert a string to it's plurlarized version, if provided number indicates
+ it should be.
+ (join): Join a list of elements in a human-readable form.
+ (out_of): Create a fraction which takes up a constant amount of characters.
+ (elapsed): Describe the amount of time elapsed as a human-readable string.
+ * Scripts/libraries/webkitcorepy/webkitcorepy/tests/string_utils_unittest.py: Added.
+ (StringUtils): Test string_utils.
+ * Scripts/webkitpy/common/unicode_compatibility.py: Replaced with webkitcorepy.string_utils.
+
2020-07-22 Aakash Jain <[email protected]>
[ews-app] Pass api key in more secure manner
Modified: trunk/Tools/Scripts/libraries/webkitcorepy/README.md (264714 => 264715)
--- trunk/Tools/Scripts/libraries/webkitcorepy/README.md 2020-07-22 18:28:32 UTC (rev 264714)
+++ trunk/Tools/Scripts/libraries/webkitcorepy/README.md 2020-07-22 18:35:42 UTC (rev 264715)
@@ -10,3 +10,16 @@
from webkitcorepy import Version
version = Version(1, 2, 3)
```
+
+Unicode stream management across Python 2 and 3
+```
+from webkitcorepy import BytesIO, StringIO, UnicodeIO, unicode
+```
+
+Encoding and decoding byte strings and unicode strings
+```
+from webkitcorepy import string_utils
+
+string_utils.encode(...)
+string_utils.decode(...)
+```
Modified: trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py (264714 => 264715)
--- trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py 2020-07-22 18:28:32 UTC (rev 264714)
+++ trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py 2020-07-22 18:35:42 UTC (rev 264715)
@@ -21,4 +21,6 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from webkitcorepy.version import Version
-version = Version(0, 0, 1)
+from webkitcorepy.string_utils import BytesIO, StringIO, UnicodeIO, unicode
+
+version = Version(0, 0, 2)
Added: trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/string_utils.py (0 => 264715)
--- trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/string_utils.py (rev 0)
+++ trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/string_utils.py 2020-07-22 18:35:42 UTC (rev 264715)
@@ -0,0 +1,102 @@
+# Copyright (C) 2020 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import io
+import sys
+
+BytesIO = io.BytesIO
+if sys.version_info > (3, 0):
+ StringIO = io.StringIO
+else:
+ from StringIO import StringIO
+UnicodeIO = io.StringIO
+
+unicode = str if sys.version_info > (3, 0) else unicode
+
+
+def encode(string, encoding='utf-8', errors='strict', target_type=bytes):
+ if type(string) == unicode and target_type == bytes:
+ return string.encode(encoding, errors=errors)
+ return string
+
+
+def decode(data, encoding='utf-8', errors='strict', target_type=unicode):
+ if type(data) == bytes and target_type == unicode:
+ return data.decode(encoding, errors=errors)
+ return data
+
+
+def ordinal(number):
+ number = int(number)
+ if 10 < number % 100 < 20:
+ return '{}th'.format(number)
+ return '{}{}'.format(
+ number, {
+ 1: 'st',
+ 2: 'nd',
+ 3: 'rd',
+ }.get(number % 10, 'th')
+ )
+
+
+def pluralize(number, string, plural=None):
+ if number == 1:
+ return '1 {}'.format(string)
+ if plural:
+ return '{} {}'.format(number, plural)
+ return '{} {}s'.format(number, string)
+
+
+def join(list, conjunction='and'):
+ if not list:
+ return 'Nothing'
+ if len(list) == 1:
+ return list[0]
+ return '{} {} {}'.format(', '.join(list[:-1]), conjunction, list[-1])
+
+
+def out_of(number, base):
+ number = str(number)
+ base = str(base)
+ return '[{}{}/{}]'.format(' ' * (len(base) - len(number)), number, base)
+
+
+def elapsed(seconds):
+ if seconds <= 0:
+ return 'no time'
+ elif seconds < 1:
+ return 'less than a second'
+
+ seconds = int(round(seconds))
+ minutes = seconds // 60
+ hours = minutes // 60
+ days = hours // 24
+
+ force = False
+ result = ''
+ for value, description in [(days, 'day'), (hours % 24, 'hour'), (minutes % 60, 'minute')]:
+ if force or value:
+ force = True
+ result += ' ' + pluralize(value, description)
+ if force:
+ return result[1:] + ' and ' + pluralize(seconds % 60, 'second')
+ return pluralize(seconds % 60, 'second')
Added: trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/tests/string_utils_unittest.py (0 => 264715)
--- trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/tests/string_utils_unittest.py (rev 0)
+++ trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/tests/string_utils_unittest.py 2020-07-22 18:35:42 UTC (rev 264715)
@@ -0,0 +1,82 @@
+# Copyright (C) 2020 Apple Inc. All rights reserved.
+import unittest
+
+from webkitcorepy import BytesIO, StringIO, UnicodeIO, unicode, string_utils
+
+
+class StringUtils(unittest.TestCase):
+ def test_bytesio(self):
+ stream = BytesIO()
+ stream.write(b'bytes data')
+ self.assertEqual(stream.getvalue(), b'bytes data')
+
+ def test_stringio(self):
+ stream = StringIO()
+ stream.write('string data')
+ self.assertEqual(stream.getvalue(), 'string data')
+
+ def test_unicodeio(self):
+ stream = UnicodeIO()
+ stream.write(u'unicod\u00E9 data')
+ self.assertEqual(stream.getvalue(), u'unicod\u00E9 data')
+
+ def test_unicode(self):
+ self.assertEqual(unicode(u'unicode: \u00E9'), u'unicode: \u00E9')
+
+ def test_encode(self):
+ self.assertEqual(string_utils.encode(u'unicode: \u00E9'), b'unicode: \xc3\xa9')
+ self.assertEqual(string_utils.encode(b'bytes data'), b'bytes data')
+
+ def test_decode(self):
+ self.assertEqual(string_utils.decode(u'unicode: \u00E9'), u'unicode: \u00E9')
+ self.assertEqual(string_utils.decode(b'unicode: \xc3\xa9'), u'unicode: \u00E9')
+
+ def test_ordinal(self):
+ self.assertEqual(string_utils.ordinal(0), '0th')
+ self.assertEqual(string_utils.ordinal(1), '1st')
+ self.assertEqual(string_utils.ordinal(2), '2nd')
+ self.assertEqual(string_utils.ordinal(3), '3rd')
+ self.assertEqual(string_utils.ordinal(4), '4th')
+ self.assertEqual(string_utils.ordinal(5), '5th')
+ self.assertEqual(string_utils.ordinal(6), '6th')
+ self.assertEqual(string_utils.ordinal(7), '7th')
+ self.assertEqual(string_utils.ordinal(8), '8th')
+ self.assertEqual(string_utils.ordinal(9), '9th')
+ self.assertEqual(string_utils.ordinal(10), '10th')
+ self.assertEqual(string_utils.ordinal(11), '11th')
+ self.assertEqual(string_utils.ordinal(12), '12th')
+ self.assertEqual(string_utils.ordinal(13), '13th')
+ self.assertEqual(string_utils.ordinal(21), '21st')
+ self.assertEqual(string_utils.ordinal(22), '22nd')
+ self.assertEqual(string_utils.ordinal(23), '23rd')
+ self.assertEqual(string_utils.ordinal(101), '101st')
+ self.assertEqual(string_utils.ordinal(111), '111th')
+
+ def test_pluralize(self):
+ self.assertEqual(string_utils.pluralize(0, 'second'), '0 seconds')
+ self.assertEqual(string_utils.pluralize(1, 'second'), '1 second')
+ self.assertEqual(string_utils.pluralize(2, 'second'), '2 seconds')
+ self.assertEqual(string_utils.pluralize(0, 'mouse', 'mice'), '0 mice')
+ self.assertEqual(string_utils.pluralize(1, 'mouse', 'mice'), '1 mouse')
+ self.assertEqual(string_utils.pluralize(2, 'mouse', 'mice'), '2 mice')
+
+ def test_list(self):
+ self.assertEqual(string_utils.join(['integer', 'string', 'float']), 'integer, string and float')
+ self.assertEqual(string_utils.join(['integer', 'string']), 'integer and string')
+ self.assertEqual(string_utils.join(['integer']), 'integer')
+ self.assertEqual(string_utils.join([]), 'Nothing')
+ self.assertEqual(string_utils.join(['integer', 'string'], conjunction='or'), 'integer or string')
+
+ def test_outof(self):
+ self.assertEqual(string_utils.out_of(1, 3), '[1/3]')
+ self.assertEqual(string_utils.out_of(1, 10), '[ 1/10]')
+ self.assertEqual(string_utils.out_of(10, 10), '[10/10]')
+
+ def test_elapsed(self):
+ self.assertEqual(string_utils.elapsed(0), 'no time')
+ self.assertEqual(string_utils.elapsed(.5), 'less than a second')
+ self.assertEqual(string_utils.elapsed(1), '1 second')
+ self.assertEqual(string_utils.elapsed(4), '4 seconds')
+ self.assertEqual(string_utils.elapsed(74), '1 minute and 14 seconds')
+ self.assertEqual(string_utils.elapsed(3 * 60 * 60), '3 hours 0 minutes and 0 seconds')
+ self.assertEqual(string_utils.elapsed(24 * 60 * 60 + 60 * 60 + 4 * 60 + 5), '1 day 1 hour 4 minutes and 5 seconds')
Modified: trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/version.py (264714 => 264715)
--- trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/version.py 2020-07-22 18:28:32 UTC (rev 264714)
+++ trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/version.py 2020-07-22 18:35:42 UTC (rev 264715)
@@ -20,10 +20,9 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-import collections
import re
-from functools import total_ordering
+from webkitcorepy.string_utils import unicode
class Version(object):
Modified: trunk/Tools/Scripts/webkitpy/common/unicode_compatibility.py (264714 => 264715)
--- trunk/Tools/Scripts/webkitpy/common/unicode_compatibility.py 2020-07-22 18:28:32 UTC (rev 264714)
+++ trunk/Tools/Scripts/webkitpy/common/unicode_compatibility.py 2020-07-22 18:35:42 UTC (rev 264715)
@@ -1,4 +1,4 @@
-# Copyright (C) 2019 Apple Inc. All rights reserved.
+# Copyright (C) 2019-2020 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -20,48 +20,19 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-import io
-import sys
+from webkitcorepy import UnicodeIO, StringIO, BytesIO, unicode, string_utils
-
-BytesIO = io.BytesIO
-if sys.version_info > (3, 0):
- StringIO = io.StringIO
-else:
- from StringIO import StringIO
-UnicodeIO = io.StringIO
-
-unicode = str if sys.version_info > (3, 0) else unicode
-
-
def encode_if_necessary(value, encoding='utf-8', errors='strict'):
- # In Python 3, string types must be encoded
- if type(value) == unicode:
- return value.encode(encoding, errors=errors)
- return value
+ return string_utils.encode(value, encoding=encoding, errors=errors)
def encode_for(value, target_type, **kwargs):
- if target_type == bytes:
- return encode_if_necessary(value, **kwargs)
+ return string_utils.encode(value, target_type=target_type, **kwargs)
- if sys.version_info < (3, 0) and target_type == str:
- return encode_if_necessary(value, **kwargs)
- return value
-
def decode_if_necessary(value, encoding='utf-8', errors='strict'):
- # In Python 2, string types might need to be decoded
- if type(value) == bytes:
- return value.decode(encoding, errors=errors)
- return value
+ return string_utils.decode(value, encoding=encoding, errors=errors)
def decode_for(value, target_type):
- if value is None:
- return None
- if type(value) == target_type:
- return value
- if target_type == unicode:
- return decode_if_necessary(bytes(value))
- return value
+ return string_utils.decode(value, target_type=target_type)