Skip to content

Valida pub-date "pub" contra hoje e contra collection (#1268) - #1273

Open
Rossi-Luciano wants to merge 2 commits into
scieloorg:masterfrom
Rossi-Luciano:feat/1268-pub-date-future-collection-tolerance
Open

Valida pub-date "pub" contra hoje e contra collection (#1268)#1273
Rossi-Luciano wants to merge 2 commits into
scieloorg:masterfrom
Rossi-Luciano:feat/1268-pub-date-future-collection-tolerance

Conversation

@Rossi-Luciano

Copy link
Copy Markdown
Contributor

O que esse PR faz?

Adiciona duas novas regras de validação em FulltextDatesValidation (packtools/sps/validation/dates.py), especificamente para pub-date[@date-type="pub"]:

  1. validate_pub_date_not_in_futurepub não pode estar no futuro além de uma tolerância em dias (pub_date_future_tolerance_days, default 0).
  2. validate_pub_date_not_too_far_before_collectionpub não pode ser mais de N meses anterior ao ano de pub-date[@date-type="collection"] (pub_date_past_collection_tolerance_months, default 12).

Ambas as tolerâncias são parametrizáveis via article_dates_rules.json (novas chaves pub_date_future_tolerance_days, pub_date_past_collection_tolerance_months, e os respectivos *_error_level, default CRITICAL).

Coleções retrospectivas (pub muito posterior ao collection, mas não no futuro) continuam permitidas — não há checagem que bloqueie esse caso, comportamento coberto por teste de regressão.

Também adiciona as mensagens de advice correspondentes aos catálogos de i18n (pt_BR e es).

Onde a revisão poderia começar?

  • packtools/sps/validation/dates.py — métodos validate_pub_date_not_in_future e validate_pub_date_not_too_far_before_collection, e o registro delas em FulltextDatesValidation.validate().
  • packtools/sps/validation_rules/article_dates_rules.json — novas chaves de configuração.
  • tests/sps/validation/test_dates.py — classe TestPubDateFutureAndCollectionDistanceValidation.

Como este poderia ser testado manualmente?

from lxml import etree
from packtools.sps.validation.xml_validator import get_validation_results

xml = b'''
<article article-type="research-article" xml:lang="pt">
    <front>
        <article-meta>
            <pub-date publication-format="electronic" date-type="pub">
                <day>27</day><month>07</month><year>2029</year>
            </pub-date>
            <pub-date publication-format="electronic" date-type="collection">
                <year>2026</year>
            </pub-date>
        </article-meta>
    </front>
</article>
'''
tree = etree.fromstring(xml)
results = [r for r in get_validation_results(tree, {}) if r.get("group") == "article dates" and r.get("response") != "OK"]
for r in results:
    print(r["response"], r["title"], r["advice"])

Deve incluir CRITICAL - pub-date pub not in future - ... must not be later than <hoje>.

pytest tests/sps/validation/test_dates.py -v cobre os 8 casos descritos na issue (A–E da tabela), incluindo o cenário exato do bug relatado (pub=2029, collection=2026).

Algum cenário de contexto que queira dar?

A issue relata que o artigo 0102-6720-abcd-39-e1948 (PID S0102-67202026000100609) ficou oculto silenciosamente em produção porque pub-date[@date-type="pub"] foi digitado como 2029 em vez de 2026. O OPAC filtra artigos com pub no futuro (mecanismo de "data de estreia" agendada), e nenhuma validação existente sinalizava isso — as validações atuais (schematron legado e year_value/complete_date do módulo novo) ou não checam valor de data, ou usam tolerâncias amplas (quase 1 ano) que não cobrem todos os casos, e nenhuma compara pub com collection.

As tolerâncias exatas (dias no futuro / meses no passado) ficam parametrizáveis e usam os defaults sugeridos no pseudocódigo da própria issue; a issue menciona que os valores exatos ainda serão confirmados com a equipe editorial.

Quais são tickets relevantes?

Closes #1268

Referências

Pseudocódigo e tabela de casos de teste vieram diretamente da issue #1268.

…on (scieloorg#1268)

Adiciona duas novas regras em FulltextDatesValidation: pub-date[date-type="pub"]
não pode estar no futuro além de uma tolerância em dias, e não pode ser mais de
N meses anterior ao ano de pub-date[date-type="collection"]. Ambas as
tolerâncias são parametrizáveis via article_dates_rules.json.

Resolve o gap relatado na issue: um typo no ano de pub (ex. 2029 em vez de
2026) fazia o OPAC ocultar o artigo silenciosamente, sem gerar erro em
nenhuma validação existente.
expected=f'<pub-date date-type="pub"> no later than {limit.isoformat()}',
obtained=pub_date.isoformat(),
advice=f'<pub-date date-type="pub"> ({pub_date.isoformat()}) must not be later than {limit.isoformat()}',
advice_text=i18n._('<pub-date date-type="pub"> ({pub_date}) must not be later than {limit}'),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rossi-Luciano suspeito que isso não funciona:

i18n._('<pub-date date-type="pub"> ({pub_date}) must not be later than {limit}')

teria que ser

i18n._('<pub-date date-type="pub"> ({pub_date}) must not be later than {limit}').format(
    pub_date=pub_date, 
    limit=limit
)

@Rossi-Luciano Rossi-Luciano Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robertatakenaka checando com calma, isso segue o mesmo padrão usado em todo o módulo sps/validation/ (não é específico dessas duas linhas): advice_text=i18n._("...{pub_date}...{limit}") é armazenado como template (sem .format()), e os valores ficam separados em advice_params. O build_response() retorna os dois como adv_text (template traduzido) e adv_params (valores), para o consumidor renderizar com adv_text.format(**adv_params), exatamente como msg_text/msg_params já fazem, documentado em tests/sps/validation/test_i18n_message_rendering.py::render_message.

Testei manualmente as duas mensagens (regra 1 e regra 2) chamando adv_text.format(**adv_params) e ambas renderizam corretamente, sem KeyError:

<pub-date date-type="pub"> (2029-07-27) must not be later than 2026-06-15
<pub-date date-type="pub"> (2024-01-01) must not be more than 12 months before <pub-date date-type="collection"> year (2026)

Se eu aplicasse .format() aqui dentro do dates.py, o adv_text passaria a conter a string já interpolada em inglês, quebrando a tradução dinâmica para outros locales (diferente de todos os outros validators do módulo). Por isso preferi manter como está, mas se você já sabia disso e mesmo assim prefere mudar o padrão aqui, me avisa que ajusto.

Também adicionei em test_dates.py a renderização explícita de adv_text.format(**adv_params) nos casos de erro, para isso ficar coberto automaticamente daqui pra frente.

expected=f'<pub-date date-type="pub"> no earlier than {earliest_allowed.isoformat()} ({tolerance_months} months before collection year {collection_year})',
obtained=pub_date.isoformat(),
advice=f'<pub-date date-type="pub"> ({pub_date.isoformat()}) must not be more than {tolerance_months} months before <pub-date date-type="collection"> year ({collection_year})',
advice_text=i18n._('<pub-date date-type="pub"> ({pub_date}) must not be more than {tolerance_months} months before <pub-date date-type="collection"> year ({collection_year})'),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rossi-Luciano mesmo problema do caso anterior

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robertatakenaka mesma explicação do comentário na linha 592 (padrão advice_text/advice_paramsadv_text/adv_params, formatado pelo consumidor, igual msg_text/msg_params). Também validei essa mensagem especificamente e renderiza corretamente com adv_text.format(**adv_params).

"month_value_error_level":"ERROR",
"pub_date_future_error_level":"CRITICAL",
"pub_date_past_collection_error_level":"CRITICAL",
"pub_date_future_tolerance_days":0,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rossi-Luciano número maior entre 4 a 7 dias

@Rossi-Luciano Rossi-Luciano Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robertatakenaka aplicado: mudei pub_date_future_tolerance_days de 0 para 7 no article_dates_rules.json. De quebra descobri que esse valor também tinha um default hardcoded (dessincronizado, ainda 0) em FulltextDatesValidation._get_default_params() no dates.py, que é o que os testes de fato usam quando instanciam o validator diretamente, então corrigi os dois lugares. Testes atualizados e passando (commit novo no PR).

pub = date(collection_year - 2, 1, 1) # bem além da tolerância de 12 meses
_, distance = self._results(pub, collection_year=collection_year)
self.assertEqual("CRITICAL", distance[0]["response"])
self.assertIn("must not be more than", distance[0]["advice"])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rossi-Luciano alguns lugares está more than e later than...

@Rossi-Luciano Rossi-Luciano Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robertatakenaka boa observação, mas não é acidental: são duas comparações diferentes. "later than {limit}" para a regra 1 (pub comparado a uma data-limite) e "more than {N} months before {collection}" para a regra 2 (pub comparado a uma duração/intervalo). Achei que cada frase fica mais natural para o tipo de comparação que descreve, mas se preferir uma redação única para as duas mensagens (facilita grep/padronização), me diga qual formato prefere que eu unifico.

"'received' está presente no histórico e não deve aparecer em missing_events")


class TestPubDateFutureAndCollectionDistanceValidation(TestCase):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rossi-Luciano tem muitos testes em que é OK. Gostaria de ver mais testes apresentando a mensagem de erro, pois ajuda a visualizar a lógica.

@Rossi-Luciano Rossi-Luciano Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robertatakenaka aplicado: adicionei assertIn/assertEqual sobre advice e sobre o adv_text.format(**adv_params) renderizado nos 3 casos de erro que antes só checavam o response ("CRITICAL"), cobrindo agora as duas regras e o caso de coleção retrospectiva + futuro. Commit novo no PR.

@robertatakenaka robertatakenaka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rossi-Luciano melhore os testes para ficar mais claro se a lógica está correta.

…cieloorg#1268)

Aplica feedback da revisão em PR scieloorg#1273: tolerância de
pub_date_future_tolerance_days alterada de 0 para 7 dias (confirmado
pela equipe editorial), sincronizada tanto no default hardcoded de
FulltextDatesValidation quanto em article_dates_rules.json (estavam
dessincronizados). Adiciona asserções de conteúdo de mensagem de erro
(via adv_text.format(**adv_params)) aos casos de erro que só
verificavam o response level.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Criar validação de valores aceitáveis para pub-date do tipo pub

2 participants