Documentação do Salic-API

Conteúdo:

SALIC API

Build status Code coverage Documentation Maintainability

API aberta para o sistema SALIC. Tem por objetivo expor os dados de projetos da lei Rouanet. A API está implantada em http://api.salic.cultura.gov.br/doc/ e possui uma documentação para o usuário no formato OpenAPI/Swagger.

O projeto ainda se encontra em fase de homologação, sujeito ainda a muitas alterações, reformulações e atualizacões.

Requisitos

A aplicação foi testada em ambientes LINUX com distribuições Debian, Archlinux e Ubuntu. A implantação é feita utilizando Docker/Docker Compose ou Docker/Rancher. O ambiente de desenvolvimento utiliza uma conexão com um banco de dados local em Sqlite, onde podemos testar a aplicação com dados sintéticos.

A instância principal do Salic-API se conecta no banco de dados MS SQL Server no Ministério da Cultura.

Instalação

Recomendamos que o desenvolvimento seja feito no virtualenv.

Virtualenv

Git clone + virtualenv + pip:

Instale o virtualenvwrapper:

$ sudo apt-get install virtualenvwrapper
$ virtualenvwrapper.sh
$ source `which virtualenvwrapper.sh`
$ mkvirtualenv -p /usr/bin/python3 salic-api
$ workon salic-api

Clone o repositorio:

$ git clone https://github.com/lappis-unb/salic-api

Instale as dependencias:

$ python setup.py develop
$ pip install -e ".[dev]"

Inicialize o banco de desenvolvimento antes de rodar a aplicação:

$ inv db -f
$ inv run

Não esqueça de rodar os testes com frequência:

$ inv test

Docker

Para gerar a build do sistema execute o seguinte comando:

$ docker build -t salic-api .

Para executar o ambiente execute os seguintes comandos:

$ docker run -it --name salic-api -p 5000:5000 -v $PWD:/app salic-api

Para executar os testes com o docker execute o seguinte comando:

$ docker run -it --name salic-api -p 5000:5000 -v $PWD:/app salic-api inv test

Docker Compose

O sistema possui dois docker-compose, um para o ambiente de desenvolvimento e outro para o ambiente de produção, para escolher qual docker compose usar passe o arquivo docker-compose.dev.yml ou docker-compose.prod.yml na flag “-f” no comando docker-compose, como no exemplo a seguir:

$ docker-compose -f docker-compose.dev.yml
ou
$ docker-compose -f docker-compose.prod.yml

Para gerar a build do sistema execute o seguinte comando:

$ docker-compose -f [docker-compose file] build

Para executar o ambiente execute os seguintes comandos:

$ docker-compose -f [docker-compose file] up

Para executar os testes com o docker execute o comando abaixo, esse comando funciona apenas com o docker-compose do ambiente de desenvolvimento, ou seja antes de rodar esse comando certifique-se de ter gerado a build do ambiente de desenvolvimento:

$ docker-compose -f docker-compose.dev.yml run --rm gunicorn inv test

Dependências básicas

  • python-dev
  • python-pip
  • freetds-bin
  • freetds-dev
  • libxml2-dev
  • libxslt1-dev
  • libz-dev
  • unixodbc-dev

Configuração

Edite o arquivo salic-api/app/example_config.py de acordo com seu ambiente. Edite o arquivo salic-api/app/general_config.py apontando o arquivo de configuração a ser usado.

Documentação

A documentação da API é feita de 2 formas:

  • SWAGGER

    • SWAGGER está sendo usado para documentar os endpoints do projeto. Seus arquivos estáticos estão na pasta:

      salic-api/salic_api/static

    • A documentação em produção pode ser acessada através desse link:

      Documentação ENDPOINTS.

  • SPHINX

    • Sphinx está sendo usado para a documentação do projeto como um todo, aproveitando as docstrings no código e também acrescentando informações nos arquivos de documentação que estão na pasta docs/ no formato rst.

    • A documentação em produção pode ser acessada através desse link:

      Documentação API.

    • Para construir a documentação do SPHINX é necessário criar uma pasta que irá conter os arquivos de documentação.

      Crie a pasta build na raiz do projeto.

      mkdir build
      

      Construa a documentação na pasta criada:

      sphinx-autobuild docs build/docs
      

      Para acessar a documentação acesse:

      localhost:8000

