Пример #1
0
 def test_should_prefix_style_url_references(self):
     src = self.get_test_image_path('test_svg_with_style_url_ref.svg')
     dst = os.path.join(tempfile.gettempdir(), 'resized_svg_image.svg')
     try:
         resize_svg_image(src,
                          dst,
                          0,
                          0,
                          crop=False,
                          optimize=True,
                          prefix='123')
         svg = file_get_contents(dst)
         self.assertEqual(
             '<?xml version="1.0" encoding="utf-8"?>\n' +
             '<svg data-prefix="b23" id="b23_Layer_1" style="enable-background:new 0 0 64 64;" version="1.1" viewBox="0 0 64 64" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px">\n\n'
             +
             '<linearGradient gradientUnits="userSpaceOnUse" id="b23_SVGID_1_" x1="0" x2="64" y1="32.3013" y2="32.3013">\n'
             + '<stop offset="0" style="stop-color:#B90404"/>\n' +
             '<stop offset="1" style="stop-color:#8E0000"/>\n' +
             '</linearGradient>\n' +
             '<path d="36.3,83.7 0.1,62.7 0,20.8 36.1,0 72.2,21.1 72.4,62.9" style="fill:url(#b23_SVGID_1_);"/>\n'
             + '</svg>', svg)
     finally:
         if os.path.isfile(dst):
             os.unlink(dst)
Пример #2
0
 def test_should_enforce_prefix_always_starting_with_letter(self):
     src = self.get_test_image_path('test_svg_with_ids.svg')
     dst = os.path.join(tempfile.gettempdir(), 'resized_svg_image.svg')
     try:
         resize_svg_image(src,
                          dst,
                          0,
                          0,
                          crop=False,
                          optimize=True,
                          prefix='foo')
         svg = file_get_contents(dst)
         self.assertEqual(
             '<?xml version="1.0" encoding="utf-8"?>\n' + \
             '<svg data-prefix="foo" id="foo_Layer_1" style="enable-background:new 0 0 164.4 83.7;" version="1.1" viewBox="0 0 164.4 83.7" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px">\n' + \
             '<polygon id="foo_base" points="36.3,83.7 0.1,62.7 0,20.8 36.1,0 72.2,21.1 72.4,62.9 "/>\n' + \
             '<polygon id="foo_cuffs" points="36.4,62.9 54.5,73 54.5,52.4 "/>\n' + \
             '<g id="foo_test" transform="matrix(0.250391,0,0,0.250391,36.1,46.1023)">\n' + \
             '<use height="512px" width="512px" x="0" xlink:href="#foo_Image1" y="0"/>\n' + \
             '</g>\n' + \
             '<defs>\n' + \
             '<image height="512px" id="foo_Image1" width="512px" xlink:href="data:image/png;base64,broken image"/>\n' + \
             '</defs>\n' + \
             '</svg>',
             svg
         )
     finally:
         if os.path.isfile(dst):
             os.unlink(dst)
Пример #3
0
def merge_files(filenames, base, filetype, dst_filename, identifier=None):
    """
    Merge multiple files together and return their content.
    """
    content = []
    for fname in filenames:
        filename = fname
        if filetype == 'js':
            filename = compile_if_require_js_hook(filename)

        # silently ignore missing files
        try:
            txt = file_get_contents(filename)
        except IOError:
            txt = ''

        # Replace any django template variables by running it through a template
        # and return the template content
        if 'templating' in filename:
            txt = serve_static_with_context(txt, identifier)

        if len(txt) > 0:
            if filetype == 'css':
                txt = relocate_css_relative_resource_urls(txt, base, filename, dst_filename)
            content.append(txt)
            content.append('\n')
    return '\n'.join(content)
Пример #4
0
    def _assertStaticFile(self, filename, contains_content=None):
        path = os.path.join(settings.STATIC_ROOT, filename)
        self.assertTrue(os.path.isfile(path),
                        'expected file to exist: %s' % path)

        if contains_content:
            self.assertIn(contains_content, file_get_contents(path))
