usawa

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | Submodules | LICENSE

commit d4340f1d41ac5210cc7355ad988964949ec244c7
parent 84805b603dac3c924427681d08522c5fbf764491
Author: lash <dev@holbrook.no>
Date:   Fri, 13 Feb 2026 10:51:12 +0000

Add XML export

Diffstat:
Mdummy/tests/asset.py | 10++++++++++
Mdummy/usawa/asset.py | 79++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mdummy/usawa/data/schema.xsd | 8+++++---
3 files changed, 83 insertions(+), 14 deletions(-)

diff --git a/dummy/tests/asset.py b/dummy/tests/asset.py @@ -2,8 +2,11 @@ import logging import os import unittest +import lxml.etree + from usawa.asset import Asset + logging.basicConfig(level=logging.DEBUG) logg = logging.getLogger() @@ -18,5 +21,12 @@ class TestAsset(unittest.TestCase): logg.debug('asset {}'.format(asset)) + def test_asset_export(self): + fp = os.path.join(testdir, 'test.xml') + asset = Asset.from_file(fp, slug='foo', description='barbarbar', extref='xyzzy', localref='plugh') + tree = asset.to_tree() + logg.debug('asset {}'.format(lxml.etree.tostring(tree))) + + if __name__ == '__main__': unittest.main() diff --git a/dummy/usawa/asset.py b/dummy/usawa/asset.py @@ -2,10 +2,14 @@ import hashlib import mimetypes import logging import os +import uuid +import lxml.etree import magic -logg = logging.getLogger('asset') +from .xml import nsmap + +logg = logging.getLogger('usawa.asset') BLOCKSIZE = 512 @@ -28,10 +32,12 @@ class Asset: self.enc = None self.slug = None self.ext = None + self.localref = None + self.extref = None + self.uuid = None + self.description = None - - def get_filename(self): s = self.slug if self.ext != None: @@ -46,15 +52,22 @@ class Asset: return s + @staticmethod + def from_file(filepath, description=None, slug=None, mimetype=None, localref=None, extref=None): + f = open(filepath, 'rb') + return Asset.from_io(f, filepath, f.close, description=description, slug=slug, mimetype=mimetype, localref=localref, extref=extref) + + """ + :todo: make sure stream close on exception + """ @staticmethod - def from_file(filepath, description=None, slug=None, mimetype=None): + def from_io(io, path, closer, description=None, slug=None, mimetype=None, localref=None, extref=None): o = Asset() h = hashlib.sha256() - f = open(filepath, 'rb') - b = f.read(BLOCKSIZE) + b = io.read(BLOCKSIZE) if mimetype == None: - v = mimetypes.guess_file_type(filepath, strict=True) + v = mimetypes.guess_file_type(path, strict=True) if v != None: mimetype = v[0] o.enc = v[1] @@ -64,24 +77,68 @@ class Asset: h.update(b) c = BLOCKSIZE while True: - b = f.read(BLOCKSIZE) + b = io.read(BLOCKSIZE) if len(b) == 0: break h.update(b) c += len(b) - f.close() + closer() o.digest = h.digest() s = mimetypes.guess_extension(o.mime, strict=True) if s != None: o.ext = s[1:] + (o.slug, o.ext) = parse_path(path) + if slug != None: + logg.info('overriding file base name {} -> {}'.format(o.slug, slug)) + o.slug = slug - (o.slug, o.ext) = parse_path(filepath) + logg.debug('asset read {} bytes from path {} mime {}'.format(c, path, o.mime)) - logg.debug('asset read {} bytes from path {} mime {}'.format(c, filepath, o.mime)) + o.uuid = str(uuid.uuid4()) + if localref == None: + localref = o.uuid + o.localref = localref + o.extref = extref + o.description = description return o + def to_tree(self): + tree = lxml.etree.Element('attachment', nsmap=nsmap()) + tree.set('mime', self.get_mimestring()) + tree.set('uuid', self.uuid) + + o = lxml.etree.SubElement(tree, 'digest') + o.text = self.digest.hex() + tree.append(o) + + o = lxml.etree.SubElement(tree, 'lookup') + o.text = '.' + o.set('method', 'local') + tree.append(o) + + o = lxml.etree.SubElement(tree, 'ref') + o.text = self.localref + tree.append(o) + + if self.extref != None: + o = lxml.etree.SubElement(tree, 'extref') + o.text = self.extref + tree.append(o) + + o = lxml.etree.SubElement(tree, 'filename') + o.text = self.get_filename() + tree.append(o) + + if self.description != None: + o = lxml.etree.SubElement(tree, 'description') + o.text = self.description + tree.append(o) + + return tree + + def __str__(self): return 'file ̈́' + self.get_filename() + ' mime ' + self.get_mimestring() + ' digest ' + self.digest.hex() diff --git a/dummy/usawa/data/schema.xsd b/dummy/usawa/data/schema.xsd @@ -135,7 +135,7 @@ <xs:complexType name="EntryData"> <xs:sequence> <xs:element name="parent" type="xs:string" /> - <xs:element name="ref" type="xs:string" /> + <xs:element name="ext" type="xs:string" /> <xs:element name="serial" type="xs:positiveInteger" /> <xs:element name="date" type="xs:date" /> <xs:element name="dateTimeRegistered" type="xs:dateTime" /> @@ -157,9 +157,11 @@ <xs:complexType name="Attachment"> <xs:sequence> <xs:element name="digest" type="Digest" /> - <xs:element name="slug" type="xs:string" /> - <xs:element name="description" type="xs:string" /> <xs:element name="lookup" type="Lookup" /> + <xs:element name="ref" type="xs:string" /> + <xs:element name="extref" type="xs:string" minOccurs="0" maxOccurs="1" /> + <xs:element name="filename" type="xs:string" minOccurs="0" maxOccurs="1" /> + <xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1" /> </xs:sequence> <xs:attribute name="mime" type="xs:string" /> <xs:attribute name="uuid" type="xs:string" />