Licença

Licensed under the GPL License.

Changelog

0.1.0

Refatoração massiva com relação à versão anterior utilizada no MinC. Primeira versão do LAPPIS.

  • Converteu projeto para o Python 3.
  • Atualizou para a última versão do Flask
  • Conecta em banco de dados Sqlite durante desenvolvimento
  • Refatoração para evitar duplicação de código
  • Adotou esquema de versionamento semver
  • Alterações de código e melhorias de estilo
  • Suite de testes baseada no Pytest
  • Documentação no Sphinx
  • Integração contínua para monitoramento de testes (travis-ci.org), monitoramento de cobertura (codecov.io), métricas de qualidade de código (codeclimate.com) e geração automática de documentação (readthedocs.org)
  • Docker e Docker compose para implantação utilizando NGNIX + GUnicorn
  • Converteu parte das strings de SQL para o ORM do SQL Alchemy

Roadmap

4.0.0

  • Trabalhos no SALIC-data: - Extração de features para uso em ML

3.0.0

  • Trabalhos no SALIC-data: - Estatísticas agregadas - Criar novo banco?

2.0.0

  • Analisar os SQL procedures a fim de reimplementá-los na camada de aplicação
  • Reimplementar todas os comandos SQL em string para o ORM do SQL Alchemy
  • Utilizar integração Flask SQL Alchemy
  • Investigar ecossistema Flask para soluções de criação de API e verificar se nós realmente não estamos reinventado a roda

2.0.0

  • Conecta em banco MS SQL Server
  • Cria testes para comparar a implementação atual com a implantanda no MinC

0.1.1

  • Corrigir bugs após comparar com os resultados da implantação atual
  • Salvar exemplos de teste a partir de dados reais da aplicação
  • Reorganizar aplicação como Flask blueprints

0.1.0

Primeira release do SALIC-API no LAPPIS. Refatoração massiva (ver no changelog).

Documentação da API

Models

Este módulo contém todos os modelos e tabelas do banco do SALIC no modelo do ORM do SQL Alchemy. Apresentamos as tabelas organizadas pelo banco em que aparecem no SALIC.

Agentes

O banco «Agentes» representa pessoas e entidades utilizadas por outras tabelas do SALIC.

class salic_api.models.Agentes(**kwargs)
class salic_api.models.Nomes(**kwargs)
class salic_api.models.Municipios(**kwargs)
class salic_api.models.Internet(**kwargs)
class salic_api.models.Pais(**kwargs)
class salic_api.models.UF(**kwargs)

Base

class salic_api.models.Prorrogacao(**kwargs)

BDCORPORATIVO

O banco «BDCORPORATIVO» representa arquivos relacionados a pagamentos e informações do projeto.

class salic_api.models.Arquivo(**kwargs)
class salic_api.models.ArquivoImagem(**kwargs)
class salic_api.models.ComprovantePagamento(**kwargs)
class salic_api.models.ComprovantePagamentoxPlanilhaAprovacao(**kwargs)
class salic_api.models.Documento(**kwargs)
class salic_api.models.DocumentoProjeto(**kwargs)
class salic_api.models.ItemCusto(**kwargs)

Fake

O banco «fake» foi criado para criar informações em ambiente de desenvolvimento que não são acessíveis.

class salic_api.models.Custos(**kwargs)

Tabela que contem valores como a de proposta, valor solictado, aprovado e outras fontes de subsídio

SAC

O banco «SAC» contém as principais informações das propostas e dos projetos.

