You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adicionar o app Django docx_parser ao repositório scielo-tools.
O núcleo de extração DOCX (parser.py, omml2mml.xsl) será implementado como pacote Python dentro do app, consumível por manuscrito e sps, mas sem acoplamento directo ao Wagtail (get_image_model() no parser) e com persistência própria. O objetivo desta issue é uma aplicação Django auto-suficiente e reutilizável:
Banco de dados próprio com migrations em docx_parser/migrations/ (layouts DOCX, jobs de parsing, imagens extraídas, configuração).
Telas Wagtail próprias para gerir layouts, testar extração e consultar histórico de jobs.
APIs REST (DRF) para parsing síncrono/assíncrono e consulta de layouts — consumíveis por manuscrito, integrações editoriais ou outros projetos.
Sem dependência do app manuscrito, rotulagem, sps, ia ou referencia.
Contrato Python estável (DocxParser, serviços de extração) para uso interno pelos demais apps.
Âmbito:
Módulo
Responsabilidade
docx_parser/parser.py
Classe DocxParser: extração de parágrafos, listas, tabelas, fórmulas OMML→MathML, imagens, detecção de secções e front matter
docx_parser/omml2mml.xsl
Transformação XSLT de fórmulas Office Math para MathML
Ordem recomendada na fragmentação:docx_parser → rotulagem → sps → manuscrito.
Decisões de design para reusabilidade
Imagens extraídas desacopladas do Wagtail:
DocxParser.extract_content não deve criar registos wagtail.images.Image directamente.
Introduzir modelo DocxExtractedImage (FileField, checksum, nome original) como armazenamento padrão.
Expor setting DOCX_PARSER_IMAGE_BACKEND (docx_parser | wagtail) e/ou callback image_store(blob, name) -> id injetável em extract_content, para projetos que já usam Wagtail media.
Layouts DOCX versionados em base de dados:
sps/utils.generate_pdf_for_xml_document referencia docx_parser/layouts/two_cols.docx no filesystem.
Modelo DocxLayout com FileField, slug (two_cols), is_default; seed migration ou fixture com two_cols.docx.
Modelo DocxParseJob: ficheiro de entrada, estado (pending, running, done, failed), resultado JSON (sections, content), erro, timestamps, utilizador opcional.
Permite Wagtail (histórico) e API (polling) sem depender de manuscrito.
Configuração editorial:
Modelo DocxParserConfig (singleton ou por tenant): merge_front default, marcadores de secção (introdução, abstract, etc.), regras extensíveis via JSON.
Wagtail snippet para editar sem deploy.
Metadados de auditoria próprios:
Classe abstrata DocxParserMetadataModel + DocxParserAdminModelForm em docx_parser/forms.py — sem core.models ou core.forms.
Subtarefas
Criar app docx_parser/ na raiz do projeto com parser.py e omml2mml.xsl.
Refactorizar parser.py: remover import directo de wagtail.images.get_image_model; usar services.store_extracted_image ou callback injectável.
Implementar modelos DocxLayout, DocxExtractedImage, DocxParseJob, DocxParserConfig com migrations próprias.
Evolução biblioteca → app: o plano de fragmentação (docs/plans/2026-06-28-fragmentar-manuscrito.md) descrevia docx_parser como biblioteca sem DB; esta issue eleva o pacote a app Django com persistência e API, alinhada ao pedido de auto-suficiência e reuso.
Consumidores downstream:rotulagem segmenta a saída de extract_content em front/body/back; manuscrito orquestra parser + rotulagem + xref; sps consome o caminho do layouttwo_cols.docx. Manter contrato de saída {sections, content} estável.
Fórmulas:omml2mml.xsl deve ser empacotado como package-data do app (docx_parser/omml2mml.xsl ao lado de parser.py).
Layout two_cols.docx: necessário para geração PDF via sps — incluir fixture ou gerar documento mínimo de duas colunas para testes.
RCT vs código: o RCT menciona docx_layouts; nesta issue o nome do app permanece docx_parser (singular), alinhado às issues sps / rotulagem.
Performance: parsing de DOCX grandes pode exceder timeout HTTP — usar DocxParseJob + Celery na API para ficheiros acima de limiar configurável.
Plano de fragmentação:docx_parser é pré-requisito de rotulagem, sps e manuscrito — ver docs/plans/2026-06-28-fragmentar-manuscrito.md.
Descrição da tarefa
Adicionar o app Django
docx_parserao repositórioscielo-tools.O núcleo de extração DOCX (
parser.py,omml2mml.xsl) será implementado como pacote Python dentro do app, consumível pormanuscritoesps, mas sem acoplamento directo ao Wagtail (get_image_model()no parser) e com persistência própria. O objetivo desta issue é uma aplicação Django auto-suficiente e reutilizável:docx_parser/migrations/(layouts DOCX, jobs de parsing, imagens extraídas, configuração).manuscrito, integrações editoriais ou outros projetos.manuscrito,rotulagem,sps,iaoureferencia.DocxParser, serviços de extração) para uso interno pelos demais apps.Âmbito:
docx_parser/parser.pyDocxParser: extração de parágrafos, listas, tabelas, fórmulas OMML→MathML, imagens, detecção de secções e front matterdocx_parser/omml2mml.xsldocx_parser/models.pyDocxLayout,DocxParseJob,DocxExtractedImage,DocxParserConfigdocx_parser/services.pydocx_parser/tasks.pydocx_parser/wagtail_hooks.pydocx_parser/api/v1/docx_parser/forms.pydocx_parser/apps.pyDocxParserConfig)Fora do âmbito desta issue:
manuscrito,rotulagemousps(são consumidores futuros).rotulagem/labeling) — recebe a saída bruta deextract_content.sps).Pré-requisitos (blockers)
python-docx==1.1.2docx_parser/parser.pylxml==4.9.4parser.py, XSLTdjangorestframeworkdocx_parser/api/docx_parser/tasks.pywagtail_hooks.py, storage opcional de imagensOrdem recomendada na fragmentação:
docx_parser→rotulagem→sps→manuscrito.Decisões de design para reusabilidade
Imagens extraídas desacopladas do Wagtail:
DocxParser.extract_contentnão deve criar registoswagtail.images.Imagedirectamente.DocxExtractedImage(FileField, checksum, nome original) como armazenamento padrão.DOCX_PARSER_IMAGE_BACKEND(docx_parser|wagtail) e/ou callbackimage_store(blob, name) -> idinjetável emextract_content, para projetos que já usam Wagtail media.Layouts DOCX versionados em base de dados:
sps/utils.generate_pdf_for_xml_documentreferenciadocx_parser/layouts/two_cols.docxno filesystem.DocxLayoutcomFileField,slug(two_cols),is_default; seed migration ou fixture comtwo_cols.docx.get_default_layout_path()resolve layout activo (DB → fallback filesystem emdocx_parser/layouts/).Jobs de parsing auditáveis:
DocxParseJob: ficheiro de entrada, estado (pending,running,done,failed), resultado JSON (sections,content), erro, timestamps, utilizador opcional.manuscrito.Configuração editorial:
DocxParserConfig(singleton ou por tenant):merge_frontdefault, marcadores de secção (introdução,abstract, etc.), regras extensíveis via JSON.Metadados de auditoria próprios:
DocxParserMetadataModel+DocxParserAdminModelFormemdocx_parser/forms.py— semcore.modelsoucore.forms.Subtarefas
docx_parser/na raiz do projeto comparser.pyeomml2mml.xsl.parser.py: remover import directo dewagtail.images.get_image_model; usarservices.store_extracted_imageou callback injectável.DocxLayout,DocxExtractedImage,DocxParseJob,DocxParserConfigcom migrations próprias.docx_parser/services.py(parse_docx_file,parse_docx_document,get_layout_path).two_cols.docxemdocx_parser/layouts/e registo inicial emDocxLayout.docx_parser/tasks.pycomtask_parse_docx(job_id).docx_parser/wagtail_hooks.py: grupo "DOCX Parser" com snippets para layouts, config e listagem de jobs.docx_parser/api/v1/serializers.pyeviews.pycom viewsets/endpoints documentados abaixo."docx_parser"emLOCAL_APPS(config/settings/base.py).DOCX_PARSER_IMAGE_BACKEND, paths default de layouts.requirements/base.txt:python-docx==1.1.2,lxml==4.9.4.config/urls.pyou router DRF global.docx_parser/tests/(extração de parágrafo, tabela, fórmula, imagem mock, API upload, resolução de layout).API pública a preservar / expor
Serviços Python (
docx_parser.parser/docx_parser.services)DocxParser.open_docx(filename)python-docx.DocumentDocxParser().extract_content(doc, doc_path, merge_front=True, image_store=None)text,table,list,image,formula,first_block, …)parse_docx_file(path, **options) -> dictDocxParseJobget_default_layout_path() -> strspsna geração PDF)get_layout_path(slug="two_cols") -> strFormato de saída de
extract_content(contrato estável)Endpoints REST
POST/api/v1/docx_parser/parse/{sections, content}POST/api/v1/docx_parser/jobs/{id, status}GET/api/v1/docx_parser/jobs/{id}/GET/api/v1/docx_parser/layouts/GET/api/v1/docx_parser/layouts/{slug}/GET/api/v1/docx_parser/config/Autenticação:
IsAuthenticatedpara escrita e jobs; leitura de layouts pode serIsAuthenticatedouIsAdminUserconforme política do projeto.Wagtail
Critérios de aceite
python manage.py checksem erros comdocx_parseremLOCAL_APPS.manuscrito,rotulagem,sps,ia,referenciaoucoredentro dedocx_parser/.docx_parser_*criadas via migrations (DocxLayout,DocxParseJob,DocxExtractedImage,DocxParserConfig).DocxParser().extract_contentfunciona sem Wagtail quandoDOCX_PARSER_IMAGE_BACKEND=docx_parser.two_colsdisponível via modelo ou filesystem;get_default_layout_path()não levantaFileNotFoundError.POST /api/v1/docx_parser/parse/com DOCX de exemplo devolve JSON comsectionsecontent.docx_parser/tests/passam no CI.Como testar manualmente
make build && make up && make django_migrate.two_colse config default.DocxExtractedImage(ou Wagtail, se backend configurado).Considerações e notas
docs/plans/2026-06-28-fragmentar-manuscrito.md) descreviadocx_parsercomo biblioteca sem DB; esta issue eleva o pacote a app Django com persistência e API, alinhada ao pedido de auto-suficiência e reuso.rotulagemsegmenta a saída deextract_contentem front/body/back;manuscritoorquestra parser + rotulagem + xref;spsconsome o caminho do layouttwo_cols.docx. Manter contrato de saída{sections, content}estável.omml2mml.xsldeve ser empacotado comopackage-datado app (docx_parser/omml2mml.xslao lado deparser.py).two_cols.docx: necessário para geração PDF viasps— incluir fixture ou gerar documento mínimo de duas colunas para testes.docx_layouts; nesta issue o nome do app permanecedocx_parser(singular), alinhado às issuessps/rotulagem.DocxParseJob+ Celery na API para ficheiros acima de limiar configurável.docx_parseré pré-requisito derotulagem,spsemanuscrito— verdocs/plans/2026-06-28-fragmentar-manuscrito.md.Referências