Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/a431278519093168_f_decimal'
Browse files Browse the repository at this point in the history
  • Loading branch information
vmaksymiv committed Oct 3, 2017
2 parents 279d7a7 + 5fa9176 commit c9d0e59
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 6 deletions.
12 changes: 8 additions & 4 deletions src/openprocurement/api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
import gevent.monkey
gevent.monkey.patch_all()
import os
import simplejson
from couchdb import Server as CouchdbServer, Session
from couchdb.http import Unauthorized, extract_credentials
from libnacl.sign import Signer, Verifier
from libnacl.public import SecretKey, PublicKey
from logging import getLogger
from openprocurement.api.auth import AuthenticationPolicy, authenticated_role, check_accreditation
from openprocurement.api.database import set_api_security
from openprocurement.api.utils import forbidden, request_params, route_prefix
from openprocurement.api.utils import forbidden, request_params, route_prefix, couchdb_json_decode
from pkg_resources import iter_entry_points
from pyramid.authorization import ACLAuthorizationPolicy as AuthorizationPolicy
from pyramid.config import Configurator
Expand All @@ -37,9 +38,10 @@ def main(global_config, **settings):
config.add_request_method(request_params, 'params', reify=True)
config.add_request_method(authenticated_role, reify=True)
config.add_request_method(check_accreditation)
config.add_renderer('prettyjson', JSON(indent=4))
config.add_renderer('jsonp', JSONP(param_name='opt_jsonp'))
config.add_renderer('prettyjsonp', JSONP(indent=4, param_name='opt_jsonp'))
config.add_renderer('json', JSON(serializer=simplejson.dumps))
config.add_renderer('prettyjson', JSON(indent=4, serializer=simplejson.dumps))
config.add_renderer('jsonp', JSONP(param_name='opt_jsonp', serializer=simplejson.dumps))
config.add_renderer('prettyjsonp', JSONP(indent=4, param_name='opt_jsonp', serializer=simplejson.dumps))

# search for plugins
plugins = settings.get('plugins') and settings['plugins'].split(',')
Expand All @@ -54,6 +56,8 @@ def main(global_config, **settings):
if aserver:
config.registry.admin_couchdb_server = aserver
config.registry.db = db
# readjust couchdb json decoder
couchdb_json_decode()

# Document Service key
config.registry.docservice_url = settings.get('docservice_url')
Expand Down
21 changes: 20 additions & 1 deletion src/openprocurement/api/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
from datetime import datetime
from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
from iso8601 import parse_date, ParseError
from uuid import uuid4
from urlparse import urlparse, parse_qs
Expand All @@ -10,7 +11,7 @@
from schematics.models import Model as SchematicsModel
from schematics.transforms import whitelist, blacklist, export_loop, convert
from schematics.types import (StringType, FloatType, URLType, IntType,
BooleanType, BaseType, EmailType, MD5Type)
BooleanType, BaseType, EmailType, MD5Type, DecimalType as BaseDecimalType)
from schematics.types.compound import (ModelType, DictType,
ListType as BaseListType)
from schematics.types.serializable import serializable
Expand All @@ -28,6 +29,24 @@
draft_role = whitelist('status')


class DecimalType(BaseDecimalType):

def __init__(self, precision=-3, min_value=None, max_value=None, **kwargs):
self.min_value, self.max_value = min_value, max_value
self.precision = Decimal("1E{:d}".format(precision))
super(DecimalType, self).__init__(**kwargs)

def to_primitive(self, value, context=None):
return value

def to_native(self, value, context=None):
try:
value = Decimal(value).quantize(self.precision, rounding=ROUND_HALF_UP).normalize()
except (TypeError, InvalidOperation):
raise ConversionError(self.messages['number_coerce'].format(value))
return value


class IsoDateTimeType(BaseType):
MESSAGES = {
'parse': u'Could not parse {0}. Should be ISO8601.',
Expand Down
25 changes: 24 additions & 1 deletion src/openprocurement/api/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# -*- coding: utf-8 -*-
import os
import json
import decimal
import simplejson
import couchdb.json
from couchdb import util
from logging import getLogger
from datetime import datetime, timedelta
from base64 import b64encode, b64decode
Expand Down Expand Up @@ -30,7 +35,7 @@
from openprocurement.api.interfaces import IOPContent
from openprocurement.api.interfaces import IContentConfigurator

json_view = partial(view, renderer='json')
json_view = partial(view, renderer='simplejson')


def validate_dkpp(items, *args):
Expand Down Expand Up @@ -572,3 +577,21 @@ def set_modetest_titles(item):
item.title_en = u'[TESTING] {}'.format(item.title_en or u'')
if not item.title_ru or u'[ТЕСТИРОВАНИЕ]' not in item.title_ru:
item.title_ru = u'[ТЕСТИРОВАНИЕ] {}'.format(item.title_ru or u'')


class DecimalEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, decimal.Decimal):
return str(obj)
return super(DecimalEncoder, self).default(obj)


def couchdb_json_decode():
my_encode = lambda obj, dumps=dumps: dumps(obj, cls=DecimalEncoder)

def my_decode(string_):
if isinstance(string_, util.btype):
string_ = string_.decode("utf-8")
return json.loads(string_, parse_float=decimal.Decimal)

couchdb.json.use(decode=my_decode, encode=my_encode)

0 comments on commit c9d0e59

Please sign in to comment.