class salic_api.models.Projeto(**kwargs)
class salic_api.models.PreProjeto(**kwargs)
class salic_api.models.Segmento(**kwargs)
class salic_api.models.Enquadramento(**kwargs)
class salic_api.models.Mecanismo(**kwargs)
class salic_api.models.Situacao(**kwargs)
class salic_api.models.Area(**kwargs)
class salic_api.models.Interessado(**kwargs)
class salic_api.models.Captacao(**kwargs)
class salic_api.models.CertidoesNegativas(**kwargs)
class salic_api.models.Verificacao(**kwargs)
class salic_api.models.PlanoDivulgacao(**kwargs)
class salic_api.models.Produto(**kwargs)
class salic_api.models.PlanoDistribuicao(**kwargs)
class salic_api.models.PlanilhaAprovacao(**kwargs)
class salic_api.models.PlanilhaItens(**kwargs)
class salic_api.models.Deslocamento(**kwargs)
class salic_api.models.PlanilhaEtapa(**kwargs)
class salic_api.models.PlanilhaUnidade(**kwargs)
class salic_api.models.Readequacao(**kwargs)
class salic_api.models.TipoReadequacao(**kwargs)
class salic_api.models.TipoEncaminhamento(**kwargs)

Tabelas

class salic_api.models.Usuarios(**kwargs)

Tabela que armazena dados do usuário.

Resources

Este módulo que contem as queries de acordo com cada entidade do projeto.

Fornecedor

class salic_api.resources.FornecedorDetail(query_data=None)

Class related with information about an specific Fornecedor

build_query_args()

Return a dictionary with arguments to be passed to the query method of the query class.

Responsable for generate Fornecedores” urls

query_class

pseudónimo de salic_api.resources.fornecedor.query.FornecedorQuery

class salic_api.resources.FornecedorList

Class related with informations about Fornecedores” list of one project

detail_resource_class

pseudónimo de salic_api.resources.fornecedor.fornecedor_detail.FornecedorDetail

prepared_detail_object(item)

Modify list of arguments to pass to a detail resource.

query_class

pseudónimo de salic_api.resources.fornecedor.query.FornecedorQuery

class salic_api.resources.ProdutoDetail(query_data=None)

Responsable for generate Projetos and Fornecedores” urls

class salic_api.resources.Produto
build_query_args()

Return a dictionary with arguments to be passed to the query method of the query class.

detail_resource_class

pseudónimo de ProdutoDetail

query_class

pseudónimo de salic_api.resources.fornecedor.query.ProductQuery

Incentivador

class salic_api.resources.DoacaoList
build_query_args()

Return a dictionary with arguments to be passed to the query method of the query class.

detail_resource_class

pseudónimo de DoacaoDetail

query_class

pseudónimo de salic_api.resources.incentivador.query.DoacaoQuery

class salic_api.resources.DoacaoDetail(query_data=None)

Return the link dictionary that is stored on “_links” field of a JSON+HAL response.

prepare_result(result)

Clean result after insertion of related objects.

The default implementation does nothing, but can be overridden in subclasses.

class salic_api.resources.IncentivadorDetail(query_data=None)
build_query_args()

Return a dictionary with arguments to be passed to the query method of the query class.

Return the link dictionary that is stored on “_links” field of a JSON+HAL response.

prepare_result(result)

Clean result after insertion of related objects.

The default implementation does nothing, but can be overridden in subclasses.

query_class

pseudónimo de salic_api.resources.incentivador.query.IncentivadorQuery

class salic_api.resources.IncentivadorList
detail_resource_class

pseudónimo de salic_api.resources.incentivador.incentivador_detail.IncentivadorDetail

prepared_detail_object(item)

Modify list of arguments to pass to a detail resource.

query_class

pseudónimo de salic_api.resources.incentivador.query.IncentivadorQuery

