diff --git a/scripts/.pylintrc b/scripts/.pylintrc
index 6262e5ddd5bbbd19ecdd7bd226c74675c1477091..c8188147c11376e615f2f1329cef71a496bb407b 100644
--- a/scripts/.pylintrc
+++ b/scripts/.pylintrc
@@ -60,6 +60,14 @@ confidence=
 # --enable=similarities". If you want to run only the classes checker, but have
 # no Warning level messages displayed, use "--disable=all --enable=classes
 # --disable=W".
+#
+# NOTE about C0330:
+# Ignoring pylint's C0330 "Wrong hanging indentation before block" error
+# here because it erronously reports indentation issues, and conflicts with
+# the black tool. See this issue on the black gitHub
+# page: https://github.com/psf/black/issues/48, and this issue on pylints
+# GitHub page referenced by the first issue:
+# https://github.com/PyCQA/pylint/issues/289
 disable=print-statement,
         parameter-unpacking,
         unpacking-in-except,
@@ -142,7 +150,8 @@ disable=print-statement,
         E0611,
         I1101,
         E1101,
-        R0901
+        R0901,
+        C0330
 
 # Enable the message, report, category or checker with the given id(s). You can
 # either give multiple identifier separated by comma (,) or put this option
diff --git a/soitool/inline_editable_soi_view.py b/soitool/inline_editable_soi_view.py
index e17c16ddecb6392c0120a018c721560c0f9a0886..1d1a459fdc521b14d39c3db54dc65a12ccad0820 100644
--- a/soitool/inline_editable_soi_view.py
+++ b/soitool/inline_editable_soi_view.py
@@ -40,7 +40,7 @@ class InlineEditableSOIView(QScrollArea):
         self.reorganize_soi_and_update_pages()
 
     def reorganize_soi_and_update_pages(self):
-        """Wrapper to reorganize SOI and update pages in one go."""
+        """Reorganize SOI and update pages in one go."""
         try:
             self.soi.reorganize()
         except ModuleLargerThanBinError:
@@ -49,7 +49,9 @@ class InlineEditableSOIView(QScrollArea):
                 "En av modulene er for store for å passe på én side!"
             )
             error_message.setInformativeText(
-                "Programmet kan desverre ikke fikse dette for deg. Se igjennom modulene og sjekk at alle moduler er mindre enn én enkelt side."
+                "Programmet kan desverre ikke fikse dette for deg. Se "
+                "igjennom modulene og sjekk at alle moduler er mindre "
+                "enn én enkelt side."
             )
             error_message.setIcon(QMessageBox.Warning)
             error_message.exec_()
@@ -141,8 +143,7 @@ class InlineEditableSOIView(QScrollArea):
         self.number_of_pages = required_pages
 
     def draw_pages(self):
-        """draw self.number_of_pages pages."""
-
+        """Draw self.number_of_pages pages."""
         for i in range(self.number_of_pages):
 
             x = 0
@@ -197,15 +198,20 @@ class InlineEditableSOIView(QScrollArea):
 
         # classification
         classification = QLabel(self.soi.classification)
-        classification.setStyleSheet("background-color: rgba(0,0,0,0%); "
-                                     "color: red")
+        classification.setStyleSheet(
+            "background-color: rgba(0,0,0,0%); " "color: red"
+        )
         classification.setFont(QFont("Times New Roman", 50))
         # source: https://stackoverflow.com/a/8638114/3545896
         # CAUTION: does not work if font is set through stylesheet
-        label_width = (classification.fontMetrics()
-                       .boundingRect(classification.text()).width())
-        x_pos = x + self.soi.CONTENT_WIDTH - label_width - \
-            self.soi.HEADER_HEIGHT
+        label_width = (
+            classification.fontMetrics()
+            .boundingRect(classification.text())
+            .width()
+        )
+        x_pos = (
+            x + self.soi.CONTENT_WIDTH - label_width - self.soi.HEADER_HEIGHT
+        )
         classification.move(x_pos, y)
         self.scene.addWidget(classification)
 
diff --git a/soitool/soi.py b/soitool/soi.py
index 65b6fd5a5cfe2da98fcd4a59cb9683ae8d44b283..b8ac743b4c1a68649022a7ff9ea74aec22aab9ed 100644
--- a/soitool/soi.py
+++ b/soitool/soi.py
@@ -5,20 +5,35 @@ from PySide2.QtCore import QPoint
 from rectpack import (
     newPacker,
     SORT_NONE,
-    SORT_SSIDE,
     SORT_AREA,
     PackingMode,
     PackingBin,
     maxrects,
+    skyline,
+    guillotine,
 )
 from soitool.modules.module_table import TableModule
 
+RECTPACK_STRING_TO_ALGORITHM_BIN = {
+    "BFF": PackingBin.BFF,
+    "BBF": PackingBin.BBF,
+}
+
+RECTPACK_STRING_TO_ALGORITHM_PACK = {
+    "MaxRectsBl": maxrects.MaxRectsBl,
+    "SkylineBl": skyline.SkylineBl,
+    "GuillotineBssfSas": guillotine.GuillotineBssfSas,
+}
+
+RECTPACK_STRING_TO_ALGORITHM_SORT = {
+    "SORT_NONE": SORT_NONE,
+    "SORT_AREA": SORT_AREA,
+}
+
 
 class ModuleLargerThanBinError(Exception):
     """At least one module is too large for the bin during rectpack packing."""
 
-    pass
-
 
 class ModuleType(Enum):
     """Enumerate with types of modules."""
@@ -27,11 +42,16 @@ class ModuleType(Enum):
     ATTACHMENT_MODULE = 1
 
 
-class SOI():
+class SOI:
     """Datastructure for SOI.
 
     Holds all info about an SOI necessary to view and edit it.
 
+    This class relies heavily on the rectpack library for optimal placement of
+    modules when placement_strategy is 'auto'. Refer to the rectpack
+    documentation for details beyond what is provided in this class:
+    https://github.com/secnot/rectpack
+
     Parameters
     ----------
     title : string
@@ -48,11 +68,18 @@ class SOI():
     placement_strategy : string
         must be one of 'manual' and 'auto'
     algorithm_bin : string
-        TODO: document when rectpack is added
+        which bin packing algorithm should be used for rectpack. Currently the
+        following are implemented: 'BFF', 'BBF'. Please refer to the
+        RECTPACK_STRING_TO_ALGORITHM_BIN variable.
     algorithm_pack : string
-        TODO: document when rectpack is added
+        which packing algorithm should be used for rectpack. Currently the
+        following are implemented: 'MaxRectsBl', 'SkylineBl',
+        'GuillotineBssfSas'. Please refer to the
+        RECTPACK_STRING_TO_ALGORITHM_PACK variable.
     algorithm_sort : string
-        TODO: document when rectpack is added
+        which sorting method should be applied to the modules before packing.
+        Currently the following are implemented: 'SORT_NONE', 'SORT_AREA'.
+        Please refer to the RECTPACK_STRING_TO_ALGORITHM_SORT variable.
 
     """
 
@@ -82,25 +109,27 @@ class SOI():
             pass
         raise NotImplementedError()
 
-    # ignoring pylints "Too many arguments" error here to keep this as simple
-    # as possible. The proper thing would probably be to put the properties in
-    # separate data classes (auto-placement stuff in one class, styling in
-    # another, etc).
+    # Ignoring pylint's r0913 "Too many arguments" error here to keep this as
+    # simple as possible. The proper thing would probably be to put the
+    # properties in separate data classes (auto-placement stuff in one class,
+    # styling in another, etc).
     # pylint: disable=r0913
-    def __init__(self,
-                 title="Default SOI title",
-                 description="Default SOI description",
-                 version="1",
-                 date=None,
-                 valid_from=None,
-                 valid_to=None,
-                 icon="soitool/media/HVlogo.png",
-                 classification="ugradert",
-                 orientation="landscape",
-                 placement_strategy="auto",
-                 algorithm_bin="BFF",
-                 algorithm_pack="MaxRectsBI",
-                 algorithm_sort="SORT_AREA"):
+    def __init__(
+        self,
+        title="Default SOI title",
+        description="Default SOI description",
+        version="1",
+        date=None,
+        valid_from=None,
+        valid_to=None,
+        icon="soitool/media/HVlogo.png",
+        classification="ugradert",
+        orientation="landscape",
+        placement_strategy="auto",
+        algorithm_bin="BFF",
+        algorithm_pack="MaxRectsBl",
+        algorithm_sort="SORT_NONE",
+    ):
 
         # populate date-related arguments if they are not supplied by the user
         if date is None:
