예제 #1
0
    def test_bundle_suprocess(self, mock_subproc_popen):
        """
        Test that bundling calls the correct subprocess command
        """
        app_name = 'app/dummy'

        def side_effect(*args, **kwargs):
            _bundle(app_name)
            return ('output', 'error')

        # mock Popen/communicate
        process_mock = mock_Popen(mock_subproc_popen, side_effect=side_effect)

        # Bundle app/dummy
        System.bundle(app_name, force=True)
        self.assertEqual(mock_subproc_popen.call_count, 1)
        command = mock_subproc_popen.call_args[0][0]
        outfile = os.path.join(settings.STATIC_ROOT, 'SYSTEMJS/{0}.js'.format(app_name))
        self.assertEqual(command, 'jspm bundle {0} {1}'.format(app_name, outfile))

        with open(outfile, 'r') as of:
            js = of.read()
        self.assertEqual(js, "alert('foo')\nSystem.import('app/dummy');\n")

        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #2
0
    def test_ioerror_caught(self, mock):
        def ioerror():
            raise IOError("Error")

        mock_Popen(mock, side_effect=ioerror)
        with self.assertRaises(BundleError):
            System.bundle("app/dummy", force=True)
    def test_sourcemap_comment_large_file(self, mock_version, mock_subproc_popen):
        """
        Same test as test_sourcemap_comment, except with a 'file' that's more
        than 100 bytes (to read multiple blocks).
        """
        mock_version.return_value = Version('0.15.7')
        app_name = 'app/dummy'

        lorem = '''
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
'''

        def side_effect(*args, **kwargs):
            content = 'alert(\'{}\')\n//# sourceMappingURL=dummy.js.map'.format(lorem)
            _bundle(app_name, content=content)
            return ('output', 'error')

        # mock Popen/communicate
        mock_Popen(mock_subproc_popen, side_effect=side_effect)

        # Bundle app/dummy
        system = System()
        system.bundle(app_name)
        outfile = os.path.join(settings.STATIC_ROOT, 'SYSTEMJS/{0}.js'.format(app_name))
        with open(outfile, 'r') as of:
            js = of.read()
        self.assertEqual(js, "alert('{}')\nSystem.import('app/dummy.js');\n"
                             "//# sourceMappingURL=dummy.js.map".format(lorem))
    def test_jspm_016_log_error(self, mock_version, mock_subproc_popen):
        """
        Test that bundles are generated with --log=err.

        JSPM > 0.16.0 has the --log option that surpresses levels of
        output.
        """
        mock_version.return_value = Version('0.16.3')

        app_name = 'app/dummy'

        def side_effect(*args, **kwargs):
            _bundle(app_name)
            return ('', 'Something went wrong')  # no stdout, no stderr -> success

        # mock Popen/communicate
        process_mock = mock_Popen(mock_subproc_popen, side_effect=side_effect)

        # Bundle app/dummy
        with self.assertRaises(BundleError) as ctx:
            system = System()
            system.bundle(app_name)

        self.assertEqual(ctx.exception.args[0], "Could not bundle \'app/dummy\': \nSomething went wrong")

        self.assertEqual(mock_subproc_popen.call_count, 1)
        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #5
0
    def test_jspm_016_log_error(self, mock_version, mock_subproc_popen):
        """
        Test that bundles are generated with --log=err.

        JSPM > 0.16.0 has the --log option that surpresses levels of
        output.
        """
        mock_version.return_value = Version('0.16.3')

        app_name = 'app/dummy'

        def side_effect(*args, **kwargs):
            _bundle(app_name)
            return ('', 'Something went wrong'
                    )  # no stdout, no stderr -> success

        # mock Popen/communicate
        process_mock = mock_Popen(mock_subproc_popen, side_effect=side_effect)

        # Bundle app/dummy
        with self.assertRaises(BundleError) as ctx:
            system = System()
            system.bundle(app_name)

        self.assertEqual(
            ctx.exception.args[0],
            "Could not bundle \'app/dummy\': \nSomething went wrong")

        self.assertEqual(mock_subproc_popen.call_count, 1)
        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #6