class salic_api.resources.IncentivadorQuery
class salic_api.resources.DoacaoQuery

Pre Projeto

class salic_api.resources.PreProjetoDetail(query_data=None)

Return the link dictionary that is stored on “_links” field of a JSON+HAL response.

query_class

pseudónimo de salic_api.resources.preprojeto.query.PreProjetoQuery

class salic_api.resources.PreProjetoList
detail_resource_class

pseudónimo de salic_api.resources.preprojeto.pre_projeto_detail.PreProjetoDetail

query_class

pseudónimo de salic_api.resources.preprojeto.query.PreProjetoQuery

class salic_api.resources.PreProjetoQuery

Projeto

class salic_api.resources.Area
detail_resource_class

pseudónimo de AreaDetail

query_class

pseudónimo de salic_api.resources.projeto.query.AreaQuery

class salic_api.resources.Captacao
query_class

pseudónimo de salic_api.resources.projeto.query.CaptacaoQuery

class salic_api.resources.ProjetoDetail(query_data=None)
hal_embedded(data)

Return a dictionary of embedded resources stored at the “_embedded” field of a JSON+HAL response.

Return the link dictionary that is stored on “_links” field of a JSON+HAL response.

Fetch all related and embedded data from other models and add it to the current result.

The default implementation does nothing, but can be overridden in subclasses.

prepare_result(result)

Clean result after insertion of related objects.

The default implementation does nothing, but can be overridden in subclasses.

query_class

pseudónimo de salic_api.resources.projeto.query.ProjetoQuery

class salic_api.resources.ProjetoList
detail_resource_class

pseudónimo de salic_api.resources.projeto.projeto_detail.ProjetoDetail

query_class

pseudónimo de salic_api.resources.projeto.query.ProjetoQuery

class salic_api.resources.Segmento
query_class

pseudónimo de salic_api.resources.projeto.query.SegmentoQuery

Query
class salic_api.resources.ProjetoQuery
class salic_api.resources.CaptacaoQuery

Returns Captacao value of a project

class salic_api.resources.AreaQuery

Returns description and id of Area

class salic_api.resources.SegmentoQuery

Returns description and id of Segmento

class salic_api.resources.CertidoesNegativasQuery

Returns certificate’s name and situation according to it’s id

class salic_api.resources.DivulgacaoQuery

Returns instrument of propagation and its type. Ex: Peça - CARTAZ/POSTER, Veiculo - IMPRESSOS

class salic_api.resources.DeslocamentoQuery

Returns descriptions of places which the project may pass.

class salic_api.resources.DistribuicaoQuery

Returns information of how the project will be distributed. Ex: ticket prices…

class salic_api.resources.ReadequacaoQuery

Proponente

class salic_api.resources.ProponenteDetail(query_data=None)
build_query_args()

Return a dictionary with arguments to be passed to the query method of the query class.

Return the link dictionary that is stored on “_links” field of a JSON+HAL response.

prepare_result(result)

Clean result after insertion of related objects.

The default implementation does nothing, but can be overridden in subclasses.

query_class

pseudónimo de salic_api.resources.proponente.query.ProponenteQuery

class salic_api.resources.ProponenteList
detail_resource_class

pseudónimo de salic_api.resources.proponente.proponente_detail.ProponenteDetail

prepared_detail_object(item)

Modify list of arguments to pass to a detail resource.

query_class

pseudónimo de salic_api.resources.proponente.query.ProponenteQuery

class salic_api.resources.ProponenteQuery

format_utils

format_utils.cgccpf_mask()

Create a CPF mask for valid CPFs.

format_utils.sanitize()

Remove unwanted whitespace from string.

query

class salic_api.resources.Query

Base class for all query objects for the SALIC api.

count(qs)

Return the number of elements on queryset.

execute_query(query, *args, **kwargs)

Execute an SQL query.

fetch(query, binds=None)

Execute the given query and fetches all results.

