Example #1
0
    def test_01_debug_mode_assets(self):
        """ Checks that the ir.attachments records created for compiled less assets in debug mode
        are correctly invalidated.
        """
        # Compile for the first time
        self._bundle(True, False)

        # Compile a second time, without changes
        self._bundle(False, False)

        # Touch the file and compile a third time
        path = get_resource_path('test_assetsbundle', 'static', 'src', 'less', 'test_lessfile1.less')
        t = time.time() + 5
        utime(path, (t, t))   # touch
        self._bundle(True, True)

        # Because we are in the same transaction since the beginning of the test, the first asset
        # created and the second one have the same write_date, but the file's last modified date
        # has really been modified. If we do not update the write_date to a posterior date, we are
        # not able to reproduce the case where we compile this bundle again without changing
        # anything.
        self.cr.execute("update ir_attachment set write_date=clock_timestamp() + interval '10 seconds' where id = (select max(id) from ir_attachment)")

        # Compile a fourth time, without changes
        self._bundle(False, False)
Example #2
0
    def test_03_date_invalidation(self):
        """ Checks that a bundle is invalidated when one of its assets' modification date is changed.
        """
        bundle0 = AssetsBundle(self.jsbundle_xmlid,
                               cr=self.cr,
                               uid=self.uid,
                               context={},
                               registry=self.registry)
        bundle0.js()
        last_modified0 = bundle0.last_modified
        version0 = bundle0.version

        path = get_resource_path('test_assetsbundle', 'static', 'src', 'js',
                                 'test_jsfile1.js')
        utime(path, None)  # touch

        bundle1 = AssetsBundle(self.jsbundle_xmlid,
                               cr=self.cr,
                               uid=self.uid,
                               context={},
                               registry=self.registry)
        bundle1.js()
        last_modified1 = bundle1.last_modified
        version1 = bundle1.version
        self.assertNotEquals(last_modified0, last_modified1)
        self.assertNotEquals(version0, version1)

        # check if the previous attachment is correctly cleaned
        self.assertEquals(len(self._any_ira_for_bundle('js')), 1)
Example #3
0
    def test_10_paginated_css_date_invalidation(self):
        """ Checks that a bundle is invalidated when one of its assets' modification date is changed.
        """
        bundle0 = AssetsBundle(self.cssbundle_xmlid,
                               env=self.env,
                               max_css_rules=1)
        bundle0.css()
        last_modified0 = bundle0.last_modified
        version0 = bundle0.version

        path = get_resource_path('test_assetsbundle', 'static', 'src', 'css',
                                 'test_cssfile1.css')
        utime(path, None)  # touch

        bundle1 = AssetsBundle(self.cssbundle_xmlid,
                               env=self.env,
                               max_css_rules=1)
        bundle1.css()
        last_modified1 = bundle1.last_modified
        version1 = bundle1.version

        self.assertNotEquals(last_modified0, last_modified1)
        self.assertNotEquals(version0, version1)

        # check if the previous attachment is correctly cleaned
        self.assertEquals(len(self._any_ira_for_bundle('css')), 3)
Example #4
0
    def test_10_paginated_css_date_invalidation(self):
        """ Checks that a bundle is invalidated when one of its assets' modification date is changed.
        """
        bundle0 = AssetsBundle(
            self.cssbundle_xmlid, cr=self.cr, uid=self.uid, context={}, registry=self.registry, max_css_rules=1
        )
        bundle0.css()
        last_modified0 = bundle0.last_modified
        version0 = bundle0.version

        path = get_resource_path("test_assetsbundle", "static", "src", "css", "test_cssfile1.css")
        utime(path, None)  # touch

        bundle1 = AssetsBundle(
            self.cssbundle_xmlid, cr=self.cr, uid=self.uid, context={}, registry=self.registry, max_css_rules=1
        )
        bundle1.css()
        last_modified1 = bundle1.last_modified
        version1 = bundle1.version

        self.assertNotEquals(last_modified0, last_modified1)
        self.assertNotEquals(version0, version1)

        # check if the previous attachment is correctly cleaned
        self.assertEquals(len(self._any_ira_for_bundle("css")), 3)