0
    def test_sourcemap_comment_end_newline(self, mock_version,
                                           mock_subproc_popen):
        """
        Asserts that the sourcemap comment is still at the end - with ending newline
        """
        mock_version.return_value = Version('0.15.7')
        app_name = 'app/dummy'

        def side_effect(*args, **kwargs):
            content = 'alert(\'foo\')\n//# sourceMappingURL=dummy.js.map\n'
            _bundle(app_name, content=content)
            return ('output', 'error')

        # mock Popen/communicate
        mock_Popen(mock_subproc_popen, side_effect=side_effect)

        # Bundle app/dummy
        system = System()
        system.bundle(app_name)
        outfile = os.path.join(settings.STATIC_ROOT,
                               'SYSTEMJS/{0}.js'.format(app_name))
        with open(outfile, 'r') as of:
            js = of.read()
        self.assertEqual(
            js, "alert('foo')\nSystem.import('app/dummy.js');\n"
            "//# sourceMappingURL=dummy.js.map")
예제 #7
0
    def test_bundle_suprocess(self, mock_subproc_popen):
        """
        Test that bundling calls the correct subprocess command
        """
        app_name = 'app/dummy'

        def side_effect(*args, **kwargs):
            _bundle(app_name)
            return ('output', 'error')

        # mock Popen/communicate
        process_mock = mock_Popen(mock_subproc_popen, side_effect=side_effect)

        # Bundle app/dummy
        system = System()
        system.bundle(app_name)
        self.assertEqual(mock_subproc_popen.call_count, 1)
        command = mock_subproc_popen.call_args[0][0]
        outfile = os.path.join(settings.STATIC_ROOT,
                               'SYSTEMJS/{0}.js'.format(app_name))
        self.assertEqual(command,
                         'jspm bundle {0} {1}'.format(app_name, outfile))

        with open(outfile, 'r') as of:
            js = of.read()
        self.assertEqual(js, "alert('foo')\nSystem.import('app/dummy.js');\n")

        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #8
0
    def test_oserror_caught(self, mock):
        def oserror():
            raise OSError('Error')

        mock_Popen(mock, side_effect=oserror)
        with self.assertRaises(BundleError):
            System.bundle('app/dummy', force=True)
예제 #9
0
    def test_ioerror_caught(self, mock):
        def ioerror():
            raise IOError('Error')

        mock_Popen(mock, side_effect=ioerror)
        with self.assertRaises(BundleError):
            system = System()
            system.bundle('app/dummy')
예제 #10
0
    def test_ioerror_caught(self, mock):

        def ioerror():
            raise IOError('Error')

        mock_Popen(mock, side_effect=ioerror)
        with self.assertRaises(BundleError):
            system = System()
            system.bundle('app/dummy')
예제 #11
0
    def test_bundlesfx_suprocess(self, mock_subproc_popen):
        """
        Test that bundling calls the correct subprocess command
        """
        # mock Popen/communicate
        process_mock = mock_Popen(mock_subproc_popen)

        # Bundle app/dummy
        System.bundle('app/dummy', sfx=True, force=True)
        self.assertEqual(mock_subproc_popen.call_count, 1)
        command = mock_subproc_popen.call_args[0][0]
        outfile = os.path.join(settings.STATIC_ROOT, 'SYSTEMJS/app/dummy.js')
        self.assertEqual(command, 'jspm bundle-sfx app/dummy {0}'.format(outfile))

        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #12
0
 def test_bundle_result(self):
     """
     Test that bundling an app returns the correct relative path.
     """
     path = System.bundle('app/dummy')
     expected_path = os.path.join(settings.SYSTEMJS_OUTPUT_DIR, 'app/dummy.js')
     self.assertEqual(path, expected_path)
예제 #13
0
    def render(self, context):
        """
        Build the filepath by appending the extension.
        """
        module_path = self.path.resolve(context)
        if not settings.SYSTEMJS_ENABLED:
            if settings.SYSTEMJS_DEFAULT_JS_EXTENSIONS:
                name, ext = posixpath.splitext(module_path)
                if not ext:
                    module_path = '{}.js'.format(module_path)
            tpl = """<script type="text/javascript">System.import('{app}');</script>"""
            return tpl.format(app=module_path)

        # else: create a bundle
        rel_path = System.get_bundle_path(module_path)
        url = staticfiles_storage.url(rel_path)

        tag_attrs = {'type': 'text/javascript'}
        for key, value in self.tag_attrs.items():
            if not isinstance(value, bool):
                value = value.resolve(context)
            tag_attrs[key] = value

        return """<script{attrs} src="{url}"></script>""".format(
            url=url, attrs=flatatt(tag_attrs))
예제 #14
0
    def test_bundle_result(self, mock_subproc_popen):
        """
        Test that bundling an app returns the correct relative path.
        """
        system = System()

        def side_effect(*args, **kwargs):
            _bundle('app/dummy')
            return ('output', 'error')

        # mock Popen/communicate
        mock_Popen(mock_subproc_popen, side_effect=side_effect)

        path = system.bundle('app/dummy')
        expected_path = os.path.join(settings.SYSTEMJS_OUTPUT_DIR, 'app/dummy.js')
        self.assertEqual(path, expected_path)
예제 #15
0
    def handle(self, **options):
        self.verbosity = 2
        self.storage = staticfiles_storage
        extensions = options.get('extensions') or ['html']
        self.symlinks = options.get('symlinks')
        self.post_process = options['post_process']
        # self.post_processed_files = []

        self.extensions = handle_extensions(extensions)

        template_dirs = list(get_app_template_dirs('templates'))
        for config in settings.TEMPLATES:
            # only support vanilla Django templates
            if config['BACKEND'] != 'django.template.backends.django.DjangoTemplates':
                continue
            template_dirs += list(config['DIRS'])

        # find all template files

        all_files = []
        for template_dir in template_dirs:
            for dirpath, dirnames, filenames in os.walk(template_dir, topdown=True, followlinks=self.symlinks):
                for filename in filenames:
                    filepath = os.path.join(dirpath, filename)
                    file_ext = os.path.splitext(filename)[1]
                    if file_ext not in self.extensions:
                        continue
                    all_files.append(filepath)

        all_apps = []
        for fp in all_files:
            with io.open(fp, 'r', encoding=settings.FILE_CHARSET) as template_file:
                src_data = template_file.read()

            for t in Lexer(src_data, None).tokenize():
                if t.token_type == TOKEN_BLOCK:
                    imatch = SYSTEMJS_TAG_RE.match(t.contents)
                    if imatch:
                        all_apps.append(imatch.group('app'))

        bundled_files = OrderedDict()
        storage = FileSystemStorage(settings.STATIC_ROOT, base_url=settings.STATIC_URL)
        for app in all_apps:
            rel_path = System.bundle(app, force=True)
            bundled_files[rel_path] = (storage, rel_path)

        if self.post_process and hasattr(self.storage, 'post_process'):
            processor = self.storage.post_process(bundled_files, dry_run=False)
            for original_path, processed_path, processed in processor:
                if isinstance(processed, Exception):  # pragma: no cover
                    self.stderr.write("Post-processing '%s' failed!" % original_path)
                    # Add a blank line before the traceback, otherwise it's
                    # too easy to miss the relevant part of the error message.
                    self.stderr.write("")
                    raise processed
                if processed:  # pragma: no cover
                    self.log("Post-processed '%s' as '%s'" %
                             (original_path, processed_path), level=1)
                else:
                    self.log("Skipped post-processing '%s'" % original_path)  # pragma: no cover
예제 #16
0
    def render(self, context):
        """
        Build the filepath by appending the extension.
        """
        module_path = self.path.resolve(context)
        if not settings.SYSTEMJS_ENABLED:
            if settings.SYSTEMJS_DEFAULT_JS_EXTENSIONS:
                name, ext = posixpath.splitext(module_path)
                if not ext:
                    module_path = '{}.js'.format(module_path)

            if settings.SYSTEMJS_SERVER_URL:
                tpl = """<script src="{url}{app}" type="text/javascript"></script>"""
            else:
                tpl = """<script type="text/javascript">System.import('{app}');</script>"""
            return tpl.format(app=module_path, url=settings.SYSTEMJS_SERVER_URL)

        # else: create a bundle
        rel_path = System.get_bundle_path(module_path)
        url = staticfiles_storage.url(rel_path)

        tag_attrs = {'type': 'text/javascript'}
        for key, value in self.tag_attrs.items():
            if not isinstance(value, bool):
                value = value.resolve(context)
            tag_attrs[key] = value

        return """<script{attrs} src="{url}"></script>""".format(
            url=url, attrs=flatatt(tag_attrs)
        )
예제 #17
0
    def test_bundle_result(self, mock_subproc_popen):
        """
        Test that bundling an app returns the correct relative path.
        """
        system = System()

        def side_effect(*args, **kwargs):
            _bundle('app/dummy')
            return ('output', 'error')

        # mock Popen/communicate
        mock_Popen(mock_subproc_popen, side_effect=side_effect)

        path = system.bundle('app/dummy')
        expected_path = os.path.join(settings.SYSTEMJS_OUTPUT_DIR,
                                     'app/dummy.js')
        self.assertEqual(path, expected_path)
