Example #1
0
def printer_label(sample):
    """Generate the PDF of a sample for the label printer.

    :param sample: the sample the label of which should be generated

    :type sample: `samples.models.Sample`

    :return:
      the PDF as a byte stream

    :rtype: str
    """
    output = StringIO()
    text = sample.name
    c = canvas.Canvas(output, pagesize=(width, height))
    c.setAuthor("JuliaBase samples database")
    c.setTitle(text)
    c.setSubject("Label of {0} for the label printer".format(text))
    try:
        print_line(c, 0, fontsize, text)
    except ExcessException:
        first, second = best_split(text)
        print_line(c, height / 2, fontsize_half, first, force=True)
        print_line(c, 0, fontsize_half, second, force=True)
    c.drawImage(ImageReader("http://chart.googleapis.com/chart?chs=116x116&cht=qr&chl={0}&chld=H|1".format(sample.id)),
                width - height, 0, height, height)
    c.showPage()
    c.save()
    return output.getvalue()
Example #2
0
def thumbnail(file, size='400x100'):
    """
    Creates a thumbnail of an image with the specified size, returning
    the URL of the thumbnail.
    """
    x, y = [int(x) for x in size.split('x')]

    filename = file.name
    if filename.find(".") != -1:
        basename, format = filename.rsplit('.', 1)
        miniature = '%s_%s.%s' % (basename, size, format)
    else:
        basename = filename
        miniature = '%s_%s' % (basename, size)

    storage = file.storage

    if not storage.exists(miniature):
        try:
            file = storage.open(filename, 'rb')
            data = StringIO(file.read())
            file.close()

            image = Image.open(data)
            image.thumbnail([x, y], Image.ANTIALIAS)

            save_image_to_storage(image, storage, miniature)
        except (IOError, KeyError) as e:
            logging.error('Error thumbnailing image file %s and saving '
                          'as %s: %s' % (filename, miniature, e),
                          exc_info=1)
            return ""

    return storage.url(miniature)
Example #3
0
    def server_connection(self, **kwargs):
        """Returns a context manager which yields an LDAP connection object.  All
        keyword parameters passed are passed to the connection constructor.
        Note that “connection” here means a Python ldap3 object rather than the
        :py:class:`LDAPConnection` class.

        :raises ldap3.LDAPInvalidCredentialsResult: if you proveded user
          credentials in ``kwargs`` and they were invalid.
        """
        connection_kwargs = {"raise_exceptions": True, "read_only": True}
        connection_kwargs.update(kwargs)
        for ad_ldap_url in settings.LDAP_URLS:
            server = ldap3.Server(**self.get_server_parameters(ad_ldap_url))
            try:
                with ldap3.Connection(server, **connection_kwargs) as connection:
                    yield connection
                    break
            except ldap3.LDAPInvalidCredentialsResult:
                raise
            except ldap3.LDAPException:
                message = StringIO()
                traceback.print_exc(file=message)
                continue
        else:
            mail_admins("JuliaBase LDAP error", message.getvalue())
            yield None
Example #4
0
    def test_for_missing_migrations(self):
        output = StringIO()
        options = {
            'interactive': False,
            'dry_run': True,
            'stdout': output,
            'check_changes': True,
        }

        if DJANGO_1_9:
            # this option was deprecated in Django 1.10
            options['exit_code'] = True
            # this option was introduced in Django 1.10
            del options['check_changes']

        try:
            call_command('makemigrations', **options)
        except SystemExit as e:
            status_code = text_type(e)
        else:
            # on Django < 1.10, the "no changes" exit code is 1
            # on Django > 1.10, the "no changes" exit code is 0
            status_code = '1' if DJANGO_1_9 else '0'

        if status_code == '0' and DJANGO_1_9:
            self.fail('There are missing migrations:\n {}'.format(
                output.getvalue()))

        if status_code == '1' and not DJANGO_1_9:
            self.fail('There are missing migrations:\n {}'.format(
                output.getvalue()))
