Browse Source

Migra usando repo git para marcos

pull/1916/head
Marcio Mazza 7 years ago
parent
commit
31cd0c83d0
  1. 1
      requirements/migration-requirements.txt
  2. 7
      sapl/legacy/migracao.py
  3. 25
      sapl/legacy/migracao_dados.py
  4. 81
      sapl/legacy/migracao_documentos.py
  5. 8
      sapl/legacy/migracao_usuarios.py

1
requirements/migration-requirements.txt

@ -1,3 +1,4 @@
-r dev-requirements.txt
GitPython
mysqlclient==1.3.12
pyaml

7
sapl/legacy/migracao.py

@ -3,15 +3,16 @@ import tarfile
from django.conf import settings
from sapl.legacy.migracao_dados import migrar_dados
from sapl.legacy.migracao_dados import REPO, gravar_marco, migrar_dados
from sapl.legacy.migracao_documentos import migrar_documentos
from sapl.legacy.migracao_usuarios import migrar_usuarios
def migrar(interativo=False):
migrar_dados(interativo=interativo)
migrar_usuarios()
migrar_documentos()
migrar_usuarios(REPO.working_dir)
migrar_documentos(REPO)
gravar_marco()
def gerar_pacote():

25
sapl/legacy/migracao_dados.py

@ -8,6 +8,7 @@ from itertools import groupby
from operator import xor
from subprocess import PIPE, call
import git
import pkg_resources
import pyaml
import pytz
@ -1256,30 +1257,44 @@ AJUSTE_DEPOIS_SALVAR = {
TIME_FORMAT = '%H:%M:%S'
# permite a gravação de tempos puros pelo pretty-yaml
def time_representer(dumper, data):
return dumper.represent_scalar('!time', data.strftime(TIME_FORMAT))
UnsafePrettyYAMLDumper.add_representer(datetime.time, time_representer)
# permite a leitura de tempos puros pelo pyyaml (no padrão gravado acima)
def time_constructor(loader, node):
value = loader.construct_scalar(node)
return datetime.datetime.strptime(value, TIME_FORMAT).time()
yaml.add_constructor(u'!time', time_constructor)
DIR_MARCO = Path(DIR_DADOS_MIGRACAO, 'marcos', nome_banco_legado)
REPO = git.Repo.init(Path(DIR_DADOS_MIGRACAO, 'repos', nome_banco_legado))
def grava_marco_base():
def gravar_marco():
"""Grava um dump de todos os dados como arquivos yaml no repo de marco
"""
# prepara ou localiza repositorio
dir_dados = Path(REPO.working_dir, 'dados')
# exporta dados como arquivos yaml
user_model = get_user_model()
models = get_models_a_migrar() + [
Composicao, user_model, Group, ContentType]
for model in models:
info('Gravando marco de [{}]'.format(model.__name__))
dir_model = Path(
DIR_MARCO, 'dados', model._meta.app_label, model.__name__)
dir_model = dir_dados.child(model._meta.app_label, model.__name__)
dir_model.mkdir(parents=True)
for data in model.objects.all().values():
nome_arq = Path(dir_model, data['id'])
nome_arq = Path(dir_model, '{}.yaml'.format(data['id']))
with open(nome_arq, 'w') as arq:
pyaml.dump(data, arq)
# salva mudanças
REPO.git.add([dir_dados.name])
if 'master' not in REPO.heads or REPO.index.diff('HEAD'):
# se de fato existe mudança
REPO.index.commit('Grava marco')
REPO.git.execute('git tag marco'.split())

81
sapl/legacy/migracao_documentos.py

@ -1,6 +1,7 @@
import os
import re
from glob import glob
from os.path import join
import yaml
from django.db import transaction
@ -14,7 +15,6 @@ from sapl.parlamentares.models import Parlamentar
from sapl.protocoloadm.models import (DocumentoAcessorioAdministrativo,
DocumentoAdministrativo)
from sapl.sessao.models import SessaoPlenaria
from sapl.settings import MEDIA_ROOT
# MIGRAÇÃO DE DOCUMENTOS ###################################################
@ -34,25 +34,41 @@ DOCS = {
DocumentoAcessorioAdministrativo: [('arquivo', 'administrativo/{}')],
}
DOCS = {model: [(campo, os.path.join('sapl_documentos', origem))
DOCS = {model: [(campo, join('sapl_documentos', origem))
for campo, origem, in campos]
for model, campos in DOCS.items()}
def em_media(caminho):
return os.path.join(MEDIA_ROOT, caminho)
def mover_documento(origem, destino):
origem, destino = [em_media(c) if not os.path.isabs(c) else c
def mover_documento(repo, origem, destino):
origem, destino = [join(repo.working_dir, c) if not os.path.isabs(c) else c
for c in (origem, destino)]
os.makedirs(os.path.dirname(destino), exist_ok=True)
os.rename(origem, destino)
repo.git.mv(origem, destino)
# conserta link do git annex (antes do commit)
# em geral é o mais seguro a fazer,
# mas foi especificamente necessário pois o conteúdo das imagens
# é acessado antes do commit pelo cropping de imagem
repo.git.execute('git annex fix'.split() + [destino])
def migrar_propriedades_da_casa():
def migrar_logotipo(repo, casa, propriedades):
print('.... Migrando logotipo da casa ....')
[(campo, origem)] = DOCS[CasaLegislativa]
# a extensão do logo pode ter sido ajustada pelo tipo real do arquivo
nome_nas_propriedades = os.path.splitext(propriedades['id_logo'])[0]
arquivos = glob(join(repo.working_dir, origem.format(nome_nas_propriedades)))
if arquivos:
assert len(arquivos) == 1, 'Há mais de um logotipo para a casa'
[logo] = arquivos
destino = join(CasaLegislativa._meta.get_field(campo).upload_to,
os.path.basename(logo))
mover_documento(repo, logo, destino)
casa.logotipo = destino
def migrar_propriedades_da_casa(repo):
print('#### Migrando propriedades da casa ####')
caminho = em_media('sapl_documentos/propriedades.yaml')
caminho = join(repo.working_dir, 'sapl_documentos/propriedades.yaml')
with open(caminho, 'r') as arquivo:
propriedades = yaml.safe_load(arquivo)
casa = CasaLegislativa.objects.first()
@ -72,31 +88,24 @@ def migrar_propriedades_da_casa():
for campo, prop in campos_para_propriedades:
setattr(casa, campo, propriedades[prop])
# Localidade
# localidade
sql_localidade = '''
select nom_localidade, sgl_uf from localidade
where cod_localidade = {}'''.format(propriedades['cod_localidade'])
[(casa.municipio, casa.uf)] = exec_legado(sql_localidade)
print('.... Migrando logotipo da casa ....')
[(campo, origem)] = DOCS[CasaLegislativa]
# a extensão do logo pode ter sido ajustada pelo tipo real do arquivo
id_logo = os.path.splitext(propriedades['id_logo'])[0]
[origem] = glob(em_media(origem.format(id_logo)))
destino = os.path.join(
CasaLegislativa._meta.get_field(campo).upload_to,
os.path.basename(origem))
mover_documento(origem, destino)
casa.logotipo = destino
# logotipo
migrar_logotipo(repo, casa, propriedades)
casa.save()
os.remove(caminho)
repo.git.rm(caminho)
def migrar_docs_por_ids(model):
def migrar_docs_por_ids(repo, model):
for campo, base_origem in DOCS[model]:
print('#### Migrando {} de {} ####'.format(campo, model.__name__))
dir_origem, nome_origem = os.path.split(em_media(base_origem))
dir_origem, nome_origem = os.path.split(join(repo.working_dir, base_origem))
nome_origem = nome_origem.format('(\d+)')
pat = re.compile('^{}\.\w+$'.format(nome_origem))
if not os.path.isdir(dir_origem):
@ -106,7 +115,7 @@ def migrar_docs_por_ids(model):
matches = [pat.match(arq) for arq in os.listdir(dir_origem)]
ids_origens = [(int(m.group(1)),
os.path.join(dir_origem, m.group(0)))
join(dir_origem, m.group(0)))
for m in matches if m]
objetos = {obj.id: obj for obj in model.objects.all()}
upload_to = model._meta.get_field(campo).upload_to
@ -117,7 +126,7 @@ def migrar_docs_por_ids(model):
obj = objetos.get(id)
if obj:
destino = upload_to(obj, os.path.basename(origem))
mover_documento(origem, destino)
mover_documento(repo, origem, destino)
setattr(obj, campo, destino)
obj.save()
else:
@ -125,16 +134,15 @@ def migrar_docs_por_ids(model):
print(msg.format(model.__name__, id, origem))
def migrar_documentos():
# aqui supomos que uma pasta chamada sapl_documentos está em MEDIA_ROOT
# com o conteúdo da pasta de mesmo nome do zope
# Os arquivos da pasta serão MOVIDOS para a nova estrutura!
# A pasta, após conferência do que não foi migrado, deve ser apagada.
def migrar_documentos(repo):
# aqui supomos que uma pasta chamada sapl_documentos está em
# <repo.working_dir> com o conteúdo exportado do zope
# Os arquivos da pasta serão (git) MOVIDOS para a nova estrutura!
#
# Isto significa que para rodar novamente esta função é preciso
# restaurar a pasta sapl_documentos ao estado inicial
migrar_propriedades_da_casa()
migrar_propriedades_da_casa(repo)
for model in [
Parlamentar,
@ -146,10 +154,11 @@ def migrar_documentos():
DocumentoAdministrativo,
DocumentoAcessorioAdministrativo,
]:
migrar_docs_por_ids(model)
migrar_docs_por_ids(repo, model)
sobrando = [os.path.join(dir, file)
for (dir, _, files) in os.walk(em_media('sapl_documentos'))
sobrando = [join(dir, file)
for (dir, _, files) in os.walk(join(repo.working_dir,
'sapl_documentos'))
for file in files]
if sobrando:
print('\n#### Encerrado ####\n\n'

8
sapl/legacy/migracao_usuarios.py

@ -1,8 +1,8 @@
import yaml
from django.contrib.auth.models import Group, User
from unipath import Path
from sapl.hashers import zope_encoded_password_to_django
from sapl.settings import MEDIA_ROOT
PERFIL_LEGADO_PARA_NOVO = {legado: Group.objects.get(name=novo)
for legado, novo in [
@ -44,9 +44,9 @@ def decode_nome(nome):
return nome
def migrar_usuarios():
def migrar_usuarios(dir_repo):
"""
o arquivo media/usuarios.yaml e importa os usuários nele listados,
o arquivo <dir_repo>/usuarios.yaml e importa os usuários nele listados,
com senhas e perfis.
Os usuários são criados se necessário e seus perfis ajustados.
@ -68,7 +68,7 @@ def migrar_usuarios():
Também podemos assumir que essa é uma tarefa de um administrador
"""
ARQUIVO_USUARIOS = MEDIA_ROOT.child('usuarios.yaml')
ARQUIVO_USUARIOS = Path(dir_repo).child('usuarios.yaml')
with open(ARQUIVO_USUARIOS, 'r') as f:
usuarios = yaml.load(f)
# conferimos de que só há um nome de usuário

Loading…
Cancel
Save