Пример #5
0
    def test_invalidate_should_rename_cached_files_and_clear_cache(self):
        # build cache
        self.cache.add('foo.html',
                       None,
                       None,
                       '<h1>Foo</h1>',
                       minify_html=False)
        self.cache.add('bar.html',
                       None,
                       None,
                       '<h1>Bar</h1>',
                       minify_html=False)
        self.cache.add('test/index.html',
                       None,
                       None,
                       '<h1>Test</h1>',
                       minify_html=False)
        self.cache.write()

        # invalidate
        self.cache.invalidate()

        # original files are gone
        self.assertFalse(
            os.path.isfile(os.path.join(settings.CACHE_ROOT, 'foo.html')))
        self.assertFalse(
            os.path.isfile(os.path.join(settings.CACHE_ROOT, 'bar.html')))
        self.assertFalse(
            os.path.isfile(
                os.path.join(settings.CACHE_ROOT, 'test', 'index.html')))

        # files renamed (. prefix)
        self.assertEqual(
            '<h1>Foo</h1>',
            file_get_contents(os.path.join(settings.CACHE_ROOT, '.foo.html')))
        self.assertEqual(
            '<h1>Bar</h1>',
            file_get_contents(os.path.join(settings.CACHE_ROOT, '.bar.html')))
        self.assertEqual(
            '<h1>Test</h1>',
            file_get_contents(
                os.path.join(settings.CACHE_ROOT, 'test', '.index.html')))

        # index file removed
        self.assertFalse(
            os.path.isfile(
                os.path.join(settings.CACHE_ROOT, self.cache.index_filename)))
Пример #6
0
    def test_should_save_timestamp_in_iso_format(self):
        ts = save_deploy_timestamp()

        timestamp = datetime.strptime(
            file_get_contents(get_deploy_timestamp_filename()),
            '%Y-%m-%dT%H:%M:%S'
        )
        self.assertEqual(datetime.now(), timestamp)
        self.assertEqual(datetime.now(), ts)
Пример #7
0
def load_resource_version_identifier():
    """
    Load resource version identifier from the website's deployment target folder.
    """
    filename = os.path.join(settings.STATIC_ROOT, 'revision')
    try:
        return file_get_contents(filename)
    except IOError:
        return None
Пример #8
0
    def test_should_overwrite_existing_file(self):
        file_put_contents(get_deploy_timestamp_filename(), 'hello world')
        save_deploy_timestamp()

        timestamp = datetime.strptime(
            file_get_contents(get_deploy_timestamp_filename()),
            '%Y-%m-%dT%H:%M:%S'
        )
        self.assertEqual(datetime.now(), timestamp)
Пример #9
0
 def get_pid(cls):
     """
     Return the process identifier (pid) that is stored in the pid file
     for the task runner. Returns None if no pid file exists or the pid
     cannot be parsed as an integer number.
     """
     try:
         return int(file_get_contents(cls.get_pid_filename()))
     except (ValueError, IOError):
         return None
