Browse Source

Merge branch 'ajustes_migracao' into 3.1.x

pull/1914/head
Marcio Mazza 7 years ago
parent
commit
d5dc43caf9
  1. 1
      requirements/migration-requirements.txt
  2. 3
      sapl/hashers.py
  3. 6
      sapl/legacy/migracao.py
  4. 96
      sapl/legacy/migracao_dados.py
  5. 134
      sapl/legacy/migracao_documentos.py
  6. 2
      sapl/legacy/models.py
  7. 4
      sapl/legacy/router.py
  8. 159
      sapl/legacy/scripts/exporta_zope/exporta_zope.py
  9. 5
      sapl/legacy/scripts/exporta_zope/requirements.txt
  10. 5
      sapl/legacy/scripts/migra_um_db.sh
  11. 5
      sapl/legacy/scripts/recria_um_db_postgres.sh
  12. 2
      sapl/legacy_migration_settings.py
  13. 20
      sapl/materia/migrations/0028_auto_20180418_1629.py
  14. 2
      sapl/materia/models.py

1
requirements/migration-requirements.txt

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

3
sapl/hashers.py

@ -46,11 +46,12 @@ ZOPE_SHA1_PREFIX = '{SSHA}'
def zope_encoded_password_to_django(encoded):
"Migra um hash de senha do zope para uso com o ZopeSHA1PasswordHasher"
if encoded.startswith(ZOPE_SHA1_PREFIX):
if encoded and encoded.startswith(ZOPE_SHA1_PREFIX):
data = encoded[len(ZOPE_SHA1_PREFIX):]
salt = get_salt_from_zope_sha1(data)
hasher = ZopeSHA1PasswordHasher()
return super(ZopeSHA1PasswordHasher, hasher).encode(data, salt)
else:
# assume it's a plain password and use the default hashing
# a None password blocks login, forcing a password reset
return make_password(encoded)

6
sapl/legacy/migracao.py

@ -14,12 +14,6 @@ def migrar(interativo=False):
migrar_documentos()
# fonte: https://stackoverflow.com/a/17081026/1877490
def make_tarfile(output_filename, source_dir):
with tarfile.open(output_filename, "w:gz") as tar:
tar.add(source_dir, arcname=os.path.basename(source_dir))
def gerar_pacote():
banco = settings.DATABASES['legacy']['NAME']

96
sapl/legacy/migracao_dados.py