Example #5
0
 def _get_wsdl_url(self):
     for cp in self:
         # production WebService
         wsdl_prod_file_path = get_resource_path(
             'delivery_carrier_label_postlogistics', 'data', 'production',
             cp.postlogistics_version + '.wsdl')
         __, wsdl_prod_path = file_open(wsdl_prod_file_path, pathinfo=True)
         wsdl_prod_url = 'file://' + wsdl_prod_path
         # integration WebService
         wsdl_int_file_path = get_resource_path(
             'delivery_carrier_label_postlogistics', 'data', 'integration',
             cp.postlogistics_version + '.wsdl')
         __, wsdl_int_path = file_open(wsdl_int_file_path, pathinfo=True)
         wsdl_int_url = 'file://' + wsdl_int_path
         if cp.postlogistics_test_mode:
             cp.postlogistics_wsdl_url = wsdl_int_url
         else:
             cp.postlogistics_wsdl_url = wsdl_prod_url
    def _get_files(self):
        def get_scripts(path):
            if not path:
                return {}
            return {
                version: glob.glob1(opj(path, version), '*.py')
                for version in os.listdir(path)
                if os.path.isdir(opj(path, version))
            }

        for pkg in self.graph:
            if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade'
                    or getattr(pkg, 'load_state', None) == 'to upgrade'):
                continue

            self.migrations[pkg.name] = {
                'module':
                get_scripts(get_resource_path(pkg.name, 'migrations')),
                'maintenance':
                get_scripts(
                    get_resource_path('base', 'maintenance', 'migrations',
                                      pkg.name)),
            }
Example #7
0
    def test_03_date_invalidation(self):
        """ Checks that a bundle is invalidated when one of its assets' modification date is changed.
        """
        bundle0 = self._get_asset(self.jsbundle_xmlid)
        bundle0.js()
        last_modified0 = bundle0.last_modified
        version0 = bundle0.version

        path = get_resource_path('test_assetsbundle', 'static', 'src', 'js', 'test_jsfile1.js')
        utime(path, None)  # touch

        bundle1 = self._get_asset(self.jsbundle_xmlid)
        bundle1.js()
        last_modified1 = bundle1.last_modified
        version1 = bundle1.version
        self.assertNotEquals(last_modified0, last_modified1)
        self.assertNotEquals(version0, version1)

        # check if the previous attachment is correctly cleaned
        self.assertEquals(len(self._any_ira_for_bundle('js')), 1)
Example #8
0
    def test_10_paginated_css_date_invalidation(self):
        """ Checks that a bundle is invalidated when one of its assets' modification date is changed.
        """
        bundle0 = self._get_asset(self.cssbundle_xmlid, env=self.env(context={'max_css_rules': 1}))
        bundle0.css()
        last_modified0 = bundle0.last_modified
        version0 = bundle0.version

        path = get_resource_path('test_assetsbundle', 'static', 'src', 'css', 'test_cssfile1.css')
        utime(path, None)  # touch

        bundle1 = self._get_asset(self.cssbundle_xmlid, env=self.env(context={'max_css_rules': 1}))
        bundle1.css()
        last_modified1 = bundle1.last_modified
        version1 = bundle1.version

        self.assertNotEquals(last_modified0, last_modified1)
        self.assertNotEquals(version0, version1)

        # check if the previous attachment is correctly cleaned
        self.assertEquals(len(self._any_ira_for_bundle('css')), 3)