Пример #10
0
    def test_create_svgicons_management_command_should_generate_svgicon_file(self):
        from cubane.svgicons.management.commands.create_svgicons import Command
        self.call_command(Command())

        # - email and location are stripped (style)
        # - phone style has been retained (see resource declaration in testapp)
        self.assertEqual(
            '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: none;"><symbol id="svgicon-email" viewBox="0 0 64 64"><g id="email-sc8O5C.tif"> <g> <path d="M6.4,13.7c17.1,0,34.1,0,51.2,0c0.1,0.1,0.2,0.1,0.4,0.2c1.3,0.8,1.4,2,0.4,3c-5.5,5.5-11,11-16.4,16.5 c-2.7,2.7-5.4,5.5-8.1,8.2c-1,1-2.6,1.1-3.5,0.1c-2-2-3.9-3.9-5.9-5.9c-3.5-3.5-6.9-7-10.4-10.5c-2.9-3-5.9-5.9-8.8-8.9 c-0.3-0.3-0.4-0.6-0.3-1C5.1,14.6,5.6,14,6.4,13.7z"/> <path d="M32,52.3c-8.1,0-16.2,0-24.4,0c-1,0-1.8-0.2-2.4-1.1c-0.5-0.9-0.5-1.4,0.3-2.1c4.5-4.6,9.1-9.1,13.6-13.7 c0.5-0.5,0.5-0.5,1,0c2.8,2.8,5.5,5.5,8.3,8.3c2,2,5.2,2,7.2,0c2.8-2.8,5.5-5.6,8.3-8.3c0.5-0.5,0.5-0.5,1,0 c2.9,2.9,5.7,5.8,8.6,8.6c1.7,1.7,3.4,3.5,5.2,5.2c0.4,0.4,0.5,0.9,0.4,1.4c-0.2,1-1.1,1.6-2.1,1.7c-0.2,0-0.4,0-0.6,0 C48.2,52.3,40.1,52.3,32,52.3z"/> <path d="M4.9,32.9c0-4,0-8,0-12.1c0-0.2-0.1-0.5,0.1-0.6c0.2-0.1,0.3,0.2,0.5,0.4c3.9,4,7.9,7.9,11.8,11.9c0.4,0.4,0.3,0.6,0,0.9 c-4,4-7.9,8-11.9,12c-0.1,0.1-0.2,0.3-0.4,0.2c-0.2-0.1-0.1-0.3-0.1-0.5C4.9,41,4.9,37,4.9,32.9z"/> <path d="M59.1,32.9c0,3.9,0,7.9,0,11.8c0,0.1,0,0.3,0,0.4c0,0.1,0.1,0.3-0.1,0.4c-0.2,0.1-0.3-0.1-0.4-0.2 c-0.7-0.7-1.4-1.4-2.1-2.1c-1.8-1.8-3.6-3.6-5.4-5.4c-1.5-1.5-3-3-4.5-4.5c-0.3-0.3-0.3-0.5,0-0.9c4-4,7.9-8,11.9-11.9 c0.1-0.1,0.2-0.2,0.3-0.2c0.1-0.1,0.3-0.1,0.3,0.1c0,0.2,0,0.3,0,0.5C59.1,24.9,59.1,28.9,59.1,32.9z"/> </g> </g></symbol><symbol id="svgicon-location" viewBox="0 0 64 64"><g id="location-xNv91c.tif"> <g> <path d="M28.4,0c1.8,0,3.5,0,5.3,0c0.1,0,0.2,0.1,0.4,0.1c8.7,1.3,15.1,5.8,18.9,13.7c2.1,4.2,2.9,8.8,1.9,13.5 c-0.7,3.4-2.2,6.5-3.9,9.6c-4.2,7.7-9.4,14.7-15,21.5c-1.5,1.9-3.1,3.7-4.7,5.6c-0.1,0-0.2,0-0.3,0C24.8,57,19,49.7,14,41.7 c-3.1-4.9-5.9-10-7-15.8c0-1.5,0-3,0-4.5c0-0.2,0.1-0.4,0.1-0.6c1.5-9.1,6.4-15.4,14.8-19.1C24,0.8,26.2,0.4,28.4,0z"/> </g> </g></symbol><symbol id="svgicon-phone" viewBox="0 0 60 60"><path d="M9.8,6.2c-0.9,0.6-7.2,5.2-8.1,10.4S0.5,27.1,6.2,36.2c5.9,9.3,17.4,20.7,27.4,21.3c8.9,0.5,15.2-5.7,15.9-8.1 c0.7-2.3-2.7-5.8-3.6-6.5c-0.8-0.6-5.6-4.9-8.4-4.3c-4.6,0.9-4.3,4.9-8.4,5.3c-2.4,0.2-5.3-1.5-9.6-6.8c-9.4-11.7-4.8-12.2-3.1-13.7 c1.7-1.5,4.7-3.2,4.1-5.6s-3-8.5-5.5-10.6c-1.8-1.7-2.1-1.6-2.8-1.7S10.7,5.6,9.8,6.2z" style="fill:#FFFFFF;"/></symbol></svg>',
            file_get_contents(self._get_path())
        )
