diff --git a/.gitignore b/.gitignore
index d5fc83d..72a0041 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
*.pyc
*.coverage
+.eggs
dist
build
packtrack.egg-info
diff --git a/.travis.yml b/.travis.yml
index 8e1e41c..cfc7264 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,7 @@
language: python
-before_install: pip install -r requirements.txt
+before_install:
+ - python setup.py install
+ - pip install -r requirements-dev.txt
-script: nosetests
\ No newline at end of file
+script: nosetests
diff --git a/packtrack/__init__.py b/packtrack/__init__.py
index 80d4852..969f14b 100755
--- a/packtrack/__init__.py
+++ b/packtrack/__init__.py
@@ -1,6 +1,6 @@
-from correios import EncomendaRepository
-from royal import RoyalMail
-from dhl_gm import DhlGmTracker
+from .correios import EncomendaRepository
+from .royal import RoyalMail
+from .dhl_gm import DhlGmTracker
class Correios(object):
diff --git a/packtrack/correios.py b/packtrack/correios.py
index 4514751..897147b 100644
--- a/packtrack/correios.py
+++ b/packtrack/correios.py
@@ -15,7 +15,7 @@ def get(self, numero, auth=None):
return func(numero, **kwargs)
def _init_scraper(self, backend):
- from scraping import CorreiosWebsiteScraper, CorreiosRastroService
+ from .scraping import CorreiosWebsiteScraper, CorreiosRastroService
if backend is None:
backend = 'www2'
@@ -34,10 +34,9 @@ def __init__(self, numero):
self.status = []
def adicionar_status(self, status):
- d = datetime
self.status.append(status)
t_format = self.validar_data(status.data)
- self.status.sort(lambda x, y: 1 if d.strptime(x.data, t_format) > d.strptime(y.data, t_format) else -1)
+ self.status.sort(key=lambda s: datetime.strptime(s.data, t_format))
def validar_data(self, data):
if re.match('^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$', data):
diff --git a/packtrack/scraping.py b/packtrack/scraping.py
index fc0c3b0..5350769 100755
--- a/packtrack/scraping.py
+++ b/packtrack/scraping.py
@@ -1,15 +1,15 @@
import os
import re
-from HTMLParser import HTMLParser
+from html import unescape
-from BeautifulSoup import BeautifulSoup
+from bs4 import BeautifulSoup
import requests
from requests.exceptions import RequestException
from zeep import Client as Zeep
from zeep.cache import InMemoryCache
from zeep.transports import Transport
-from correios import Encomenda, Status
+from .correios import Encomenda, Status
class CorreiosWebsiteScraper(object):
@@ -46,49 +46,36 @@ def get_encomenda_info(self, numero):
except RequestException:
return None
- html = response.content
-
+ html = response.text
if html:
- try:
- html = html.decode('latin-1')
- except UnicodeDecodeError:
- pass
encomenda = Encomenda(numero)
for status in self._get_all_status_from_html(html):
encomenda.adicionar_status(status)
return encomenda
def _text(self, value):
- value = BeautifulSoup(value.strip()).text
- return value.replace(' ', ' ')
+ text = BeautifulSoup(value.strip(), 'html.parser').text
+ return re.sub(r'[\s\t]+', ' ', text)
def _get_all_status_from_html(self, html):
status = []
- html_parser = HTMLParser()
- if "
).*', html, re.S)
- if not html_info:
- return status
-
- table = html_info.group(1)
- soup = BeautifulSoup(table)
-
- for tr in soup.table:
+ # O bs4 converte o para \xa0 ao invés de espaço.
+ clean_html = html.replace(' ', ' ')
+ soup = BeautifulSoup(clean_html, 'html.parser')
+ for tr in soup.select('table.sro tr'):
try:
tds = tr.findAll('td')
except AttributeError:
continue
for td in tds:
- content = td.renderContents().replace('\r', ' ') \
- .split('
')
+ content = td.encode_contents().decode().replace('\r', ' ').split('
')
class_ = td['class']
- if class_ == 'sroDtEvent':
+ if 'sroDtEvent' in class_:
data = '%s %s' % (content[0].strip(), content[1].strip())
- local = '/'.join(self._text(content[2]).rsplit(' / ', 1)).upper()
- elif class_ == 'sroLbEvent':
- situacao = html_parser.unescape(self._text(content[0]))
- detalhes = html_parser.unescape(self._text(content[1]))
+ local = '/'.join(self._text(content[2]).rsplit(' / ', 1)).upper().rstrip('/')
+ elif 'sroLbEvent' in class_:
+ situacao = unescape(self._text(content[0]))
+ detalhes = unescape(self._text(content[1]))
if detalhes:
detalhes = u'%s %s' % (situacao, detalhes)
status.append(Status(data=data, local=local,
diff --git a/requirements-dev.txt b/requirements-dev.txt
new file mode 100644
index 0000000..f3c7e8e
--- /dev/null
+++ b/requirements-dev.txt
@@ -0,0 +1 @@
+nose
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 5e0d12c..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-BeautifulSoup==3.2.1
-argparse==1.2.1
-beautifulsoup4==4.3.2
-lxml==2.3.5
-mockito==0.5.1
-requests==2.18.1
-wsgiref==0.1.2
-zeep==1.6.0
diff --git a/setup.py b/setup.py
index dfbab09..81159e0 100755
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
setup(
name='packtrack',
- version='1.6',
+ version='2.0',
packages=['packtrack'],
author='Ale Borba',
author_email='ale.borba@codingforchange.com',
@@ -13,9 +13,8 @@
url='https://github.com/aleborba/packtrack',
long_description='API Python para obter informacoes de encomendas. Para mais detalhes veja a documentacao no Github: https://github.com/aleborba/packtrack/blob/master/README.textile',
install_requires=[
- 'BeautifulSoup >= 3.1.0',
- 'requests >= 0.14.2',
- 'beautifulsoup4 >= 4.3.2',
+ 'requests',
+ 'beautifulsoup4 >= 4.9.3',
'lxml >= 2.3.5',
'zeep >= 1.6.0',
],
diff --git a/tests/correios_api_test.py b/tests/correios_api_test.py
index 6777ec3..222ef13 100644
--- a/tests/correios_api_test.py
+++ b/tests/correios_api_test.py
@@ -1,29 +1,25 @@
-import unittest
-
-from mock import Mock
-from mockito import when
+from unittest import TestCase
+from unittest.mock import Mock
from packtrack import Correios
-class CorreiosTest(unittest.TestCase):
+class CorreiosTest(TestCase):
def test_should_use_repository_to_get_encomenda(self):
encomenda_repository_mock = Mock()
- when(encomenda_repository_mock).get('123', auth=None) \
- .thenReturn('encomenda123')
-
+ encomenda_repository_mock.get.return_value = 'encomenda123'
Correios._backends[None] = encomenda_repository_mock
assert Correios.track('123') == 'encomenda123'
+ encomenda_repository_mock.get.assert_called_with('123', auth=None)
def test_service_should_receive_auth(self):
auth = ('mi', 'mimi')
encomenda_repository_mock = Mock()
- when(encomenda_repository_mock).get('123', auth=auth) \
- .thenReturn('encomenda123')
-
+ encomenda_repository_mock.get.return_value = 'encomenda123'
Correios._backends['service'] = encomenda_repository_mock
assert Correios.track(
'123', backend='service', auth=auth) == 'encomenda123'
+ encomenda_repository_mock.get.assert_called_with('123', auth=auth)
diff --git a/tests/correios_test.py b/tests/correios_test.py
index d24712e..65cc364 100644
--- a/tests/correios_test.py
+++ b/tests/correios_test.py
@@ -1,23 +1,23 @@
import unittest
-
-from mock import Mock
-from mockito import *
+from unittest.mock import Mock
from packtrack.correios import Encomenda, Status, EncomendaRepository
+
class EncomendaRepositoryTest(unittest.TestCase):
def test_should_get_encomenda_by_numero(self):
encomenda_123 = Status(data='2009-01-28 17:49:00')
-
+
correios_website_scraper_mock = Mock()
- when(correios_website_scraper_mock).get_encomenda_info('123', auth=None).thenReturn(encomenda_123)
-
+ correios_website_scraper_mock.get_encomenda_info.return_value = encomenda_123
+
repository = EncomendaRepository()
repository.correios_website_scraper = correios_website_scraper_mock
encomenda = repository.get('123')
assert encomenda
assert encomenda.data == '2009-01-28 17:49:00'
+ correios_website_scraper_mock.get_encomenda_info.assert_called_with('123', auth=None)
def test_select_default_backend(self):
repository = EncomendaRepository()
diff --git a/tests/scraping_test.py b/tests/scraping_test.py
index 547c605..0cb1dc7 100644
--- a/tests/scraping_test.py
+++ b/tests/scraping_test.py
@@ -1,8 +1,7 @@
# encoding: UTF-8
import os
import unittest
-
-import mock
+from unittest.mock import Mock
from packtrack.scraping import CorreiosWebsiteScraper
from packtrack.dhl_gm import DhlGmTracker
@@ -17,14 +16,13 @@ def _assert_status(self, status, data, local, situacao, detalhes):
self.assertEqual(detalhes, status.detalhes)
def test_should_get_data_from_correios_website(self):
- example_file = open('%s/tests/correios_website/exemplo_rastreamento_correios1.html' % os.getcwd())
- sample_html = example_file.read()
- example_file.close()
+ with open(f'{os.getcwd()}/tests/correios_website/exemplo_rastreamento_correios1.html', 'r', encoding='latin-1') as f:
+ sample_html = f.read()
- http_client_mock = mock.Mock()
- response_mock = mock.Mock()
+ http_client_mock = Mock()
+ response_mock = Mock()
http_client_mock.post.return_value = response_mock
- response_mock.content = sample_html
+ response_mock.text = sample_html
correios_website_scraper = CorreiosWebsiteScraper(http_client_mock)
numero = 'PJ859656941BR'
@@ -47,10 +45,10 @@ class CorreiosTimeoutTest(unittest.TestCase):
def test_timeout_undefined(self):
- http_client_mock = mock.Mock()
- response_mock = mock.Mock()
+ http_client_mock = Mock()
+ response_mock = Mock()
http_client_mock.post.return_value = response_mock
- response_mock.content = ''
+ response_mock.text = ''
TIMEOUT = 3
scraper = CorreiosWebsiteScraper(http_client_mock, timeout=TIMEOUT)
scraper.get_encomenda_info('ES446391025BR')