Args:
query:
An SQL query
binds:
An optional dictionary with binds from variable names to their corresponding values to be inserted into the query.
raw_query(*args, **kwargs)

Create a raw SQLAlchemy query object in the current session.

select_as(*args, **kwargs)

Apply all filters in the given dictionary.

>>> q.select_as(                                     
...     ModelA, {'field_a': value_a, 'field_b': value_b},
...     ModelB, {'field_c': value_c})

If a single model is present, the query can be simpler:

>>> q.select_as(ModelA,                              
...                field_a=value_a,
...                field_b=value_b)

resource

class salic_api.resources.SalicResource(query_data=None)

Base class for List and Detail resources.

apply_hal_data(result)

Insert HAL information on output data.

HAL info usually comprises of a _links and a _embedded fields

build_query_args()

Return a dictionary with arguments to be passed to the query method of the query class.

fetch_result()

Happy path for obtaining a raw representation of the resulting object from the database.

filter_cgccpf(cgccpf, elements)

Given a cgc/cpf/cnpj, makes sure it return only elements with exact match. Used to correct the use of SQL LIKE statement

get(**kwargs)

Default response to a GET request.

Return the link dictionary that is stored on “_links” field of a JSON+HAL response.

query_db()

Return a query with all requested objects

render(data, headers={}, status_code=200, raw=False)

Render response for given data.

Args:
data:
Raw data structure
headers (dict):
A mapping with extra headers for inclusion in the response.
status_code (int):
HTTP Response status code
raw (bool):
If True, do not serialize data to the desired format. Useful for testing.
resolve_content()

Content Type resolution.

url(*args, **kwargs)

Return a normalized URL for a path relative to the current resource.

If path begins with a backslash, treat it as a absolute path relative to the API_ROOT_URL.

class salic_api.resources.ListResource

Base class for all Salic-API end points that return lists.

apply_hal_data(result)

Insert HAL information on output data.

HAL info usually comprises of a _links and a _embedded fields

fetch_result()

Happy path for obtaining a raw representation of the resulting object from the database.

Create pagination links: self, first, last, next.

prepare_item(item)

Clean item inserted in the result list.

prepared_detail_object(item)

Modify list of arguments to pass to a detail resource.

query_db()

Return a pair of (queryset, size) with a possibly truncated queryset of results and the number of elements in the complete queryset.

render(data, headers=None, **kwargs)

Render response for given data.

Args:
data:
Raw data structure
headers (dict):
A mapping with extra headers for inclusion in the response.
status_code (int):
HTTP Response status code
raw (bool):
If True, do not serialize data to the desired format. Useful for testing.
class salic_api.resources.DetailResource(query_data=None)

Base class for all end points that return dictionaries.

apply_hal_data(result)

Insert HAL information on output data.

HAL info usually comprises of a _links and a _embedded fields

fetch_result()

Happy path for obtaining a raw representation of the resulting object from the database.

hal_embedded(data)

Return a dictionary of embedded resources stored at the “_embedded” field of a JSON+HAL response.

Return a dictionary mapping each embedded list with its corresponding dictionary of links.

This method does nothing and should be overridden on subclasses.

Fetch all related and embedded data from other models and add it to the current result.

The default implementation does nothing, but can be overridden in subclasses.

prepare_result(result)

Clean result after insertion of related objects.

The default implementation does nothing, but can be overridden in subclasses.

query_db()

Return a query with all requested objects

class salic_api.resources.InvalidResult(message, status_code=500)

Exception raised for invalid errors

render(resource)

Render error message using the supplied resource renderer.

serialization

serialization.listify_queryset()

Returns a fully serializable list of dictionaries

serialization.serialize(format, **kwargs)

Return a string of serialized data for the given output format.

serialization.convert_atom()

Convert atomic Python data type to JSON compatible value.

serialization.convert_object()

Convert an instance of a queryset to a JSON compatible value.

