From c13fcafe1c50efc5eab88fd246f0c69b171dbe87 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Dec 06 2018 20:12:25 +0000 Subject: Move parse_path into pagure.utils so it can be re-used elsewhere Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure-ev/pagure_stream_server.py b/pagure-ev/pagure_stream_server.py index a114deb..45b00fe 100644 --- a/pagure-ev/pagure_stream_server.py +++ b/pagure-ev/pagure_stream_server.py @@ -110,60 +110,11 @@ OBJECTS = { } -def _parse_path(path): - """Get the repo name, object type, object ID, and (if present) - username and/or namespace from a URL path component. Will only - handle the known object types from the OBJECTS dict. Assumes: - * Project name comes immediately before object type - * Object ID comes immediately after object type - * If a fork, path starts with /fork/(username) - * Namespace, if present, comes after fork username (if present) or at start - * No other components come before the project name - * None of the parsed items can contain a / - """ - username = None - namespace = None - # path always starts with / so split and throw away first item - items = path.split('/')[1:] - # find the *last* match for any object type - try: - objtype = [item for item in items if item in OBJECTS][-1] - except IndexError: - raise PagureEvException( - "No known object type found in path: %s" % path) - try: - # objid is the item after objtype, we need all items up to it - items = items[:items.index(objtype) + 2] - # now strip the repo, objtype and objid off the end - (repo, objtype, objid) = items[-3:] - items = items[:-3] - except (IndexError, ValueError): - raise PagureEvException( - "No project or object ID found in path: %s" % path) - # now check for a fork - if items and items[0] == 'fork': - try: - # get the username and strip it and 'fork' - username = items[1] - items = items[2:] - except IndexError: - raise PagureEvException( - "Path starts with /fork but no user found! Path: %s" % path) - # if we still have an item left, it must be the namespace - if items: - namespace = items.pop(0) - # if we have any items left at this point, we've no idea - if items: - raise PagureEvException( - "More path components than expected! Path: %s" % path) - - return username, namespace, repo, objtype, objid - - def get_obj_from_path(path): """ Return the Ticket or Request object based on the path provided. """ - (username, namespace, reponame, objtype, objid) = _parse_path(path) + (username, namespace, reponame, objtype, objid) = pagure.utils.parse_path( + path) session = _get_session() repo = pagure.lib.query.get_authorized_project( session, reponame, user=username, namespace=namespace) @@ -212,7 +163,7 @@ def handle_client(client_reader, client_writer): try: obj = get_obj_from_path(url.path) - except PagureEvException as err: + except PagureException as err: log.warning(err.message) return diff --git a/pagure/utils.py b/pagure/utils.py index 8ef3d35..719831f 100644 --- a/pagure/utils.py +++ b/pagure/utils.py @@ -22,6 +22,7 @@ import pygit2 import six import werkzeug +from pagure.exceptions import PagureException from pagure.config import config as pagure_config @@ -742,3 +743,57 @@ def project_has_hook_attr_value(project, hook, attr, value): retval = True return retval + + +def parse_path(path): + """Get the repo name, object type, object ID, and (if present) + username and/or namespace from a URL path component. Will only + handle the known object types from the OBJECTS dict. Assumes: + * Project name comes immediately before object type + * Object ID comes immediately after object type + * If a fork, path starts with /fork/(username) + * Namespace, if present, comes after fork username (if present) or at start + * No other components come before the project name + * None of the parsed items can contain a / + """ + username = None + namespace = None + # path always starts with / so split and throw away first item + items = path.split("/")[1:] + # find the *last* match for any object type + try: + objtype = [ + item for item in items if item in ["issue", "pull-request"] + ][-1] + except IndexError: + raise PagureException("No known object type found in path: %s" % path) + try: + # objid is the item after objtype, we need all items up to it + items = items[: items.index(objtype) + 2] + # now strip the repo, objtype and objid off the end + (repo, objtype, objid) = items[-3:] + items = items[:-3] + except (IndexError, ValueError): + raise PagureException( + "No project or object ID found in path: %s" % path + ) + # now check for a fork + if items and items[0] == "fork": + try: + # get the username and strip it and 'fork' + username = items[1] + items = items[2:] + except IndexError: + raise PagureException( + "Path starts with /fork but no user found! Path: %s" % path + ) + # if we still have an item left, it must be the namespace + if items: + namespace = items.pop(0) + # if we have any items left at this point, we've no idea + if items: + raise PagureException( + "More path components than expected! Path: %s" % path + ) + + return username, namespace, repo, objtype, objid diff --git a/tests/test_stream_server.py b/tests/test_stream_server.py index 0c84e4e..5c4a37a 100644 --- a/tests/test_stream_server.py +++ b/tests/test_stream_server.py @@ -33,7 +33,7 @@ if six.PY3: raise unittest.case.SkipTest('Skipping on python3') import pagure.lib.query # pylint: disable=wrong-import-position -from pagure.exceptions import PagureEvException # pylint: disable=wrong-import-position +from pagure.exceptions import PagureException, PagureEvException # pylint: disable=wrong-import-position import tests # pylint: disable=wrong-import-position # comes from ev-server/ import pagure_stream_server as pss # pylint: disable=wrong-import-position, import-error @@ -110,70 +110,76 @@ class StreamingServerTests(tests.Modeltests): """Tests for _parse_path.""" # Result format is: (username, namespace, repo, objtype, objid) # Simple case: issue for non-namespaced, non-forked repo. - result = pss._parse_path('/pagure/issue/1') + result = pagure.utils.parse_path('/pagure/issue/1') self.assertEqual(result, (None, None, 'pagure', 'issue', '1')) # Pull request for namespaced repo. - result = pss._parse_path('/fedora-qa/fedfind/pull-request/2') + result = pagure.utils.parse_path('/fedora-qa/fedfind/pull-request/2') self.assertEqual(result, (None, 'fedora-qa', 'fedfind', 'pull-request', '2')) # Issue for forked repo. - result = pss._parse_path('/fork/adamwill/pagure/issue/3') + result = pagure.utils.parse_path('/fork/adamwill/pagure/issue/3') self.assertEqual(result, ('adamwill', None, 'pagure', 'issue', '3')) # Issue for forked, namespaced repo. - result = pss._parse_path('/fork/pingou/fedora-qa/fedfind/issue/4') + result = pagure.utils.parse_path('/fork/pingou/fedora-qa/fedfind/issue/4') self.assertEqual(result, ('pingou', 'fedora-qa', 'fedfind', 'issue', '4')) # Issue for repo named 'pull-request' (yeah, now we're getting tricksy). - result = pss._parse_path('/pull-request/issue/5') + result = pagure.utils.parse_path('/pull-request/issue/5') self.assertEqual(result, (None, None, 'pull-request', 'issue', '5')) # Unknown object type. six.assertRaisesRegex( self, - PagureEvException, + PagureException, r"No known object", - pss._parse_path, '/pagure/unexpected/1' + pagure.utils.parse_path, + '/pagure/unexpected/1' ) # No object ID. six.assertRaisesRegex( self, - PagureEvException, + PagureException, r"No project or object ID", - pss._parse_path, '/pagure/issue' + pagure.utils.parse_path, + '/pagure/issue' ) # No repo name. Note: we cannot catch 'namespace but no repo name', # but that should fail later in pagure.lib.query.get_project six.assertRaisesRegex( self, - PagureEvException, + PagureException, r"No project or object ID", - pss._parse_path, '/issue/1' + pagure.utils.parse_path, + '/issue/1' ) # /fork but no user name. six.assertRaisesRegex( self, - PagureEvException, + PagureException, r"no user found!", - pss._parse_path, '/fork/pagure/issue/1' + pagure.utils.parse_path, + '/fork/pagure/issue/1' ) # Too many path components before object type. six.assertRaisesRegex( self, - PagureEvException, + PagureException, r"More path components", - pss._parse_path, '/fork/adamwill/fedora-qa/fedfind/unexpected/issue/1' + pagure.utils.parse_path, + '/fork/adamwill/fedora-qa/fedfind/unexpected/issue/1' ) six.assertRaisesRegex( self, - PagureEvException, + PagureException, r"More path components", - pss._parse_path, '/fedora-qa/fedfind/unexpected/issue/1' + pagure.utils.parse_path, + '/fedora-qa/fedfind/unexpected/issue/1' ) def test_get_issue(self):