From d89bc7ce7173345118e36bc4e937c1baf4787e50 Mon Sep 17 00:00:00 2001 From: "joao.carabetta@gmail.com" Date: Sun, 5 Mar 2017 21:53:05 -0300 Subject: [PATCH 1/6] skeleton api camara --- {methods => cn_api_client}/__init__.py | 4 + cn_api_client/camara/__init__.py | 31 +++++++ cn_api_client/camara/deputados.py | 41 +++++++++ cn_api_client/camara/orgaos.py | 48 ++++++++++ cn_api_client/camara/proposicoes.py | 51 +++++++++++ cn_api_client/camara/sessoesreunioes.py | 29 ++++++ cn_api_client/senado/__init__.py | 0 cn_api_client/senado/senado.py | 15 +++ cn_api_client/utils.py | 0 docs/conf.py | 8 +- methods/skeleton.py | 117 ------------------------ requirements.txt | 5 +- setup.cfg | 2 +- setup.py | 2 +- tests/conftest.py | 2 +- 15 files changed, 228 insertions(+), 127 deletions(-) rename {methods => cn_api_client}/__init__.py (83%) create mode 100644 cn_api_client/camara/__init__.py create mode 100644 cn_api_client/camara/deputados.py create mode 100644 cn_api_client/camara/orgaos.py create mode 100644 cn_api_client/camara/proposicoes.py create mode 100644 cn_api_client/camara/sessoesreunioes.py create mode 100644 cn_api_client/senado/__init__.py create mode 100644 cn_api_client/senado/senado.py create mode 100644 cn_api_client/utils.py delete mode 100644 methods/skeleton.py diff --git a/methods/__init__.py b/cn_api_client/__init__.py similarity index 83% rename from methods/__init__.py rename to cn_api_client/__init__.py index c280328..33f7322 100644 --- a/methods/__init__.py +++ b/cn_api_client/__init__.py @@ -1,7 +1,11 @@ # -*- coding: utf-8 -*- import pkg_resources +from .camara import Camara + try: __version__ = pkg_resources.get_distribution(__name__).version except: __version__ = 'unknown' + + diff --git a/cn_api_client/camara/__init__.py b/cn_api_client/camara/__init__.py new file mode 100644 index 0000000..9d316c2 --- /dev/null +++ b/cn_api_client/camara/__init__.py @@ -0,0 +1,31 @@ +from .deputados import DeputadosClient +from .orgaos import OrgaosClient +from .proposicoes import ProposicoesClient +from .sessoesreunioes import SessoesClient + +class Camara(object): + """ + Camara dos Deputados Federal of Brazil low-level client. Provides a mapping from Python to REST endpoints. + + The instance has attributes ``deputados``, ``orgaos``, ``proposicoes``, ``sessoesreunioes``, + that provide access to instances of + :class:`~cn_api_client.camara.DeputadosClient`, + :class:`~cn_api_client.camara.OrgaosClient`, + :class:`~cn_api_client.camara.ProposicoesClient` and + :class:`~cn_api_client.camara.SessoesClient` respectively. This is the + preferred (and only supported) way to get access to those classes and their + methods. + + You can initialize your connection class by: + + camara = cn_api_client.Camara() + + and you'll be ready to use the API on your Python projetct. + """ + + def __init__(self): + + self.deputados = DeputadosClient() + self.orgaos = OrgaosClient() + self.proposicoes = ProposicoesClient() + self.sessoes = SessoesClient() diff --git a/cn_api_client/camara/deputados.py b/cn_api_client/camara/deputados.py new file mode 100644 index 0000000..de79ae9 --- /dev/null +++ b/cn_api_client/camara/deputados.py @@ -0,0 +1,41 @@ +""" +ObterDeputados: Retorna os deputados em exercício na Câmara dos Deputados +ObterDetalhesDeputado: Retorna detalhes dos deputados com histórico de participação em comissões, períodos de exercício, filiações partidárias e lideranças. +ObterLideresBancadas: Retorna os deputados líderes e vice-líderes em exercício das bancadas dos partidos +ObterPartidosCD: Retorna os partidos com representação na Câmara dos Deputados +ObterPartidosBlocoCD: Retorna os blocos parlamentares na Câmara dos Deputados. +""" +class DeputadosClient: + + def obter_deputados(self): + """ + Retorna os deputados em exercício na Câmara dos Deputados + + API ENDPOINT: + `` + + API DOC: + 'http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/deputados/obterdeputados' + + This method does not have input parameters + """ + + print('obter_deputados') + + def obter_detalhes_deputado(self): + + print('obter_detalhes_deputado') + + def obter_lideres_bancadas(self): + + print('lideres_bancadas') + + def obter_partidos(self): + + print('partids') + + def obter_partidos_bloco(self): + + print('bloco') + + diff --git a/cn_api_client/camara/orgaos.py b/cn_api_client/camara/orgaos.py new file mode 100644 index 0000000..6223cb7 --- /dev/null +++ b/cn_api_client/camara/orgaos.py @@ -0,0 +1,48 @@ +"""ListarCargosOrgaosLegislativosCD Retorna a lista dos tipos de cargo para os órgãos legislativos da Câmara dos Deputados (ex: presidente, primeiro-secretário, etc) +ListarTiposOrgaos Retorna a lista dos tipos de órgãos que participam do processo legislativo na Câmara dos Deputados +ObterAndamento Retorna o andamento de uma proposição pelos órgãos internos da Câmara a partir de uma data específica +ObterEmendasSubstitutivoRedacaoFinal Retorna as emendas, substitutivos e redações finais de uma determinada proposição +ObterIntegraComissoesRelator Retorna os dados de relatores e pareces, e o link para a íntegra de uma determinada proposição +ObterMembrosOrgao Retorna os parlamentares membros de uma determinada comissão +ObterOrgaos Retorna a lista de órgãos legislativos da Câmara dos Deputados (comissões, Mesa Diretora, conselhos, etc.) +ObterPauta Retorna as pautas das reuniões de comissões e das sessões plenárias realizadas em um determinado período +ObterRegimeTramitacaoDespacho Retorna os dados do último despacho da proposição""" + + +class OrgaosClient: + + def listar_cargos_orgaos_legislativo(self): + + print('cargos') + + def listar_tipos_orgaos(self): + + print('tipos') + + def obter_andamento(self): + + print('andamento') + + def obter_emendas_substitutivo_redacao_final(self): + + print('emendas') + + def obter_integra_comissoes_relator(self): + + print('integra') + + def obter_membros_orgaos(self): + + print('membros') + + def obter_orgaos(self): + + print('orgaos') + + def obter_pauta(self): + + print('pauta') + + def obter_regime_tramitacao_despacho(self): + + print('tramitacao') \ No newline at end of file diff --git a/cn_api_client/camara/proposicoes.py b/cn_api_client/camara/proposicoes.py new file mode 100644 index 0000000..648a206 --- /dev/null +++ b/cn_api_client/camara/proposicoes.py @@ -0,0 +1,51 @@ +""" +ListarProposicoes Retorna a lista de proposições que satisfaçam os critérios estabelecidos +ListarSiglasTipoProposicao Retorna a lista de siglas de proposições +ListarSituacoesProposicao Retorna a lista de situações para proposições +ListarTiposAutores Retorna a lista de tipos de autores das proposições +ObterProposicao Retorna os dados de uma determinada proposição a partir do tipo, número e ano +ObterProposicaoPorID Retorna os dados de uma determinada proposição a partir do seu ID +ObterVotacaoProposicao Retorna os votos dos deputados a uma determinada proposição em votações ocorridas no Plenário da Câmara dos Deputados +ListarProposicoesVotadasEmPlenario Retorna todas as proposições votadas em plenário num determinado período +listarProposicoesTramitadasNoPeriodo Retorna uma lista de proposições movimentadas em determinado período. +""" + + +class ProposicoesClient: + + def listar_proposicoes(self): + + print('props') + + def listar_siglas_tipo_proposicao(self): + + print('siglas') + + def listar_situacoes_proposicao(self): + + print('situacoes') + + def listar_tipos_autores(self): + + print('tipos') + + def obter_proposicao(self): + + print('proposs') + + #TODO: bind this with obter proposicao + def obter_proposicao_por_ID(self): + + print('por_id') + + def obter_proposicao_votacao(self): + + print('vot') + + def listar_proposicoes_votadas_em_plenario(self): + + print('plen') + + def listar_proposicoes_tramitadas_no_periodo(self): + + print('per') \ No newline at end of file diff --git a/cn_api_client/camara/sessoesreunioes.py b/cn_api_client/camara/sessoesreunioes.py new file mode 100644 index 0000000..409e644 --- /dev/null +++ b/cn_api_client/camara/sessoesreunioes.py @@ -0,0 +1,29 @@ +""" +ListarDiscursosPlenario Retorna a lista dos deputados que proferiam discurso no Plenário da Cãmara dos Deputados em um determinado período. +ListarPresencasDia Retorna a lista de presença de deputados em um determinado dia. +ListarPresencasParlamentar Retorna as presenças de um deputado em um determinado período. +ListarSituacoesReuniaoSessao Retorna a lista de situações para as reuniões de comissão e sessões plenárias da Câmara dos Deputados +ObterInteiroTeorDiscursosPlenario Retorna o inteiro teor do discurso proferido no Plenário. +""" + +class SessoesClient: + + def listar_discursos_plenario(self): + + print('disc') + + def listar_presencas_dia(self): + + print('dia') + + def listar_presencas_parlamentar(self): + + print('prese') + + def listar_situacoes_reuniao_sessao(self): + + print('sessao') + + def obter_inteiro_teor_discursos_plenario(self): + + print('teor') \ No newline at end of file diff --git a/cn_api_client/senado/__init__.py b/cn_api_client/senado/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cn_api_client/senado/senado.py b/cn_api_client/senado/senado.py new file mode 100644 index 0000000..49c9445 --- /dev/null +++ b/cn_api_client/senado/senado.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +This is a set of cn_api_client intended to hook the API from the Brazilian Senate. + + The API documentation can be red at http://legis.senado.leg.br/dadosabertos/docs/ +""" + +import requests + +class SenadoClient: + + def example(self): + + print('oi') diff --git a/cn_api_client/utils.py b/cn_api_client/utils.py new file mode 100644 index 0000000..e69de29 diff --git a/docs/conf.py b/docs/conf.py index 45e1720..8bd99c3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -31,7 +31,7 @@ inspect.getfile(inspect.currentframe()))) output_dir = os.path.join(__location__, "../docs/api") - module_dir = os.path.join(__location__, "../methods") + module_dir = os.path.join(__location__, "../cn_api_client") cmd_line_template = "sphinx-apidoc -f -o {outputdir} {moduledir}" cmd_line = cmd_line_template.format(outputdir=output_dir, moduledir=module_dir) apidoc.main(cmd_line.split(" ")) @@ -61,7 +61,7 @@ master_doc = 'index' # General information about the project. -project = u'methods' +project = u'cn_api_client' copyright = u'2017, joao.carabetta@gmail.com' # The version info for the project you're documenting, acts as replacement for @@ -193,7 +193,7 @@ # html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'methods-doc' +htmlhelp_basename = 'cn_api_client-doc' # -- Options for LaTeX output -------------------------------------------------- @@ -212,7 +212,7 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'user_guide.tex', u'methods Documentation', + ('index', 'user_guide.tex', u'cn_api_client Documentation', u'joao.carabetta@gmail.com', 'manual'), ] diff --git a/methods/skeleton.py b/methods/skeleton.py deleted file mode 100644 index 458490f..0000000 --- a/methods/skeleton.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -""" -This is a skeleton file that can serve as a starting point for a Python -console script. To run this script uncomment the following line in the -entry_points section in setup.cfg: - - console_scripts = - fibonacci = methods.skeleton:run - -Then run `python setup.py install` which will install the command `fibonacci` -inside your current environment. -Besides console scripts, the header (i.e. until _logger...) of this file can -also be used as template for Python modules. - -Note: This skeleton file can be safely removed if not needed! -""" -from __future__ import division, print_function, absolute_import - -import argparse -import sys -import logging - -from methods import __version__ - -__author__ = "joao.carabetta@gmail.com" -__copyright__ = "joao.carabetta@gmail.com" -__license__ = "none" - -_logger = logging.getLogger(__name__) - - -def fib(n): - """Fibonacci example function - - Args: - n (int): integer - - Returns: - int: n-th Fibonacci number - """ - assert n > 0 - a, b = 1, 1 - for i in range(n-1): - a, b = b, a+b - return a - - -def parse_args(args): - """Parse command line parameters - - Args: - args ([str]): command line parameters as list of strings - - Returns: - :obj:`argparse.Namespace`: command line parameters namespace - """ - parser = argparse.ArgumentParser( - description="Just a Fibonnaci demonstration") - parser.add_argument( - '--version', - action='version', - version='methods {ver}'.format(ver=__version__)) - parser.add_argument( - dest="n", - help="n-th Fibonacci number", - type=int, - metavar="INT") - parser.add_argument( - '-v', - '--verbose', - dest="loglevel", - help="set loglevel to INFO", - action='store_const', - const=logging.INFO) - parser.add_argument( - '-vv', - '--very-verbose', - dest="loglevel", - help="set loglevel to DEBUG", - action='store_const', - const=logging.DEBUG) - return parser.parse_args(args) - - -def setup_logging(loglevel): - """Setup basic logging - - Args: - loglevel (int): minimum loglevel for emitting messages - """ - logformat = "[%(asctime)s] %(levelname)s:%(name)s:%(message)s" - logging.basicConfig(level=loglevel, stream=sys.stdout, - format=logformat, datefmt="%Y-%m-%d %H:%M:%S") - - -def main(args): - """Main entry point allowing external calls - - Args: - args ([str]): command line parameter list - """ - args = parse_args(args) - setup_logging(args.loglevel) - _logger.debug("Starting crazy calculations...") - print("The {}-th Fibonacci number is {}".format(args.n, fib(args.n))) - _logger.info("Script ends here") - - -def run(): - """Entry point for console_scripts - """ - main(sys.argv[1:]) - - -if __name__ == "__main__": - run() diff --git a/requirements.txt b/requirements.txt index d9db656..ac277f2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ # Add your requirements here like: -# numpy -# scipy>=0.9 - +requests +xml diff --git a/setup.cfg b/setup.cfg index ef4d760..2d6efa6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [metadata] -name = methods +name = CongressoEmNumeros-get_api summary = Add a short description here! author = joao.carabetta@gmail.com author-email = joao.carabetta@gmail.com diff --git a/setup.py b/setup.py index 38bf9e3..20e46ad 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- """ - Setup file for methods. + Setup file for cn_api_client. This file was generated with PyScaffold 2.5.7, a tool that easily puts up a scaffold for your new Python project. Learn more under: diff --git a/tests/conftest.py b/tests/conftest.py index b40ac08..516d31c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- """ - Dummy conftest.py for methods. + Dummy conftest.py for cn_api_client. If you don't know what this is for, just leave it empty. Read more about conftest.py under: From 17f29c1ec84022525a2c9255346f10171f93f648 Mon Sep 17 00:00:00 2001 From: "joao.carabetta@gmail.com" Date: Sun, 5 Mar 2017 22:01:50 -0300 Subject: [PATCH 2/6] README update --- README.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index beb9496..2154c65 100644 --- a/README.rst +++ b/README.rst @@ -1,17 +1,19 @@ -======= -methods -======= +=============================== +Congresso Em Numeros API Client +=============================== +This is a Python Client for the legislative federal houses of Brazil. -Add a short description here! - +We intend to cover and maintain all the API endpoints from Camara dos Deputados and Senado Federal Description =========== -A longer description of your project goes here... +To use the Camara Client just:: + import cn_api_client as cn + camara = cn.Camara() Note ==== From 0d6188f0b2fde5d02e7127dc4b6226340f6c7ed6 Mon Sep 17 00:00:00 2001 From: "joao.carabetta@gmail.com" Date: Sun, 5 Mar 2017 23:41:37 -0300 Subject: [PATCH 3/6] perform request and build camara urls --- cn_api_client/camara/deputados.py | 30 +++++++++++++++--- cn_api_client/connection.py | 14 +++++++++ cn_api_client/utils.py | 51 +++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 cn_api_client/connection.py diff --git a/cn_api_client/camara/deputados.py b/cn_api_client/camara/deputados.py index de79ae9..deea2ee 100644 --- a/cn_api_client/camara/deputados.py +++ b/cn_api_client/camara/deputados.py @@ -1,11 +1,13 @@ """ -ObterDeputados: Retorna os deputados em exercício na Câmara dos Deputados ObterDetalhesDeputado: Retorna detalhes dos deputados com histórico de participação em comissões, períodos de exercício, filiações partidárias e lideranças. ObterLideresBancadas: Retorna os deputados líderes e vice-líderes em exercício das bancadas dos partidos ObterPartidosCD: Retorna os partidos com representação na Câmara dos Deputados ObterPartidosBlocoCD: Retorna os blocos parlamentares na Câmara dos Deputados. """ -class DeputadosClient: + +from ..connection import Connection +from ..utils import _make_url +class DeputadosClient(Connection): def obter_deputados(self): """ @@ -19,12 +21,30 @@ def obter_deputados(self): This method does not have input parameters """ + return self.perform_request('http://www.camara.leg.br/SitCamaraWS/Deputados.asmx/ObterDeputados') + + def obter_detalhes_deputado(self, ideCadastro=None, numLegislatura=None): + """ + Retorna detalhes dos deputados com histórico de participação em comissões, períodos de exercício, + filiações partidárias e liderancas. - print('obter_deputados') + API ENDPOINT: + http://www.camara.leg.br/SitCamaraWS/Deputados.asmx/ObterDetalhesDeputado?ideCadastro=141428&numLegislatura= - def obter_detalhes_deputado(self): + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/deputados/obterDetalhesDeputado + + Args: + ideCadastro: String(Optinal):: Identificador do deputado obtido na chamada ao ObterDeputados. + numLegislatura: Int(Opcional) Número da legislatura. Campo vazio, todas as legislaturas do Deputado. + """ + base_url = 'http://www.camara.leg.br/SitCamaraWS/Deputados.asmx/ObterDetalhesDeputado?' + params = dict([('ideCadastro', ideCadastro), + ('numLegislatura', numLegislatura)]) - print('obter_detalhes_deputado') + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) def obter_lideres_bancadas(self): diff --git a/cn_api_client/connection.py b/cn_api_client/connection.py new file mode 100644 index 0000000..b02b33d --- /dev/null +++ b/cn_api_client/connection.py @@ -0,0 +1,14 @@ +import requests + +class Connection(): + + def perform_request(self, url): + + try: + req = requests.get(url) + + return req.text + + except Exception as e: + + raise ConnectionError(e) \ No newline at end of file diff --git a/cn_api_client/utils.py b/cn_api_client/utils.py index e69de29..5c533bd 100644 --- a/cn_api_client/utils.py +++ b/cn_api_client/utils.py @@ -0,0 +1,51 @@ +def _make_url(api_house=None, base_url= None, params=None): + """ + It builds the url based on the house webservice and parameters + Args: + api_house: str:: 'camara' or 'senado' + webservice: str:: specify a webservice such as 'deputados', ' + params: dict:: parameters that compose the url + + Returns: str + The API url + """ + + if api_house == None: + raise ReferenceError ('No API House Specified') + + if base_url == None: + raise ReferenceError ('No Base Url Specified') + + elif api_house == 'camara': + + # EndPoints + for i, items in enumerate(params.items()): + key, value = [_treat_inputs(i) for i in items] + + if value == None: + value = '' + + base_url += key + '=' + value + + if len(params) - i > 1: + + base_url += '&' + + print(base_url) + return base_url + +def _treat_inputs(value): + """ + Make sure that inputs are in the right type + + Args: + value: value input + + Returns: + + """ + + if isinstance(value, (int, float)): + value = str(value) + + return value \ No newline at end of file From 87bc0f3f439049a28e395baafa8ce3db16e5bc8d Mon Sep 17 00:00:00 2001 From: "joao.carabetta@gmail.com" Date: Mon, 6 Mar 2017 12:36:31 -0300 Subject: [PATCH 4/6] deputados.py completed, orgaos on going, added _must_contain in utils.py --- cn_api_client/camara/deputados.py | 59 +++++++++++++++++++----- cn_api_client/camara/orgaos.py | 70 +++++++++++++++++++++++++---- cn_api_client/connection.py | 9 ++-- cn_api_client/utils.py | 25 ++++++++++- requirements.txt | 1 - tests/__init__.py | 0 tests/conftest.py | 12 ----- tests/test_camara/__init__.py | 0 tests/test_camara/test_deputados.py | 14 ++++++ tests/test_senado/__init__.py | 0 tests/test_skeleton.py | 17 ------- 11 files changed, 153 insertions(+), 54 deletions(-) create mode 100644 tests/__init__.py delete mode 100644 tests/conftest.py create mode 100644 tests/test_camara/__init__.py create mode 100644 tests/test_camara/test_deputados.py create mode 100644 tests/test_senado/__init__.py delete mode 100644 tests/test_skeleton.py diff --git a/cn_api_client/camara/deputados.py b/cn_api_client/camara/deputados.py index deea2ee..371205a 100644 --- a/cn_api_client/camara/deputados.py +++ b/cn_api_client/camara/deputados.py @@ -1,12 +1,6 @@ -""" -ObterDetalhesDeputado: Retorna detalhes dos deputados com histórico de participação em comissões, períodos de exercício, filiações partidárias e lideranças. -ObterLideresBancadas: Retorna os deputados líderes e vice-líderes em exercício das bancadas dos partidos -ObterPartidosCD: Retorna os partidos com representação na Câmara dos Deputados -ObterPartidosBlocoCD: Retorna os blocos parlamentares na Câmara dos Deputados. -""" - from ..connection import Connection from ..utils import _make_url + class DeputadosClient(Connection): def obter_deputados(self): @@ -21,6 +15,7 @@ def obter_deputados(self): This method does not have input parameters """ + return self.perform_request('http://www.camara.leg.br/SitCamaraWS/Deputados.asmx/ObterDeputados') def obter_detalhes_deputado(self, ideCadastro=None, numLegislatura=None): @@ -46,16 +41,58 @@ def obter_detalhes_deputado(self, ideCadastro=None, numLegislatura=None): base_url=base_url, params=params)) + def obter_lideres_bancadas(self): + """ + Retorna os deputados líderes e vice-líderes em exercício das bancadas dos partidos + + API ENDPOINT: + http://www.camara.leg.br/SitCamaraWS/Deputados.asmx/ObterLideresBancadas + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/deputados/obterlideresbancadas + + This method does not have input parameters + """ + + return self.perform_request('http://www.camara.leg.br/SitCamaraWS/Deputados.asmx/ObterLideresBancadas') - print('lideres_bancadas') def obter_partidos(self): + """ + Retorna os partidos com representação na Câmara dos Deputados - print('partids') + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Deputados.asmx/ObterPartidosCD - def obter_partidos_bloco(self): + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/deputados/obterpartidosCD - print('bloco') + This method does not have input parameters + """ + + return self.perform_request('http://www.camara.gov.br/SitCamaraWS/Deputados.asmx/ObterPartidosCD') + + # This API endpoint is giving 403 ERROR + def obter_partidos_bloco(self, idBloco=None, numLegislatura=None): + """ + Retorna os blocos parlamentares na Câmara dos Deputados. + + API ENDPOINT: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/deputados/obterPartidosBlocoCD + API DOC: + http://www.camara.gov.br/SitCamaraWS/Deputados.asmx/ObterPartidosBlocoCD?numLegislatura=54&idBloco= + Args: + ideCadastro: String(Optinal):: ID do Bloco Parlamentar + numLegislatura: Int(Opcional):: Número da Legislatura. Campo Vazio, legislatura atual. Apenas legislatura 53 em diante. + """ + + base_url = 'http://www.camara.gov.br/SitCamaraWS/Deputados.asmx/ObterPartidosBlocoCD?' + params = dict([('idBloco', idBloco), + ('numLegislatura', numLegislatura)]) + + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) \ No newline at end of file diff --git a/cn_api_client/camara/orgaos.py b/cn_api_client/camara/orgaos.py index 6223cb7..0469524 100644 --- a/cn_api_client/camara/orgaos.py +++ b/cn_api_client/camara/orgaos.py @@ -1,4 +1,4 @@ -"""ListarCargosOrgaosLegislativosCD Retorna a lista dos tipos de cargo para os órgãos legislativos da Câmara dos Deputados (ex: presidente, primeiro-secretário, etc) +""" ListarTiposOrgaos Retorna a lista dos tipos de órgãos que participam do processo legislativo na Câmara dos Deputados ObterAndamento Retorna o andamento de uma proposição pelos órgãos internos da Câmara a partir de uma data específica ObterEmendasSubstitutivoRedacaoFinal Retorna as emendas, substitutivos e redações finais de uma determinada proposição @@ -7,21 +7,75 @@ ObterOrgaos Retorna a lista de órgãos legislativos da Câmara dos Deputados (comissões, Mesa Diretora, conselhos, etc.) ObterPauta Retorna as pautas das reuniões de comissões e das sessões plenárias realizadas em um determinado período ObterRegimeTramitacaoDespacho Retorna os dados do último despacho da proposição""" +from ..connection import Connection +from ..utils import _make_url, _must_contain - -class OrgaosClient: +class OrgaosClient(Connection): def listar_cargos_orgaos_legislativo(self): + """ + Retorna a lista dos tipos de cargo para os órgãos legislativos da Câmara dos Deputados (ex: presidente, primeiro-secretário, etc) - print('cargos') + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ListarCargosOrgaosLegislativosCD - def listar_tipos_orgaos(self): + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/orgaos/listarcargosorgaoslegislativoscd - print('tipos') + This method does not have input parameters + """ - def obter_andamento(self): + return self.perform_request('http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ListarCargosOrgaosLegislativosCD') - print('andamento') + def listar_tipos_orgaos(self): + """ + Retorna a lista dos tipos de órgãos que participam do processo legislativo na Câmara dos Deputados + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ListarTiposOrgaos + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/orgaos/listartiposorgao + + This method does not have input parameters + """ + + return self.perform_request('http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ListarTiposOrgaos') + + def obter_andamento(self, + sigla=None, + numero=None, + ano=None, + dataIni=None, + codOrgao=None): + """ + Retorna o andamento de uma proposição pelos órgãos internos da Câmara a partir de uma data específica + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterAndamento?sigla=PL&numero=3962&ano=2008&dataIni=01/01/2009&codOrgao= + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/orgaos/obterandamento + + Args: + sigla: String(Obrigatorio) :: Sigla do tipo de proposição + numero: Int(Obrigatorio) :: Numero da proposição + ano: Int(Obrigatorio) :: Ano da proposição + dataIni: String(Opcional) :: Data a partir da qual as tramitações do histórico de andamento serão retornadas (dd/mm/aaaa) + codOrgao: String(Opcional) :: ID do órgão numerador da proposição + """ + base_url = 'http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterAndamento?' + params = dict([('sigla', sigla), + ('numero', numero), + ('ano', ano), + ('dataIni', dataIni), + ('codOrgao', codOrgao)]) + + _must_contain(this=params, keys=['ano', 'numero', 'sigla']) + + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) def obter_emendas_substitutivo_redacao_final(self): diff --git a/cn_api_client/connection.py b/cn_api_client/connection.py index b02b33d..7bff914 100644 --- a/cn_api_client/connection.py +++ b/cn_api_client/connection.py @@ -4,11 +4,12 @@ class Connection(): def perform_request(self, url): - try: - req = requests.get(url) + req = requests.get(url) + + if req.status_code == 200: return req.text - except Exception as e: + else: + req.raise_for_status() - raise ConnectionError(e) \ No newline at end of file diff --git a/cn_api_client/utils.py b/cn_api_client/utils.py index 5c533bd..0d81804 100644 --- a/cn_api_client/utils.py +++ b/cn_api_client/utils.py @@ -48,4 +48,27 @@ def _treat_inputs(value): if isinstance(value, (int, float)): value = str(value) - return value \ No newline at end of file + return value + + +def _must_contain(this=None, keys=None): + """ + Check whether the specified values exists on a dict + + Args: + this: dict :: variable names and their values + keys: list :: variable names that must not be None + + Returns: + True if the dict contains the values + Raise error if there are missing values + """ + + result = [{k: v == None} for k, v in this.items() if k in keys] + + for r in result: + if True in r.values(): + raise AttributeError('{} must have a value'.format(list(r.keys())[0])) + + else: + return True \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index ac277f2..554cbe8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ # Add your requirements here like: requests -xml diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index 516d31c..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -""" - Dummy conftest.py for cn_api_client. - - If you don't know what this is for, just leave it empty. - Read more about conftest.py under: - https://pytest.org/latest/plugins.html -""" -from __future__ import print_function, absolute_import, division - -import pytest diff --git a/tests/test_camara/__init__.py b/tests/test_camara/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_camara/test_deputados.py b/tests/test_camara/test_deputados.py new file mode 100644 index 0000000..8e31505 --- /dev/null +++ b/tests/test_camara/test_deputados.py @@ -0,0 +1,14 @@ +import pytest +from unittest import TestCase +from cn_api_client.camara.deputados import DeputadosClient + + +class Tests(TestCase): + + @pytest.fixture(autouse=True) + def deputados(self): + return DeputadosClient() + + def test_obter_deputados(self, deputados): + + self.assertIsInstance(deputados.obter_deputados(), str) \ No newline at end of file diff --git a/tests/test_senado/__init__.py b/tests/test_senado/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_skeleton.py b/tests/test_skeleton.py deleted file mode 100644 index ecf8efb..0000000 --- a/tests/test_skeleton.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import pytest -from methods.skeleton import fib - -__author__ = "joao.carabetta@gmail.com" -__copyright__ = "joao.carabetta@gmail.com" -__license__ = "none" - - -def test_fib(): - assert fib(1) == 1 - assert fib(2) == 1 - assert fib(7) == 13 - with pytest.raises(AssertionError): - fib(-10) From b4dfcc0150d1f7649516341d9b5cb6dd770199ff Mon Sep 17 00:00:00 2001 From: "joao.carabetta@gmail.com" Date: Tue, 7 Mar 2017 11:57:10 -0300 Subject: [PATCH 5/6] Completed Camara API --- cn_api_client/camara/orgaos.py | 167 ++++++++++++-- cn_api_client/camara/proposicoes.py | 275 +++++++++++++++++++++--- cn_api_client/camara/sessoesreunioes.py | 182 ++++++++++++++-- 3 files changed, 559 insertions(+), 65 deletions(-) diff --git a/cn_api_client/camara/orgaos.py b/cn_api_client/camara/orgaos.py index 0469524..56317b5 100644 --- a/cn_api_client/camara/orgaos.py +++ b/cn_api_client/camara/orgaos.py @@ -1,15 +1,7 @@ -""" -ListarTiposOrgaos Retorna a lista dos tipos de órgãos que participam do processo legislativo na Câmara dos Deputados -ObterAndamento Retorna o andamento de uma proposição pelos órgãos internos da Câmara a partir de uma data específica -ObterEmendasSubstitutivoRedacaoFinal Retorna as emendas, substitutivos e redações finais de uma determinada proposição -ObterIntegraComissoesRelator Retorna os dados de relatores e pareces, e o link para a íntegra de uma determinada proposição -ObterMembrosOrgao Retorna os parlamentares membros de uma determinada comissão -ObterOrgaos Retorna a lista de órgãos legislativos da Câmara dos Deputados (comissões, Mesa Diretora, conselhos, etc.) -ObterPauta Retorna as pautas das reuniões de comissões e das sessões plenárias realizadas em um determinado período -ObterRegimeTramitacaoDespacho Retorna os dados do último despacho da proposição""" from ..connection import Connection from ..utils import _make_url, _must_contain + class OrgaosClient(Connection): def listar_cargos_orgaos_legislativo(self): @@ -77,26 +69,161 @@ def obter_andamento(self, base_url=base_url, params=params)) - def obter_emendas_substitutivo_redacao_final(self): + def obter_emendas_substitutivo_redacao_final(self, + tipo=None, + ano=None, + numero=None): + """ + Retorna as emendas, substitutivos e redações finais de uma determinada proposição + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterEmendasSubstitutivoRedacaoFinal?tipo=PL&numero=3962&ano=2008 + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/orgaos/obteremendassubstitutivoredacaofinal + + Args: + tipo: String (Obrigatorio) :: Sigla do tipo de proposição + ano: Int (Obrigatorio) :: Numero da proposição + numero: Int (Obrigatorio) :: Ano da proposição + """ + + base_url = 'http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterEmendasSubstitutivoRedacaoFinal?' + params = dict([('tipo', tipo), + ('numero', numero), + ('ano', ano)]) + + _must_contain(this=params, keys=['ano', 'numero', 'tipo']) + + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) + + def obter_integra_comissoes_relator(self, + tipo=None, + ano=None, + numero=None): + """ + Retorna os dados de relatores e pareces, e o link para a íntegra de uma determinada proposição - print('emendas') + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterIntegraComissoesRelator?tipo=PL&numero=3962&ano=2008 - def obter_integra_comissoes_relator(self): + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/orgaos/obterintegracomissoesrelator - print('integra') + Args: + tipo: String (Obrigatorio) :: Sigla do tipo de proposição + ano: Int (Obrigatorio) :: Numero da proposição + numero: Int (Obrigatorio) :: Ano da proposição + """ + + base_url = 'http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterIntegraComissoesRelator?' + params = dict([('tipo', tipo), + ('numero', numero), + ('ano', ano)]) + + _must_contain(this=params, keys=['ano', 'numero', 'tipo']) + + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) + + + + def obter_membros_orgaos(self, idOrgao=None): + """ + Retorna os parlamentares membros de uma determinada comissão + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterMembrosOrgao?IDOrgao=2004 + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/orgaos/obtermembrosorgao + + Args: + idOrgao: Int (Obrigatorio) + """ - def obter_membros_orgaos(self): + base_url = 'http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterMembrosOrgao?' + params = dict([('idOrgao', idOrgao)]) - print('membros') + _must_contain(this=params, keys=['idOrgao']) + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) def obter_orgaos(self): + """ + Retorna a lista de órgãos legislativos da Câmara dos Deputados (comissões, Mesa Diretora, conselhos, etc.) + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterOrgaos + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/orgaos/obterorgaos + + This method does not have input parameters + """ + + return self.perform_request('http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterOrgaos') + + def obter_pauta(self, + idOrgao=None, + dataIni=None, + dataFim=None): + """ + Retorna as pautas das reuniões de comissões e das sessões plenárias realizadas em um determinado período - print('orgaos') + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterPauta?IDOrgao=2004&datIni=01/01/2012&datFim=30/04/2012 - def obter_pauta(self): + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/orgaos/obterpauta - print('pauta') + Args: + idOrgao: Int(Obrigatorio) ID do órgão (comissão) da Câmara dos Deputados + dataIni: String(Opcional) O métoto retorna a pauta das reuniões que foram realizadas em uma data maior ou igual a datIni + dataFim: String(Opcional) O métoto retorna a pauta das reuniões que foram realizadas em uma data menor ou igual a datFim + """ - def obter_regime_tramitacao_despacho(self): + base_url = 'http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterPauta?' + params = dict([('idOrgao', idOrgao), + ('dataIni', dataIni), + ('dataFim', dataFim)]) - print('tramitacao') \ No newline at end of file + _must_contain(this=params, keys=['idOrgao']) + + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) + + def obter_regime_tramitacao_despacho(self, + tipo=None, + numero=None, + ano=None): + """ + Retorna os dados do último despacho da proposição + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterRegimeTramitacaoDespacho?tipo=PL&numero=8035&ano=2010 + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/orgaos/obterregimetramitacaodespacho + + Args: + tipo: String (Obrigatorio) :: Sigla do tipo de proposição + numero: Int (Obrigatorio) :: Numero da proposição + ano: Int (Obrigatorio) :: Ano da proposição + """ + + base_url = 'http://www.camara.gov.br/SitCamaraWS/Orgaos.asmx/ObterRegimeTramitacaoDespacho?' + params = dict([('tipo', tipo), + ('numero', numero), + ('ano', ano)]) + + _must_contain(this=params, keys=['tipo', 'ano', 'numero']) + + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) \ No newline at end of file diff --git a/cn_api_client/camara/proposicoes.py b/cn_api_client/camara/proposicoes.py index 648a206..a2bfdcf 100644 --- a/cn_api_client/camara/proposicoes.py +++ b/cn_api_client/camara/proposicoes.py @@ -1,51 +1,270 @@ -""" -ListarProposicoes Retorna a lista de proposições que satisfaçam os critérios estabelecidos -ListarSiglasTipoProposicao Retorna a lista de siglas de proposições -ListarSituacoesProposicao Retorna a lista de situações para proposições -ListarTiposAutores Retorna a lista de tipos de autores das proposições -ObterProposicao Retorna os dados de uma determinada proposição a partir do tipo, número e ano -ObterProposicaoPorID Retorna os dados de uma determinada proposição a partir do seu ID -ObterVotacaoProposicao Retorna os votos dos deputados a uma determinada proposição em votações ocorridas no Plenário da Câmara dos Deputados -ListarProposicoesVotadasEmPlenario Retorna todas as proposições votadas em plenário num determinado período -listarProposicoesTramitadasNoPeriodo Retorna uma lista de proposições movimentadas em determinado período. -""" +from ..connection import Connection +from ..utils import _make_url, _must_contain +class ProposicoesClient(Connection): -class ProposicoesClient: + def listar_proposicoes(self, + sigla=None, + ano=None, + numero=None, + datApresentacaoIni=None, + datApresentacaoFim=None, + idTipoAutor=None, + parteNomeAutor=None, + siglaPartidoAutor=None, + siglaUfAutor=None, + generoAutor=None, + codEstado=None, + codOrgaoEstado=None, + emTramitacao=None + ): + """ + Retorna a lista de proposições que satisfaçam os critérios estabelecidos - def listar_proposicoes(self): + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarProposicoes?sigla=PL& + numero=& + ano=2011& + datApresentacaoIni=14/11/2011& + datApresentacaoFim=16/11/2011& + parteNomeAutor=& + idTipoAutor=& + siglaPartidoAutor=& + siglaUFAutor=& + generoAutor=& + codEstado=& + codOrgaoEstado=& + emTramitacao= - print('props') + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/proposicoes-1/listarproposicoes + + Args: + sigla: String(Obrigatorio se ParteNomeAutor não for preenchido) :: Sigla do tipo de proposição + ano: Int(Obrigatorio se ParteNomeAutor não for preenchido) :: Ano da proposição + + numero: Int(Obrigatorio) :: Numero da proposição + datApresentacaoIni: Date(Opcional) :: Menor data desejada para a data de apresentação da proposição. + Formato: DD/MM/AAAA + datApresentacaoFim: Date(Opcional) :: Maior data desejada para a data de apresentação da proposição + Formato: DD/MM/AAAA + idTipoAutor: Int(Optional) :: Identificador do tipo de órgão autor da proposição, + como obtido na chamada ao ListarTiposOrgao + parteNomeAutor: String(Optional) :: Parte do nome do autor(5 ou + caracteres) da proposição. + siglaPartidoAutor: String(Optional) :: Sigla do partido do autor da proposição + siglaUfAutor: String(Optional) :: UF de representação do autor da proposição + generoAutor: String(Optional) :: Gênero do autor
M - Masculino; F - Feminino; + Default - Todos + emTramitacao: int(Opcional) :: Indicador da situação de tramitação da proposição + 1 - Em Tramitação no Congresso; + 2- Tramitação Encerrada no Congresso; + Default - Todas + """ + + base_url = 'http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarProposicoes?' + params = dict([('sigla', sigla), + ('ano', ano), + ('numero', numero), + ('datApresentacaoIni', datApresentacaoIni), + ('datApresentacaoFim', datApresentacaoFim), + ('idTipoAutor', idTipoAutor), + ('parteNomeAutor', parteNomeAutor), + ('siglaPartidoAutor', siglaPartidoAutor), + ('siglaUfAutor', siglaUfAutor), + ('generoAutor', generoAutor), + ('codEstado', codEstado), + ('codOrgaoEstado', codOrgaoEstado), + ('emTramitacao', emTramitacao)]) + + try: + _must_contain(params, ['parteNomeAutor']) + except AttributeError: + _must_contain(params, ['sigla', 'ano']) + + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) def listar_siglas_tipo_proposicao(self): + """ + Retorna a lista de siglas de proposições - print('siglas') + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarSiglasTipoProposicao + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/proposicoes-1/listarsiglastipoproposicao + + This method does not have input parameters + """ + + return self.perform_request('http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarSiglasTipoProposicao') def listar_situacoes_proposicao(self): + """ + Retorna a lista de situações para proposições + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarSituacoesProposicao - print('situacoes') + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/proposicoes-1/listarsituacoesproposicao + + This method does not have input parameters + """ + + return self.perform_request('http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarSituacoesProposicao') def listar_tipos_autores(self): + """ + Retorna a lista de situações para proposições + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarTiposAutores + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/proposicoes-1/listartiposautores + + This method does not have input parameters + """ + + return self.perform_request('http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarTiposAutores') + + def obter_proposicao(self, + tipo=None, + ano=None, + numero=None, + idProp=None): + """ + Retorna os dados de uma determinada proposição + + Grupo I + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ObterProposicao?tipo=PL&numero=3962&ano=2008 + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/proposicoes-1/obterproposicao + + Grupo II + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ObterProposicaoPorID?IdProp=354258 + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/proposicoes-1/obterproposicaoporid + + Args: + Completar ou Grupo I ou Grupo II + + Grupo I + tipo: String (Obrigatorio) :: Sigla do tipo de proposição + ano: Int (Obrigatorio) :: Numero da proposição + numero: Int (Obrigatorio) :: Ano da proposição + + Grupo II + idProp: Int (Obrigatorio) :: ID da proposição desejada + """ + + params = dict([('tipo', tipo), + ('ano', ano), + ('numero', numero), + ('idProp', idProp), + ]) + + try: + _must_contain(params, ['tipo', 'ano', 'numero']) + base_url = 'http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ObterProposicao?' + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) + + except AttributeError: + _must_contain(params, ['idProp']) + base_url = 'http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ObterProposicaoPorID?' + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) + + + + def obter_proposicao_votacao(self, + tipo=None, + ano=None, + numero=None): + """ + Retorna os votos dos deputados a uma determinada proposição em votações ocorridas no Plenário da Câmara dos Deputados + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ObterVotacaoProposicao?tipo=PL&numero=1992&ano=2007 + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/proposicoes-1/obtervotacaoproposicao + + Args: + tipo: String (Obrigatorio) :: Sigla do tipo de proposição + ano: Int (Obrigatorio) :: Numero da proposição + numero: Int (Obrigatorio) :: Ano da proposição + """ + base_url = 'http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarProposicoes?' + params = dict([('tipo', tipo), + ('ano', ano), + ('numero', numero), + ]) + + _must_contain(params, ['tipo', 'ano', 'numero']) + + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) + + def listar_proposicoes_votadas_em_plenario(self, + ano=None, + tipo=None): + """ + Retorna a lista de proposições que sofreram votação em plenário em determinado ano. - print('tipos') + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarProposicoesVotadasEmPlenario?ano=2013&tipo= - def obter_proposicao(self): + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/proposicoes-1/ProposicoesVotadasEmPlenario - print('proposs') + Args: + ano: int(Obrigatorio) :: Ano da proposição + tipo: String(Opcional) :: Tipo de proposição + """ + base_url = 'http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarProposicoesVotadasEmPlenario?' + params = dict([('tipo', tipo), + ('ano', ano), + ]) - #TODO: bind this with obter proposicao - def obter_proposicao_por_ID(self): + _must_contain(params, ['ano']) - print('por_id') + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) - def obter_proposicao_votacao(self): + def listar_proposicoes_tramitadas_no_periodo(self, + dtInicio=None, + dtFim=None): + """ + Retorna lista de proposições que tramitaram em determinado período. O período máximo é de 7 dias - print('vot') + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarProposicoesTramitadasNoPeriodo?dtInicio=20/09/2013&dtFim=21/09/2013 - def listar_proposicoes_votadas_em_plenario(self): + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/proposicoes-1/listarProposicoesTramitadasNoPeriodo - print('plen') + Args: + dtInicio: String (Obrigatorio) :: Data de início + dtFim: String (Obrigatorio) :: Data final + """ + base_url = 'http://www.camara.gov.br/SitCamaraWS/Proposicoes.asmx/ListarProposicoesTramitadasNoPeriodo?' + params = dict([('dtInicio', dtInicio), + ('dtFim', dtFim)]) - def listar_proposicoes_tramitadas_no_periodo(self): + _must_contain(params, ['dtInicio', 'dtFim']) - print('per') \ No newline at end of file + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) \ No newline at end of file diff --git a/cn_api_client/camara/sessoesreunioes.py b/cn_api_client/camara/sessoesreunioes.py index 409e644..261f9f4 100644 --- a/cn_api_client/camara/sessoesreunioes.py +++ b/cn_api_client/camara/sessoesreunioes.py @@ -1,29 +1,177 @@ -""" -ListarDiscursosPlenario Retorna a lista dos deputados que proferiam discurso no Plenário da Cãmara dos Deputados em um determinado período. -ListarPresencasDia Retorna a lista de presença de deputados em um determinado dia. -ListarPresencasParlamentar Retorna as presenças de um deputado em um determinado período. -ListarSituacoesReuniaoSessao Retorna a lista de situações para as reuniões de comissão e sessões plenárias da Câmara dos Deputados -ObterInteiroTeorDiscursosPlenario Retorna o inteiro teor do discurso proferido no Plenário. -""" +from ..connection import Connection +from ..utils import _make_url, _must_contain -class SessoesClient: +class SessoesClient(Connection): - def listar_discursos_plenario(self): + def listar_discursos_plenario(self, + dataIni=None, + data=None, + dataFim=None, + codigoSessao=None, + parteNomeParlamentar=None, + siglaPartido=None, + siglaUF=None): + """ + Retorna a lista dos deputados que proferiam discurso no Plenário da Câmara dos Deputados em um determinado período. - print('disc') - def listar_presencas_dia(self): - print('dia') + API ENDPOINT: + http://www.camara.gov.br/sitcamaraws/SessoesReunioes.asmx/ListarDiscursosPlenario?dataIni=23/11/2012& + dataFim=23/11/2012& + codigoSessao=& + parteNomeParlamentar=& + siglaPartido=& + siglaUF= - def listar_presencas_parlamentar(self): + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/sessoesreunioes-2/listardiscursosplenario - print('prese') + dataIni: Date (Obrigatorio) :: Data início do período desejado (formato: DD/MM/AAAA) + dataFim: Date (Obrigatorio) :: Data de fim do período desejado (formato (DD/MM/AAAA) + codigoSessao: String (Opcional) :: Código da sessão a ser pesquisada + parteNomeParlamentar: String (Opcional) :: Parte do nome do Deputado a ser pesquisada + siglaPartido: String (Opcional) :: Sigla do Partido do Deputado + siglaUF: String (Opcional) :: Sigla da UF do Deputado + """ + base_url = 'http://www.camara.gov.br/sitcamaraws/SessoesReunioes.asmx/ListarDiscursosPlenario?' + params = dict([('dataIni', dataIni), + ('dataFim', dataFim), + ('codigoSessao', codigoSessao), + ('parteNomeParlamentar', parteNomeParlamentar), + ('siglaPartido', siglaPartido), + ('siglaUF', siglaUF)]) + + _must_contain(params, ['dataIni', 'dataFim']) + + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) + + def listar_presencas_dia(self, + data=None, + numMatriculaParlamentar=None, + siglaPartido=None, + siglaUF=None): + """ + Retorna a quantidade de sessões ocorridas no dia especificado e a presença dos parlamentares em cada sessão. + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/sessoesreunioes.asmx/ListarPresencasDia? + data=10/04/2012& + numLegislatura=54& + numMatriculaParlamentar=1& + siglaPartido=& + siglaUF= + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/sessoesreunioes-2/listarpresencasdia + + Args: + data: Date(Obrigatorio) :: Data da Sessão (formato: DD/MM/AAAA) + numMatriculaParlamentar: Int(Opcional) :: Numero da matrícula do Parlamentar obtido pelo método ObterDeputados + siglaPartido: String(Opcional) :: Sigla do Partido + siglaUF: String(Opcional) :: Sigla da UF a ser pesquisada + """ + base_url = 'http://www.camara.gov.br/SitCamaraWS/sessoesreunioes.asmx/ListarPresencasDia?' + params = dict([('data', data), + ('numMatriculaParlamentar', numMatriculaParlamentar), + ('siglaPartido', siglaPartido), + ('siglaUF', siglaUF),]) + + + + _must_contain(params, ['data']) + + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) + + def listar_presencas_parlamentar(self, + dataIni=None, + dataFim=None, + numMatriculaParlamentar=None, + ): + """ + Retorna a quantidade de sessões ocorridas no Plenário em um período especificado e a presença dos parlamentares em cada sessão. + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/sessoesreunioes.asmx/ListarPresencasParlamentar? + dataIni=20/11/2012& + dataFim=23/11/2012& + numMatriculaParlamentar=1 + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/sessoesreunioes-2/listarpresencasparlamentar + + Args: + dataIni Date(Obrigatorio) :: Data inicial + dataFim Date(Obrigatorio) :: Data Final + numMatriculaParlamentar Int(Obrigatorio) :: Numero da matrícula do Parlamentar obtido pelo método ObterDeputados + """ + base_url = 'http://www.camara.gov.br/SitCamaraWS/sessoesreunioes.asmx/ListarPresencasParlamentar?' + params = dict([('dataIni', dataIni), + ('dataFim', dataFim), + ('numMatriculaParlamentar', numMatriculaParlamentar)]) + + + _must_contain(params, ['dataIni', 'dataFim', 'numMatriculaParlamentar']) + + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) def listar_situacoes_reuniao_sessao(self): + """ + Retorna a lista de situações para as reuniões de comissão e sessões plenárias da Câmara dos Deputados + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/SessoesReunioes.asmx/ListarSituacoesReuniaoSessao + + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/sessoesreunioes-2/listarsituacoesreuniaosessao + + This method does not have input parameters + """ + + return self.perform_request('http://www.camara.gov.br/SitCamaraWS/SessoesReunioes.asmx/ListarSituacoesReuniaoSessao') + + + def obter_inteiro_teor_discursos_plenario(self, + codSessao=None, + numOrador=None, + numQuarto=None, + numInsercao=None): + """ + Retorna o inteiro teor de um discurso proferido no Plenário. + + Modo de utilização: primeiro deve-se chamar o método ListarDiscursosPlenario para obtenção dos parâmetros + necessários para a identificação única do discurso desejado. São eles o código da sessão, o número do orador, + e mais 2 parâmetros numéricos, numQuarto e numInsercao. + + API ENDPOINT: + http://www.camara.gov.br/SitCamaraWS/SessoesReunioes.asmx/obterInteiroTeorDiscursosPlenario? + codSessao=022.3.54.O& + numOrador=1& + numQuarto=11& + numInsercao=0 + API DOC: + http://www2.camara.leg.br/transparencia/dados-abertos/dados-abertos-legislativo/webservices/sessoesreunioes-2/obterinteiroteordiscursosplenario - print('sessao') + Args: + codSessao: String (Obrigatorio) :: codigo que identifica uma sessão do Plenário + numOrador: Inteiro (Obrigatorio) :: Identificador do orador na sessão + numQuarto: Inteiro (Obrigatorio) :: Número da fração taquigráfica que identifica o início do discurso + numInsercao: Inteiro (Obrigatorio) :: Número da inserção taquigráfica que identifica o início do discurso + """ + base_url = 'http://www.camara.gov.br/SitCamaraWS/SessoesReunioes.asmx/obterInteiroTeorDiscursosPlenario?' + params = dict([ ('codSessao', codSessao), + ('numOrador', numOrador), + ('numQuarto', numQuarto), + ('numInsercao', numInsercao)]) - def obter_inteiro_teor_discursos_plenario(self): + _must_contain(params, ['codSessao','numOrador','numQuarto','numInsercao']) - print('teor') \ No newline at end of file + return self.perform_request(_make_url(api_house='camara', + base_url=base_url, + params=params)) From 14cfb59e68e8f9877496bbf29a9a6bc046ea6699 Mon Sep 17 00:00:00 2001 From: "joao.carabetta@gmail.com" Date: Wed, 8 Mar 2017 13:30:10 -0300 Subject: [PATCH 6/6] tests added to connection and utils --- cn_api_client/camara/sessoesreunioes.py | 1 - cn_api_client/utils.py | 22 ++++++++---- tests/test_camara/test_deputados.py | 6 ++-- tests/test_connection.py | 14 ++++++++ tests/test_utils.py | 45 +++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 tests/test_connection.py create mode 100644 tests/test_utils.py diff --git a/cn_api_client/camara/sessoesreunioes.py b/cn_api_client/camara/sessoesreunioes.py index 261f9f4..36c703b 100644 --- a/cn_api_client/camara/sessoesreunioes.py +++ b/cn_api_client/camara/sessoesreunioes.py @@ -5,7 +5,6 @@ class SessoesClient(Connection): def listar_discursos_plenario(self, dataIni=None, - data=None, dataFim=None, codigoSessao=None, parteNomeParlamentar=None, diff --git a/cn_api_client/utils.py b/cn_api_client/utils.py index 0d81804..058521a 100644 --- a/cn_api_client/utils.py +++ b/cn_api_client/utils.py @@ -38,13 +38,19 @@ def _treat_inputs(value): """ Make sure that inputs are in the right type - Args: - value: value input + Ints and floats are converted to strings - Returns: + Args: + value: str, int, float + Returns: Ints and floats are converted to strings """ + if not isinstance(value, (int, float, str)): + raise AttributeError('This is a {}.\n' + 'Make sure to insert an int, float or str' + .format(type(value))) + if isinstance(value, (int, float)): value = str(value) @@ -55,6 +61,7 @@ def _must_contain(this=None, keys=None): """ Check whether the specified values exists on a dict + This function presumes that all keys are mapped on this dict Args: this: dict :: variable names and their values keys: list :: variable names that must not be None @@ -64,11 +71,12 @@ def _must_contain(this=None, keys=None): Raise error if there are missing values """ - result = [{k: v == None} for k, v in this.items() if k in keys] + result = {k: v is None for k, v in this.items() if k in keys} + + missing_keys = [k for k, v in result.items() if v is True] - for r in result: - if True in r.values(): - raise AttributeError('{} must have a value'.format(list(r.keys())[0])) + if len(missing_keys) != 0: + raise AttributeError('{} must have a value'.format(','.join(str(p) for p in missing_keys))) else: return True \ No newline at end of file diff --git a/tests/test_camara/test_deputados.py b/tests/test_camara/test_deputados.py index 8e31505..4890a1a 100644 --- a/tests/test_camara/test_deputados.py +++ b/tests/test_camara/test_deputados.py @@ -5,10 +5,12 @@ class Tests(TestCase): - @pytest.fixture(autouse=True) + @pytest.fixture() def deputados(self): return DeputadosClient() - def test_obter_deputados(self, deputados): + def test_obter_deputados(self): + + deputados = DeputadosClient() self.assertIsInstance(deputados.obter_deputados(), str) \ No newline at end of file diff --git a/tests/test_connection.py b/tests/test_connection.py new file mode 100644 index 0000000..dc698cd --- /dev/null +++ b/tests/test_connection.py @@ -0,0 +1,14 @@ +from cn_api_client.connection import Connection +from unittest import TestCase +import pytest + +class Test(TestCase): + + @pytest.fixture(autouse=True) + def connection(self): + return Connection() + + def test_perform_request(self): + connection = Connection() + self.assertIsInstance(connection.perform_request(url='http://www.google.com'), + str) \ No newline at end of file diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..72e033f --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,45 @@ +from cn_api_client.utils import _must_contain, _make_url, _treat_inputs +from unittest import TestCase + +class Test(TestCase): + + def test_must_contain(self): + + this = {'test1': None, 'test2': 2, 'test3': 'no'} + + self.assertTrue(_must_contain(this=this, + keys=[])) + + self.assertTrue(_must_contain(this=this, + keys=['test2'])) + + with self.assertRaises(AttributeError): + _must_contain(this=this, keys=['test1']) + + def test_treat_inpust(self): + + self.assertIsInstance(_treat_inputs(2), str) + + self.assertIsInstance(_treat_inputs(2.3), str) + + self.assertIsInstance(_treat_inputs('str'), str) + + with self.assertRaises(AttributeError): + _treat_inputs(['a']) + _treat_inputs({'as': 3}) + + + def test_make_url(self): + + with self.assertRaises(ReferenceError): + _make_url() + _make_url(api_house='camara') + + base_url = 'http://www.camara.gov.br/sitcamaraws/SessoesReunioes.asmx/ListarDiscursosPlenario?' + params = dict([('dataIni', '23/03/2013'), + ('dataFim', '24/03/2013')]) + + self.assertIsInstance(_make_url(api_house='camara', + base_url=base_url, + params=params), str) +