@@ -191,67 +220,100 @@ class SOI():
 
         module["widget"].set_pos(QPoint(new_x, new_y))
 
+    def get_module_with_name(self, name):
+        """Return module with given name.
+
+        Parameters
+        ----------
+        name : str
+            name of module to look for
+
+        Returns
+        -------
+        module in self.modules
+        """
+        for module in self.modules:
+            if module["meta"]["name"] == name:
+                return module
+        return None
+
     def reorganize(self):
-        self.reorganize_rectpack()
+        """Reorganize modules using chosen strategy."""
+        if self.placement_strategy == "auto":
+            self.reorganize_rectpack()
+        else:
+            raise Exception(
+                "Unknown placement strategy: {}".format(
+                    self.placement_strategy
+                )
+            )
 
-    def reorganize_rectpack(self):
+    def get_rectpack_packer(self):
+        """Return rectpack packer set up for this SOI.
+
+        Returns
+        -------
+        packer : rectpack packer
+        """
+        # based on string stored in self.algorithm_... variables fetch real
+        # implementations of chosen algorithms
+        chosen_algorithm_bin = RECTPACK_STRING_TO_ALGORITHM_BIN[
+            self.algorithm_bin
+        ]
+        chosen_algorithm_pack = RECTPACK_STRING_TO_ALGORITHM_PACK[
+            self.algorithm_pack
+        ]
+        chosen_algorithm_sort = RECTPACK_STRING_TO_ALGORITHM_SORT[
+            self.algorithm_sort
+        ]
 
         packer = newPacker(
             rotation=False,
             mode=PackingMode.Offline,
-            bin_algo=PackingBin.BBF,
-            sort_algo=SORT_NONE,
-            pack_algo=maxrects.MaxRectsBl,
+            bin_algo=chosen_algorithm_bin,
+            sort_algo=chosen_algorithm_sort,
+            pack_algo=chosen_algorithm_pack,
         )
 
+        return packer
+
+    def reorganize_rectpack(self):
+        """Reorganize modules optimally using the rectpack library."""
+        packer = self.get_rectpack_packer()
+
         for module in self.modules:
             module_width, module_height = module["widget"].get_size()
-            print("size is:", str(module_width), str(module_height))
             packer.add_rect(
                 module_width, module_height, module["meta"]["name"]
             )
 
+        # float("inf") to add infinite bins. See https://github.com/secnot/rectpack/blob/master/README.md#api
         packer.add_bin(
-            self.CONTENT_WIDTH, self.CONTENT_HEIGHT - self.HEADER_HEIGHT
-        )
-        packer.add_bin(
-            self.CONTENT_WIDTH, self.CONTENT_HEIGHT - self.HEADER_HEIGHT
+            self.CONTENT_WIDTH,
+            self.CONTENT_HEIGHT - self.HEADER_HEIGHT,
+            float("inf"),
         )
 
         packer.pack()
-
         packed_rects = packer.rect_list()
 
+        # explode if rectpack failed to pack all rects
         if len(packed_rects) != len(self.modules):
             raise ModuleLargerThanBinError()
 
-        def get_module_with_name(name):
-            """Returns module with given name. """
-            for module in self.modules:
-                if module["meta"]["name"] == name:
-                    return module
-            return None
-
+        # update modules based on packed rects returned from rectpack
         for packed_rect in packed_rects:
 
-            print("packed rect: ", packed_rect)
-
             packed_rect_bin = packed_rect[0]
             packed_rect_x = packed_rect[1]
             packed_rect_y = packed_rect[2]
-            packed_rect_w = packed_rect[3]
-            packed_rect_h = packed_rect[4]
             packed_rect_id = packed_rect[5]
 
-            corresponding_module = get_module_with_name(packed_rect_id)
-            if not corresponding_module:
+            corresponding_module = self.get_module_with_name(packed_rect_id)
+            if corresponding_module is None:
                 raise Exception("Module was lost during packing!")
 
             corresponding_module["meta"]["x"] = packed_rect_x
             corresponding_module["meta"]["y"] = packed_rect_y
             corresponding_module["meta"]["page"] = packed_rect_bin + 1
             self.update_module_widget_position(corresponding_module)
-
-        print("---MODULES AFTER PACKING---")
-        for module in self.modules:
-            print(module)