Seus dados acadêmicos,
em Python ou no terminal.
Consulte notas, faltas, avaliações e horários. Use os métodos em português ou exporte os registros para trabalhar com eles em uma planilha.
O cliente usa o SUAP do IFRN por padrão. Outras instituições podem ter APIs e permissões diferentes. Este é um projeto independente.
Esta página descreve a 1.4.1. Enquanto ela não estiver no PyPI, instale o código do repositório para usar os novos comandos.
Instalação
Use Python 3.10 ou superior. Em um ambiente virtual:
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade suapy
No Windows, ative com .venv\Scripts\activate. Para conversão em DataFrame, instale python -m pip install "suapy[pandas]". CSV e JSON não precisam de Pandas.
Versão do repositório
git clone https://github.com/kellyson71/suapy.git
cd suapy
python -m pip install -e ".[dev,pandas]"
Pelo terminal
Execute suapy para abrir o menu interativo. Para uma consulta direta, use um dos comandos abaixo. Quando necessário, o terminal solicita matrícula e senha.
suapy periodos
suapy boletim --ano 2026 --periodo 2
suapy turmas --ano 2026 --periodo 2
suapy avaliacoes
suapy mensagens --status nao_lidas
suapy progresso
Escolha ano e período a partir de suapy periodos; os valores do exemplo não garantem que existam registros na sua conta. Use suapy --help ou suapy boletim --help para ver as opções.
| Opção | Uso |
|---|---|
--formato tabela|json|csv | Formato da consulta; o padrão é tabela. |
--saida arquivo | Cria um arquivo JSON ou CSV; não sobrescreve arquivos existentes. |
--sem-sessao | Não acessa o token salvo no computador. |
--url-base URL | Seleciona outra instituição, inclusive uma URL com prefixo como /suap. |
Em Python
Autentique e selecione o período mais recente informado pela API:
from getpass import getpass
from suapy import Suap, SuapError
try:
with Suap(timeout=(5, 30)) as suap:
suap.login(input("Matrícula: "), getpass("Senha: "))
periodos = list(suap.iterar_resultados(
suap.ensino.obter_periodos_letivos()
))
if periodos:
atual = max(periodos, key=lambda p: (
int(p["ano_letivo"]), int(p["periodo_letivo"])
))
boletim = suap.ensino.obter_boletim(
atual["ano_letivo"], atual["periodo_letivo"]
)
for disciplina in suap.iterar_resultados(boletim):
print(disciplina.get("disciplina"),
disciplina.get("numero_faltas"))
except SuapError as erro:
print(f"Consulta indisponível: {erro}")
O bloco with libera conexões HTTP. Se não usá-lo, chame suap.fechar(). A biblioteca mantém credenciais somente em memória.
Exportar dados
As consultas de listagem incluem todas as páginas. Avisos e prompts usam stderr; JSON e CSV usam stdout ou o arquivo escolhido.
suapy boletim --ano 2026 --periodo 2 --formato csv --saida boletim.csv
suapy avaliacoes --formato json > avaliacoes.json
suapy mensagens --status todas --formato json --saida mensagens.json
Arquivos de --saida são criados com acesso restrito em POSIX. Uma redireção com > usa as permissões do shell e pode sobrescrever arquivos.
JSON preserva objetos e listas. No CSV, as colunas reúnem as chaves dos registros, valores aninhados viram JSON e campos ausentes ficam vazios. Textos que poderiam ser interpretados como fórmulas recebem um apóstrofo inicial.
Com Pandas
import pandas as pd
from suapy import para_dataframe
# Com suap autenticado e ano/periodo selecionados:
resposta = suap.ensino.obter_boletim(ano, periodo)
df = para_dataframe(list(suap.iterar_resultados(resposta)))
if "media_final_disciplina" in df.columns:
notas = pd.to_numeric(df["media_final_disciplina"], errors="coerce")
if notas.notna().any():
print(notas.mean())
Essa é uma média simples das notas disponíveis, não necessariamente o índice acadêmico oficial.
Login e sessão
O CLI do IFRN salva um refresh token em ~/.suapy/session.json. A senha não é gravada. O token é uma credencial em texto simples; em POSIX, a pasta usa permissão 700 e o arquivo 600.
suapy --sem-sessao
suapy boletim --ano 2026 --periodo 2 --sem-sessao
suapy --logout
--sem-sessao ignora a sessão existente e não a modifica, mesmo ao sair. --logout remove o arquivo local; não revoga o token no servidor. As duas opções não podem ser combinadas.
Uma --url-base alternativa não lê nem grava a sessão do IFRN. Você autentica naquela instituição durante a execução.
O cliente renova o acesso após um HTTP 401 e repete a chamada uma vez. Falhas de conexão não provocam novas tentativas automáticas.
URLs e paginação
Um prefixo na URL base é preservado nos endpoints do cliente:
suap = Suap(url_base="https://instituicao.example/suap")
# obter_boletim(2026, 2) consulta:
# https://instituicao.example/suap/api/ensino/meu-boletim/2026/2/
Listas e objetos continuam sendo usados como JSON. Páginas com results são dicionários com um atributo interno para a URL de origem; os campos do JSON não são alterados. Assim, um next como ?page=2 é resolvido contra a URL consultada.
Para páginas carregadas de outro lugar, informe a URL de origem se o link seguinte for relativo:
pagina = {"results": [], "next": "?page=2"}
registros = suap.iterar_resultados(
pagina,
url_origem="https://instituicao.example/suap/api/lista/"
)
Links absolutos e relativos à raiz seguem a semântica da URL retornada pelo servidor. Links externos e ciclos são rejeitados. O iterador é incremental, mas cada página é carregada em memória. A exportação do CLI reúne todos os registros antes de escrever.
Métodos da API
Todos os métodos dependem dos endpoints e das permissões da instituição.
| Módulo | Métodos |
|---|---|
ensino | obter_dados_aluno(), obter_periodos_letivos(), obter_boletim(ano, periodo), obter_turmas_virtuais(ano, periodo), obter_turma_virtual(pk), obter_proximas_avaliacoes(), obter_mensagens_aluno(status), obter_requisitos_conclusao(), obter_eventos(), obter_horario_aulas(), obter_diarios(ano=None, periodo=None). |
usuario | obter_meus_dados_resumidos(), obter_meus_dados(), obter_historico_funcional(), obter_contracheques(), obter_contracheque_detalhado(ano, mes). |
infraestrutura | obter_campi(), obter_setores(). |
pesquisa_extensao | obter_projetos_pesquisa(), obter_projetos_extensao(). |
Para notas e faltas de alunos, use boletim. Diários podem exigir perfil de professor. Métodos funcionais podem exigir vínculo de servidor.
Interpretar horários
from suapy import parse_horario
print(parse_horario("2V34 / 4V56"))
O retorno contém dia_semana, dia_num, turno e horarios. O número 2 representa segunda-feira; V representa tarde. Os números 3 e 4 representam tempos de aula, não horas do relógio.
Erros e validação
| Exceção | Quando ocorre |
|---|---|
ValueError | URL base inválida; ano que não tem quatro dígitos; período não positivo; argumentos parciais de diários; status de mensagem desconhecido. |
SuapAuthError | Tokens inválidos ou respostas HTTP 401/403. |
SuapApiError | Outros erros HTTP, JSON inválido ou paginação incompatível. |
SuapError | Classe base e erros de conexão/timeout. |
A validação de ano/período se aplica a boletim, turmas e diários. Aceita inteiros e strings decimais; rejeita booleanos. Não limita o período a dois semestres: consulte os períodos disponíveis na instituição.
No CLI, erro de argumentos retorna código 2, erro de execução retorna 1 e interrupção retorna 130. Consultas concluídas retornam 0.
Testes
Os testes padrão simulam a API e não acessam uma conta:
python -m pip install -e ".[dev,pandas]"
python -m pytest -q
Uma conta real de teste
Em Bash, forneça as credenciais sem gravar a senha no histórico:
read -r -p "Matrícula de teste: " SUAP_TEST_USERNAME
read -r -s -p "Senha de teste: " SUAP_TEST_PASSWORD
export SUAP_TEST_USERNAME SUAP_TEST_PASSWORD
python scripts/test_live.py
unset SUAP_TEST_USERNAME SUAP_TEST_PASSWORD
Para outra instituição, defina também SUAP_TEST_URL. O teste autentica, renova o token e consulta dados do aluno, períodos, boletim, turmas e avaliações. Não imprime respostas nem salva tokens. Uma lista vazia não permite validar os campos dos registros.
Sem credenciais ou sem períodos, o teste retorna 2 (pendente/incompleto). Erros retornam 1. Isso não substitui testes com os diferentes perfis e permissões usados pela instituição.
Publicação e diagnóstico
O publicador deve ser do tipo GitHub no PyPI: proprietário kellyson71, repositório suapy, workflow release.yml, environment pypi.
Para testar somente a autenticação, abra Actions → Publish to PyPI → Run workflow, ou use:
gh workflow run release.yml --ref main
A execução manual troca a identidade do GitHub por uma credencial temporária do PyPI e a descarta. Não constrói, envia ou republica pacotes. Um erro invalid-publisher pede revisão do provedor e dos quatro campos do cadastro.
A publicação real ocorre ao publicar uma release com tag correspondente à versão em pyproject.toml. Ela passa pelos testes e pela validação dos pacotes. Uma versão já publicada não pode ser sobrescrita.
Consulte a documentação do PyPI e o guia de contribuição.