Пример #11
0
    def test_should_save_version_to_file(self):
        version = generate_resource_version_identifier()
        save_resource_version_identifier(version)

        filename = get_resource_version_filename()
        self.assertTrue(os.path.isfile(filename))

        content = file_get_contents(filename)
        os.remove(filename)
        self.assertEqual(version, content)
Пример #12
0
def load_deploy_timestamp():
    """
    Load resource version identifier from the website's deployment target folder.
    """
    try:
        return datetime.strptime(
            file_get_contents(get_deploy_timestamp_filename()),
            TIMESTAMP_FORMAT)
    except (IOError, ValueError):
        return None
Пример #13
0
    def test_should_write_file_content_as_unicode(self):
        tmp = tempfile.gettempdir()
        filename = os.path.join(tmp, 'test.txt')
        content = unicode('Hello World')
        file_put_contents(filename, content)

        content_read = file_get_contents(filename)
        self.assertEqual(content_read, content)
        self.assertIsInstance(content_read, unicode)

        os.remove(filename)
Пример #14
0
    def test_should_receive_file_content_as_unicode(self):
        tmp = tempfile.gettempdir()
        filename = os.path.join(tmp, 'test.txt')
        content = unicode('Hello World')
        with codecs.open(filename, 'w', encoding='utf-8') as f:
            f.write(content)

        content_read = file_get_contents(filename)
        self.assertEqual(content_read, content)
        self.assertIsInstance(content_read, unicode)

        os.remove(filename)
Пример #15
0
def _copy_file(src_path, dst_path, context):
    """
    Copy the given file to the given dest. path. The filename and it's
    content may be substituted.
    """
    if is_text_file(src_path):
        # text, substritute content against given context
        content = file_get_contents(src_path)
        content = _get_substituted_content(content, context)
        file_put_contents(dst_path, content)
    else:
        # binary, directly copy without substitution
        shutil.copyfile(src_path, dst_path)
Пример #16
0
    def test_should_generate_src_files_if_feature_is_turned_on(self):
        base_path = self.get_testapp_static_path()
        dst_filename = os.path.join(tempfile.gettempdir(), 'minified.css')
        src_filename = os.path.join(tempfile.gettempdir(), 'minified.css.src')

        minify_files([os.path.join(base_path, 'css', 'test_minify.css')],
                     base_path, dst_filename, 'css')

        content = file_get_contents(src_filename)
        os.remove(dst_filename)
        os.remove(src_filename)

        self.assertEqual('\nbody {\n    color: red;\n}\n\n', content)
Пример #17
0
    def test_add_file_to_cache_should_remove_invalidated_content_version_if_exists(
            self):
        # build cache
        lastmod = datetime(2016, 6, 18, 16, 55, 23)
        self.cache.add('index.html',
                       lastmod,
                       None,
                       '<h1>Foo</h1>',
                       minify_html=False)
        self.cache.write()

        # invalidate
        self.cache.invalidate()
        self.assertFalse(
            os.path.isfile(os.path.join(settings.CACHE_ROOT, 'index.html')))
        self.assertEqual(
            '<h1>Foo</h1>',
            file_get_contents(os.path.join(settings.CACHE_ROOT,
                                           '.index.html')))

        # add updated content with a newer timestamp again (changed)
        new_lastmod = datetime(2016, 6, 18, 17, 55, 23)
        self.cache = Cache()
        self.cache.add('index.html',
                       new_lastmod,
                       None,
                       '<h1>Foo</h1>',
                       minify_html=False)
        self.cache.write()

        # invalidated version should have been removed
        self.assertFalse(
            os.path.isfile(os.path.join(settings.CACHE_ROOT, '.index.html')))
        self.assertEqual(
            '<h1>Foo</h1>',
            file_get_contents(os.path.join(settings.CACHE_ROOT, 'index.html')))
        self.assertEqual(new_lastmod, self._get_cache_mtime('index.html'))
