Skip to content

Instantly share code, notes, and snippets.

@jamilatta
Last active December 18, 2015 01:28
Show Gist options
  • Save jamilatta/5703579 to your computer and use it in GitHub Desktop.
Save jamilatta/5703579 to your computer and use it in GitHub Desktop.
#coding: utf-8
import itertools
import zipfile
import xml.etree.cElementTree as etree
class SPSMixin(object):
@property
def xmls(self):
fps = self.get_fps('xml')
for fp in fps:
yield etree.parse(fp)
@property
def xml(self):
xmls = list(itertools.islice(self.xmls, 2))
if len(xmls) == 1:
return xmls[0]
else:
raise AttributeError('there is not a single xml file')
class Xray(object):
def __init__(self, filename):
self._filename = filename
self._zip_pkg = zipfile.ZipFile(filename, 'r')
self._pkg_names = {}
self._classify()
def __del__(self):
self._zip_pkg.close()
def _classify(self):
for fileinfo, filename in zip(self._zip_pkg.infolist(), self._zip_pkg.namelist()):
# ignore directories
if fileinfo.file_size:
_, ext = filename.rsplit('.', 1)
ext_node = self._pkg_names.setdefault(ext, [])
ext_node.append(filename)
def get_ext(self, ext):
try:
return self._pkg_names[ext]
except KeyError:
raise AttributeError("the package does not contain a '%s' file" % ext)
def get_fps(self, ext):
filenames = self.get_ext(ext)
for filename in filenames:
yield self._zip_pkg.open(filename, 'r')
class PackageAnalyzer(SPSMixin, Xray):
def __init__(self, *args):
super(PackageAnalyzer, self).__init__(*args)
self._errors = []
@property
def errors(self):
"""
Returns an list of errors or empty list
"""
return self._errors
@errors.setter
def errors(self, error):
"""
Set an error to the errors list
"""
if not error in self._errors:
self._errors.append(error)
def is_valid_package(self):
"""
Validate if exist at least one xml file and one pdf file
"""
try:
self.get_ext('xml')
self.get_ext('pdf')
return True
except AttributeError, e:
self.errors = e.message
return False
def is_valid_content(self):
"""
Validate the content of the xml(s) file(s)
"""
for xml in self.xmls:
pass
@gustavofonseca
Copy link

Outra coisa,

  • linha 69: Listas são mutáveis. Se você retornar a referência para a uma estrutura interna, mutável, do objeto que armazena o estado dos erros, concorda que coisas bizarras podem acontecer?
    Eu trocaria para:
return tuple(self._errors)

Não sei se é necessário essa segurança

@jamilatta
Copy link
Author

linha 72: setter para a property errors promove uma sintaxe bizarra e nada pythonica (self.errors = e.message). Penso que esse seja um encapsulamento totalmente desnecessário uma vez que é muito mais natural: self._errors.append(error)

Em relação a sintaxe concordo que é estranha mas é um recurso da linguagem..., mas em relação ao método append realmente seria fácil utiliza-lá, porém note que preciso garantir que não exista duplicidades de erros o que me levou a utilizar o setter da property claro que poderíamos ter um método para garantir isso.

linha 79: método is_valid_package. Será que é correto dizer que o pacote é válido apenas pelo fato de possuir arquivos de determinadas extensões? Tenho minhas dúvidas...

É também tenho dúvidas, mas esse é o escopo atual que definimos no documento de especificação.

linha 91: método is_valid_content. Mesmo comentário que o anterior. Na verdade esses métodos não se fazem necessários, é a mesma idéia da exceção. Você tenta realizar a tarefa sem ficar pedindo licença, caso consiga ótimo, caso contrário trata-se o caso.

Note que esse método não está implementado ainda vou escrever o corpo dele garantindo que os xml(s) tenha o mínimo de conteúdo esperado.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment