Repository: django-oscar/django-oscar

Issue:
webob in use, but not referenced in pip dependencies
Hello,
I update django-oscar 1.4 to 1.5.1. webob is now used in /oscar/test/utils.py:6. But webob is not added to python dependencies, so it's not added to requirements with pip-compile.


Discussion:
Webob is a dependency of [webtest](https://pypi.python.org/pypi/WebTest), which is part of the [test dependencies](https://github.com/django-oscar/django-oscar/blob/master/setup.py#L59-L70) for Oscar. 

It isn't listed in `requirements.txt` (which only lists development dependencies), but rather in `setup.py`. It looks like that is the issue you have. I think the way to resolve it is to run `setup.py test` after installation.
It's dependency of external package - I don't see any issue here.
So, T4m is right. We're using `webob` in `oscar.test` which is shipped as part of Oscar itself - i.e., projects should be able to use the tools provided there. I think we either need to add `webob` to `setup.py` or stop using it in `oscar.test`. We only use it in [one place](https://github.com/django-oscar/django-oscar/blob/b77d2cf8f6083875534dc116074d0c7575497e6e/src/oscar/test/utils.py#L6) and could easily drop it - I think this would be better than adding a dependency.
Agreed. Let's drop it.
Did you try to rework cookie tests without `bytes_`? It was not easily possible when I refactored tests and moved away from test client usage.
I have an idea that I think should work - will give it a go over the weekend.

Resolving patch:
diff --git a/src/oscar/core/compat.py b/src/oscar/core/compat.py
--- a/src/oscar/core/compat.py
+++ b/src/oscar/core/compat.py
@@ -10,6 +10,13 @@
 from oscar.core.loading import get_model
 
 
+try:
+    # Python 3
+    from http.cookies import _unquote
+except ImportError:
+    from Cookie import _unquote
+
+
 # A setting that can be used in foreign key declarations
 AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
 try:
@@ -73,6 +80,13 @@ class Meta:
 
 # Python3 compatibility layer
 
+def unquote_cookie(cookie_value):
+    """
+    Make sure a cookie value is unescaped from double quotes
+    """
+    return _unquote(cookie_value)
+
+
 """
 Unicode compatible wrapper for CSV reader and writer that abstracts away
 differences between Python 2 and 3. A package like unicodecsv would be


Test patch:
diff --git a/src/oscar/test/utils.py b/src/oscar/test/utils.py
--- a/src/oscar/test/utils.py
+++ b/src/oscar/test/utils.py
@@ -3,8 +3,6 @@
 from django.contrib.sessions.backends.db import SessionStore
 from django.core.signing import Signer
 from django.test import RequestFactory as BaseRequestFactory
-from webob.compat import bytes_
-from webob.cookies import _unquote
 
 from oscar.core.loading import get_class, get_model
 
@@ -28,13 +26,3 @@ def request(self, user=None, basket=None, **request):
         request.cookies_to_delete = []
 
         return request
-
-
-def extract_cookie_value(response_cookies, cookie_name):
-    """
-    Making sure cookie unescaped from double quotes when extracting from
-    test response using Webob approach of cookie parsing.
-    """
-    oscar_open_basket_cookie = bytes_(response_cookies[cookie_name])
-    oscar_open_basket_cookie = _unquote(oscar_open_basket_cookie)
-    return oscar_open_basket_cookie.decode('utf-8')
diff --git a/tests/functional/customer/test_history.py b/tests/functional/customer/test_history.py
--- a/tests/functional/customer/test_history.py
+++ b/tests/functional/customer/test_history.py
@@ -2,12 +2,11 @@
 from django.http import HttpRequest
 from django.urls import reverse
 
-from oscar.test.factories import create_product
-from oscar.core.compat import get_user_model
 from oscar.apps.customer import history
+from oscar.core.compat import get_user_model, unquote_cookie
 from oscar.templatetags.history_tags import get_back_button
+from oscar.test.factories import create_product
 from oscar.test.testcases import WebTestCase
-from oscar.test.utils import extract_cookie_value
 
 
 User = get_user_model()
@@ -26,7 +25,7 @@ def test_viewing_product_creates_cookie(self):
     def test_id_gets_added_to_cookie(self):
         response = self.app.get(self.product.get_absolute_url())
         request = HttpRequest()
-        request.COOKIES[COOKIE_NAME] = extract_cookie_value(response.test_app.cookies, COOKIE_NAME)
+        request.COOKIES[COOKIE_NAME] = unquote_cookie(response.test_app.cookies[COOKIE_NAME])
         self.assertTrue(self.product.id in history.extract(request))
 
     def test_get_back_button(self):
diff --git a/tests/functional/test_basket.py b/tests/functional/test_basket.py
--- a/tests/functional/test_basket.py
+++ b/tests/functional/test_basket.py
@@ -7,15 +7,14 @@
 from django.utils.six.moves import http_client
 from django.utils.translation import ugettext
 
-from oscar.test.factories import create_product
-from oscar.core.compat import get_user_model
-from oscar.test import factories
-from oscar.test.basket import add_product
-from oscar.test.utils import extract_cookie_value
 from oscar.apps.basket import reports
 from oscar.apps.basket.models import Basket
-from oscar.test.testcases import WebTestCase
 from oscar.apps.partner import strategy
+from oscar.core.compat import get_user_model, unquote_cookie
+from oscar.test import factories
+from oscar.test.basket import add_product
+from oscar.test.factories import create_product
+from oscar.test.testcases import WebTestCase
 
 
 User = get_user_model()
@@ -60,9 +59,7 @@ def test_cookie_is_created(self):
         self.assertTrue('oscar_open_basket' in self.response.test_app.cookies)
 
     def test_price_is_recorded(self):
-        oscar_open_basket_cookie = extract_cookie_value(
-            self.response.test_app.cookies, 'oscar_open_basket'
-        )
+        oscar_open_basket_cookie = unquote_cookie(self.response.test_app.cookies['oscar_open_basket'])
         basket_id = oscar_open_basket_cookie.split(':')[0]
         basket = Basket.objects.get(id=basket_id)
         line = basket.lines.get(product=self.product)