Title: [269114] trunk/Tools
Revision
269114
Author
[email protected]
Date
2020-10-28 12:08:28 -0700 (Wed, 28 Oct 2020)

Log Message

[webkitflaskpy] Create shared library for WebKit's flask tooling
https://bugs.webkit.org/show_bug.cgi?id=218257
<rdar://problem/70736269>

Rubber-stamped by Aakash Jain.

* Scripts/libraries/resultsdbpy/resultsdbpy/__init__.py:
(_maybe_add_webkit_python_library_paths): Add webkitcorepy and webkitflaskpy.
(_maybe_add_webkitcorepy_path): Renamed _maybe_add_webkit_python_library_paths.
* Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util.py: Moved to webkitflaskpy/util.py.
* Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util_unittest.py: Moved to webkitflaskpy/util_unittest.py.
* Scripts/libraries/webkitflaskpy: Added.
* Scripts/libraries/webkitflaskpy/MANIFEST.in: Added.
* Scripts/libraries/webkitflaskpy/README.md: Added.
* Scripts/libraries/webkitflaskpy/setup.py: Added.
* Scripts/libraries/webkitflaskpy/webkitflaskpy: Added.
* Scripts/libraries/webkitflaskpy/webkitflaskpy/__init__.py: Added.
* Scripts/libraries/webkitflaskpy/webkitflaskpy/util.py: Moved from resultsdpy/flask_support/util.py.
* Scripts/libraries/webkitflaskpy/webkitflaskpy/util_unittest.py: Moved from resultsdpy/flask_support/util_unittest.py.
* Scripts/webkitpy/test/main.py:
(main): Add

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Tools/ChangeLog (269113 => 269114)


--- trunk/Tools/ChangeLog	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/ChangeLog	2020-10-28 19:08:28 UTC (rev 269114)
@@ -1,3 +1,27 @@
+2020-10-28  Jonathan Bedard  <[email protected]>
+
+        [webkitflaskpy] Create shared library for WebKit's flask tooling
+        https://bugs.webkit.org/show_bug.cgi?id=218257
+        <rdar://problem/70736269>
+
+        Rubber-stamped by Aakash Jain.
+
+        * Scripts/libraries/resultsdbpy/resultsdbpy/__init__.py:
+        (_maybe_add_webkit_python_library_paths): Add webkitcorepy and webkitflaskpy.
+        (_maybe_add_webkitcorepy_path): Renamed _maybe_add_webkit_python_library_paths.
+        * Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util.py: Moved to webkitflaskpy/util.py.
+        * Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util_unittest.py: Moved to webkitflaskpy/util_unittest.py.
+        * Scripts/libraries/webkitflaskpy: Added.
+        * Scripts/libraries/webkitflaskpy/MANIFEST.in: Added.
+        * Scripts/libraries/webkitflaskpy/README.md: Added.
+        * Scripts/libraries/webkitflaskpy/setup.py: Added.
+        * Scripts/libraries/webkitflaskpy/webkitflaskpy: Added.
+        * Scripts/libraries/webkitflaskpy/webkitflaskpy/__init__.py: Added.
+        * Scripts/libraries/webkitflaskpy/webkitflaskpy/util.py: Moved from resultsdpy/flask_support/util.py.
+        * Scripts/libraries/webkitflaskpy/webkitflaskpy/util_unittest.py: Moved from resultsdpy/flask_support/util_unittest.py.
+        * Scripts/webkitpy/test/main.py:
+        (main): Add
+
 2020-10-28  Sam Weinig  <[email protected]>
 
         Reduce Preference Override Methods: TabsToLinks/SpatialNavigation

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/__init__.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/__init__.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/__init__.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -24,15 +24,16 @@
 import sys
 
 
-def _maybe_add_webkitcorepy_path():
-    # Hopefully we're beside webkitcorepy, otherwise webkitcorepy will need to be installed.
+def _maybe_add_webkit_python_library_paths():
+    # Hopefully we're beside webkit*py libraries, otherwise webkit*py will need to be installed.
     libraries_path = os.path.dirname(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
-    webkitcorepy_path = os.path.join(libraries_path, 'webkitcorepy')
-    if os.path.isdir(webkitcorepy_path) and os.path.isdir(os.path.join(webkitcorepy_path, 'webkitcorepy')) and webkitcorepy_path not in sys.path:
-        sys.path.insert(0, webkitcorepy_path)
+    for library in ['webkitcorepy', 'webkitflaskpy']:
+        library_path = os.path.join(libraries_path, library)
+        if os.path.isdir(library_path) and os.path.isdir(os.path.join(library_path, library)) and library_path not in sys.path:
+            sys.path.insert(0, library_path)
 
 
-_maybe_add_webkitcorepy_path()
+_maybe_add_webkit_python_library_paths()
 
 try:
     from webkitcorepy.version import Version

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/archive_controller.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/archive_controller.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/archive_controller.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -26,12 +26,11 @@
 import time
 
 from flask import abort, jsonify, request, send_file
-from resultsdbpy.controller.commit import Commit
 from resultsdbpy.controller.commit_controller import uuid_range_for_query, HasCommitContext
 from resultsdbpy.controller.configuration import Configuration
 from resultsdbpy.controller.configuration_controller import configuration_for_query
 from resultsdbpy.controller.suite_controller import time_range_for_query
-from resultsdbpy.flask_support.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
+from webkitflaskpy.util import AssertRequest, query_as_kwargs, boolean_query
 
 
 class ArchiveController(HasCommitContext):

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/ci_controller.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/ci_controller.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/ci_controller.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -25,7 +25,7 @@
 from resultsdbpy.controller.configuration import Configuration
 from resultsdbpy.controller.configuration_controller import configuration_for_query
 from resultsdbpy.controller.suite_controller import time_range_for_query
-from resultsdbpy.flask_support.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
+from webkitflaskpy.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
 
 
 class CIController(HasCommitContext):

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/commit.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/commit.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/commit.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -25,7 +25,7 @@
 import re
 
 from datetime import datetime
-from resultsdbpy.flask_support.util import FlaskJSONEncoder
+from webkitflaskpy.util import FlaskJSONEncoder
 
 
 class Commit(object):

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/commit_controller.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/commit_controller.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/commit_controller.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -24,9 +24,9 @@
 
 from collections import defaultdict
 from flask import abort, jsonify, request
-from resultsdbpy.flask_support.util import AssertRequest, query_as_kwargs, limit_for_query
 from resultsdbpy.model.repository import SCMException
 from resultsdbpy.controller.commit import Commit
+from webkitflaskpy.util import AssertRequest, query_as_kwargs, limit_for_query
 
 
 def _find_comparison(commit_context, repository_id, branch, id, uuid, timestamp, priority=min):

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/configuration.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/configuration.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/configuration.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -22,7 +22,7 @@
 
 import json
 
-from resultsdbpy.flask_support.util import FlaskJSONEncoder
+from webkitflaskpy.util import FlaskJSONEncoder
 
 
 class Configuration(object):

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/configuration_controller.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/configuration_controller.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/configuration_controller.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -20,8 +20,8 @@
 # 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.
 
-from resultsdbpy.flask_support.util import boolean_query
 from resultsdbpy.controller.configuration import Configuration
+from webkitflaskpy.util import boolean_query
 
 
 def configuration_for_query():

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/failure_controller.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/failure_controller.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/failure_controller.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -25,7 +25,7 @@
 from resultsdbpy.controller.configuration import Configuration
 from resultsdbpy.controller.configuration_controller import configuration_for_query
 from resultsdbpy.controller.suite_controller import time_range_for_query
-from resultsdbpy.flask_support.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
+from webkitflaskpy.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
 
 
 class FailureController(HasCommitContext):

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/suite_controller.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/suite_controller.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/suite_controller.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -24,7 +24,7 @@
 from resultsdbpy.controller.commit_controller import uuid_range_for_query, HasCommitContext
 from resultsdbpy.controller.configuration import Configuration
 from resultsdbpy.controller.configuration_controller import configuration_for_query
-from resultsdbpy.flask_support.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
+from webkitflaskpy.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
 
 
 def time_range_for_query():

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/test_controller.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/test_controller.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/test_controller.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -25,7 +25,7 @@
 from resultsdbpy.controller.configuration import Configuration
 from resultsdbpy.controller.configuration_controller import configuration_for_query
 from resultsdbpy.controller.suite_controller import time_range_for_query
-from resultsdbpy.flask_support.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
+from webkitflaskpy.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
 
 
 class TestController(HasCommitContext):

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/upload_controller.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/upload_controller.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/controller/upload_controller.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -25,11 +25,11 @@
 
 from collections import defaultdict
 from flask import abort, jsonify, request
-from resultsdbpy.flask_support.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
 from resultsdbpy.controller.commit import Commit
 from resultsdbpy.controller.commit_controller import uuid_range_for_query, HasCommitContext
 from resultsdbpy.controller.configuration import Configuration
 from resultsdbpy.controller.configuration_controller import configuration_for_query
+from webkitflaskpy.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
 
 
 class UploadController(HasCommitContext):

Deleted: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -1,131 +0,0 @@
-# Copyright (C) 2019 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 json
-from flask import abort, request
-
-
-class FlaskJSONEncoder(json.JSONEncoder):
-    # Flask's jsonify only accepts a dictionary and does not accept a JSON encoder. When overriding the default JSON
-    # encoder, encoder.default(...) will return a dictionary to be serialized. However, the default encoder will raise
-    # an exception if default(...) is called on primative JSON types. Implement a version of the default encoder which
-    # passes primative JSON types back to the caller.
-    def default(self, obj):
-        if isinstance(obj, dict):
-            return {key: self.default(value) for key, value in obj.items()}
-        if isinstance(obj, list):
-            return [self.default(value) for value in obj]
-        return obj
-
-
-class AssertRequest(object):
-    @classmethod
-    def is_type(cls, supported_requests=None):
-        if supported_requests is None:
-            supported_requests = ['GET']
-        if not supported_requests:
-            abort(500, description='Endpoint does not support any requests')
-        if request.method not in supported_requests:
-            abort(405, description='Endpoint only supports {} requests'.format(
-                supported_requests[0] if len(supported_requests) == 1 else ', '.join(supported_requests[:-1]) + ' and ' + supported_requests[-1],
-            ))
-
-    @classmethod
-    def no_query(cls):
-        if request.query_string:
-            abort(400, description='Queries not supported on this endpoint')
-
-    @classmethod
-    def query_kwargs_empty(cls, **kwargs):
-        for key, value in kwargs.items():
-            if value:
-                abort(400, description=f"'{key}' not supported in queries by this endpoint")
-
-
-def query_as_kwargs():
-    def decorator(method):
-        def real_method(val, method=method, **kwargs):
-            for key, value in request.args.to_dict(flat=False).items():
-                if key in kwargs:
-                    abort(400, description=f'{key} is not a valid query parameter on this endpoint')
-                kwargs[key] = tuple(value)
-            return method(val, **kwargs)
-
-        real_method.__name__ = method.__name__
-        return real_method
-    return decorator
-
-
-def query_as_string():
-    query = '?'
-    for key, values in request.args.to_dict(flat=False).items():
-        for value in values:
-            query += f'{key}={value}&'
-    return query[:-1]
-
-
-def boolean_query(*args):
-
-    def func(string):
-        if string.lower() in ['true', 'yes']:
-            return True
-        try:
-            return bool(int(string))
-        except ValueError:
-            return False
-
-    return [func(arg) for arg in args]
-
-
-def limit_for_query(default_limit=100):
-    def decorator(method):
-        def real_method(self=None, method=method, limit=None, **kwargs):
-            limit_to_use = default_limit
-            if limit:
-                try:
-                    limit_to_use = int(limit[-1])
-                    if limit_to_use <= 0:
-                        raise ValueError()
-                except ValueError:
-                    abort(400, description='Limit must be a positive integer')
-            if self:
-                return method(self=self, limit=limit_to_use, **kwargs)
-            return method(limit=limit_to_use, **kwargs)
-
-        real_method.__name__ = method.__name__
-        return real_method
-    return decorator
-
-
-def cache_for(hours=12):
-    def decorator(method):
-        def real_method(self=None, method=method, **kwargs):
-            if self:
-                response = method(self=self, **kwargs)
-            else:
-                response = method(**kwargs)
-            response.headers.add('Cache-Control', f'public,max-age={hours * 60 * 60}')
-            return response
-
-        real_method.__name__ = method.__name__
-        return real_method
-    return decorator

Deleted: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util_unittest.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util_unittest.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util_unittest.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -1,50 +0,0 @@
-# Copyright (C) 2019 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 unittest
-
-from werkzeug.exceptions import BadRequest
-from resultsdbpy.flask_support.util import boolean_query, limit_for_query
-
-
-class UtilTest(unittest.TestCase):
-
-    def test_boolean_query(self):
-        self.assertTrue(all(boolean_query('True', 'true')))
-        self.assertTrue(all(boolean_query('Yes', 'yes')))
-        self.assertTrue(all(boolean_query('1', '100')))
-
-        self.assertFalse(any(boolean_query('False', 'false')))
-        self.assertFalse(any(boolean_query('No', 'no')))
-        self.assertFalse(any(boolean_query('0', 'any string')))
-
-    def test_limit_decorator(self):
-        @limit_for_query()
-        def func(limit=None):
-            return limit
-
-        self.assertEqual(func(), 100)
-        self.assertEqual(func(limit=['10']), 10)
-        self.assertEqual(func(limit=['10', '1']), 1)
-        self.assertRaises(BadRequest, func, limit=['string'])
-        self.assertRaises(BadRequest, func, limit=['0'])
-        self.assertRaises(BadRequest, func, limit=['-1'])

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/archive_view.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/archive_view.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/archive_view.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -20,14 +20,12 @@
 # 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 json
-
 from flask import abort, jsonify, request, Response
 from resultsdbpy.controller.commit_controller import uuid_range_for_query, HasCommitContext
 from resultsdbpy.controller.configuration_controller import configuration_for_query
 from resultsdbpy.controller.suite_controller import time_range_for_query
-from resultsdbpy.flask_support.util import AssertRequest, boolean_query, cache_for, limit_for_query, query_as_kwargs, query_as_string
 from resultsdbpy.view.site_menu import SiteMenu
+from webkitflaskpy.util import AssertRequest, boolean_query, cache_for, limit_for_query, query_as_kwargs, query_as_string
 
 
 class ArchiveView(HasCommitContext):

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/ci_view.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/ci_view.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/ci_view.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -21,9 +21,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 from flask import abort, redirect, request
-from resultsdbpy.controller.commit import Commit
-from resultsdbpy.flask_support.util import AssertRequest, query_as_kwargs
-from resultsdbpy.view.site_menu import SiteMenu
+from webkitflaskpy.util import query_as_kwargs
 
 
 class CIView(object):

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/commit_view.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/commit_view.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/commit_view.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -22,8 +22,8 @@
 
 from flask import abort, redirect, request
 from resultsdbpy.controller.commit import Commit
-from resultsdbpy.flask_support.util import AssertRequest, query_as_kwargs
 from resultsdbpy.view.site_menu import SiteMenu
+from webkitflaskpy.util import AssertRequest, query_as_kwargs
 
 
 class CommitView(object):

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/suite_view.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/suite_view.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/suite_view.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -26,8 +26,8 @@
 from resultsdbpy.controller.commit_controller import uuid_range_for_query, HasCommitContext
 from resultsdbpy.controller.configuration_controller import configuration_for_query
 from resultsdbpy.controller.suite_controller import time_range_for_query
-from resultsdbpy.flask_support.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
 from resultsdbpy.view.site_menu import SiteMenu
+from webkitflaskpy.util import AssertRequest, query_as_kwargs, limit_for_query, boolean_query
 
 
 class SuiteView(HasCommitContext):

Modified: trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/view_routes.py (269113 => 269114)


--- trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/view_routes.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/view/view_routes.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -26,7 +26,6 @@
 
 from flask import abort, jsonify, send_from_directory, redirect, Response
 from jinja2 import Environment, PackageLoader, select_autoescape
-from resultsdbpy.flask_support.util import AssertRequest, cache_for
 from resultsdbpy.flask_support.authed_blueprint import AuthedBlueprint
 from resultsdbpy.view.archive_view import ArchiveView
 from resultsdbpy.view.ci_view import CIView
@@ -34,6 +33,7 @@
 from resultsdbpy.view.site_menu import SiteMenu
 from resultsdbpy.view.suite_view import SuiteView
 from werkzeug.exceptions import HTTPException, InternalServerError
+from webkitflaskpy.util import AssertRequest, cache_for
 
 
 class ViewRoutes(AuthedBlueprint):

Added: trunk/Tools/Scripts/libraries/webkitflaskpy/MANIFEST.in (0 => 269114)


--- trunk/Tools/Scripts/libraries/webkitflaskpy/MANIFEST.in	                        (rev 0)
+++ trunk/Tools/Scripts/libraries/webkitflaskpy/MANIFEST.in	2020-10-28 19:08:28 UTC (rev 269114)
@@ -0,0 +1 @@
+include README.md

Added: trunk/Tools/Scripts/libraries/webkitflaskpy/README.md (0 => 269114)


--- trunk/Tools/Scripts/libraries/webkitflaskpy/README.md	                        (rev 0)
+++ trunk/Tools/Scripts/libraries/webkitflaskpy/README.md	2020-10-28 19:08:28 UTC (rev 269114)
@@ -0,0 +1,3 @@
+# webkitflaskpy
+
+Python package used by some of WebKit's web services to share CSS and _javascript_.

Copied: trunk/Tools/Scripts/libraries/webkitflaskpy/setup.py (from rev 269111, trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util_unittest.py) (0 => 269114)


--- trunk/Tools/Scripts/libraries/webkitflaskpy/setup.py	                        (rev 0)
+++ trunk/Tools/Scripts/libraries/webkitflaskpy/setup.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -0,0 +1,64 @@
+# 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.
+
+from webkitflaskpy import version
+from setuptools import setup
+
+
+def readme():
+    with open('README.md') as f:
+        return f.read()
+
+
+setup(
+    name='webkitflaskpy',
+    version=str(version),
+    description='Library for visualizing, processing and storing test results.',
+    long_description=readme(),
+    classifiers=[
+        'Development Status :: 4 - Beta',
+        'Framework :: Flask',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: BSD License',
+        'Operating System :: MacOS',
+        'Natural Language :: English',
+        'Programming Language :: Python :: 3 :: Only',
+        'Topic :: Software Development :: Libraries :: Python Modules',
+        'Topic :: Software Development :: Testing',
+    ],
+    keywords='web _javascript_ webkit',
+    url='',
+    author='Jonathan Bedard',
+    author_email='[email protected]',
+    license='Modified BSD',
+    packages=[
+        'webkitflaskpy',
+    ],
+    install_requires=[
+        'Flask',
+        'Flask-Cors',
+        'gunicorn',
+        'webkitcorepy',
+    ],
+    include_package_data=True,
+    zip_safe=False,
+)

Copied: trunk/Tools/Scripts/libraries/webkitflaskpy/webkitflaskpy/__init__.py (from rev 269111, trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/__init__.py) (0 => 269114)


--- trunk/Tools/Scripts/libraries/webkitflaskpy/webkitflaskpy/__init__.py	                        (rev 0)
+++ trunk/Tools/Scripts/libraries/webkitflaskpy/webkitflaskpy/__init__.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -0,0 +1,55 @@
+# 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 os
+import sys
+
+
+def _maybe_add_webkitcorepy_path():
+    # Hopefully we're beside webkitcorepy, otherwise webkitcorepy will need to be installed.
+    libraries_path = os.path.dirname(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
+    webkitcorepy_path = os.path.join(libraries_path, 'webkitcorepy')
+    if os.path.isdir(webkitcorepy_path) and os.path.isdir(os.path.join(webkitcorepy_path, 'webkitcorepy')) and webkitcorepy_path not in sys.path:
+        sys.path.insert(0, webkitcorepy_path)
+
+
+_maybe_add_webkitcorepy_path()
+
+try:
+    from webkitcorepy import AutoInstall, Package, Version
+except ImportError:
+    raise ImportError(
+        "'webkitcorepy' could not be found on your Python path.\n" +
+        "You are not running from a WebKit checkout.\n" +
+        "Please install webkitcorepy with `pip install webkitcorepy --extra-index-url <package index URL>`"
+    )
+
+version = Version(0, 1, 0)
+
+AutoInstall.register(Package('click'), Version(7, 1, 2))
+AutoInstall.register(Package('flask'), Version(1, 1, 2))
+AutoInstall.register(Package('itsdangerous'), Version(2, 0, 0))
+AutoInstall.register(Package('jinja2'), Version(3, 0, 0))
+AutoInstall.register(Package('markupsafe'), Version(2, 0, 0))
+AutoInstall.register(Package('werkzeug'), Version(1, 0, 1))
+
+name = 'webkitflaskpy'

Copied: trunk/Tools/Scripts/libraries/webkitflaskpy/webkitflaskpy/util.py (from rev 269111, trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util.py) (0 => 269114)


--- trunk/Tools/Scripts/libraries/webkitflaskpy/webkitflaskpy/util.py	                        (rev 0)
+++ trunk/Tools/Scripts/libraries/webkitflaskpy/webkitflaskpy/util.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -0,0 +1,131 @@
+# Copyright (C) 2019 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 json
+from flask import abort, request
+
+
+class FlaskJSONEncoder(json.JSONEncoder):
+    # Flask's jsonify only accepts a dictionary and does not accept a JSON encoder. When overriding the default JSON
+    # encoder, encoder.default(...) will return a dictionary to be serialized. However, the default encoder will raise
+    # an exception if default(...) is called on primative JSON types. Implement a version of the default encoder which
+    # passes primative JSON types back to the caller.
+    def default(self, obj):
+        if isinstance(obj, dict):
+            return {key: self.default(value) for key, value in obj.items()}
+        if isinstance(obj, list):
+            return [self.default(value) for value in obj]
+        return obj
+
+
+class AssertRequest(object):
+    @classmethod
+    def is_type(cls, supported_requests=None):
+        if supported_requests is None:
+            supported_requests = ['GET']
+        if not supported_requests:
+            abort(500, description='Endpoint does not support any requests')
+        if request.method not in supported_requests:
+            abort(405, description='Endpoint only supports {} requests'.format(
+                supported_requests[0] if len(supported_requests) == 1 else ', '.join(supported_requests[:-1]) + ' and ' + supported_requests[-1],
+            ))
+
+    @classmethod
+    def no_query(cls):
+        if request.query_string:
+            abort(400, description='Queries not supported on this endpoint')
+
+    @classmethod
+    def query_kwargs_empty(cls, **kwargs):
+        for key, value in kwargs.items():
+            if value:
+                abort(400, description="'{}' not supported in queries by this endpoint".format(key))
+
+
+def query_as_kwargs():
+    def decorator(method):
+        def real_method(val, method=method, **kwargs):
+            for key, value in request.args.to_dict(flat=False).items():
+                if key in kwargs:
+                    abort(400, description='{} is not a valid query parameter on this endpoint'.format(key))
+                kwargs[key] = tuple(value)
+            return method(val, **kwargs)
+
+        real_method.__name__ = method.__name__
+        return real_method
+    return decorator
+
+
+def query_as_string():
+    query = '?'
+    for key, values in request.args.to_dict(flat=False).items():
+        for value in values:
+            query += '{}={}&'.format(key, value)
+    return query[:-1]
+
+
+def boolean_query(*args):
+
+    def func(string):
+        if string.lower() in ['true', 'yes']:
+            return True
+        try:
+            return bool(int(string))
+        except ValueError:
+            return False
+
+    return [func(arg) for arg in args]
+
+
+def limit_for_query(default_limit=100):
+    def decorator(method):
+        def real_method(self=None, method=method, limit=None, **kwargs):
+            limit_to_use = default_limit
+            if limit:
+                try:
+                    limit_to_use = int(limit[-1])
+                    if limit_to_use <= 0:
+                        raise ValueError()
+                except ValueError:
+                    abort(400, description='Limit must be a positive integer')
+            if self:
+                return method(self=self, limit=limit_to_use, **kwargs)
+            return method(limit=limit_to_use, **kwargs)
+
+        real_method.__name__ = method.__name__
+        return real_method
+    return decorator
+
+
+def cache_for(hours=12):
+    def decorator(method):
+        def real_method(self=None, method=method, **kwargs):
+            if self:
+                response = method(self=self, **kwargs)
+            else:
+                response = method(**kwargs)
+            response.headers.add('Cache-Control', 'public,max-age={}'.format(hours * 60 * 60))
+            return response
+
+        real_method.__name__ = method.__name__
+        return real_method
+    return decorator

Copied: trunk/Tools/Scripts/libraries/webkitflaskpy/webkitflaskpy/util_unittest.py (from rev 269111, trunk/Tools/Scripts/libraries/resultsdbpy/resultsdbpy/flask_support/util_unittest.py) (0 => 269114)


--- trunk/Tools/Scripts/libraries/webkitflaskpy/webkitflaskpy/util_unittest.py	                        (rev 0)
+++ trunk/Tools/Scripts/libraries/webkitflaskpy/webkitflaskpy/util_unittest.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -0,0 +1,50 @@
+# Copyright (C) 2019 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 unittest
+
+from werkzeug.exceptions import BadRequest
+from webkitflaskpy.util import boolean_query, limit_for_query
+
+
+class UtilTest(unittest.TestCase):
+
+    def test_boolean_query(self):
+        self.assertTrue(all(boolean_query('True', 'true')))
+        self.assertTrue(all(boolean_query('Yes', 'yes')))
+        self.assertTrue(all(boolean_query('1', '100')))
+
+        self.assertFalse(any(boolean_query('False', 'false')))
+        self.assertFalse(any(boolean_query('No', 'no')))
+        self.assertFalse(any(boolean_query('0', 'any string')))
+
+    def test_limit_decorator(self):
+        @limit_for_query()
+        def func(limit=None):
+            return limit
+
+        self.assertEqual(func(), 100)
+        self.assertEqual(func(limit=['10']), 10)
+        self.assertEqual(func(limit=['10', '1']), 1)
+        self.assertRaises(BadRequest, func, limit=['string'])
+        self.assertRaises(BadRequest, func, limit=['0'])
+        self.assertRaises(BadRequest, func, limit=['-1'])

Modified: trunk/Tools/Scripts/webkitpy/test/main.py (269113 => 269114)


--- trunk/Tools/Scripts/webkitpy/test/main.py	2020-10-28 18:59:31 UTC (rev 269113)
+++ trunk/Tools/Scripts/webkitpy/test/main.py	2020-10-28 19:08:28 UTC (rev 269114)
@@ -64,6 +64,7 @@
     tester.add_tree(os.path.join(_webkit_root, 'Tools', 'Scripts'), 'webkitpy')
     tester.add_tree(os.path.join(_webkit_root, 'Tools', 'Scripts', 'libraries', 'webkitcorepy'), 'webkitcorepy')
     tester.add_tree(os.path.join(_webkit_root, 'Tools', 'Scripts', 'libraries', 'webkitscmpy'), 'webkitscmpy')
+    tester.add_tree(os.path.join(_webkit_root, 'Tools', 'Scripts', 'libraries', 'webkitflaskpy'), 'webkitflaskpy')
 
     # There is no WebKit2 on Windows, so we don't need to run WebKit2 unittests on it.
     if not (sys.platform.startswith('win') or sys.platform == 'cygwin'):
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to