feat(pubmed): processamento em lote (.zip) na CLI + registro como comando instalável#1249
Open
Rossi-Luciano wants to merge 8 commits into
Open
feat(pubmed): processamento em lote (.zip) na CLI + registro como comando instalável#1249Rossi-Luciano wants to merge 8 commits into
Rossi-Luciano wants to merge 8 commits into
Conversation
…os elementos pipeline_pubmed() gerava um <Article> solto, sem o envelope <ArticleSet> e DOCTYPE exigidos pela DTD do PubMed. Extrai a construção do <Article> para build_pubmed_article() e adiciona pipeline_pubmed_set() para agrupar múltiplos artigos num único <ArticleSet> (pré-requisito da scieloorg#1241). Validação contra a DTD oficial (lxml.etree.DTD + https://dtd.nlm.nih.gov/ncbi/pubmed/in/PubMed.dtd) expôs 2 bugs no pipeline, corrigidos aqui: Abstract/OtherAbstract precisavam vir antes de CopyrightInformation/CoiStatement/ObjectList/ReferenceList, e VernacularTitle nunca era chamado apesar de implementado e testado. Refs scieloorg#1226, scieloorg#1234
This was referenced Jul 4, 2026
Reconcilia scieloorg#1242 com o envelope ArticleSet desta branch. Journal/PubDate é obrigatório na DTD do PubMed; build_pubmed_article agora levanta MissingRequiredPubDateError quando não encontra data, em vez de gerar um Journal inválido. pipeline_pubmed_set continua estrito (propaga o erro para qualquer artigo inválido do lote). Extrai build_article_set_xml (wrap de <Article>s já construídos em <ArticleSet> + DOCTYPE) de dentro de pipeline_pubmed_set, para uso por chamadores que precisem filtrar artigos inválidos antes de montar o documento final (caso do CLI em lote da scieloorg#1241). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
bf3a067 to
7a91eee
Compare
…el error Per review on scieloorg#1250: the required-element check belongs to the pipe function that builds the element, not bolted on after the fact in build_pubmed_article -- and a missing element reflects incomplete source data, not a transform bug. MissingRequiredPubDateError becomes MissingRequiredElementError(element_path), raised directly inside xml_pubmed_pub_date_pipe, ready to be reused for the other DTD-required Journal children (PublisherName, JournalTitle, Issn) in a follow-up.
7a91eee to
bfdd2dd
Compare
…perdida Encontrados ao validar as 26 amostras reais de tests/samples/ contra a DTD real do PubMed em vez de só 1-2 arquivos escolhidos a dedo. 1. get_date() só olhava article_date (epub), ignorando collection_date (pub-type="epub-ppub"/date-type="collection") -- o padrão mais comum em artigos SciELO mais antigos. Isso descartava 21 de 26 (81%) das amostras reais do lote inteiro por "falta de PubDate", quando na verdade tinham data. references.py e oai_dc.py já fazem esse fallback manualmente; só pubmed.py não fazia. 2. xml_pubmed_citations quebrava com AttributeError quando <ref-list> não tem <title> (opcional no JATS), pois presumia que xml_pubmed_title_reference_list já tinha criado <ReferenceList>. Agora cria o elemento se necessário -- válido pela DTD (ReferenceList (Title?, Reference*, ReferenceList*)). 3. get_first_page só olhava elocation-id, nunca fpage; LastPage não existia. Artigos com paginação tradicional (fpage/lpage) perdiam essa informação por completo. Agora FirstPage prefere fpage e cai para elocation-id só quando não há paginação (fluxo de Publicação Contínua); LastPage foi implementado. Validado: 24/26 amostras reais passam na DTD real (as 2 restantes dependem do fix de Author FirstName/LastName de scieloorg#1236/scieloorg#1245, ainda não mesclado nesta branch -- não são regressão destes fixes).
bfdd2dd to
668d4a5
Compare
…ra a DTD Diferente de test_pubmed.py (uma pipe por vez, XML sintético mínimo), este teste roda o pipeline completo (build_pubmed_article + build_article_set_xml) em cada amostra real de tests/samples/*.xml e valida o resultado contra a DTD real do PubMed. A DTD foi vendorizada em tests/fixtures/pubmed/PubMed.dtd para o teste não depender de rede (CI sem acesso à internet, ou instabilidade do servidor da NLM não devem quebrar a suíte). Essa é exatamente a lacuna que deixou passar despercebidos os 3 bugs corrigidos no commit anterior (PubDate/collection_date, crash em citations, FirstPage/LastPage) por 8 PRs já abertos. Duas amostras (example.xml, 0034-8910-rsp-48-2-0249.xml) ainda dependem de fixes que vivem em scieloorg#1236/PR scieloorg#1245 (Author FirstName/ LastName pairing e fallback `or []` em get_affiliations), ainda não mesclados nesta branch -- marcadas em KNOWN_FAILURES com asserção inversa, para que a suíte avise (ao invés de silenciosamente continuar verde) quando alguém puder remover a entrada.
…ando instalável pubmed_generator.py hoje só processa um XML por vez e nem está registrado como comando instalável (diferente de pdf_generator). - get_xml_trees_and_errors(path) usa packtools.sps.pid_provider.xml_sps_lib.get_xml_items, que já trata .xml e .zip de forma transparente (mesmo componente usado pelo spsvalidator) — retorna a lista de xmltree válidos e os erros por arquivo, sem que um XML corrompido no pacote derrube o lote inteiro. - main() usa pubmed.pipeline_pubmed_set (da scieloorg#1234) para gerar um único <ArticleSet> com um <Article> por XML de entrada, avisos de erro em stderr, exit code 1 só se nenhum artigo foi processado com sucesso. - Registrado pubmed_generator=packtools.sps.formats.pubmed_generator:main em setup.py, no mesmo padrão de pdf_generator. Refs scieloorg#1226, scieloorg#1241
… lote Reconcilia scieloorg#1242 com o CLI de processamento em lote. build_pubmed_article agora levanta MissingRequiredPubDateError (da branch scieloorg#1234) quando um artigo não tem data de publicação; antes isso derrubaria a geração do <ArticleSet> inteiro via pipeline_pubmed_set. main() agora usa build_articles_and_errors, que constrói cada <Article> individualmente e trata essa exceção do mesmo jeito que os erros de parsing já tratados por get_xml_trees_and_errors: aviso em stderr identificando o artigo (por PII/DOI via get_elocation) e segue processando o resto do lote. build_article_set_xml (extraída na scieloorg#1234) monta o <ArticleSet> final só com os artigos que puderam ser gerados. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…mentError Segue o refactor de scieloorg#1250/scieloorg#1234 que generalizou a exceção de required-PubDate. Sem mudança de comportamento.
668d4a5 to
e6f0482
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Nota: esta branch parte de
feat/1234-pubmed-article-set-envelope(PR #1243, ainda não mergeado), porque depende depipeline_pubmed_setpara agrupar múltiplos artigos num únicoArticleSet. O diff inclui os commits do #1243 até ele ser mergeado emmaster.Este PR fecha a última sub-issue da quebra da #1226 — finaliza a solicitação original da issue-mãe.
O que esse PR faz?
A issue #1226 pede: "Utilitário de CLI: [...] aceitando argumentos de entrada (
--input/-i) e saída (--output/-o), além de permitir o processamento em lote." Hojepubmed_generator.pysó processa um XML por vez e nem está registrado como comando instalável (diferente depdf_generator, que já está).get_xml_trees_and_errors(path)(nova, testável isoladamente): usapacktools.sps.pid_provider.xml_sps_lib.get_xml_items, que já trata.xmlou.zipde forma transparente — é o mesmo componente usado pelospsvalidatorpara iterar pacotes SciELO. Retorna a lista dexmltreeválidos e a lista de erros por arquivo, para que um XML corrompido dentro de um.zipnão derrube o lote inteiro.main()reescrito: usapubmed.pipeline_pubmed_set(da Pubmed XML: adicionar envelope ArticleSet/FileHeader + DOCTYPE #1234) para gerar um único<ArticleSet>com um<Article>por XML de entrada (seja de um.xmlsó ou de todos os XMLs de um.zip). Avisos de arquivos com erro vão parastderr;exit code 1só se nenhum artigo foi processado com sucesso.setup.py: registradopubmed_generator=packtools.sps.formats.pubmed_generator:mainementry_points.console_scripts, no mesmo padrão depdf_generator.Onde a revisão poderia começar?
packtools/sps/formats/pubmed_generator.py(reescrito quase por completo) e a entrada nova emsetup.py.Como usar a funcionalidade
Depois de instalado (
pip install -e .neste repo, ou após publicado o pacote), o comando fica disponível direto no terminal:Sem instalar o pacote, funciona do mesmo jeito via
python -m:Se algum XML do
.zipestiver corrompido, o utilitário não para o lote inteiro — processa os válidos e avisa nostderrquais falharam:Como testar localmente (passo a passo)
Ambiente:
Suíte automatizada:
Esperado: 67 passed (suíte combinada de todas as sub-issues da Implementar função e utilitário de CLI para conversão de SciELO XML (SPS 1.10) para PubMed XML #1226 já mergeadas neste branch + as 5 novas em
test_pubmed_generator.py: XML único,.zipcom 2 artigos,.zipcom 1 artigo inválido + 1 válido, e 2 testes end-to-end viamain()).Rodar a CLI manualmente com artigos reais do repositório (não precisa instalar nada, roda com
python -m):Esperado: saída com
<!DOCTYPE ArticleSet ...>+<ArticleSet>contendo 2<Article>.Validar contra a DTD oficial do PubMed (critério de aceitação original da Implementar função e utilitário de CLI para conversão de SciELO XML (SPS 1.10) para PubMed XML #1226: "O XML de saída gerado pela ferramenta deve ser validado com sucesso [...], retornando zero erros de DTD" — o validador web citado na issue-mãe não serve para este formato, ver comentário em Implementar função e utilitário de CLI para conversão de SciELO XML (SPS 1.10) para PubMed XML #1226):
Resultado obtido nesta implementação:
VALID: True, zero erros, tanto para o artigo único quanto para o lote de 2 artigos.Testar resiliência a erro (um XML corrompido dentro do
.zipnão deve derrubar o lote):Esperado:
returncode == 0, 1 artigo processado, 1 erro reportado emstderrsem interromper o restante.Algum cenário de contexto que queira dar?
Esta é a última sub-issue da quebra da #1226. Durante a validação end-to-end deste PR contra a DTD oficial, usando o artigo real
tests/samples/example.xml, encontrei mais um bug (fora do escopo direto da #1241, mas que bloqueava a validação real do lote): um contrib desse artigo tem<given-names>sem<surname>, e a DTD do PubMed exigeFirstName+LastNamesempre juntos emAuthor— gerandoAuthorinválido. Corrigi isso no PR #1245 (#1236), que já foi atualizado e re-testado; a #1246 (#1237) também foi atualizada para incorporar esse fix, já que reaproveita as mesmas funções.Depois dessa correção, validei todos os 7 PRs combinados (#1243, #1244, #1245, #1246, #1247, #1248 e este) localmente — merge temporário de todas as branches, sem alterar nenhuma delas — e o resultado final é: 67 testes passando,
VALID: Truecontra a DTD oficial tanto para artigos individuais quanto para o lote gerado via.zip, cobrindo todas as features implementadas na quebra da #1226 (ArticleSet, JournalTitle correto, Suffix/CollectiveName, GroupList, CopyrightInformation/CoiStatement, Object grant, e agora o processamento em lote).Quais são tickets relevantes?
Closes #1241. Depende de #1243 (#1234). Relacionado a #1226 (issue-mãe, que esta PR finaliza a quebra de sub-issues).
Referências
ArticleSet (Article+)— https://dtd.nlm.nih.gov/ncbi/pubmed/in/PubMed.dtdpacktools.sps.pid_provider.xml_sps_lib.get_xml_items— componente já usado pelospsvalidatorpara processar pacotes.xml/.zip