Пример #18
0
 def test_should_crop_to_new_aspect_ratio_based_on_center_position_for_portrait(self):
     src = self.get_test_image_path('test_svg_crop_portrait.svg')
     dst = os.path.join(tempfile.gettempdir(), 'resized_svg_image.svg')
     try:
         resize_svg_image(src, dst, 400, 400, prefix='')
         svg = file_get_contents(dst)
         self.assertEqual(
             '<?xml version="1.0" encoding="utf-8"?>\n' + \
             '<svg id="Layer_1" style="enable-background:new 0 40 80 80;" version="1.1" viewBox="0 40 80 80" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px">\n' + \
             '<polygon fill="red" points="36.3,83.7 0.1,62.7 0,20.8 36.1,0 72.2,21.1 72.4,62.9 "/>\n' + \
             '</svg>',
             svg
         )
     finally:
         if os.path.isfile(dst):
             os.unlink(dst)
Пример #19
0
    def handle(self, *args, **options):
        """
        Run command.
        """
        # load source data
        filename = os.path.join(settings.CUBANE_PATH, 'rawdata', 'countries.json')
        json = decode_json(file_get_contents(filename))

        # generate xml file content
        xml = []
        xml.append('<?xml version="1.0" encoding="utf-8"?>')
        xml.append('<django-objects version="1.0">')
        for c in json:
            # country name(s)
            name = c.get('name')

            # num code
            num_code = c.get('ccn3')

            # calling code
            calling_code = c.get('callingCode')
            if len(calling_code) >= 1:
                calling_code = calling_code[0]
            else:
                calling_code = None

            # generate xml
            xml.append('  <object pk="%s" model="cubane.country">' % c.get('cca2'))
            xml.append('    <field type="CharField" name="name">%s</field>' % name.get('common').upper())
            xml.append('    <field type="BooleanField" name="flag_state">0</field>')
            xml.append('    <field type="CharField" name="printable_name">%s</field>' % name.get('common'))
            xml.append('    <field type="CharField" name="iso3">%s</field>' % c.get('cca3'))
            xml.append('    <field type="BooleanField" name="landlocked">%s</field>' % ('1' if c.get('landlocked') else '0'))
            if num_code:
                xml.append('    <field type="PositiveSmallIntegerField" name="numcode">%s</field>' % num_code)
            xml.append('    <field type="CharField" name="calling_code">%s</field>' % calling_code)
            xml.append('  </object>')
        xml.append('</django-objects>')

        # save to xml file (fixture)
        filename = os.path.join(settings.CUBANE_PATH, 'fixtures', 'cubane', 'country.xml')
        file_put_contents(filename, '\n'.join(xml))

        # import fixture file
        call_command('loaddata', 'cubane/country.xml', interactive=False)
Пример #20
0
    def _get_minified_content(self, filenames, filetype):
        """
        Minify given list of files of given file type.
        """
        if not isinstance(filenames, list):
            filenames = [filenames]

        dst_filename = os.path.join(tempfile.gettempdir(), 'minified')
        base_path = self.get_testapp_static_path()
        filenames = [
            os.path.join(base_path, filename) for filename in filenames
        ]

        minify_files(filenames, base_path, dst_filename, filetype)
        content = file_get_contents(dst_filename)
        os.remove(dst_filename)

        return content
Пример #21
0
def get_resource(url_path):
    """
    Return the actual content of the file given by url_path, which is the
    absolute web path.
    """
    path = get_resource_path(url_path)

    # fail in DEBUG, otherwise return empty content in production
    if settings.DEBUG:
        if not os.path.isfile(path):
            raise ValueError(
                'Unable to load resource content from file \'%s\'.' % path
            )

    try:
        return file_get_contents(path)
    except IOError:
        return ''