Example #5
0
 def test_spelling(self):
     status = StringIO()
     with TemporaryDirectory() as OUT_DIR:
         with tmp_list_append(sys.argv, 'spelling'):
             app = Sphinx(
                 srcdir=DOCS_DIR,
                 confdir=DOCS_DIR,
                 outdir=OUT_DIR,
                 doctreedir=OUT_DIR,
                 buildername="spelling",
                 warningiserror=True,
                 status=status,
                 confoverrides={
                     'extensions': [
                         'djangocms',
                         'sphinx.ext.intersphinx',
                         'sphinxcontrib.spelling'
                     ]
                 }
             )
             try:
                 app.build()
             except:
                 print(status.getvalue())
                 raise
             self.assertEqual(app.statuscode, 0, status.getvalue())
Example #6
0
    def test_dsn_full(self):
        out = StringIO()
        err = StringIO()
        call_command('dbparams', 'default', dsn=True,
                     stdout=out, stderr=err, skip_checks=True)
        output = out.getvalue()
        assert (
            output
            == (
                "F=/tmp/defaults.cnf,u=ausername,p=apassword,"
                + "h=ahost.example.com,P=12345,D=mydatabase"
            )
        )

        errors = err.getvalue()
        assert "SSL params can't be" in errors
Example #7
0
    def test_copy_filled_placeholder(self):
        """
        If an existing title in the target language has plugins in a placeholder
        that placeholder is skipped
        """
        site = 1
        number_start_plugins = CMSPlugin.objects.all().count()

        # create an empty title language
        root_page = Page.objects.on_site(site).get_home()
        create_title("de", "root page de", root_page)
        ph = root_page.placeholders.get(slot="body")
        add_plugin(ph, "TextPlugin", "de", body="Hello World")

        out = StringIO()
        management.call_command('cms',
                                'copy',
                                'lang',
                                '--from-lang=en',
                                '--to-lang=de',
                                interactive=False,
                                stdout=out)

        self.assertEqual(
            CMSPlugin.objects.filter(language='en').count(),
            number_start_plugins)
        # one placeholder (with 7 plugins) is skipped, so the difference must be 6
        self.assertEqual(
            CMSPlugin.objects.filter(language='de').count(),
            number_start_plugins - 6)
    def test_copy_filled_placeholder_force_copy(self):
        """
        If an existing title in the target language has plugins in a placeholder
        and the command is called with *force-copy*, the plugins are copied on
        top of the existing one
        """
        site = 1
        number_start_plugins = CMSPlugin.objects.all().count()

        # create an empty title language
        root_page = Page.objects.on_site(site).get_home()
        create_title("de", "root page de", root_page)
        ph = root_page.placeholders.get(slot="body")
        add_plugin(ph, "TextPlugin", "de", body="Hello World")

        root_plugins = CMSPlugin.objects.filter(placeholder=ph)
        text_de_orig, _ = root_plugins.get(language='de', plugin_type='TextPlugin').get_plugin_instance()

        out = StringIO()
        management.call_command(
            'cms', 'copy', 'lang', '--from-lang=en', '--to-lang=de', '--force', interactive=False,
            stdout=out
        )

        CMSPlugin.objects.filter(placeholder=root_page.placeholders.get(slot="body"))

        self.assertEqual(CMSPlugin.objects.filter(language='en').count(), number_start_plugins)
        # we have an existing plugin in one placeholder, so we have one more
        self.assertEqual(CMSPlugin.objects.filter(language='de').count(), number_start_plugins+1)
Example #9
0
    def test_copy_filled_placeholder(self):
        """
        If an existing title in the target language has plugins in a placeholder
        that placeholder is skipped
        """
        site = 1
        number_start_plugins = CMSPlugin.objects.all().count()

        # create an empty title language
        root_page = Page.objects.on_site(site).get_home()
        create_title("de", "root page de", root_page)
        ph = root_page.placeholders.get(slot="body")
        add_plugin(ph, "TextPlugin", "de", body="Hello World")

        out = StringIO()
        command = cms.Command()
        command.stdout = out
        command.handle("copy-lang", "en", "de")

        self.assertEqual(
            CMSPlugin.objects.filter(language='en').count(),
            number_start_plugins)
        # one placeholder (with 7 plugins) is skipped, so the difference must be 6
        self.assertEqual(
            CMSPlugin.objects.filter(language='de').count(),
            number_start_plugins - 6)
Example #10
0
    def render(self, data, *args, **kwargs):
        charset = 'utf-8'
        root_node = 'xforms'
        xmlns = "http://openrosa.org/xforms/xformsList"

        if 'detail' in data.keys():
            stream = StringIO()

            xml = SimplerXMLGenerator(stream, charset)
            xml.startDocument()
            xml.startElement(root_node, {'xmlns': xmlns})

            for key, value in six.iteritems(data):
                xml.startElement(key, {})
                xml.characters(smart_text(value))
                xml.endElement(key)

            xml.endElement(root_node)
            xml.endDocument()
            return stream.getvalue()
        else:
            json = self.transform_to_xform_json(data)
            survey = create_survey_element_from_dict(json)
            xml = survey.xml()
            fix_languages(xml)
            xml = xml.toxml()

            xml = self.insert_version_attribute(xml,
                                                data.get('id_string'),
                                                data.get('version'))
            xml = self.insert_uuid_bind(xml, data.get('id_string'))

            return xml
Example #11
0
    def setUp(self):
        super(BaseRBSiteTestCase, self).setUp()

        # We want to capture both stdout and stderr. Nose takes care of
        # stdout for us, but not stderr, so that's our responsibility.
        self._old_stderr = sys.stderr
        sys.stderr = StringIO()
Example #12
0
    def test_copy_existing_title(self):
        """
        Even if a title already exists the copy is successfull, the original
        title remains untouched
        """
        site = 1
        number_start_plugins = CMSPlugin.objects.all().count()

        # create an empty title language
        root_page = Page.objects.on_site(site).get_home()
        create_title("de", "root page de", root_page)

        out = StringIO()
        command = cms.Command()
        command.stdout = out
        command.handle("copy-lang", "en", "de")
        pages = Page.objects.on_site(site).drafts()
        for page in pages:
            self.assertEqual(set((u'en', u'de')), set(page.get_languages()))

        # Original Title untouched
        self.assertEqual("root page de",
                         Page.objects.on_site(site).get_home().get_title("de"))

        # Plugins still copied
        self.assertEqual(CMSPlugin.objects.all().count(),
                         number_start_plugins * 2)
        self.assertEqual(
            CMSPlugin.objects.filter(language='en').count(),
            number_start_plugins)
        self.assertEqual(
            CMSPlugin.objects.filter(language='de').count(),
            number_start_plugins)
    def test_fix_tree_regression_5641(self):
        # ref: https://github.com/divio/django-cms/issues/5641
        alpha = create_page("Alpha", "nav_playground.html", "en", published=True)
        beta = create_page("Beta", "nav_playground.html", "en", published=False)
        gamma = create_page("Gamma", "nav_playground.html", "en", published=False)
        delta = create_page("Delta", "nav_playground.html", "en", published=True)
        theta = create_page("Theta", "nav_playground.html", "en", published=True)

        beta.move_page(alpha, position='last-child')
        gamma.move_page(beta.reload(), position='last-child')
        delta.move_page(gamma.reload(), position='last-child')
        theta.move_page(delta.reload(), position='last-child')

        out = StringIO()
        management.call_command('cms', 'fix-tree', interactive=False, stdout=out)

        alpha = alpha.reload()
        beta = beta.reload()
        gamma = gamma.reload()
        delta = delta.reload()
        theta = theta.reload()

        tree = [
            (alpha, '0001'),
            (beta, '00010001'),
            (gamma, '000100010001'),
            (delta, '0001000100010001'),
            (theta, '00010001000100010001'),
            (alpha.publisher_public, '0002'),
            (delta.publisher_public, '0003'),
            (theta.publisher_public, '00030001'),
        ]

        for page, path in tree:
            self.assertEqual(page.path, path)