serialization.to_xml()
serialization.to_json()
serialization.to_csv(columns)

test_resource

class salic_api.resources.TestResource

A simple endpoint that return a welcoming message for testing purposes.

get()

Default response to a GET request.

Fixtures

Módulo que contem exemplos de objetos relacinados as tabelas dos bancos.

fixtures.clear_tables()

Clear all data in tables for the current session.

Works only with the «memory» connector used in tests.

fixtures.populate(*, app=None, driver=None, size=1, factories=None)

Populate database with some examples.

Args:
session:
The current SQL alchemy session object.
app:
Flask application instance.
driver (str):
Driver name used to create a connection
size (int):
Optional size used to generate values from the factory functions
factories:
A list of factory functions. Each factory function is a callable that return a list of objects and might accept an optional size argument.
fixtures.fixture_for_pytest(factories, size=1)

Create a Pytest fixture from a list of factories.

fixtures.examples(size=1)

Populate using the provided factories and remove objects after leaving the with block.

Examples:
>>> with examples([factory1, factory2]) as objs:
...     do_something_with_objects(objs)
... # now the database is clean!

Agentes

fixtures.nomes_example()
fixtures.agentes_example()
fixtures.internet_example()
fixtures.pais_example()
fixtures.uf_example()
fixtures.municipio_example()
fixtures.deslocamento_example()

Base

fixtures.prorrogacao_example()

BDCorporativo

fixtures.tbcomprovantepagamentoxplanilhaaprovacao_example()
fixtures.tbcomprovantepagamento_example()
fixtures.arquivo_imagem_example()
fixtures.documento_example()
fixtures.documento_projeto_example()

Fake

fixtures.custos_example()

SAC

fixtures.areas_example()
fixtures.projeto_example()
fixtures.pre_projeto_example()
fixtures.segmento_example()
fixtures.enquadramento_example()
fixtures.mecanismo_example()
fixtures.situacao_example()
fixtures.interessado_example()
fixtures.captacao_example()
fixtures.certidoes_negativas_example()
fixtures.verificacao_example()
fixtures.plano_divulgacao_example()
fixtures.produto_example()
fixtures.plano_distribuicao_example()

Tabelas

Connector

Este módulo contêm classes e funções responsáveis por estabelecer a conexão com o banco de dados. O SALIC API possui conectores para SQLite (para testes) e para o MS SQL Server. Futuramente, é possível criar conectores para outros bancos como postgres ou MySQL.

class salic_api.connector.SqlConnector(driver=None, app=None)

Represents a connection with the database.

Args:
driver (str):
An optional string describing which database should be used. Valid values are: «sqlite», «memory», «pyodbc» (MS SQL Server), «postgres», «pymssql».
app:
Optional Flask app instance.
salic_api.connector.get_engine(driver=None, app=None)

Return the engine object for the current SQL connector.

Accept the same arguments as salic_api.connector.SqlConnector

salic_api.connector.get_session(driver=None, app=None)

Return a session for the current SQL connector.

Accept the same arguments as salic_api.connector.SqlConnector

salic_api.connector.load_engine(driver, app=None)

Return engine for the given driver and config mapping.

Accept the same arguments as salic_api.connector.SqlConnector

Utils

class salic_api.utils.MLStripper

Strip HTML from strings in Python Has some fixes to the stackoverflow version https://stackoverflow.com/questions/753052/strip-html-from-strings-in-python

salic_api.utils.decrypt(text)

Uses AES to decrypt text with a global secret key.

It extracts the initialization vector from the input message.

salic_api.utils.encrypt(text)

Uses AES to encrypt text with a global secret key.

It saves the initialization vector with the resulting message.

salic_api.utils.pc_quote(st)

Comenta string com sinais de “%”

salic_api.utils.timer(action, verbose=True)

Log results for the time required to execute the given action.

Used as a context manager: >>> with timer(“foo”): … print(“hello world!”)

Flask Application