Пример #22
0
 def test_should_inline_style(self):
     src = self.get_test_image_path('test_svg_with_style.svg')
     dst = os.path.join(tempfile.gettempdir(), 'resized_svg_image.svg')
     try:
         resize_svg_image(src, dst, 164.4, 83.7, optimize=True, prefix='')
         svg = file_get_contents(dst)
         self.assertEqual(
             '<?xml version="1.0" encoding="utf-8"?>\n' + \
             '<svg id="Layer_1" style="enable-background:new 0 0 164 84;" version="1.1" viewBox="0 0 164 84" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px">\n' + \
             '\n' + \
             '<polygon points="36.3,83.7 0.1,62.7 0,20.8 36.1,0 72.2,21.1 72.4,62.9 " style="fill:#E8318A;"/>\n' + \
             '<polygon points="36.4,62.9 54.5,73 54.5,52.4 " style="fill:#BF2174;"/>\n' + \
             '<polygon points="36.4,62.9 36.7,42.1 54.5,52.4 " style="opacity:0.56;fill:#EA53A2;"/>\n' + \
             '</svg>',
             svg
         )
     finally:
         if os.path.isfile(dst):
             os.unlink(dst)
Пример #23
0
 def test_should_prefix_clip_path_url_references(self):
     src = self.get_test_image_path('test_svg_with_clippath_url_ref.svg')
     dst = os.path.join(tempfile.gettempdir(), 'resized_svg_image.svg')
     try:
         resize_svg_image(src, dst, 0, 0, crop=False, optimize=True, prefix='123')
         svg = file_get_contents(dst)
         self.assertEqual(
             '<?xml version="1.0" encoding="utf-8"?>\n' +
             '<svg data-prefix="b23" id="b23_Layer_1" style="enable-background:new 0 0 64 64;" version="1.1" viewBox="0 0 64 64" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px">\n' +
             '<clipPath id="b23_clip"><path d="M441.105,324.213l44.837,10.308l13.761,-59.851l-44.837,-10.309l-13.761,59.852l0,0Z"/></clipPath>\n' +
             '<g clip-path="url(#b23_clip)">\n' +
             '<path d="36.3,83.7 0.1,62.7 0,20.8 36.1,0 72.2,21.1 72.4,62.9"/>\n' +
             '</g>\n' +
             '</svg>',
             svg
         )
     finally:
         if os.path.isfile(dst):
             os.unlink(dst)
Пример #24
0
    def _assert_downsampling(self, filename):
        src = self.get_test_image_path(filename)
        dst = os.path.join(tempfile.gettempdir(), 'resized_svg_image.svg')
        try:
            resize_svg_image(src, dst, 50, 50)

            # svg file with bitmap data embedded should NOT be the same
            # image after resize...
            self.assertFalse(is_same_file(src, dst))

            # image size should be less
            self.assertTrue(os.path.getsize(dst) < os.path.getsize(src))

            # the resulting image should still be an svg image with path
            # information in it
            content = file_get_contents(dst)
            self.assertIn('<svg', content)
            self.assertIn('<path', content)
        finally:
            if os.path.isfile(dst):
                os.unlink(dst)
Пример #25
0
def inline_svgicons(target):
    """
    Renders inline markup for defining an SVG icon sheet for all SVG icon
    assets defined for the given bucket name (target). SVG assets are using the
    standard resource system that is also used for CSS and Javascript assets in
    combination with resources and inline_resources template tags.
    """
    if target not in get_resource_target_definition():
        raise AttributeError(
            'Expected valid \'target\' argument for template ' +
            'tag \'inline_svgicons\'.')

    if settings.DEBUG:
        return mark_safe(
            get_combined_svg(get_resources(target, 'svg'),
                             get_resources(target, 'svg', 'with-style')))
    else:
        identifier = load_resource_version_identifier()
        filename = get_svgicons_filename(target, identifier)
        path = os.path.join(settings.STATIC_ROOT, filename)
        return mark_safe(file_get_contents(path))