예제 #18
0
    def test_bundlesfx_suprocess(self, mock_subproc_popen):
        """
        Test that bundling calls the correct subprocess command
        """
        # mock Popen/communicate
        process_mock = mock_Popen(mock_subproc_popen)

        # Bundle app/dummy
        system = System(sfx=True)
        system.bundle('app/dummy')
        self.assertEqual(mock_subproc_popen.call_count, 1)
        command = mock_subproc_popen.call_args[0][0]
        outfile = os.path.join(settings.STATIC_ROOT, 'SYSTEMJS/app/dummy.js')
        self.assertEqual(command,
                         'jspm bundle-sfx app/dummy {0}'.format(outfile))

        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #19
0
    def test_jspm_version_suprocess(self, mock_subproc_popen):
        """
        Test that JSPM version discovery works.
        """
        # mock Popen/communicate
        return_value = (b'0.15.7\nRunning against global jspm install.\n', '')
        process_mock = mock_Popen(mock_subproc_popen, return_value=return_value)

        system = System()

        # Call version
        version = system.get_jspm_version({'jspm': 'jspm'})
        self.assertEqual(mock_subproc_popen.call_count, 1)
        self.assertEqual(version, Version('0.15.7'))

        command = mock_subproc_popen.call_args[0][0]
        self.assertEqual(command, 'jspm --version')
        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #20
0
    def test_jspm_version_suprocess(self, mock_subproc_popen):
        """
        Test that JSPM version discovery works.
        """
        # mock Popen/communicate
        return_value = (b'0.15.7\nRunning against global jspm install.\n', '')
        process_mock = mock_Popen(mock_subproc_popen,
                                  return_value=return_value)

        system = System()

        # Call version
        version = system.get_jspm_version({'jspm': 'jspm'})
        self.assertEqual(mock_subproc_popen.call_count, 1)
        self.assertEqual(version, Version('0.15.7'))

        command = mock_subproc_popen.call_args[0][0]
        self.assertEqual(command, 'jspm --version')
        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #21
0
    def test_jspm_version_suprocess_error(self, mock_subproc_popen):
        """
        Test that bundling calls the correct subprocess command
        """
        # mock Popen/communicate
        return_value = (b'gibberish', 'a jspm error')
        process_mock = mock_Popen(mock_subproc_popen, return_value=return_value)

        system = System()

        # Call version
        with self.assertRaises(BundleError):
            system.get_jspm_version({'jspm': 'jspm'})

        self.assertEqual(mock_subproc_popen.call_count, 1)

        command = mock_subproc_popen.call_args[0][0]
        self.assertEqual(command, 'jspm --version')
        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #22
0
    def test_jspm_016_log(self, mock_version, mock_subproc_popen):
        """
        Test that bundles are generated with --log=err.

        JSPM > 0.16.0 has the --log option that surpresses levels of
        output.
        """
        mock_version.return_value = Version('0.16.3')

        app_name = 'app/dummy'

        def side_effect(*args, **kwargs):
            _bundle(app_name)
            return ('', '')  # no stdout, no stderr -> success

        # mock Popen/communicate
        process_mock = mock_Popen(mock_subproc_popen, side_effect=side_effect)

        # Bundle app/dummy
        system = System()
        system.bundle(app_name)
        self.assertEqual(mock_subproc_popen.call_count, 1)

        command = mock_subproc_popen.call_args
        outfile = os.path.join(settings.STATIC_ROOT,
                               'SYSTEMJS/{0}.js'.format(app_name))

        self.assertEqual(
            command,
            mock.call('jspm bundle {0} {1} --log err'.format(
                app_name, outfile),
                      stderr=subprocess.PIPE,
                      stdout=subprocess.PIPE,
                      stdin=subprocess.PIPE,
                      shell=True,
                      cwd=None))

        with open(outfile, 'r') as of:
            js = of.read()
        self.assertEqual(js, "alert('foo')\nSystem.import('app/dummy.js');\n")

        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #23
0
    def test_jspm_version_suprocess_error(self, mock_subproc_popen):
        """
        Test that bundling calls the correct subprocess command
        """
        # mock Popen/communicate
        return_value = (b'gibberish', 'a jspm error')
        process_mock = mock_Popen(mock_subproc_popen,
                                  return_value=return_value)

        system = System()

        # Call version
        with self.assertRaises(BundleError):
            system.get_jspm_version({'jspm': 'jspm'})

        self.assertEqual(mock_subproc_popen.call_count, 1)

        command = mock_subproc_popen.call_args[0][0]
        self.assertEqual(command, 'jspm --version')
        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #24