Example #9
0
    def binary_content(self, xmlid=None, model='ir.attachment', id=None, field='datas', unique=False, filename=None, filename_field='datas_fname', download=False, mimetype=None, default_mimetype='application/octet-stream', env=None):
        """ Get file, attachment or downloadable content

        If the ``xmlid`` and ``id`` parameter is omitted, fetches the default value for the
        binary field (via ``default_get``), otherwise fetches the field for
        that precise record.

        :param str xmlid: xmlid of the record
        :param str model: name of the model to fetch the binary from
        :param int id: id of the record from which to fetch the binary
        :param str field: binary field
        :param bool unique: add a max-age for the cache control
        :param str filename: choose a filename
        :param str filename_field: if not create an filename with model-id-field
        :param bool download: apply headers to download the file
        :param str mimetype: mintype of the field (for headers)
        :param str default_mimetype: default mintype if no mintype found
        :param Environment env: by default use request.env
        :returns: (status, headers, content)
        """
        env = env or request.env
        # get object and content
        obj = None
        if xmlid:
            obj = env.ref(xmlid, False)
        elif id and model in env.registry:
            obj = env[model].browse(int(id))

        # obj exists
        if not obj or not obj.exists() or field not in obj:
            return (404, [], None)

        # check read access
        try:
            last_update = obj['__last_update']
        except openerp.exceptions.AccessError:
            return (403, [], None)

        status, headers, content = None, [], None

        # attachment by url check
        module_resource_path = None
        if model == 'ir.attachment' and obj.type == 'url' and obj.url:
            url_match = re.match("^/(\w+)/(.+)$", obj.url)
            if url_match:
                module = url_match.group(1)
                module_path = get_module_path(module)
                module_resource_path = get_resource_path(module, url_match.group(2))
                if module_path and module_resource_path:
                    module_path = os.path.join(os.path.normpath(module_path), '')  # join ensures the path ends with '/'
                    module_resource_path = os.path.normpath(module_resource_path)
                    if module_resource_path.startswith(module_path):
                        with open(module_resource_path, 'rb') as f:
                            content = base64.b64encode(f.read())
                        last_update = str(os.path.getmtime(module_resource_path))

            if not module_resource_path:
                module_resource_path = obj.url

            if not content:
                status = 301
                content = module_resource_path
        else:
            content = obj[field] or ''

        # filename
        if not filename:
            if filename_field in obj:
                filename = obj[filename_field]
            elif module_resource_path:
                filename = os.path.basename(module_resource_path)
            else:
                filename = "%s-%s-%s" % (obj._model._name, obj.id, field)

        # mimetype
        mimetype = 'mimetype' in obj and obj.mimetype or False
        if not mimetype:
            if filename:
                mimetype = mimetypes.guess_type(filename)[0]
            if not mimetype and getattr(env[model]._fields[field], 'attachment', False):
                # for binary fields, fetch the ir_attachement for mimetype check
                attach_mimetype = env['ir.attachment'].search_read(domain=[('res_model', '=', model), ('res_id', '=', id), ('res_field', '=', field)], fields=['mimetype'], limit=1)
                mimetype = attach_mimetype and attach_mimetype[0]['mimetype']
            if not mimetype:
                mimetype = guess_mimetype(base64.b64decode(content), default=default_mimetype)

        headers += [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')]

        # cache
        etag = hasattr(request, 'httprequest') and request.httprequest.headers.get('If-None-Match')
        retag = '"%s"' % hashlib.md5(last_update).hexdigest()
        status = status or (304 if etag == retag else 200)
        headers.append(('ETag', retag))
        headers.append(('Cache-Control', 'max-age=%s' % (STATIC_CACHE if unique else 0)))

        # content-disposition default name
        if download:
            headers.append(('Content-Disposition', self.content_disposition(filename)))
        return (status, headers, content)
Example #10
0
    def binary_content(
        self,
        xmlid=None,
        model="ir.attachment",
        id=None,
        field="datas",
        unique=False,
        filename=None,
        filename_field="datas_fname",
        download=False,
        mimetype=None,
        default_mimetype="application/octet-stream",
        env=None,
    ):
        """ Get file, attachment or downloadable content

        If the ``xmlid`` and ``id`` parameter is omitted, fetches the default value for the
        binary field (via ``default_get``), otherwise fetches the field for
        that precise record.

        :param str xmlid: xmlid of the record
        :param str model: name of the model to fetch the binary from
        :param int id: id of the record from which to fetch the binary
        :param str field: binary field
        :param bool unique: add a max-age for the cache control
        :param str filename: choose a filename
        :param str filename_field: if not create an filename with model-id-field
        :param bool download: apply headers to download the file
        :param str mimetype: mintype of the field (for headers)
        :param str default_mimetype: default mintype if no mintype found
        :param Environment env: by default use request.env
        :returns: (status, headers, content)
        """
        env = env or request.env
        # get object and content
        obj = None
        if xmlid:
            obj = env.ref(xmlid, False)
        elif id and model in env.registry:
            obj = env[model].browse(int(id))

        # obj exists
        if not obj or not obj.exists() or field not in obj:
            return (404, [], None)

        # check read access
        try:
            last_update = obj["__last_update"]
        except openerp.exceptions.AccessError:
            return (403, [], None)

        status, headers, content = None, [], None

        # attachment by url check
        module_resource_path = None
        if model == "ir.attachment" and obj.type == "url" and obj.url:
            url_match = re.match("^/(\w+)/(.+)$", obj.url)
            if url_match:
                module = url_match.group(1)
                module_path = get_module_path(module)
                module_resource_path = get_resource_path(module, url_match.group(2))
                if module_path and module_resource_path:
                    module_path = os.path.join(os.path.normpath(module_path), "")  # join ensures the path ends with '/'
                    module_resource_path = os.path.normpath(module_resource_path)
                    if module_resource_path.startswith(module_path):
                        with open(module_resource_path, "r") as f:
                            content = base64.b64encode(f.read())
                        last_update = str(os.path.getmtime(module_resource_path))

            if not module_resource_path:
                module_resource_path = obj.url

            if not content:
                status = 301
                content = module_resource_path
        else:
            content = obj[field] or ""

        # filename
        if not filename:
            if filename_field in obj:
                filename = obj[filename_field]
            elif module_resource_path:
                filename = os.path.basename(module_resource_path)
            else:
                filename = "%s-%s-%s" % (obj._model._name, obj.id, field)

        # mimetype
        if not mimetype:
            if "mimetype" in obj and obj.mimetype and obj.mimetype != "application/octet-stream":
                mimetype = obj.mimetype
            elif filename:
                mimetype = mimetypes.guess_type(filename)[0]
            if not mimetype:
                mimetype = default_mimetype
        headers.append(("Content-Type", mimetype))

        # cache
        etag = hasattr(request, "httprequest") and request.httprequest.headers.get("If-None-Match")
        retag = hashlib.md5(last_update).hexdigest()
        status = status or (304 if etag == retag else 200)
        headers.append(("ETag", retag))
        headers.append(("Cache-Control", "max-age=%s" % (STATIC_CACHE if unique else 0)))

        # content-disposition default name
        if download:
            headers.append(("Content-Disposition", self.content_disposition(filename)))

        return (status, headers, content)
Example #11
0
    def binary_content(self, xmlid=None, model='ir.attachment', id=None, field='datas', unique=False, filename=None, filename_field='datas_fname', download=False, mimetype=None, default_mimetype='application/octet-stream', env=None):
        """ Get file, attachment or downloadable content

        If the ``xmlid`` and ``id`` parameter is omitted, fetches the default value for the
        binary field (via ``default_get``), otherwise fetches the field for
        that precise record.

        :param str xmlid: xmlid of the record
        :param str model: name of the model to fetch the binary from
        :param int id: id of the record from which to fetch the binary
        :param str field: binary field
        :param bool unique: add a max-age for the cache control
        :param str filename: choose a filename
        :param str filename_field: if not create an filename with model-id-field
        :param bool download: apply headers to download the file
        :param str mimetype: mintype of the field (for headers)
        :param str default_mimetype: default mintype if no mintype found
        :param Environment env: by default use request.env
        :returns: (status, headers, content)
        """
        env = env or request.env
        # get object and content
        obj = None
        if xmlid:
            obj = env.ref(xmlid, False)
        elif id and model in env.registry:
            obj = env[model].browse(int(id))

        # obj exists
        if not obj or not obj.exists() or field not in obj:
            return (404, [], None)

        # check read access
        try:
            last_update = obj['__last_update']
        except openerp.exceptions.AccessError:
            return (403, [], None)

        status, headers, content = None, [], None

        # attachment by url check
        module_resource_path = None
        if model == 'ir.attachment' and obj.type == 'url' and obj.url:
            url_match = re.match("^/(\w+)/(.+)$", obj.url)
            if url_match:
                module = url_match.group(1)
                module_path = get_module_path(module)
                module_resource_path = get_resource_path(module, url_match.group(2))
                if module_path and module_resource_path:
                    module_path = os.path.join(os.path.normpath(module_path), '')  # join ensures the path ends with '/'
                    module_resource_path = os.path.normpath(module_resource_path)
                    if module_resource_path.startswith(module_path):
                        with open(module_resource_path, 'r') as f:
                            content = base64.b64encode(f.read())
                        last_update = str(os.path.getmtime(module_resource_path))

            if not module_resource_path:
                module_resource_path = obj.url

            if not content:
                status = 301
                content = module_resource_path
        else:
            content = obj[field] or ''

        # filename
        if not filename:
            if filename_field in obj:
                filename = obj[filename_field]
            elif module_resource_path:
                filename = os.path.basename(module_resource_path)
            else:
                filename = "%s-%s-%s" % (obj._model._name, obj.id, field)

        # mimetype
        mimetype = 'mimetype' in obj and obj.mimetype or False
        if not mimetype:
            if filename:
                mimetype = mimetypes.guess_type(filename)[0]
            if not mimetype and getattr(env[model]._fields[field], 'attachment', False):
                # for binary fields, fetch the ir_attachement for mimetype check
                attach_mimetype = env['ir.attachment'].search_read(domain=[('res_model', '=', model), ('res_id', '=', id), ('res_field', '=', field)], fields=['mimetype'], limit=1)
                mimetype = attach_mimetype and attach_mimetype[0]['mimetype']
            if not mimetype:
                mimetype = default_mimetype
        headers += [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')]

        # cache
        etag = hasattr(request, 'httprequest') and request.httprequest.headers.get('If-None-Match')
        retag = hashlib.md5(last_update).hexdigest()
        status = status or (304 if etag == retag else 200)
        headers.append(('ETag', retag))
        headers.append(('Cache-Control', 'max-age=%s' % (STATIC_CACHE if unique else 0)))

        # content-disposition default name
        if download:
            headers.append(('Content-Disposition', self.content_disposition(filename)))

        return (status, headers, content)