fix: parametriza número de colunas do corpo (era 2 fixo em vários lugares) - #1298
fix: parametriza número de colunas do corpo (era 2 fixo em vários lugares)#1298Rossi-Luciano wants to merge 1 commit into
Conversation
…ares) Várias funções de layout dividiam a largura disponível por 2 direto no código, assumindo que o corpo do artigo sempre tem duas colunas: _compute_single_column_width e a conta duplicada dentro de decide_figure_layout (figure.py), _compute_table_width (table.py), e _setup_two_column_body_section/_add_two_column_section (pipeline/docx.py, essa última usada pra restaurar o layout depois de uma tabela/figura de largura total). Generaliza todas pra usar page_attributes['default_column_count'] (novo campo em PAGE_ATTRIBUTES, default 2 - preserva o comportamento atual). Com N colunas, a largura de uma coluna passa a ser (content_width - (N-1)*spacing) / N, que se reduz exatamente à fórmula antiga quando N=2, e correspode à largura total quando N=1 (não precisa de caso especial: com 1 coluna já não existe "largura de coluna vs largura total" pra decidir). De caminho, corrige decide_figure_layout pra chamar _compute_single_column_width em vez de duplicar a mesma conta - as duas podiam divergir se só uma fosse atualizada. Validado ponta a ponta: com default_column_count=2 (padrão), a saída pros 4 fixtures reais (a1-a4) é idêntica à do master sem essa mudança (mesma contagem de página). Com default_column_count=1 forçado (ainda sem exposição via CLI/config - isso fica pra próxima etapa), gerando a3.xml, o corpo e as tabelas passam a ocupar a largura inteira da página corretamente, em vez de ficar espremidos em metade dela. Refs scieloorg#1278.
| def _body_column_count(): | ||
| """Number of columns configured for the body, from PAGE_ATTRIBUTES.""" | ||
| return max(1, pdf_enum.PAGE_ATTRIBUTES.get('default_column_count', 2)) |
| section = docx_renderer.section.get_or_create_second_section(docx) | ||
| docx_renderer.section.setup_section_columns(section, 2, pdf_enum.TWO_COLUMNS_SPACING) | ||
| column_count = _body_column_count() | ||
| spacing = pdf_enum.TWO_COLUMNS_SPACING if column_count > 1 else 0 |
There was a problem hiding this comment.
E se o número de colunas for 3, usaria o espaço entre colunas adequado para 2?
Isso é apenas uma nota. Nada que bloqueie o PR, até porque não lembro de ter visto paper com 3 colunas. Caso haja um pdf_enum.N_COLUMNS_SPACING ou algo mais dinâmico, melhor.
| @@ -521,13 +528,15 @@ | |||
|
|
|||
|
|
|||
| def _add_two_column_section(docx): | |||
There was a problem hiding this comment.
Agora esta função não adiciona necessariamente uma seção de duas colunas; ela restaura a quantidade configurada para o corpo. Podemos renomeá-la para algo como _restore_body_column_section?
Pelo mesmo motivo, _setup_two_column_body_section poderia se chamar _setup_body_section.
| self.assertEqual(table_width, expected) | ||
| self.assertEqual(layout, pdf_enum.DOUBLE_COLUMN_PAGE_LABEL) | ||
|
|
||
| def test_one_column_equals_full_content_width(self): |
There was a problem hiding this comment.
Estes testes comprovam os casos de uma coluna e a compatibilidade com as duas colunas anteriores, mas a implementação e a mensagem do commit afirmam suporte genérico a N colunas. Podemos acrescentar um caso com três colunas, validando explicitamente:
expected = (
content_width - 2 * spacing_cm
) / 3| def _render_tables(docx, tables): | ||
| """Render tables, switching to single column when required by layout.""" | ||
| for table in tables: | ||
| if table.get('layout') == pdf_enum.SINGLE_COLUMN_PAGE_LABEL: |
There was a problem hiding this comment.
Quando default_column_count == 1, um elemento de largura total já está no mesmo espaço disponível do corpo. Mesmo assim, este fluxo adiciona uma seção contínua antes do elemento e outra depois dele. O mesmo ocorre em _render_figures.
No fixture A3 com uma coluna, o resultado visual ficou correto, mas o documento continuou acumulando essas seções redundantes. Como as seções também afetam cabeçalhos, rodapés e numeração - algo que apareceu no PR #1296 -, poderíamos evitar a troca quando o corpo já tiver uma coluna?
Algo como considerar a troca necessária somente quando layout == SINGLE_COLUMN_PAGE_LABEL e _body_column_count() > 1, por exemplo.
pitangainnovare
left a comment
There was a problem hiding this comment.
A parametrização está funcionando corretamente para 1, 2 e 3 colunas, e os testes atuais estão passando. Antes da aprovação, peço dois ajustes:
- Quando
default_column_count == 1, tabelas e figuras de largura total ainda criam duas seções contínuas desnecessárias. Como essas seções afetam também cabeçalhos, rodapés e numeração, sugiro evitar a troca quando o corpo já tiver uma coluna. - Como a implementação declara suporte genérico a
Ncolunas, incluir um teste com três colunas para a largura de figuras, tabelas e restauração da seção. Os casos atuais com 1 e 2 colunas não protegem completamente o termo(column_count - 1). - Como melhoria de clareza, também sugiro renomear
_setup_two_column_body_sectione_add_two_column_section, pois agora essas funções configuram/restauram a quantidade de colunas definida no perfil, não necessariamente duas.
Nota de integração: ao resolver o conflito com o PR #1296 em PAGE_ATTRIBUTES, devem ser preservados tanto start_type=CONTINUOUS quanto default_column_count=2.
O que esse PR faz?
Problema existente: o número de colunas do corpo está fixo em
2em vários pontos do código (_setup_two_column_body_section,_add_two_column_section), e as contas de largura de figura/tabela (_compute_single_column_width,_compute_table_width) sempre dividem o espaço disponível por2, sem ler nenhuma configuração. Não existe hoje forma de gerar um PDF com corpo em 1 coluna — e mesmo que existisse, essas contas dariam resultado errado (metade da largura real). Gap já registrado na issue #1278.Solução proposta: generalizar as quatro funções pra usar
page_attributes['default_column_count'](novo campo, default2— preserva o comportamento atual). Com N colunas, a largura de uma coluna passa a ser(largura_disponível - (N-1)*espaçamento) / N, que se reduz exatamente à fórmula antiga quando N=2, e corresponde à largura total quando N=1 (sem precisar de caso especial). De caminho, corrigidodecide_figure_layoutpra chamar_compute_single_column_widthem vez de duplicar a mesma conta (as duas podiam divergir se só uma fosse atualizada).Resultado: com a configuração padrão (
default_column_count: 2), a saída é idêntica à atual — validado nos 4 fixtures reais, mesma contagem de página. Comdefault_column_count: 1, corpo e tabelas passam a ocupar a largura inteira da página corretamente, em vez de ficarem espremidos em metade dela (imagem anexada).Onde a revisão poderia começar?
packtools/sps/formats/pdf/renderer/docx/figure.py::_compute_single_column_widthepacktools/sps/formats/pdf/pipeline/docx.py::_body_column_count.Como este poderia ser testado manualmente?
Com a configuração padrão, nenhuma mudança visível:
Pra ver o efeito da nova opção (ainda não exposta via CLI — fica pra uma etapa seguinte de configuração de layout), definir
default_column_count=1diretamente via API Python antes de chamarpipeline_docx.Testes automatizados:
python -m unittest discover -s tests/sps/formats/pdf -v.Algum cenário de contexto que queira dar?
Encontrado durante um levantamento mais amplo de qualidade do gerador de PDF, ao investigar se seria possível oferecer layout de 1 coluna como opção de configuração (issue #1278). O gap já estava documentado na própria issue, mas nunca tinha sido corrigido.
Screenshots
Quais são os tickets relevantes?
Refs #1278. Closes #1297.
Referências
N/A
Segurança da informação (NSI.04)
Este PR manipula dados sensíveis ou pessoais (LGPD)?
Este PR altera autenticação, autorização, controle de acesso ou gerenciamento de sessão?
Este PR introduz, atualiza ou remove dependências de terceiros?
Este PR foi validado pelo pipeline de segurança (SonarQube / Trivy)?
SECURITY_ADHERENCE.md. Os gates automáticos reais deste repositório (Snyk e GitGuardian) rodam via CI neste PR.Este PR concatena, monta ou executa comandos SQL, HTML ou JavaScript a partir de entrada externa?
Este PR expõe novos endpoints, telas ou serviços?
Algum segredo, senha, chave ou token está sendo adicionado ao código-fonte?