@ -1,3 +1,4 @@
import datetime
import re
import traceback
from collections import OrderedDict, defaultdict, namedtuple
@ -8,6 +9,7 @@ from operator import xor
from subprocess import PIPE, call
import pkg_resources
import pyaml
import pytz
import reversion
import yaml
@ -18,6 +20,7 @@ from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from django.db import connections, transaction
from django.db.models import Max, Q
from pyaml import UnsafePrettyYAMLDumper
from unipath import Path
from sapl.base.models import AppConfig as AppConf
@ -143,6 +146,15 @@ CAMPOS_VIRTUAIS_PROPOSICAO = {
for campo_virtual in CAMPOS_VIRTUAIS_PROPOSICAO.values():
campos_novos_para_antigos[campo_virtual] = 'cod_mat_ou_doc'
CAMPOS_VIRTUAIS_TIPO_PROPOSICAO = {
'M': CampoVirtual(TipoProposicao, TipoMateriaLegislativa),
'D': CampoVirtual(TipoProposicao, TipoDocumento)
}
for campo_virtual in CAMPOS_VIRTUAIS_TIPO_PROPOSICAO.values():
campos_novos_para_antigos[campo_virtual] = 'tip_mat_ou_doc'
# campos virtuais de Autor para funcionar com get_fk_related
CAMPOS_VIRTUAIS_AUTOR = {related: CampoVirtual(Autor, related)
for related in (Parlamentar, Comissao, Partido)}
@ -201,7 +213,7 @@ class ForeignKeyFaltando(ObjectDoesNotExist):
campo = campos_novos_para_antigos[self.field]
_, tabela, campos_pk = get_estrutura_legado(self.field.model)
pk = {c: getattr(self.old, c) for c in campos_pk}
sql = 'select * from {} where {}'.format(
sql = 'select * from {} where {};'.format(
tabela,
' and '.join(['{} = {}'.format(k, v) for k, v in pk.items()]))
return OrderedDict((('campo', campo),
@ -494,6 +506,8 @@ PROPAGACOES_DE_EXCLUSAO = [
('parlamentar', 'dependente', 'cod_parlamentar'),
('parlamentar', 'filiacao', 'cod_parlamentar'),
('parlamentar', 'mandato', 'cod_parlamentar'),
('parlamentar', 'composicao_mesa', 'cod_parlamentar'),
('parlamentar', 'composicao_comissao', 'cod_parlamentar'),
# comissao
('comissao', 'composicao_comissao', 'cod_comissao'),
@ -518,6 +532,11 @@ PROPAGACOES_DE_EXCLUSAO = [
('materia_legislativa', 'anexada', 'cod_materia_principal'),
('materia_legislativa', 'anexada', 'cod_materia_anexada'),
('materia_legislativa', 'documento_acessorio', 'cod_materia'),
('materia_legislativa', 'numeracao', 'cod_materia'),
# norma
('norma_juridica', 'vinculo_norma_juridica', 'cod_norma_referente'),
('norma_juridica', 'vinculo_norma_juridica', 'cod_norma_referida'),
# documento administrativo
('documento_administrativo', 'tramitacao_administrativo', 'cod_documento'),
@ -548,6 +567,9 @@ def uniformiza_banco():
garante_coluna_no_legado('tipo_materia_legislativa',
'quorum_minimo_votacao int(11) NULL')
garante_coluna_no_legado('materia_legislativa',
'txt_resultado TEXT NULL')
# Cria campos cod_presenca_sessao (sendo a nova PK da tabela)
# e dat_sessao em sessao_plenaria_presenca
if not existe_coluna_no_legado('sessao_plenaria_presenca',
@ -763,6 +785,12 @@ def populate_renamed_fields(new, old):
def migrar_dados(interativo=True):
# executa ajustes pré-migração, se existirem
arq_ajustes_pre_migracao = DIR_DADOS_MIGRACAO.child(
'ajustes_pre_migracao', '{}.sql'.format(sigla_casa))
if arq_ajustes_pre_migracao.exists():
exec_legado(arq_ajustes_pre_migracao.read_file())
uniformiza_banco()
# excluindo database antigo.
@ -800,8 +828,7 @@ def migrar_dados(interativo=True):
arq_ocorrencias = dir_ocorrencias.child(
nome_banco_legado + '.yaml')
with open(arq_ocorrencias, 'w') as arq:
dump = yaml.dump(dict(ocorrencias), allow_unicode=True)
arq.write(dump.replace('\n- ', '\n\n- '))
pyaml.dump(ocorrencias, arq, vspacing=1)
info('Ocorrências salvas em\n {}'.format(arq_ocorrencias))
# recria tipos de autor padrão que não foram criados pela migração
@ -816,7 +843,7 @@ def move_para_depois_de(lista, movido, referencias):
return lista
def migrar_todos_os_models():
def get_models_a_migrar():
models = [model for app in appconfs for model in app.models.values()
if model in field_renames]
# Devido à referência TipoProposicao.tipo_conteudo_related
@ -829,7 +856,11 @@ def migrar_todos_os_models():
move_para_depois_de(models, Proposicao,
[MateriaLegislativa, DocumentoAdministrativo])
for model in models:
return models
def migrar_todos_os_models():
for model in get_models_a_migrar():
migrar_model(model)
@ -1061,22 +1092,16 @@ def adjust_tipoafastamento(new, old):
new.indicador = 'F'
TIPO_MATERIA_OU_TIPO_DOCUMENTO = {'M': TipoMateriaLegislativa,
'D': TipoDocumento}
def set_generic_fk(new, campo_virtual, old):
new.content_type = content_types[campo_virtual.related_model]
new.object_id = get_fk_related(campo_virtual, old)
def adjust_tipoproposicao(new, old):
"Aponta para o tipo relacionado de matéria ou documento"
value = old.tip_mat_ou_doc
model_tipo = TIPO_MATERIA_OU_TIPO_DOCUMENTO[old.ind_mat_ou_doc]
tipo = model_tipo.objects.filter(pk=value)
if tipo:
new.tipo_conteudo_related = tipo[0]
else:
raise ForeignKeyFaltando(
field=TipoProposicao.tipo_conteudo_related,
value=(model_tipo.__name__, value),
label={'ind_mat_ou_doc': old.ind_mat_ou_doc})
if old.tip_mat_ou_doc:
campo_virtual = CAMPOS_VIRTUAIS_TIPO_PROPOSICAO[old.ind_mat_ou_doc]
set_generic_fk(new, campo_virtual, old)
def adjust_proposicao_antes_salvar(new, old):
@ -1085,8 +1110,7 @@ def adjust_proposicao_antes_salvar(new, old):
if old.cod_mat_ou_doc:
tipo_mat_ou_doc = type(new.tipo.tipo_conteudo_related)
campo_virtual = CAMPOS_VIRTUAIS_PROPOSICAO[tipo_mat_ou_doc]
new.content_type = content_types[campo_virtual.related_model]
new.object_id = get_fk_related(campo_virtual, old)
set_generic_fk(new, campo_virtual, old)
def adjust_statustramitacao(new, old):
@ -1226,4 +1250,36 @@ AJUSTE_DEPOIS_SALVAR = {
NormaJuridica: adjust_normajuridica_depois_salvar,
}
# CHECKS ####################################################################
# MARCO ######################################################################
TIME_FORMAT = '%H:%M:%S'
def time_representer(dumper, data):
return dumper.represent_scalar('!time', data.strftime(TIME_FORMAT))
UnsafePrettyYAMLDumper.add_representer(datetime.time, time_representer)
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)
def grava_marco_base():
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.mkdir(parents=True)
for data in model.objects.all().values():
nome_arq = Path(dir_model, data['id'])
with open(nome_arq, 'w') as arq:
pyaml.dump(data, arq)

134
sapl/legacy/migracao_documentos.py

@ -1,12 +1,12 @@
import mimetypes
import os
import re
from glob import glob
import yaml
from django.db import transaction
from sapl.base.models import CasaLegislativa
from sapl.legacy.migracao_dados import exec_legado, warn
from sapl.legacy.migracao_dados import exec_legado
from sapl.materia.models import (DocumentoAcessorio, MateriaLegislativa,
Proposicao)
from sapl.norma.models import NormaJuridica
@ -16,88 +16,26 @@ from sapl.protocoloadm.models import (DocumentoAcessorioAdministrativo,
from sapl.sessao.models import SessaoPlenaria
from sapl.settings import MEDIA_ROOT
# MIGRAÇÃO DE DOCUMENTOS ###################################################
def get_ano(obj):
return [obj.ano]
def ___(obj):
return []
DOCS = {
CasaLegislativa: [
('logotipo',
'props_sapl/{}.*',
'public/casa/logotipo/',
___)
],
Parlamentar: [
('fotografia',
'parlamentar/fotos/{}_foto_parlamentar',
'public/parlamentar/{0}/',
___)
],
MateriaLegislativa: [
('texto_original',
'materia/{}_texto_integral',
'public/materialegislativa/{1}/{0}/',
get_ano)
],
DocumentoAcessorio: [
('arquivo',
'materia/{}',
'public/documentoacessorio/{1}/{0}/',
lambda obj: [obj.materia.ano])
],
NormaJuridica: [
('texto_integral',
'norma_juridica/{}_texto_integral',
'public/normajuridica/{1}/{0}/',
get_ano)
],
SessaoPlenaria: [
('upload_pauta',
'pauta_sessao/{}_pauta_sessao',
'public/sessaoplenaria/{0}/pauta/',
___),
('upload_ata',
'ata_sessao/{}_ata_sessao',
'public/sessaoplenaria/{0}/ata/',
___),
('upload_anexo',
'anexo_sessao/{}_texto_anexado',
'public/sessaoplenaria/{0}/anexo/',
___)
],
Proposicao: [
('texto_original',
'proposicao/{}',
'private/proposicao/{0}/',
get_ano)
],
DocumentoAdministrativo: [
('texto_integral',
'administrativo/{}_texto_integral',
'private/documentoadministrativo/{0}/',
get_ano)
],
DocumentoAcessorioAdministrativo: [
('arquivo',
'administrativo/{}',
'private/documentoacessorioadministrativo/{0}/',
___)
],
CasaLegislativa: [('logotipo', 'props_sapl/{}.*')],
Parlamentar: [('fotografia', 'parlamentar/fotos/{}_foto_parlamentar')],
MateriaLegislativa: [('texto_original', 'materia/{}_texto_integral')],
DocumentoAcessorio: [('arquivo', 'materia/{}')],
NormaJuridica: [('texto_integral', 'norma_juridica/{}_texto_integral')],
SessaoPlenaria: [('upload_pauta', 'pauta_sessao/{}_pauta_sessao'),
('upload_ata', 'ata_sessao/{}_ata_sessao'),
('upload_anexo', 'anexo_sessao/{}_texto_anexado')],
Proposicao: [('texto_original', 'proposicao/{}')],
DocumentoAdministrativo: [('texto_integral',
'administrativo/{}_texto_integral')],
DocumentoAcessorioAdministrativo: [('arquivo', 'administrativo/{}')],
}
DOCS = {model: [(campo,
os.path.join('sapl_documentos', origem),
os.path.join('sapl', destino),
get_extra_args)
for campo, origem, destino, get_extra_args in campos]
DOCS = {model: [(campo, os.path.join('sapl_documentos', origem))
for campo, origem, in campos]
for model, campos in DOCS.items()}
@ -141,11 +79,13 @@ def migrar_propriedades_da_casa():
[(casa.municipio, casa.uf)] = exec_legado(sql_localidade)
print('.... Migrando logotipo da casa ....')
[(_, origem, destino, __)] = DOCS[CasaLegislativa]
[(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(destino, os.path.basename(origem))
destino = os.path.join(
CasaLegislativa._meta.get_field(campo).upload_to,
os.path.basename(origem))
mover_documento(origem, destino)
casa.logotipo = destino
casa.save()
@ -153,36 +93,36 @@ def migrar_propriedades_da_casa():
def migrar_docs_por_ids(model):
for campo, base_origem, base_destino, get_extra_args in DOCS[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))
nome_origem = nome_origem.format('(\d+)')
pat = re.compile('^{}\.\w+$'.format(nome_origem))
if not os.path.isdir(dir_origem):
print(' >>> O diretório {} não existe! Abortado.'.format(
dir_origem))
continue
for arq in os.listdir(dir_origem):
match = pat.match(arq)
if match:
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)))
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
with transaction.atomic():
for id, origem in ids_origens:
# associa documento ao objeto
origem = os.path.join(dir_origem, match.group(0))
id = match.group(1)
try:
obj = model.objects.get(pk=id)
except model.DoesNotExist:
msg = ' {} (pk={}) não encontrado para documento em [{}]'
print(msg.format(model.__name__, id, origem))
else:
destino = os.path.join(
base_destino.format(id, *get_extra_args(obj)),
os.path.basename(origem))
obj = objetos.get(id)
if obj:
destino = upload_to(obj, os.path.basename(origem))
mover_documento(origem, destino)
setattr(obj, campo, destino)
obj.save()
else:
msg = ' {} (pk={}) não encontrado para documento em [{}]'
print(msg.format(model.__name__, id, origem))
def migrar_documentos():
@ -215,5 +155,3 @@ def migrar_documentos():
print('\n#### Encerrado ####\n\n'
'{} documentos sobraram sem ser migrados!!!'.format(
len(sobrando)))
for doc in sobrando:
print(' {}'. format(doc))

2
sapl/legacy/models.py

@ -433,7 +433,7 @@ class MateriaLegislativa(models.Model):
cod_regime_tramitacao = models.IntegerField()
dat_publicacao = models.DateField(blank=True, null=True)
tip_origem_externa = models.IntegerField(blank=True, null=True)
num_origem_externa = models.CharField(max_length=5, blank=True, null=True)
num_origem_externa = models.CharField(max_length=10, blank=True, null=True)
ano_origem_externa = models.SmallIntegerField(blank=True, null=True)
dat_origem_externa = models.DateField(blank=True, null=True)
cod_local_origem_externa = models.IntegerField(blank=True, null=True)

4
sapl/legacy/router.py

@ -16,7 +16,7 @@ class LegacyRouter:
return True
return None
def allow_migrate(self, db, model):
if model._meta.app_label == 'legacy':
def allow_migrate(self, db, app_label, model_name=None, **hints):
if app_label == 'legacy':
return False
return None

159
sapl/legacy/scripts/exporta_zope/exporta_zope.py

@ -5,6 +5,8 @@
# Esse script precisa rodar em python 2
# e depende apenas do descrito no arquivo requiments.txt
import cStringIO
import hashlib
import mimetypes
import os
import sys
@ -12,8 +14,12 @@ from collections import defaultdict
from contextlib import contextmanager
from functools import partial
import git
import magic
import pyaml
import yaml
from unipath import Path
import ZODB.DB
import ZODB.FileStorage
from ZODB.broken import Broken
@ -38,6 +44,9 @@ EXTENSOES = {
'image/tiff': '.tiff',
'application/tiff': '.tiff',
'audio/x-wav': '.wav',
'video/mp4': '.mp4',
'image/x-icon': '.ico',
'application/vnd.oasis.opendocument.text-template': '.ott',
# TODO rever...
'text/richtext': '.rtf',
@ -56,26 +65,25 @@ def br(obj):
return obj
def guess_extension(caminho):
mime = magic.from_file(caminho, mime=True)
def guess_extension(fullname, buffer):
mime = magic.from_buffer(buffer, mime=True)
try:
return EXTENSOES[mime]
except KeyError as e:
msg = '\n'.join([
'Extensão não conhecida para o arquivo:',
caminho,
'E mimetype:',
mime,
' Algumas possibilidades são:', ] +
possibilidades = '\n'.join(
[" '{}': '{}',".format(mime, ext)
for ext in mimetypes.guess_all_extensions(mime)] +
['Atualize o código do dicionário EXTENSOES!']
)
for ext in mimetypes.guess_all_extensions(mime)])
msg = '''Extensão não conhecida para o arquivo: {}
e mimetype: {}
Algumas possibilidades são:
{}
Atualize o código do dicionário EXTENSOES!
'''.format(fullname, mime, possibilidades)
print(msg)
raise Exception(msg, e)
def dump_file(doc, path):
def dump_file(doc, path, salvar):
name = doc['__name__']
fullname = os.path.join(path, name)
@ -95,22 +103,11 @@ def dump_file(doc, path):
doc['data'] = pdata
pdata = doc
with open(fullname, 'w') as arq:
while pdata:
arq.write(pdata.pop('data'))
pdata = br(pdata.pop('next', None))
base, original_extension = os.path.splitext(fullname)
extension = guess_extension(fullname)
if extension == '.xml' and original_extension in ['.xsl', '.xslt']:
# não trocamos as extensões XSL e XSLT
final_name = fullname
else:
# trocamos a extensão pela adivinhada
final_name = base + extension
os.rename(fullname, final_name)
print(final_name)
output = cStringIO.StringIO()
while pdata:
output.write(pdata.pop('data'))
pdata = br(pdata.pop('next', None))
salvar(fullname, output.getvalue())
return name
@ -155,7 +152,7 @@ def logando_nao_identificados():
print('#' * 80)
def dump_folder(folder, path='', enum=enumerate_folder):
def dump_folder(folder, path, salvar, enum=enumerate_folder):
name = folder['id']
path = os.path.join(path, name)
if not os.path.exists(path):
@ -165,7 +162,7 @@ def dump_folder(folder, path='', enum=enumerate_folder):
if dump == '?':
nao_identificados[meta_type].append(path + '/' + id)
elif dump:
id_interno = dump(obj, path)
id_interno = dump(obj, path, salvar)
assert id == id_interno
return name
@ -201,18 +198,16 @@ def read_sde(element):
return data
def save_as_yaml(path, name, obj):
def save_as_yaml(path, name, obj, salvar):
fullname = os.path.join(path, name)
with open(fullname, 'w') as arquivo:
yaml.safe_dump(obj, arquivo, allow_unicode=True)
print(fullname)
return fullname
conteudo = yaml.safe_dump(obj, allow_unicode=True)
salvar(fullname, conteudo)
def dump_sde(strdoc, path, tipo):
def dump_sde(strdoc, path, salvar, tipo):
id = strdoc['id']
sde = read_sde(strdoc)
save_as_yaml(path, '{}.{}.yaml'.format(id, tipo), sde)
save_as_yaml(path, '{}.{}.yaml'.format(id, tipo), sde, salvar)
return id
@ -233,7 +228,7 @@ DUMP_FUNCTIONS = {
def get_app(data_fs_path):
storage = ZODB.FileStorage.FileStorage(data_fs_path)
storage = ZODB.FileStorage.FileStorage(data_fs_path, read_only=True)
db = ZODB.DB(storage)
connection = db.open()
root = connection.root()
@ -255,42 +250,106 @@ def find_sapl(app):
return sapl
def dump_propriedades(docs, path, encoding='iso-8859-1'):
def dump_propriedades(docs, path, salvar, encoding='iso-8859-1'):
props_sapl = br(docs['props_sapl'])
ids = [p['id'] for p in props_sapl['_properties']]
props = {id: props_sapl[id] for id in ids}
props = {id: p.decode(encoding) if isinstance(p, str) else p
for id, p in props.items()}
save_as_yaml(path, 'sapl_documentos/propriedades.yaml', props)
save_as_yaml(path, 'sapl_documentos/propriedades.yaml', props, salvar)
def dump_usuarios(sapl, path):
def dump_usuarios(sapl, path, salvar):
users = br(br(sapl['acl_users'])['data'])
users = {k: br(v) for k, v in users['data'].items()}
save_as_yaml(path, 'usuarios.yaml', users)
save_as_yaml(path, 'usuarios.yaml', users, salvar)
def dump_sapl(data_fs_path, destino='../../../../media'):
def _dump_sapl(data_fs_path, destino, salvar):
assert Path(data_fs_path).exists()
app, close_db = get_app(data_fs_path)
try:
sapl = find_sapl(app)
# extrai folhas XSLT
dump_folder(br(sapl['XSLT']), destino)
dump_folder(br(sapl['XSLT']), destino, salvar)
# extrai usuários com suas senhas e perfis
dump_usuarios(sapl, destino)
dump_usuarios(sapl, destino, salvar)
# extrai documentos
docs = br(sapl['sapl_documentos'])
with logando_nao_identificados():
dump_folder(docs, destino)
dump_propriedades(docs, destino)
dump_folder(docs, destino, salvar)
dump_propriedades(docs, destino, salvar)
finally:
close_db()
DIR_DADOS_MIGRACAO = Path('~/migracao_sapl/').expand()
def repo_execute(repo, cmd, *args):
return repo.git.execute(cmd.split() + list(args))
def get_annex_hashes(repo):
hashes = repo_execute(
repo, 'git annex find', '--format=${keyname}\n', '--include=*')
return {os.path.splitext(h)[0] for h in hashes.splitlines()}
def ajusta_extensao(fullname, conteudo):
base, extensao = os.path.splitext(fullname)
if extensao not in ['.xsl', '.xslt', '.yaml']:
# não trocamos as extensões XSL, XSLT e YAML
extensao = guess_extension(fullname, conteudo)
return base + extensao
def build_salvar(repo):
"""Constroi função salvar que pula arquivos que já estão no annex
"""
hashes = get_annex_hashes(repo)
def salvar(fullname, conteudo):
sha = hashlib.sha256()
sha.update(conteudo)
if sha.hexdigest() not in hashes:
fullname = ajusta_extensao(fullname, conteudo)
if os.path.exists(fullname):
# destrava arquivo pré-existente (o conteúdo mudou)
repo_execute(repo, 'git annex unlock', fullname)
with open(fullname, 'w') as arq:
arq.write(conteudo)
print(fullname)
return salvar
def dump_sapl(sigla):
data_fs_path = DIR_DADOS_MIGRACAO.child('datafs',
'Data_cm_{}.fs'.format(sigla))
assert data_fs_path.exists(), 'Origem não existe: {}'.format(data_fs_path)
nome_banco_legado = 'sapl_cm_{}'.format(sigla)
destino = DIR_DADOS_MIGRACAO.child('repos', nome_banco_legado)
destino.mkdir(parents=True)
repo = git.Repo.init(destino)
repo_execute(repo, 'git annex init')
repo_execute(repo, 'git config annex.thin true')
salvar = build_salvar(repo)
_dump_sapl(data_fs_path, destino, salvar)
# grava mundaças
repo_execute(repo, 'git annex add sapl_documentos')
repo.git.add(A=True)
if 'master' not in repo.heads or repo.index.diff('HEAD'):
# se de fato existe mudança
repo.index.commit('Exporta documentos do zope')
if __name__ == "__main__":
if len(sys.argv) == 2:
data_fs_path = sys.argv[1]
dump_sapl(data_fs_path)
sigla = sys.argv[1]
dump_sapl(sigla)
else:
print('Uso: python exporta_zope <caminho p Data.fs>')
print('Uso: python exporta_zope <sigla>')

5
sapl/legacy/scripts/exporta_zope/requirements.txt

@ -1,3 +1,6 @@
# ZODB version 3.7.4
PyYAML==3.12
ZODB==5.3.0
PyYAML
Unipath
GitPython
pyaml

5
sapl/legacy/scripts/migra_um_db.sh

@ -32,11 +32,6 @@ if [ $# -ge 2 ]; then
echo "O banco legado foi restaurado" |& tee -a $LOG
echo >> $LOG
echo "--- DJANGO MIGRATE ---" | tee -a $LOG
echo >> $LOG
DATABASE_NAME=$1 ./manage.py migrate --settings sapl.legacy_migration_settings
echo >> $LOG
echo "--- MIGRACAO ---" | tee -a $LOG
echo >> $LOG
DATABASE_NAME=$1 ./manage.py migracao_25_31 --force --dados --settings sapl.legacy_migration_settings 2>&1 | tee -a $LOG

5
sapl/legacy/scripts/recria_um_db_postgres.sh

@ -4,3 +4,8 @@
echo "Database $1"
sudo -u postgres psql -c "drop DATABASE if exists $1"
sudo -u postgres psql -c "CREATE DATABASE $1 WITH OWNER = sapl ENCODING = 'UTF8' TABLESPACE = pg_default LC_COLLATE = 'pt_BR.UTF-8' LC_CTYPE = 'pt_BR.UTF-8' CONNECTION LIMIT = -1 TEMPLATE template0;"
echo "--- DJANGO MIGRATE ---" | tee -a $LOG
DATABASE_NAME=$1 ./manage.py migrate --settings sapl.legacy_migration_settings

2
sapl/legacy_migration_settings.py

@ -33,3 +33,5 @@ DEBUG = True
# delisga indexação fulltext em tempo real
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.BaseSignalProcessor'
SHELL_PLUS_DONT_LOAD = ['legacy']

20
sapl/materia/migrations/0028_auto_20180418_1629.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-04-18 19:29
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('materia', '0027_auto_20180409_1443'),
]
operations = [
migrations.AlterField(
model_name='materialegislativa',
name='numero_origem_externa',
field=models.CharField(blank=True, max_length=10, verbose_name='Número'),
),
]

2
sapl/materia/models.py

@ -167,7 +167,7 @@ class MateriaLegislativa(models.Model):
on_delete=models.PROTECT,
verbose_name=_('Tipo'))
numero_origem_externa = models.CharField(
max_length=5, blank=True, verbose_name=_('Número'))
max_length=10, blank=True, verbose_name=_('Número'))
ano_origem_externa = models.PositiveSmallIntegerField(
blank=True, null=True, verbose_name=_('Ano'), choices=RANGE_ANOS)
data_origem_externa = models.DateField(

Loading…
Cancel
Save