Example #14
0
def crop_image(f, x, y, width, height):
    """
    Crops an image at the specified coordinates and dimensions, returning the
    resulting URL of the cropped image.
    """
    filename = f.name
    storage = f.storage
    basename = filename

    if filename.find(".") != -1:
        basename = filename.rsplit('.', 1)[0]
    new_name = '%s_%d_%d_%d_%d.png' % (basename, x, y, width, height)

    if not storage.exists(new_name):
        try:
            f = storage.open(filename)
            data = StringIO(f.read())
            f.close()

            image = Image.open(data)
            image = image.crop((x, y, x + width, y + height))

            save_image_to_storage(image, storage, new_name)
        except (IOError, KeyError) as e:
            logger.exception(
                'Error cropping image file %s at %d, %d, %d, %d '
                'and saving as %s: %s', filename, x, y, width, height,
                new_name, e)
            return ""

    return storage.url(new_name)
Example #15
0
    def test_mysql_cache_migration_alias(self):
        out = StringIO()
        call_command('mysql_cache_migration', 'default', stdout=out)
        output = out.getvalue()

        num_run_sqls = (len(output.split('RunSQL')) - 1)
        assert num_run_sqls == 1
    def test_copy_existing_title(self):
        """
        Even if a title already exists the copy is successfull, the original
        title remains untouched
        """
        site = 1
        number_start_plugins = CMSPlugin.objects.all().count()

        # create an empty title language
        root_page = Page.objects.on_site(site).get_home()
        create_title("de", "root page de", root_page)

        out = StringIO()
        management.call_command(
            'cms', 'copy', 'lang', '--from-lang=en', '--to-lang=de', interactive=False, stdout=out
        )
        pages = Page.objects.on_site(site).drafts()
        for page in pages:
            self.assertEqual(set((u'en', u'de')), set(page.get_languages()))

        # Original Title untouched
        self.assertEqual("root page de", Page.objects.on_site(site).get_home().get_title("de"))

        # Plugins still copied
        self.assertEqual(CMSPlugin.objects.all().count(), number_start_plugins*2)
        self.assertEqual(CMSPlugin.objects.filter(language='en').count(), number_start_plugins)
        self.assertEqual(CMSPlugin.objects.filter(language='de').count(), number_start_plugins)
Example #17
0
 def test_mysql_full(self):
     out = StringIO()
     call_command('dbparams', stdout=out, skip_checks=True)
     output = out.getvalue()
     assert (output == "--defaults-file=/tmp/defaults.cnf --user=ausername "
             "--password=apassword --host=ahost.example.com --port=12345 "
             "--ssl-ca=/tmp/mysql.cert mydatabase")
