Skip to content

Commit

Permalink
refactoring reverse path and fix arg error
Browse files Browse the repository at this point in the history
  • Loading branch information
hadpro24 committed Jul 26, 2021
1 parent 51eca35 commit 25dabb9
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 27 deletions.
49 changes: 32 additions & 17 deletions nimba/http/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from wsgiref.headers import Headers
import pathlib
import urllib.parse
from collections.abc import Iterable

import traceback
import mimetypes
Expand Down Expand Up @@ -38,35 +39,49 @@
REVERSE_ROUTE_INFO = {}
PROJECT_MASK = 'PROJECT_MASK_PATH'

def reverse(name_path:str, args=None, kwargs=None) -> str:
def reverse(name_path:str, *args, **kwargs) -> str:
if not isinstance(name_path, str) or not re.match(r"^[^\d\W][\w-]*\Z", name_path):
raise ValueError("Name path must but a valid identifier name.")
args = args or {}
kwargs = kwargs or {}

args = kwargs.get('args') or args or {}
kwargs.pop('args', None)
kwargs = kwargs.get('kwargs') or kwargs or {}

if args and kwargs:
raise ValueError(("Don't use *args and **kwargs."
"*args is for get and **kwargs for post method."))
path = REVERSE_ROUTE_INFO.get(name_path)
raise ValueError(("You can't mix *args and **kwargs."))
if not isinstance(args, Iterable) or not isinstance(kwargs, dict):
raise ValueError("*args or ** kwargs must be list and dict respectively")

path, view = REVERSE_ROUTE_INFO.get(name_path) or (None, None)
original_path = path
if not path:
raise NoReverseFound(f"Reverse for {name_path} not found.")

regex = r'<(?:(?P<converter>[^>:]+):)?(?P<parameter>[^>]+)>'
url = re.compile(regex, 0)
params_path = list(url.finditer(path))
got_params = args or kwargs
if len(params_path) != len(got_params):
raise ValueError((f"The view `{view}` expects {len(params_path)} "
f"parameters but has received {len(got_params)}"))
if args:
path = path +'?'+ urllib.parse.urlencode(args)
for arg, match in zip(args, params_path):
path = re.sub(
original_path[match.start():match.end()],
urllib.parse.quote(str(arg)),
path
)
else:
regex = r'<(?:(?P<converter>[^>:]+):)?(?P<parameter>[^>]+)>'
url = re.compile(regex, 0)
helper_path = path
for match in url.finditer(path):
for match in params_path:
value = kwargs.get(match['parameter'])
if not value:
raise NoReverseFound((f"Reverse for {name_path} not found. "
raise NoReverseFound((f"Reverse for `{name_path}` not found. "
"Keyword arguments '%s' not found." % match['parameter']))
path = re.sub(
helper_path[match.start():match.end()],
str(value),
original_path[match.start():match.end()],
urllib.parse.quote(str(value)),
path
)
return path
return path

def load_static(value):
return os.path.join('/staticfiles/', value)
Expand Down Expand Up @@ -125,7 +140,7 @@ def request_response_application(callback):
ROUTES[new_path] = (callback, converters, path, methods)

# if: pass
REVERSE_ROUTE_INFO[name or callback.__name__] = path
REVERSE_ROUTE_INFO[name or callback.__name__] = path, callback.__name__
def application(environ, start_response):
request = Request(environ)
#authorized
Expand Down
3 changes: 2 additions & 1 deletion nimba/test/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ def get(self, path, data=None, secure=False):
query_string = urllib.parse.urlencode(data)
url = path+'?'+query_string
else:
url = path
url = urllib.parse.quote(path)

url = self.base_url+url
res = {}
f = open(os.devnull, 'w')
Expand Down
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = nimba
version = 0.0.10
version = 0.0.11
description = Nimba is a fast coding, web framework with Python.
long_description = file: README.rst
keywords = python, python3, framework, nimba, nimba-solution, web
Expand All @@ -17,9 +17,9 @@ classifiers =
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Topic :: Internet :: WWW/HTTP
Topic :: Internet :: WWW/HTTP :: Dynamic Content
Topic :: Internet :: WWW/HTTP :: WSGI
Expand Down
16 changes: 9 additions & 7 deletions tests/test_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import shutil
import sys
import time
import pytest
import shutil
from unittest.mock import patch

Expand Down Expand Up @@ -66,7 +65,7 @@ def test_route_about(self):
self.assertEqual(TEST, response['text'])

def test_route_about_with_query(self):
response = self.get('/about?id=5')
response = self.get('/about', data={'id': 5})
self.assertEqual(200, response['status_code'])
self.assertEqual('yes', response['text'])

Expand Down Expand Up @@ -110,13 +109,12 @@ def test_reverse_with_name_and_kwargs(self):
#give kwargs and args
with self.assertRaises(ValueError) as error:
reverse('article', kwargs={'id': 5}, args={'name': 'test'})
self.assertEqual(str(error.exception), ("Don't use *args and **kwargs."
"*args is for get and **kwargs for post method."))
self.assertEqual(str(error.exception), "You can't mix *args and **kwargs.")
#invalid parmas name
invalid_params = 'id_wrong'
with self.assertRaises(NoReverseFound) as error:
reverse('article', kwargs={invalid_params: 5})
self.assertEqual(str(error.exception), ("Reverse for article not found. "
self.assertEqual(str(error.exception), ("Reverse for `article` not found. "
"Keyword arguments 'id' not found."))
#valid
_id = 5
Expand All @@ -127,8 +125,12 @@ def test_reverse_with_name_and_kwargs(self):

def test_reverse_with_args(self):
name = 'Harouna Diallo'
url = reverse('info', args={'name': name})
response = self.get(url)
with self.assertRaises(ValueError) as error:
url = reverse('info', args={'name': name})
self.assertEqual(str(error.exception),
f"The view `info` expects 0 parameters but has received 1")
url = reverse('info')
response = self.get(url, data={'name': name})
self.assertEqual(200, response['status_code'])
self.assertEqual(name, response['text'])

Expand Down

0 comments on commit 25dabb9

Please sign in to comment.