Пример #26
0
    def get_status(cls):
        """
        Return task runner status information.
        """
        try:
            taskinfo = decode_json(file_get_contents(
                cls.get_status_filename()))

            # calc. percentage
            if taskinfo.get('stopped', False):
                percent = 0
            else:
                counter = taskinfo.get('recordCounter', 0)
                total = taskinfo.get('totalRecords', 0)
                if counter > total:
                    total = counter
                if total == 0:
                    total = 1
                percent = int(round(float(counter) / float(total) * 100.0))
            taskinfo['percent'] = percent

            return taskinfo
        except IOError:
            return {}
Пример #27
0
def resize_svg_image(filename,
                     dst_filename,
                     width,
                     height,
                     focal_point=None,
                     optimize=True,
                     crop=True,
                     prefix=None):
    """
    Scale the given vector image (SVG) to the given width and height and save
    the result as a new vector image as the given dest. filename. Vector
    images, such as SVG do not necessarily need to be resized, however they may
    contain bitmap data which we will scale accordingly. Any vector data and
    viewport information is preserved.

    In addition, we will prefix all id attribute values and internal references
    with a short prefix that is unique to the file. We do this in case we inline
    multiple SVG files into the actual websites and we do not want to have any
    identifiers and/or references colliding.

    Finally, we also remove any style from the SVG, since this may then become
    global to the document when we inline an SVG.
    """
    def _scale_image(data, width, height):
        """
        Scale given image data blog to fit the given width and height.
        """
        # open image data
        try:
            img = WandImage(blob=data)
        except NOT_AN_IMAGE_WAND_EXCEPTIONS:
            # not an image! -> ignore and leave as is
            return None

        # do not upscale!
        w, h = img.size
        if width > w or height > h:
            width = w
            height = h

        if width < 1:
            width = 1

        if height < 1:
            height = 1

        # calc. new width and height by fitting it into the
        # desired boundaries
        w, h = get_image_fitting(w, h, width, height)
        img.resize(w, h)

        # return image blob
        blob = io.BytesIO()
        img.strip()
        img.save(file=blob)
        return blob.getvalue()

    def _match_image(m):
        """
        Process SVG <image> tag. Only deal with base64 embedded image data and
        ignore external references.
        """
        # extract attributes
        attr = {}
        for attrname, value in re.findall(
                r'(?P<attrname>\w+)="(?P<value>.*?)"', m.group('attr')):
            attr[attrname] = value

        # get image data
        data = attr.get('href', '')
        href = re.match(r'^data:image\/(?P<fmt>\w+);base64,(?P<data>.*?)$',
                        data)
        data = None
        fmt = None
        if href:
            fmt = href.group('fmt')
            try:
                data = base64.b64decode(href.group('data'))
            except TypeError:
                # base64 decoding error! -> ignore and leave as is
                pass

        # scale embedded image down to the max. given width, hegiht is
        # determined by aspect ratio of the image...
        if data is not None:
            data = _scale_image(data, width, height)
            if data is not None:
                data = base64.b64encode(data)
                attr['href'] = 'data:image/%s;base64,%s' % (fmt, data)
                return '<image %s/>' % ' '.join([
                    '%s="%s"' % (name, value) for name, value in attr.items()
                ])

        # fallback -> leave as is
        return m.group(0)

    def _replace_images(svg):
        """
        Find any replace any references to images.
        """
        return re.sub(r'<image (?P<attr>.*?)(?P<tail>(/>)|(></image>))',
                      _match_image, svg)

    def _get_viewbox(xml):
        """
        Return the viewbox coordinates from the viewBox attribute on the svg tag.
        """
        # parse vieewBox attribute
        viewbox = xml.svg.get('viewBox', '')
        components = re.split(r'[\s,]', viewbox, 4)
        x, y, w, h = (0.0, 0.0, 64.0, 64.0)
        if len(components) == 4:
            try:
                x, y, w, h = [float(c) for c in components]
            except:
                pass

        # do not allow an invalid viewbox, default to square
        if h == 0.0:
            h = 1.0

        return x, y, w, h

    def _set_viewbox(xml, x, y, w, h):
        """
        Set the viewBox within the given SVG xml markup to the new dimensions
        as given.
        """
        # set viewBox
        xml.svg['viewBox'] = '%s %s %s %s' % (x, y, w, h)

        # rewrite enable-background style (not really used by many browsders,
        # but we want to be consistent)
        style = xml.svg.get('style', '')
        style = re.sub(
            r'enable-background:\s*new\s+([-.,\d]+)\s+([-.,\d]+)\s+([-.,\d]+)\s+([-.,\d]+);?',
            'enable-background:new %s %s %s %s;' % (x, y, w, h), style)
        xml.svg['style'] = style

    def _normalised(x):
        """
        Return integer of x, if x has no fraction component.
        """
        intx = int(x)
        return intx if intx == x else x

    def _scale_viewbox(xml, width, height):
        """
        Scale the viewBox to the new aspect ratio of the given width and height.
        """
        # get viewBox from current SVG
        x, y, w, h = _get_viewbox(xml)

        # make the target width the same with as the SVG. The target height
        # is adjusted based on the target aspect ratio
        if height == 0:
            height = 1
        ar = float(width) / float(height)
        width = w
        height = width / ar

        # determine new cropping area
        cropx, cropy, cropw, croph = get_image_crop_area(
            w, h, width, height, focal_point)

        # adjust to new (cropped) viewBox
        cropx += x
        cropy += y

        # normalise values to int if we do not have a fraction
        cropx = _normalised(cropx)
        cropy = _normalised(cropy)
        cropw = _normalised(cropw)
        croph = _normalised(croph)

        # apply new viewbox
        _set_viewbox(xml, cropx, cropy, cropw, croph)

    def _inline_style(xml):
        """
        Take embedded style and inline all style information.
        """
        # extract style
        style = ''
        for tag in xml.svg.find_all('style'):
            style += '\n'.join(tag.contents) + '\n'
            tag.decompose()

        # inline all collected style
        inline_style(xml.svg, parse_style(style))
        remove_attr(xml.svg, ['class'])

    def _get_prefix(filename, prefix):
        """
        Return a unique prefix to be used, if the given prefix is None. Since
        the prefix may be used as unique identifiers, they must start with
        a letter and cannot start with a number.
        """
        # generate hash based on filename
        if prefix is None:
            m = hashlib.sha224()
            m.update(filename)
            prefix = m.hexdigest()[:6]

        # if the first character is a number, it becomes a letter
        # between a-f depending on the number.
        if prefix:
            try:
                n = int(prefix[0])
                prefix = ['a', 'b', 'c', 'd', 'e', 'f'][n % 6] + prefix[1:]
            except ValueError:
                pass

        if prefix != '' and not prefix.endswith('_'):
            prefix += '_'

        return prefix

    def _prefix_ids(node, prefix):
        prefix_ids(node, prefix)

    # open svg file as text and replace embedded bitmap data
    markup = file_get_contents(filename)
    markup = _replace_images(markup)

    # load xml
    if optimize or crop:
        xml = BeautifulSoup(markup, 'xml')
    else:
        xml = None

    # is SVG?
    if xml and xml.svg:
        # crop
        if crop:
            _scale_viewbox(xml, width, height)

        if optimize:
            _inline_style(xml)
            _prefix = _get_prefix(dst_filename, prefix)
            _prefix_ids(xml, _prefix)
            if _prefix:
                xml.svg['data-prefix'] = _prefix[:-1]

        # render xml out
        if xml:
            markup = unicode(xml)

    # write output to target filename
    file_put_contents(dst_filename, markup)