Example #18
0
    def test_copy_langs(self):
        """
        Various checks here:

         * plugins are exactly doubled, half per language with no orphaned plugin
         * the bottom-most plugins in the nesting chain maintain the same position and the same content
         * the top-most plugin are of the same type
        """
        site = 1
        number_start_plugins = CMSPlugin.objects.all().count()

        out = StringIO()
        command = cms.Command()
        command.stdout = out
        command.handle("copy-lang", "en", "de")
        pages = Page.objects.on_site(site).drafts()
        for page in pages:
            self.assertEqual(set((u'en', u'de')), set(page.get_languages()))
        # These asserts that no orphaned plugin exists
        self.assertEqual(CMSPlugin.objects.all().count(),
                         number_start_plugins * 2)
        self.assertEqual(
            CMSPlugin.objects.filter(language='en').count(),
            number_start_plugins)
        self.assertEqual(
            CMSPlugin.objects.filter(language='de').count(),
            number_start_plugins)

        root_page = Page.objects.on_site(site).get_home()
        root_plugins = CMSPlugin.objects.filter(
            placeholder=root_page.placeholders.get(slot="body"))

        first_plugin_en, _ = root_plugins.get(
            language='en', parent=None).get_plugin_instance()
        first_plugin_de, _ = root_plugins.get(
            language='de', parent=None).get_plugin_instance()

        self.assertEqual(first_plugin_en.plugin_type,
                         first_plugin_de.plugin_type)

        link_en, _ = root_plugins.get(
            language='en', plugin_type='LinkPlugin').get_plugin_instance()
        link_de, _ = root_plugins.get(
            language='de', plugin_type='LinkPlugin').get_plugin_instance()

        self.assertEqual(link_en.url, link_de.url)
        self.assertEqual(link_en.get_position_in_placeholder(),
                         link_de.get_position_in_placeholder())

        stack_plugins = CMSPlugin.objects.filter(
            placeholder=StaticPlaceholder.objects.order_by('?')[0].draft)

        stack_text_en, _ = stack_plugins.get(
            language='en', plugin_type='TextPlugin').get_plugin_instance()
        stack_text_de, _ = stack_plugins.get(
            language='de', plugin_type='TextPlugin').get_plugin_instance()

        self.assertEqual(stack_text_en.plugin_type, stack_text_de.plugin_type)
        self.assertEqual(stack_text_en.body, stack_text_de.body)
 def test_uninstall_plugins_with_plugin(self):
     out = StringIO()
     placeholder = Placeholder.objects.create(slot="test")
     add_plugin(placeholder, TextPlugin, "en", body="en body")
     self.assertEqual(CMSPlugin.objects.filter(plugin_type=PLUGIN).count(), 1)
     management.call_command('cms', 'uninstall', 'plugins', PLUGIN, interactive=False, stdout=out)
     self.assertEqual(out.getvalue(), "1 'TextPlugin' plugins uninstalled\n")
     self.assertEqual(CMSPlugin.objects.filter(plugin_type=PLUGIN).count(), 0)
Example #20
0
    def test_copy_bad_languages(self):
        out = StringIO()
        command = cms.Command()
        command.stdout = out
        with self.assertRaises(CommandError) as command_error:
            command.handle("copy-lang", "it", "fr")

        self.assertEqual(str(command_error.exception), 'Both languages have to be present in settings.LANGUAGES and settings.CMS_LANGUAGES')
Example #21
0
    def test_parse(self):
        """ Make sure the `QueryDict` works OK """
        parser = FormParser()

        stream = StringIO(self.string)
        data = parser.parse(stream)

        self.assertEqual(Form(data).is_valid(), True)
Example #22
0
 def test_list_apphooks(self):
     out = StringIO()
     create_page('Hello Title', "nav_playground.html", "en", apphook=APPHOOK)
     self.assertEqual(Page.objects.filter(application_urls=APPHOOK).count(), 1)
     command = cms.Command()
     command.stdout = out
     command.handle("list", "apphooks", interactive=False)
     self.assertEqual(out.getvalue(), "SampleApp (draft)\n")
Example #23
0
def render_markdown_from_file(f, **markdown_kwargs):
    """Render Markdown text from a file stream to HTML."""
    s = StringIO()
    markdownFromFile(input=f, output=s, **markdown_kwargs)
    html = s.getvalue()
    s.close()

    return html