0
    def test_jspm_016_log(self, mock_version, mock_subproc_popen):
        """
        Test that bundles are generated with --log=err.

        JSPM > 0.16.0 has the --log option that surpresses levels of
        output.
        """
        mock_version.return_value = Version('0.16.3')

        app_name = 'app/dummy'

        def side_effect(*args, **kwargs):
            _bundle(app_name)
            return ('', '')  # no stdout, no stderr -> success

        # mock Popen/communicate
        process_mock = mock_Popen(mock_subproc_popen, side_effect=side_effect)

        # Bundle app/dummy
        system = System()
        system.bundle(app_name)
        self.assertEqual(mock_subproc_popen.call_count, 1)

        command = mock_subproc_popen.call_args
        outfile = os.path.join(settings.STATIC_ROOT, 'SYSTEMJS/{0}.js'.format(app_name))

        self.assertEqual(
            command,
            mock.call(
                'jspm bundle {0} {1} --log err'.format(app_name, outfile),
                stderr=subprocess.PIPE, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
                shell=True, cwd=None
            )
        )

        with open(outfile, 'r') as of:
            js = of.read()
        self.assertEqual(js, "alert('foo')\nSystem.import('app/dummy.js');\n")

        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #25
0
    def render(self, context):
        """
        Build the filepath by appending the extension.
        """
        module_path = self.path.resolve(context)
        if not settings.SYSTEMJS_ENABLED:
            tpl = """<script type="text/javascript">System.import('{app}');</script>"""
            return tpl.format(app=module_path)

        # else: create a bundle
        rel_path = System.bundle(module_path)
        url = staticfiles_storage.url(rel_path)
        return """<script type="text/javascript" src="{url}"></script>""".format(url=url)
예제 #26
0
    def test_bundle_minify_suprocess(self, mock_subproc_popen):
        """
        Test that bundling calls the correct subprocess command
        """

        app_name = 'app/dummy'

        def side_effect(*args, **kwargs):
            _bundle(app_name)
            return ('output', 'error')

        # mock Popen/communicate
        process_mock = mock_Popen(mock_subproc_popen, side_effect=side_effect)

        # Bundle app/dummy
        system = System(minify=True)
        system.bundle('app/dummy')
        self.assertEqual(mock_subproc_popen.call_count, 1)
        command = mock_subproc_popen.call_args[0][0]
        outfile = os.path.join(settings.STATIC_ROOT, 'SYSTEMJS/app/dummy.js')
        self.assertEqual(command, 'jspm bundle app/dummy {0} --minify'.format(outfile))

        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #27
0
    def test_sourcemap_comment_end_newline(self, mock_version, mock_subproc_popen):
        """
        Asserts that the sourcemap comment is still at the end - with ending newline
        """
        mock_version.return_value = Version('0.15.7')
        app_name = 'app/dummy'

        def side_effect(*args, **kwargs):
            content = 'alert(\'foo\')\n//# sourceMappingURL=dummy.js.map\n'
            _bundle(app_name, content=content)
            return ('output', 'error')

        # mock Popen/communicate
        mock_Popen(mock_subproc_popen, side_effect=side_effect)

        # Bundle app/dummy
        system = System()
        system.bundle(app_name)
        outfile = os.path.join(settings.STATIC_ROOT, 'SYSTEMJS/{0}.js'.format(app_name))
        with open(outfile, 'r') as of:
            js = of.read()
        self.assertEqual(js, "alert('foo')\nSystem.import('app/dummy.js');\n"
                             "//# sourceMappingURL=dummy.js.map")
예제 #28
0
    def test_sourcemap_comment_large_file(self, mock_version,
                                          mock_subproc_popen):
        """
        Same test as test_sourcemap_comment, except with a 'file' that's more
        than 100 bytes (to read multiple blocks).
        """
        mock_version.return_value = Version('0.15.7')
        app_name = 'app/dummy'

        lorem = '''
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
'''

        def side_effect(*args, **kwargs):
            content = 'alert(\'{}\')\n//# sourceMappingURL=dummy.js.map'.format(
                lorem)
            _bundle(app_name, content=content)
            return ('output', 'error')

        # mock Popen/communicate
        mock_Popen(mock_subproc_popen, side_effect=side_effect)

        # Bundle app/dummy
        system = System()
        system.bundle(app_name)
        outfile = os.path.join(settings.STATIC_ROOT,
                               'SYSTEMJS/{0}.js'.format(app_name))
        with open(outfile, 'r') as of:
            js = of.read()
        self.assertEqual(
            js, "alert('{}')\nSystem.import('app/dummy.js');\n"
            "//# sourceMappingURL=dummy.js.map".format(lorem))
