Descrição
Vários builders em packtools/sps/formats/sps_xml/ (disp_formula.py, fig.py, ref.py, permissions.py, table_wrap.py) criam elementos namespaced (mml:math, xlink:href, etc.) usando notação Clark ("{http://www.w3.org/1998/Math/MathML}math") sem informar nsmap ao criar o Element/SubElement.
Já packtools/sps/formats/sps_xml/article.py (build_article) chama ET.register_namespace("xlink", ...) e ET.register_namespace("mml", ...), o que altera o mapa global de namespaces do lxml para todo o processo Python.
Como resultado, o prefixo serializado para essas namespaces (mml/xlink vs. ns0/ns1) passa a depender de qual código rodou primeiro no processo, e não é determinístico/local a cada chamada.
Como reproduzir
Os testes passam isoladamente, mas falham quando test_article.py roda antes na mesma sessão pytest:
.venv/bin/python -m pytest tests/sps/formats/sps_xml -q
Falhas:
test_disp_formula.py (5 testes)
test_fig.py::TestBuildFigXlink::test_build_fig_xlink
test_permissions.py (7 testes)
test_ref.py::TestBuildRefExtLink (2 testes)
test_table_wrap.py::TestBuildTableAlternatives::test_build_table_wrap_alternatives
Exemplo de diff (test_build_disp_formula_id):
- <...><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" id="m1">...
+ <...><ns0:math xmlns:ns0="http://www.w3.org/1998/Math/MathML" id="m1">...
Rodando cada arquivo de teste isoladamente, todos passam — confirmando que o problema é de estado global compartilhado, não de lógica local.
Impacto
Além de quebrar a suíte de testes dependendo da ordem de execução, isso é uma fragilidade real em uso de produção: uma aplicação (ex.: serviço web) que use packtools.sps.formats para gerar múltiplos formatos no mesmo processo Python pode obter saídas XML com prefixos de namespace inconsistentes (ns0 em vez de mml/xlink) dependendo da ordem em que as funções são chamadas. Embora ns0:math e mml:math sejam semanticamente equivalentes (mesma URI), consumidores que validem/parseiem a saída de forma sensível ao prefixo podem falhar.
Sugestão de correção
- Evitar
ET.register_namespace() (efeito colateral global) em build_article, OU
- Especificar explicitamente
nsmap={"mml": "...", "xlink": "..."} ao criar cada Element/SubElement namespaced nos builders de sps_xml/ (disp_formula.py, fig.py, ref.py, permissions.py, table_wrap.py), garantindo prefixos determinísticos independentemente do estado global/ordem de chamadas.
Contexto
Identificado durante revisão/execução da suíte tests/sps/formats.
Descrição
Vários builders em
packtools/sps/formats/sps_xml/(disp_formula.py,fig.py,ref.py,permissions.py,table_wrap.py) criam elementos namespaced (mml:math,xlink:href, etc.) usando notação Clark ("{http://www.w3.org/1998/Math/MathML}math") sem informarnsmapao criar oElement/SubElement.Já
packtools/sps/formats/sps_xml/article.py(build_article) chamaET.register_namespace("xlink", ...)eET.register_namespace("mml", ...), o que altera o mapa global de namespaces do lxml para todo o processo Python.Como resultado, o prefixo serializado para essas namespaces (
mml/xlinkvs.ns0/ns1) passa a depender de qual código rodou primeiro no processo, e não é determinístico/local a cada chamada.Como reproduzir
Os testes passam isoladamente, mas falham quando
test_article.pyroda antes na mesma sessão pytest:Falhas:
test_disp_formula.py(5 testes)test_fig.py::TestBuildFigXlink::test_build_fig_xlinktest_permissions.py(7 testes)test_ref.py::TestBuildRefExtLink(2 testes)test_table_wrap.py::TestBuildTableAlternatives::test_build_table_wrap_alternativesExemplo de diff (
test_build_disp_formula_id):Rodando cada arquivo de teste isoladamente, todos passam — confirmando que o problema é de estado global compartilhado, não de lógica local.
Impacto
Além de quebrar a suíte de testes dependendo da ordem de execução, isso é uma fragilidade real em uso de produção: uma aplicação (ex.: serviço web) que use
packtools.sps.formatspara gerar múltiplos formatos no mesmo processo Python pode obter saídas XML com prefixos de namespace inconsistentes (ns0em vez demml/xlink) dependendo da ordem em que as funções são chamadas. Emborans0:mathemml:mathsejam semanticamente equivalentes (mesma URI), consumidores que validem/parseiem a saída de forma sensível ao prefixo podem falhar.Sugestão de correção
ET.register_namespace()(efeito colateral global) embuild_article, OUnsmap={"mml": "...", "xlink": "..."}ao criar cadaElement/SubElementnamespaced nos builders desps_xml/(disp_formula.py,fig.py,ref.py,permissions.py,table_wrap.py), garantindo prefixos determinísticos independentemente do estado global/ordem de chamadas.Contexto
Identificado durante revisão/execução da suíte
tests/sps/formats.