Example #24
0
    def test_delete_orphaned_plugins(self):
        apps = ["cms", "menus", "sekizai", "cms.test_utils.project.sampleapp"]
        with SettingsOverride(INSTALLED_APPS=apps):
            placeholder = Placeholder.objects.create(slot="test")
            add_plugin(placeholder, TextPlugin, "en", body="en body")
            add_plugin(placeholder, TextPlugin, "en", body="en body")
            add_plugin(placeholder,
                       "LinkPlugin",
                       "en",
                       name="A Link",
                       url="https://www.django-cms.org")

            instanceless_plugin = CMSPlugin(language="en",
                                            plugin_type="TextPlugin")
            instanceless_plugin.save()

            # create a bogus CMSPlugin to simulate one which used to exist but
            # is no longer installed
            bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
            bogus_plugin.save()

            report = plugin_report()

            # there should be reports for three plugin types
            self.assertEqual(len(report), 3)

            # check the bogus plugin
            bogus_plugins_report = report[0]
            self.assertEqual(len(bogus_plugins_report["instances"]), 1)

            # check the link plugin
            link_plugins_report = report[1]
            self.assertEqual(len(link_plugins_report["instances"]), 1)

            # check the text plugins
            text_plugins_report = report[2]
            self.assertEqual(len(text_plugins_report["instances"]), 3)

            self.assertEqual(len(text_plugins_report["unsaved_instances"]), 1)

            management.call_command('cms',
                                    'delete_orphaned_plugins',
                                    stdout=StringIO(),
                                    interactive=False)
            report = plugin_report()

            # there should be reports for two plugin types (one should have been deleted)
            self.assertEqual(len(report), 2)

            # check the link plugin
            link_plugins_report = report[0]
            self.assertEqual(len(link_plugins_report["instances"]), 1)

            # check the text plugins
            text_plugins_report = report[1]
            self.assertEqual(len(text_plugins_report["instances"]), 2)

            self.assertEqual(len(text_plugins_report["unsaved_instances"]), 0)
Example #25
0
    def parse(self):
        """
        Parses the diff, returning a list of File objects representing each
        file in the diff.
        """
        self.files = []
        i = 0
        preamble = StringIO()

        while i < len(self.lines):
            next_i, file_info, new_diff = self._parse_diff(i)

            if file_info:
                if self.files:
                    self.files[-1].finalize()

                self._ensure_file_has_required_fields(file_info)

                file_info.prepend_data(preamble.getvalue())
                preamble.close()
                preamble = StringIO()

                self.files.append(file_info)
            elif new_diff:
                # We found a diff, but it was empty and has no file entry.
                # Reset the preamble.
                preamble.close()
                preamble = StringIO()
            else:
                preamble.write(self.lines[i])
                preamble.write(b'\n')

            i = next_i

        try:
            if self.files:
                self.files[-1].finalize()
            elif preamble.getvalue().strip() != b'':
                # This is probably not an actual git diff file.
                raise DiffParserError('This does not appear to be a git diff',
                                      0)
        finally:
            preamble.close()

        return self.files
Example #26
0
 def test_uninstall_plugins_without_plugin(self):
     out = StringIO()
     management.call_command('cms',
                             'uninstall',
                             'plugins',
                             PLUGIN,
                             interactive=False,
                             stdout=out)
     self.assertEqual(out.getvalue(), "no 'TextPlugin' plugins found\n")
Example #27
0
 def test_uninstall_apphooks_without_apphook(self):
     out = StringIO()
     management.call_command('cms',
                             'uninstall',
                             'apphooks',
                             APPHOOK,
                             interactive=False,
                             stdout=out)
     self.assertEqual(out.getvalue(), "no 'SampleApp' apphooks found\n")
