Projet

Général

Profil

0001-formdata-improve-migration-of-attachments-to-absolut.patch

Emmanuel Cazenave, 11 janvier 2022 14:29

Télécharger (5,3 ko)

Voir les différences:

Subject: [PATCH] formdata: improve migration of attachments to absolute path
 (#60380)

 tests/test_formdata.py | 67 ++++++++++++++++++++++++++++++++++++++++++
 wcs/workflows.py       | 16 +++++-----
 2 files changed, 76 insertions(+), 7 deletions(-)
tests/test_formdata.py
3 3
import io
4 4
import os.path
5 5
import time
6
import uuid
6 7
from unittest import mock
7 8

  
8 9
import pytest
......
19 20
from wcs.formdef import FormDef
20 21
from wcs.qommon import force_str
21 22
from wcs.qommon.http_request import HTTPRequest
23
from wcs.qommon.misc import file_digest
24
from wcs.qommon.storage import atomic_write
22 25
from wcs.qommon.substitution import CompatibilityNamesDict
23 26
from wcs.qommon.template import Template
24 27
from wcs.qommon.upload_storage import PicklableUpload
......
3428 3431
    # check it was converted to relative path
3429 3432
    formdata = formdef.data_class().get(formdata.id)
3430 3433
    assert formdata.evolution[-1].parts[0].filename.startswith('attachments/')
3434

  
3435
    # More realistic situation :
3436
    # * an absolute path serialized to storage
3437
    # * fetch the formadata
3438
    # * store it again and check that the path is converted to a a relative path
3439

  
3440
    FormDef.wipe()
3441
    formdef = FormDef()
3442
    formdef.name = 'test'
3443
    formdef.fields = []
3444
    formdef.store()
3445

  
3446
    formdef.data_class().wipe()
3447
    formdata = formdef.data_class()()
3448
    formdata.just_created()
3449
    formdata.status = 'wf-new'
3450
    formdata.evolution[-1].status = 'wf-new'
3451
    attachment_evolution_part = AttachmentEvolutionPart(
3452
        'hello.txt', fp=io.BytesIO(b'test'), content_type='text/plain', varname='testfile'
3453
    )
3454
    formdata.evolution[-1].parts = [attachment_evolution_part]
3455

  
3456
    # monkeypatch so that the filename is stored as an absolute path
3457
    def get_state():
3458
        odict = attachment_evolution_part.__dict__.copy()
3459
        del odict['__getstate__']
3460
        if not odict.get('fp'):
3461
            if 'filename' not in odict:
3462
                # we need a filename as an identifier: create one from nothing
3463
                # instead of file_digest(self.fp) (see below)
3464
                odict['filename'] = 'uuid-%s' % uuid.uuid4()
3465
                attachment_evolution_part.filename = odict['filename']
3466
            return odict
3467

  
3468
        del odict['fp']
3469

  
3470
        # there is no filename, or it was a temporary one: create it
3471
        if 'filename' not in odict or odict['filename'].startswith('uuid-'):
3472
            filename = file_digest(attachment_evolution_part.fp)
3473
            # create subdirectory with digest prefix as name
3474
            dirname = os.path.join('attachments', filename[:4])
3475
            abs_dirname = os.path.join(get_publisher().app_dir, dirname)
3476
            os.makedirs(abs_dirname, exist_ok=True)
3477
            odict['filename'] = os.path.join(abs_dirname, filename)
3478
            attachment_evolution_part.filename = odict['filename']
3479
            attachment_evolution_part.fp.seek(0)
3480
            atomic_write(attachment_evolution_part.get_file_path(), attachment_evolution_part.fp)
3481

  
3482
        return odict
3483

  
3484
    attachment_evolution_part.__getstate__ = get_state
3485

  
3486
    formdata.store()
3487
    # check that the path is absolute
3488
    assert formdata.evolution[-1].parts[0].filename.startswith(pub.APP_DIR)
3489
    assert os.path.exists(formdata.evolution[-1].parts[0].get_file_path())
3490

  
3491
    # get a frech instance not monkeypatched
3492
    formdata = formdef.data_class().get(formdata.id)
3493
    formdata.store()
3494

  
3495
    # check it was converted to relative path
3496
    formdata = formdef.data_class().get(formdata.id)
3497
    assert formdata.evolution[-1].parts[0].filename.startswith('attachments/')
wcs/workflows.py
297 297

  
298 298
    def __getstate__(self):
299 299
        odict = self.__dict__.copy()
300
        if not odict.get('fp'):
301
            if 'filename' not in odict:
302
                # we need a filename as an identifier: create one from nothing
303
                # instead of file_digest(self.fp) (see below)
304
                odict['filename'] = 'uuid-%s' % uuid.uuid4()
305
                self.filename = odict['filename']
300
        if not odict.get('fp') and 'filename' not in odict:
301
            # we need a filename as an identifier: create one from nothing
302
            # instead of file_digest(self.fp) (see below)
303
            odict['filename'] = 'uuid-%s' % uuid.uuid4()
304
            self.filename = odict['filename']
306 305
            return odict
307 306

  
308
        del odict['fp']
307
        if 'fp' in odict:
308
            del odict['fp']
309 309

  
310 310
        # there is no filename, or it was a temporary one: create it
311 311
        if 'filename' not in odict or odict['filename'].startswith('uuid-'):
312
            if not self.fp:
313
                return odict
312 314
            filename = file_digest(self.fp)
313 315
            # create subdirectory with digest prefix as name
314 316
            dirname = os.path.join('attachments', filename[:4])
315
-