Skip to content

Commit

Permalink
Refactor to_decimal util function to remove pt_BR locale dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
osantana committed Apr 25, 2017
1 parent d2b41e3 commit 2897ec1
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 31 deletions.
18 changes: 6 additions & 12 deletions correios/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,25 @@
# limitations under the License.


import os
import locale
from datetime import datetime
from decimal import Decimal
from typing import Union, Sequence, List, Dict, Optional

from decimal import Decimal
import os

from correios import xml_utils, DATADIR
from correios.exceptions import PostingListSerializerError, TrackingCodesLimitExceededError
from correios.models.data import EXTRA_SERVICE_MP, EXTRA_SERVICE_AR
from correios.utils import to_decimal
from .models.address import ZipAddress, ZipCode
from .models.posting import (NotFoundTrackingEvent, TrackingCode, PostingList, ShippingLabel,
TrackingEvent, EventStatus, Package, Freight, MONEY_QUANTIZATION)
TrackingEvent, EventStatus, Package, Freight)
from .models.user import User, FederalTaxNumber, StateTaxNumber, Contract, PostingCard, Service, ExtraService
from .soap import SoapClient


KG = 1000 # g


def local_number_to_decimal(value):
locale.setlocale(locale.LC_NUMERIC, "pt_BR.UTF-8")
return Decimal(locale.atof(value)).quantize(MONEY_QUANTIZATION)


class ModelBuilder:
def build_service(self, service_data):
service = Service(
Expand Down Expand Up @@ -164,9 +158,9 @@ def load_tracking_events(self, tracking_codes: Dict[str, TrackingCode], response
def build_freights_list(self, response):
result = []
for service in response.Servicos.cServico:
value = local_number_to_decimal(service.Valor)
value = to_decimal(service.Valor)
delivery_time = int(service.PrazoEntrega)
declared_value = local_number_to_decimal(service.ValorValorDeclarado)
declared_value = to_decimal(service.ValorValorDeclarado)
freight = Freight(
service=service.Codigo,
total=value,
Expand Down
20 changes: 3 additions & 17 deletions correios/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,23 @@
# limitations under the License.


import os
from datetime import datetime
from datetime import datetime # noqa: F401
from decimal import Decimal
from typing import Union, Optional, Sequence, List # noqa: F401

import os
from PIL import Image

from correios import DATADIR
from correios.exceptions import (InvalidFederalTaxNumberError, InvalidExtraServiceError,
InvalidRegionalDirectionError, InvalidUserContractError,
MaximumDeclaredValueError, MinimumDeclaredValueError)
from correios.utils import to_integer, to_datetime
from .data import EXTRA_SERVICES, REGIONAL_DIRECTIONS, SERVICES, EXTRA_SERVICE_VD

EXTRA_SERVICE_CODE_SIZE = 2


def to_integer(number: Union[int, str]) -> int:
try:
return int(number.strip()) # type: ignore
except AttributeError:
return int(number)


def to_datetime(date: Union[datetime, str], fmt="%Y-%m-%d %H:%M:%S%z") -> datetime:
if isinstance(date, str):
last_colon_pos = date.rindex(":")
date = date[:last_colon_pos] + date[last_colon_pos + 1:]
return datetime.strptime(date, fmt)
return date


def _to_federal_tax_number(federal_tax_number) -> "FederalTaxNumber":
if isinstance(federal_tax_number, FederalTaxNumber):
return federal_tax_number
Expand Down
32 changes: 31 additions & 1 deletion correios/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import re
from decimal import Decimal
from datetime import datetime
from itertools import chain
from typing import Container, Iterable, Sized
from typing import Container, Iterable, Sized, Union


def capitalize_phrase(phrase: str) -> str:
Expand Down Expand Up @@ -51,3 +54,30 @@ def __contains__(self, elem):

def __len__(self):
return sum(len(r) for r in self.ranges)


def to_integer(number: Union[int, str]) -> int:
try:
return int(str(number).strip())
except AttributeError:
return int(number)


def to_datetime(date: Union[datetime, str], fmt="%Y-%m-%d %H:%M:%S%z") -> datetime:
if isinstance(date, str):
last_colon_pos = date.rindex(":")
date = date[:last_colon_pos] + date[last_colon_pos + 1:]
return datetime.strptime(date, fmt)
return date


def to_decimal(value: Union[str, float], precision=2):
value = rreplace(str(value), ",", ".", 1)
if "." in value:
real, imag = value.rsplit(".", 1)
else:
real, imag = value, "0"
real = re.sub("[,.]", "", real)

quantize = Decimal("0." + "0" * precision)
return Decimal("{}.{}".format(real, imag)).quantize(quantize)
33 changes: 32 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from decimal import Decimal

import pytest

from correios.utils import capitalize_phrase, RangeSet, rreplace
from correios.utils import capitalize_phrase, RangeSet, rreplace, to_decimal

phrase = 'FOo bAr BAZ qux'

Expand Down Expand Up @@ -56,3 +58,32 @@ def test_rreplace():
assert rreplace(phrase, ' ', '-', 2) == 'foo bar-baz-qux'
assert rreplace(phrase, ' ', '-', 3) == 'foo-bar-baz-qux'
assert rreplace(phrase, ' ', '-') == 'foo-bar-baz-qux'


@pytest.mark.parametrize('s, d', (
("", Decimal("0.00")),
("3", Decimal("3.00")),
("3.57", Decimal("3.57")),
("3.468", Decimal("3.47")),
("3.4", Decimal("3.40")),
("3,57", Decimal("3.57")),
("3,468", Decimal("3.47")),
("3,4", Decimal("3.40")),
("1,357.93", Decimal("1357.93")),
("1.357,93", Decimal("1357.93")),
("1_357.93", Decimal("1357.93")),
("1_357,93", Decimal("1357.93")),
))
def test_to_decimal(s, d):
assert to_decimal(s) == d


@pytest.mark.parametrize('v, p, r', (
("3.4", 1, Decimal("3.4")),
("3.4", 4, Decimal("3.4000")),
("3.4", 0, Decimal("3")),
("3.6", 0, Decimal("4")),
("3.46876", 2, Decimal("3.47")),
))
def test_to_decimal_precision(v, p, r):
assert to_decimal(v, p) == r

0 comments on commit 2897ec1

Please sign in to comment.