diff options
author | Kristofer Hallin <kristofer@sunet.se> | 2021-10-01 10:21:54 +0200 |
---|---|---|
committer | Kristofer Hallin <kristofer@sunet.se> | 2021-10-01 10:21:54 +0200 |
commit | cb47680777b3fd3bcd955f9e81ddf45c9b69ecfa (patch) | |
tree | 1fa8dfae5e9f39c634498f2c60b56a99558cae9a /src/couch/resource.py | |
parent | 0398e77a809abcaf78c6f7d3e6064a5bee50be23 (diff) |
* Use py-couchdb.
* Other minor fixes and tweaks.
Diffstat (limited to 'src/couch/resource.py')
-rw-r--r-- | src/couch/resource.py | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/couch/resource.py b/src/couch/resource.py new file mode 100644 index 0000000..da1e0dd --- /dev/null +++ b/src/couch/resource.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +# Based on py-couchdb (https://github.com/histrio/py-couchdb) + + +from __future__ import unicode_literals + +import json +import requests + +from couch import utils +from couch import exceptions + + +class Resource(object): + def __init__(self, base_url, full_commit=True, session=None, + credentials=None, authmethod="session", verify=False): + + self.base_url = base_url +# self.verify = verify + + if not session: + self.session = requests.session() + + self.session.headers.update({"accept": "application/json", + "content-type": "application/json"}) + self._authenticate(credentials, authmethod) + + if not full_commit: + self.session.headers.update({'X-Couch-Full-Commit': 'false'}) + else: + self.session = session + self.session.verify = verify + + def _authenticate(self, credentials, method): + if not credentials: + return + + if method == "session": + data = {"name": credentials[0], "password": credentials[1]} + data = utils.force_bytes(json.dumps(data)) + + post_url = utils.urljoin(self.base_url, "_session") + r = self.session.post(post_url, data=data) + if r.status_code != 200: + raise exceptions.AuthenticationFailed() + + elif method == "basic": + self.session.auth = credentials + + else: + raise RuntimeError("Invalid authentication method") + + def __call__(self, *path): + base_url = utils.urljoin(self.base_url, *path) + return self.__class__(base_url, session=self.session) + + def _check_result(self, response, result): + try: + error = result.get('error', None) + reason = result.get('reason', None) + except AttributeError: + error = None + reason = '' + + # This is here because couchdb can return http 201 + # but containing a list of conflict errors + if error == 'conflict' or error == "file_exists": + raise exceptions.Conflict(reason or "Conflict") + + if response.status_code > 205: + if response.status_code == 404 or error == 'not_found': + raise exceptions.NotFound(reason or 'Not found') + elif error == 'bad_request': + raise exceptions.BadRequest(reason or "Bad request") + raise exceptions.GenericError(result) + + def request(self, method, path, params=None, data=None, + headers=None, stream=False, **kwargs): + + if headers is None: + headers = {} + + headers.setdefault('Accept', 'application/json') + + if path: + if not isinstance(path, (list, tuple)): + path = [path] + url = utils.urljoin(self.base_url, *path) + else: + url = self.base_url + + response = self.session.request(method, url, stream=stream, + data=data, params=params, + headers=headers, **kwargs) + # Ignore result validation if + # request is with stream mode + + if stream and response.status_code < 400: + result = None + self._check_result(response, result) + else: + result = utils.as_json(response) + + if result is None: + return response, result + + if isinstance(result, list): + for res in result: + self._check_result(response, res) + else: + self._check_result(response, result) + + return response, result + + def get(self, path=None, **kwargs): + return self.request("GET", path, **kwargs) + + def put(self, path=None, **kwargs): + return self.request("PUT", path, **kwargs) + + def post(self, path=None, **kwargs): + return self.request("POST", path, **kwargs) + + def delete(self, path=None, **kwargs): + return self.request("DELETE", path, **kwargs) + + def head(self, path=None, **kwargs): + return self.request("HEAD", path, **kwargs) |