Uma Nova API Python

Tenho o prazer de compartilhar fluent-discourse, um novo pacote Python para consumir a API do Discourse.

Já existem alguns pacotes para consumir a API do Discourse via Python. Então, por que criar outro?

Os outros pacotes do Discourse disponíveis tendem a abordar o problema de forma semelhante: criar uma função Python exclusiva para cada endpoint da API.

Essa abordagem tem algumas desvantagens:

  1. É muito difícil alcançar paridade total de recursos com a API. A API do Discourse é parcialmente subdocumentada e, muitas vezes, é necessário fazer engenharia reversa dos endpoints. Além disso, existem inúmeros plugins que expõem endpoints de API que nem fazem parte do núcleo. Isso coloca o usuário da biblioteca diante da difícil escolha de abrir pull requests para adicionar os endpoints necessários à biblioteca ou criar uma solução personalizada para os endpoints extras.
  2. Você precisa aprender outra API. Além de aprender os métodos e endpoints da API do Discourse, você precisa descobrir qual é a chamada de função correspondente em Python.
  3. Há muito mais código para testar, tornando mais difícil obter 100% de cobertura de testes. Assim, há menos confiança na qualidade do software produzido.

Em contraste com essa abordagem, utilizei uma interface “fluent”, onde você usa encadeamento de métodos para construir solicitações. Vamos dar um exemplo.
Para obter os tópicos mais recentes em uma categoria ‘foo’ com id=5, use este endpoint:
GET /c/foo/5.json.
Para fazer essa solicitação com esta biblioteca, basta chamar:
client.c.foo[5].json.get()

Você pode ver que há paridade semântica entre o endpoint da API e a chamada correspondente em Python.

Essa abordagem:

  1. Oferece, prontamente, paridade total de recursos com a API do Discourse, incluindo endpoints não documentados, endpoints de plugins e endpoints que ainda serão definidos (à prova de futuro).
  2. Você só precisa aprender a API do Discourse. É fácil traduzir qualquer chamada de API dessa forma, e, portanto, você não precisa procurar a função correspondente.
  3. Toda a biblioteca tem cerca de 150 linhas de código. Isso torna trivial alcançar 100% de cobertura de testes.

Há 100% de cobertura de testes com um punhado de testes de integração contra um servidor Discourse ao vivo.

Se isso lhe parecer atraente, espero que você experimente este pacote!

21 curtidas

Essa é uma abordagem interessante…

Para fazer algo semelhante em PHP, teríamos que depender de métodos mágicos e, assim, perder o benefício da autocompletura do IDE, etc. Mas pode ser um preço que vale a pena pagar.

Qual é a vantagem dessa abordagem em relação a simplesmente passar a URL como argumento: client.get(url)?

Esse é um bom ponto; a conclusão automática do IDE não será de grande ajuda aqui. Pode valer a pena usar uma biblioteca diferente se isso for importante para você.

Como cada cadeia de métodos retorna um novo cliente, uma vantagem que consigo pensar é armazenar uma cadeia de métodos específica em uma variável e reutilizá-la para chamadas subsequentes. Por exemplo, digamos que você tenha uma lista de dados para novas postagens que deseja criar.

post_data = [
  {
    "raw": "Hello World!",
    "topic_id": 123,
    ...
  },
  {
    "raw": "Tester",
    "topic_id": 501,
    ...
  },
  ...
]

Você poderia armazenar a cadeia de métodos “Nova postagem” e reutilizá-la para criar cada uma das postagens na lista.

new_post_endpoint = client.posts.json

for post in post_data:
  new_post_endpoint.post(data=post) 

Você pode imaginar outros cenários em que essa capacidade de reutilizar um cliente seja útil. Além disso, não há uma grande vantagem em relação a simplesmente passar a URL como você sugeriu. Incentivo você a ler sobre a biblioteca Universal Client, que contém algumas informações sobre a lógica por trás desse tipo de abordagem.

Além disso, para uma implementação específica em PHP dessa abordagem, confira a API PHP do SendGrid. Fiquei inspirado a construir isso quando li sobre a API Python do SendGrid.

3 curtidas