Repository: aio-libs/aiohttp

Issue:
Support load/save cookie_jar
I found that cookie_jar do not provide any function to _load or save cookie_jar_

Is there any pythonic way to implement  these two method?

```
session.cookie_jar.load('foo.cookie.txt')
....# do sth.
session.cookie_jar.save()

```



Discussion:
Thank you for raising the question!

It's definitely possible but not implemented yet.

The problem is the cookies storage format.
I believe making it compatible with everything doesn't make sense.
If we'll make an agreement that the storage is just opaque binary data (a pickled dict of SimpleCookies actually) -- implementation is reduced to pickling/unpickling `CookieJar._cookies` attribute.

Another option is adding pickle support to `CookieJar` itself without adding `load()`/`save()` methods.

@ahui132 would you work on Pull Request?

I've commited [support load/save cookie_jar](https://github.com/KeepSafe/aiohttp/compare/master...ahui132:master). And it works well.

But encountered a problem about py.test(I have never written a py.test case before), 
It seemed that I should install fixture _event_loop_ and _mocker_, I do not know how to do it.

```
___________________________________ ERROR at setup of test_index ___________________________________
file /usr/local/lib/python3.5/site-packages/aiohttp.src/demos/polls/tests/test_integration.py, line 13
  def test_index(create_app, event_loop, app_db):
file /usr/local/lib/python3.5/site-packages/aiohttp.src/demos/polls/tests/conftest.py, line 9
  @pytest.yield_fixture
  def create_app(event_loop, unused_tcp_port):
E       fixture 'event_loop' not found
>       available fixtures: LineMatcher, _pytest, anypython, app_db, cache, capfd, capsys, create_app, doctest_namespace, linecomp, loop, monkeypatch, pytestconfig, record_xml_property, recwarn, test_client, test_server, testdir, tmpdir, tmpdir_factory, unused_port
>       use 'pytest --fixtures [testpath]' for help on them.

____________________________ ERROR at setup of test_access_logger_atoms ____________________________
file /usr/local/lib/python3.5/site-packages/aiohttp.src/tests/test_helpers.py, line 148
  def test_access_logger_atoms(mocker):
E       fixture 'mocker' not found
>       available fixtures: LineMatcher, _pytest, anypython, cache, capfd, capsys, doctest_namespace, linecomp, log, loop, monkeypatch, pytestconfig, record_xml_property, recwarn, test_client, test_server, testdir, tmpdir, tmpdir_factory, unused_port
>       use 'pytest --fixtures [testpath]' for help on them.

```

I won't add pull request until this problem is solved.

Did you try `pip install -r requirements-dev.txt` ?


Resolving patch:
diff --git a/aiohttp/cookiejar.py b/aiohttp/cookiejar.py
--- a/aiohttp/cookiejar.py
+++ b/aiohttp/cookiejar.py
@@ -1,4 +1,6 @@
 import datetime
+import pathlib
+import pickle
 import re
 from collections import defaultdict
 from collections.abc import Mapping
@@ -37,6 +39,16 @@ def __init__(self, *, unsafe=False, loop=None):
         self._next_expiration = ceil(self._loop.time())
         self._expirations = {}
 
+    def save(self, file_path):
+        file_path = pathlib.Path(file_path)
+        with file_path.open(mode='wb') as f:
+            pickle.dump(self._cookies, f, pickle.HIGHEST_PROTOCOL)
+
+    def load(self, file_path):
+        file_path = pathlib.Path(file_path)
+        with file_path.open(mode='rb') as f:
+            self._cookies = pickle.load(f)
+
     def clear(self):
         self._cookies.clear()
         self._host_only_cookies.clear()


Test patch:
diff --git a/tests/test_cookiejar.py b/tests/test_cookiejar.py
--- a/tests/test_cookiejar.py
+++ b/tests/test_cookiejar.py
@@ -1,5 +1,7 @@
 import asyncio
 import datetime
+import os
+import tempfile
 import unittest
 from http.cookies import SimpleCookie
 from unittest import mock
@@ -141,6 +143,25 @@ def test_constructor(loop, cookies_to_send, cookies_to_receive):
     assert jar._loop is loop
 
 
+def test_save_load(loop, cookies_to_send, cookies_to_receive):
+    file_path = tempfile.mkdtemp() + '/aiohttp.test.cookie'
+
+    # export cookie jar
+    jar_save = CookieJar(loop=loop)
+    jar_save.update_cookies(cookies_to_receive)
+    jar_save.save(file_path=file_path)
+
+    jar_load = CookieJar(loop=loop)
+    jar_load.load(file_path=file_path)
+
+    jar_test = SimpleCookie()
+    for cookie in jar_load:
+        jar_test[cookie.key] = cookie
+
+    os.unlink(file_path)
+    assert jar_test == cookies_to_receive
+
+
 def test_ctor_ith_default_loop(loop):
     asyncio.set_event_loop(loop)
     jar = CookieJar()