Example #28
0
def thumbnail(f, size='400x100'):
    """Create a thumbnail of the given image.

    This will create a thumbnail of the given ``file`` (a Django FileField or
    ImageField) with the given size. Size can either be a string of WxH (in
    pixels), or a 2-tuple. If the size is a tuple and the second part is None,
    it will be calculated to preserve the aspect ratio.

    This will return the URL to the stored thumbnail.
    """
    if isinstance(size, six.string_types):
        x, y = (int(x) for x in size.split('x'))
        size_str = size
    elif isinstance(size, tuple):
        x, y = size

        if y is None:
            size_str = '%d' % x
        else:
            size_str = '%dx%d' % (x, y)
    else:
        raise ValueError('Thumbnail size "%r" could not be be parsed', size)

    filename = f.name
    if filename.find(".") != -1:
        basename, format = filename.rsplit('.', 1)
        miniature = '%s_%s.%s' % (basename, size_str, format)
    else:
        basename = filename
        miniature = '%s_%s' % (basename, size_str)

    storage = f.storage

    if not storage.exists(miniature):
        try:
            f = storage.open(filename, 'rb')
            data = StringIO(f.read())
            f.close()

            image = Image.open(data)

            if y is None:
                x = min(image.size[0], x)

                # Calculate height based on width
                y = int(x * (image.size[1] / image.size[0]))

            image.thumbnail([x, y], Image.ANTIALIAS)

            save_image_to_storage(image, storage, miniature)
        except (IOError, KeyError) as e:
            logger.exception(
                'Error thumbnailing image file %s and saving '
                'as %s: %s', filename, miniature, e)
            return ""

    return storage.url(miniature)
    def test_copy_bad_languages(self):
        out = StringIO()
        with self.assertRaises(CommandError) as command_error:
            management.call_command(
                'cms', 'copy', 'lang', '--from-lang=it', '--to-lang=fr', interactive=False,
                stdout=out
            )

        self.assertEqual(str(command_error.exception), 'Both languages have to be present in settings.LANGUAGES and settings.CMS_LANGUAGES')
    def test_copy_sites(self):
        """
        Various checks here:

         * plugins are exactly doubled, half per site with no orphaned plugin
         * the bottom-most plugins in the nesting chain maintain the same position and the same content
         * the top-most plugin are of the same type
        """
        site_1_pk = 1
        site_2 = Site.objects.create(name='site 2')
        site_2_pk = site_2.pk
        phs = []
        for page in Page.objects.on_site(site_1_pk).drafts():
            phs.extend(page.placeholders.values_list('pk', flat=True))
        number_start_plugins = CMSPlugin.objects.filter(placeholder__in=phs).count()

        out = StringIO()
        management.call_command(
            'cms', 'copy', 'site', '--from-site=%s' % site_1_pk, '--to-site=%s' % site_2_pk,
            stdout=out
        )
        for page in Page.objects.on_site(site_1_pk).drafts():
            page.publish('en')
        for page in Page.objects.on_site(site_2_pk).drafts():
            page.publish('en')
        pages_1 = list(Page.objects.on_site(site_1_pk).drafts())
        pages_2 = list(Page.objects.on_site(site_2_pk).drafts())
        for index, page in enumerate(pages_1):
            self.assertEqual(page.get_title('en'), pages_2[index].get_title('en'))
            self.assertEqual(page.depth, pages_2[index].depth)

        phs_1 = []
        phs_2 = []
        for page in Page.objects.on_site(site_1_pk).drafts():
            phs_1.extend(page.placeholders.values_list('pk', flat=True))
        for page in Page.objects.on_site(site_2_pk).drafts():
            phs_2.extend(page.placeholders.values_list('pk', flat=True))

        # These asserts that no orphaned plugin exists
        self.assertEqual(CMSPlugin.objects.filter(placeholder__in=phs_1).count(), number_start_plugins)
        self.assertEqual(CMSPlugin.objects.filter(placeholder__in=phs_2).count(), number_start_plugins)

        root_page_1 = Page.objects.on_site(site_1_pk).get_home(site_1_pk)
        root_page_2 = Page.objects.on_site(site_2_pk).get_home(site_2_pk)
        root_plugins_1 = CMSPlugin.objects.filter(placeholder=root_page_1.placeholders.get(slot="body"))
        root_plugins_2 = CMSPlugin.objects.filter(placeholder=root_page_2.placeholders.get(slot="body"))

        first_plugin_1, _ = root_plugins_1.get(language='en', parent=None).get_plugin_instance()
        first_plugin_2, _ = root_plugins_2.get(language='en', parent=None).get_plugin_instance()

        self.assertEqual(first_plugin_1.plugin_type, first_plugin_2.plugin_type)

        link_1, _ = root_plugins_1.get(language='en', plugin_type='LinkPlugin').get_plugin_instance()
        link_2, _ = root_plugins_2.get(language='en', plugin_type='LinkPlugin').get_plugin_instance()

        self.assertEqual(link_1.url, link_2.url)
        self.assertEqual(link_1.get_position_in_placeholder(), link_2.get_position_in_placeholder())