-
Notifications
You must be signed in to change notification settings - Fork 10
implementa BaseDateRange e utilitários de limpeza de XML/HTML #1264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
implementa BaseDateRange e utilitários de limpeza de XML/HTML #1264
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Este PR introduz um novo modelo abstrato para intervalos de data com precisão flexível (padrão SciELO) e adiciona utilitários para limpeza/padronização de texto vindo de XML/HTML, visando facilitar a migração de DateField para CharField mantendo compatibilidade via propriedades ISO.
Changes:
- Adiciona
BaseDateRange(datas como string) e propriedades ISO emBaseHistory(marcado como legado). - Implementa utilitários de limpeza:
remove_html_tags,clean_xml_tag_contente validaçãohas_only_alpha_or_space. - Mantém os utilitários existentes de padronização e amplia o suporte para conteúdo com tags.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| core/utils/standardizer.py | Adiciona helpers para extrair texto de HTML/XML e validar conteúdo alfabético antes de padronizar. |
| core/models.py | Introduz BaseDateRange para datas em string e adiciona propriedades ISO em BaseHistory para transição gradual. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| class BaseDateRange(models.Model): | ||
| # Used to replace BaseHistory, which will be DEPRECATED | ||
| # Uso de datas em formato YYYY-MM-DD, YYYY-MM ou YYYY adotado por SciELO | ||
| initial_date = models.CharField(_("Initial Date"), max_length=10, null=True, blank=True) | ||
| final_date = models.CharField(_("Final Date"), max_length=10, null=True, blank=True) |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BaseDateRange stores dates as free-form CharFields but (per the comment/PR description) the accepted formats are constrained to YYYY, YYYY-MM, or YYYY-MM-DD. Without a validator (e.g., a RegexValidator) or normalization, invalid values can be persisted and later break consumers that assume SciELO-compliant date strings.
| text = text.replace("<", "BREAKTAG<") | ||
| text = text.replace(">", ">BREAKTAG") | ||
| for part in text.split("BREAKTAG"): | ||
| if part.startswith("<") and part.endswith(">"): |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove_html_tags uses the literal sentinel string "BREAKTAG" to split the input. If the source text contains "BREAKTAG" naturally, it will be removed/altered by the split+join, producing incorrect output. Consider replacing this approach with a proper HTML/XML text extractor (e.g., Django's strip_tags or html.parser) or, at minimum, use a collision-safe strategy that cannot appear in user content.
| def remove_html_tags(text): | ||
| if not text: | ||
| return text |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove_html_tags returns text directly for falsy inputs (e.g. None), but yields parts (generator) for non-empty inputs. This inconsistent return type makes the function error-prone for callers. It should consistently return a string (recommended, given the name) or consistently be a generator (and just return early for falsy input).
| """ Verifica se o conteúdo do texto é válido como string, ou seja, | ||
| não é vazio e não contém números. """ |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docstring for has_only_alpha_or_space says the function only rejects empty strings and numbers, but the implementation rejects any token that is not purely alphabetic (e.g., punctuation, hyphens). Please align the docstring with the actual behavior (or adjust the logic if the intent is only to block digits).
| """ Verifica se o conteúdo do texto é válido como string, ou seja, | |
| não é vazio e não contém números. """ | |
| """Verifica se o conteúdo do texto é válido como string: o texto não é | |
| vazio e cada parte separada por espaço contém apenas letras | |
| (caracteres alfabéticos), sem dígitos, pontuação ou outros símbolos.""" |
| def remove_html_tags(text): | ||
| if not text: | ||
| return text | ||
| text = text.replace("<", "BREAKTAG<") | ||
| text = text.replace(">", ">BREAKTAG") | ||
| for part in text.split("BREAKTAG"): | ||
| if part.startswith("<") and part.endswith(">"): | ||
| continue | ||
| if part.startswith("<"): | ||
| continue | ||
| if part.endswith(">"): | ||
| continue | ||
| yield part | ||
|
|
||
|
|
||
| def has_only_alpha_or_space(text): | ||
| """ Verifica se o conteúdo do texto é válido como string, ou seja, | ||
| não é vazio e não contém números. """ | ||
| if not text: | ||
| return False | ||
| parts = text.split() | ||
| for part in parts: | ||
| if not part.isalpha(): | ||
| return False | ||
| return True | ||
|
|
||
|
|
||
| def clean_xml_tag_content(text, assert_string=True): | ||
| if not text: | ||
| return text | ||
| text = "".join(remove_html_tags(text)) | ||
| text_ = remove_extra_spaces(text) | ||
| if assert_string: | ||
| if has_only_alpha_or_space(text_): | ||
| return text_ | ||
| else: | ||
| return None | ||
| return text_ |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New behaviors were added in this module (remove_html_tags, has_only_alpha_or_space, clean_xml_tag_content), but the existing core/tests_standardizer.py only covers the older helpers. Please add unit tests for the new functions (including cases with nested tags, adjacent tags, empty/None inputs, and assert_string=True/False).
Descrição do PR
🟢 O que foi feito?
Models:
Adicionada a classe abstrata
BaseDateRangepara lidar com datas em formato string (YYYY-MM-DD,YYYY-MM), conforme padrão SciELO.Adicionadas propriedades
initial_date_isoformatefinal_date_isoformatna classeBaseHistorypara facilitar a transição.Marcada a classe
BaseHistorycomo legada (deprecated).Utils:
Implementada a função
remove_html_tagspara extrair texto limpo de strings com tags.Implementada a função
clean_xml_tag_contentpara padronização de conteúdos vindos de XML.Adicionada validação
has_only_alpha_or_spacepara garantir integridade de strings alfabéticas.🎯 Motivação
A migração de
DateFieldparaCharFieldno intervalo de datas é necessária para suportar a flexibilidade de precisão (apenas ano ou ano/mês) exigida pelos padrões de indexação, mantendo a compatibilidade com os dados existentes através das propriedades ISO.🧪 Como testar?
BaseDateRangeaceita strings parciais de data.<p>Texto</p>) e valide se o retorno é apenas o conteúdo textual.clean_xml_tag_contentretornaNoneao encontrar números quandoassert_string=True.