예제 #29
0
    def test_bundle_minify_suprocess(self, mock_subproc_popen):
        """
        Test that bundling calls the correct subprocess command
        """

        app_name = 'app/dummy'

        def side_effect(*args, **kwargs):
            _bundle(app_name)
            return ('output', 'error')

        # mock Popen/communicate
        process_mock = mock_Popen(mock_subproc_popen, side_effect=side_effect)

        # Bundle app/dummy
        system = System(minify=True)
        system.bundle('app/dummy')
        self.assertEqual(mock_subproc_popen.call_count, 1)
        command = mock_subproc_popen.call_args[0][0]
        outfile = os.path.join(settings.STATIC_ROOT, 'SYSTEMJS/app/dummy.js')
        self.assertEqual(command,
                         'jspm bundle app/dummy {0} --minify'.format(outfile))

        self.assertEqual(process_mock.communicate.call_count, 1)
예제 #30
0
    def handle(self, **options):
        super(Command, self).handle(**options)

        self.post_process = options['post_process']
        self.minimal = options.get('minimal')

        self.verbosity = 2
        self.storage = copy(staticfiles_storage)
        self.storage.systemjs_bundling = True  # set flag to check later

        # initialize SystemJS specific objects to process the bundles
        tracer = SystemTracer(node_path=options.get('node_path'))
        system_opts = self.get_system_opts(options)
        system = System(**system_opts)

        has_different_options = self.minimal and tracer.get_bundle_options() != system_opts

        # discover the apps being imported in the templates
        all_apps = self.find_apps(templates=options.get('templates'))
        all_apps = set(sum(all_apps.values(), []))

        bundled_files = OrderedDict()
        # FIXME: this should be configurable, if people use S3BotoStorage for example, it needs to end up there
        storage = FileSystemStorage(settings.STATIC_ROOT, base_url=settings.STATIC_URL)
        for app in all_apps:
            # do we need to generate the bundle for this app?
            if self.minimal and not (has_different_options or tracer.check_needs_update(app)):
                # check if the bundle actually exists - if it doesn't, don't skip it
                # this happens on the first ever bundle
                bundle_path = System.get_bundle_path(app)
                if self.storage.exists(bundle_path):
                    self.stdout.write('Checked bundle for app \'{app}\', no changes found'.format(app=app))
                    continue

            rel_path = system.bundle(app)
            if not self.storage.exists(rel_path):
                self.stderr.write('Could not bundle {app}'.format(app=app))
            else:
                self.stdout.write('Bundled {app} into {out}'.format(app=app, out=rel_path))
            bundled_files[rel_path] = (storage, rel_path)

        if self.minimal and bundled_files:
            self.stdout.write('Generating the new depcache and writing to file...')
            all_deps = {app: tracer.trace(app) for app in all_apps}
            tracer.write_depcache(all_deps, system_opts)

        if self.post_process and hasattr(self.storage, 'post_process'):
            # post-process system.js if it's within settings.STATIC_ROOT
            systemjs_path = find_systemjs_location()
            try:
                within_static_root = self.storage.exists(systemjs_path)
            except SuspiciousFileOperation:
                within_static_root = False
            if within_static_root:
                relative = os.path.relpath(systemjs_path, settings.STATIC_ROOT)
                bundled_files[relative] = (storage, relative)

            processor = self.storage.post_process(bundled_files, dry_run=False)
            for original_path, processed_path, processed in processor:
                if isinstance(processed, Exception):  # pragma: no cover
                    self.stderr.write("Post-processing '%s' failed!" % original_path)
                    # Add a blank line before the traceback, otherwise it's
                    # too easy to miss the relevant part of the error message.
                    self.stderr.write("")
                    raise processed
                if processed:  # pragma: no cover
                    self.log("Post-processed '%s' as '%s'" % (original_path, processed_path), level=1)
                else:
                    self.log("Skipped post-processing '%s'" % original_path)  # pragma: no cover