# Buggy code
def __init__(self, fileManager, analysisQueue, printerProfileManager):
    from collections import deque

    self._logger = logging.getLogger(__name__)

    self._dict = (
        frozendict
        if settings().getBoolean(["devel", "useFrozenDictForPrinterState"])
        else dict
    )

    self._analysisQueue = analysisQueue
    self._fileManager = fileManager
    self._printerProfileManager = printerProfileManager

    # state
    # TODO do we really need to hold the temperature here?
    self._temp = None
    self._bedTemp = None
    self._targetTemp = None
    self._targetBedTemp = None
    self._temps = TemperatureHistory(
        cutoff=settings().getInt(["temperature", "cutoff"]) * 60
    )
    self._tempBacklog = []

    self._messages = deque([], 300)
    self._messageBacklog = []

    self._log = deque([], 300)
    self._logBacklog = []

    self._state = None

    self._currentZ = None

    self._printAfterSelect = False
    self._posAfterSelect = None

    # sd handling
    self._sdPrinting = False
    self._sdStreaming = False
    self._sdFilelistAvailable = threading.Event()
    self._streamingFinishedCallback = None
    self._streamingFailedCallback = None

    # job handling & estimation
    self._selectedFileMutex = threading.RLock()
    self._selectedFile = None

    self._estimator_factory = PrintTimeEstimator
    analysis_queue_hooks = plugin_manager().get_hooks(
        "octoprint.printer.estimation.factory"
    )
    for name, hook in analysis_queue_hooks.items():
        try:
            estimator = hook()
            if estimator is not None:
                self._logger.info(
                    "Using print time estimator provided by {}".format(name)
                )
                self._estimator_factory = estimator
        except:
            self._logger.exception(
                "Error while processing analysis queues from {}".format(name)
            )

    # comm
    self._comm = None

    # callbacks
    self._callbacks = []

    # progress plugins
    self._lastProgressReport = None
    self._progressPlugins = plugin_manager().get_implementations(ProgressPlugin)

    self._stateMonitor = StateMonitor(
        interval=0.5,
        on_update=self._sendCurrentDataCallbacks,
        on_add_temperature=self._sendAddTemperatureCallbacks,
        on_add_log=self._sendAddLogCallbacks,
        on_add_message=self._sendAddMessageCallbacks,
        on_get_progress=self._updateProgressDataCallback,
    )
    self._stateMonitor.reset(
        state=self._dict(text=self.get_state_string(), flags=self._getStateFlags()),
        job_data=self._dict(
            file=self._dict(name=None, path=None, size=None, origin=None, date=None),
            estimatedPrintTime=None,
            lastPrintTime=None,
            filament=self._dict(length=None, volume=None),
            user=None,
        ),
        progress=self._dict(
            completion=None,
            filepos=None,
            printTime=None,
            printTimeLeft=None,
            printTimeOrigin=None,
        ),
        current_z=None,
        offsets=self._dict(),
    )

    eventManager().subscribe(
        Events.METADATA_ANALYSIS_FINISHED, self._on_event_MetadataAnalysisFinished
    )
    eventManager().subscribe(
        Events.METADATA_STATISTICS_UPDATED, self._on_event_MetadataStatisticsUpdated
    )


# Traceback (AttributeError)
2018-07-05 05:17:16,231 - octoprint.util.comm - INFO - Externally triggered heatup detected
2018-07-05 05:18:34,517 - octoprint.util.comm - INFO - Printer seems to support the busy protocol, telling it to set the busy interval to our "communicationBusy" timeout - 1s = 2s
2018-07-05 05:19:27,589 - octoprint.util.comm - INFO - Timeout while in an active heatup, considering heatup to be over.
2018-07-05 05:19:30,594 - octoprint.util.comm - INFO - Communication timeout while idle, trying to trigger response from printer.
2018-07-05 05:19:32,426 - octoprint.util.comm - INFO - Changing monitoring state from "Operational" to "Printing from SD"
2018-07-05 05:19:32,512 - octoprint.plugins.Octoslack - ERROR - Error processing event: PrintStarted, Error: 'Printer' object has no attribute '_estimator'
Traceback (most recent call last):
File "/home/pi/oprint/local/lib/python2.7/site-packages/octoprint_Octoslack/__init__.py", line 591, in handle_event
self.process_slack_event(event, event_settings, channel_override, payload)
File "/home/pi/oprint/local/lib/python2.7/site-packages/octoprint_Octoslack/__init__.py", line 648, in process_slack_event
printer_data = self._printer.get_current_data()
File "/home/pi/oprint/local/lib/python2.7/site-packages/octoprint/server/__init__.py", line 384, in wrapper
return f(*args, **kwargs)
File "/home/pi/oprint/local/lib/python2.7/site-packages/octoprint/printer/standard.py", line 565, in get_current_data
return util.thaw_frozendict(self._stateMonitor.get_current_data())
File "/home/pi/oprint/local/lib/python2.7/site-packages/octoprint/printer/standard.py", line 1326, in get_current_data
self._progress = self._get_current_progress()
File "/home/pi/oprint/local/lib/python2.7/site-packages/octoprint/printer/standard.py", line 1255, in _get_current_progress
return self._on_get_progress()
File "/home/pi/oprint/local/lib/python2.7/site-packages/octoprint/printer/standard.py", line 773, in _updateProgressDataCallback
printTimeLeft, printTimeLeftOrigin = self._estimator.estimate(progress,
AttributeError: 'Printer' object has no attribute '_estimator'
2018-07-05 05:20:41,680 - octoprint.util.comm - INFO - Communication timeout while printing, trying to trigger response from printer.
2018-07-05 05:20:41,718 - octoprint.util.comm - INFO - Changing monitoring state from "Printing from SD" to "Cancelling"
2018-07-05 05:20:41,880 - octoprint.util.comm - INFO - Changing monitoring state from "Cancelling" to "Operational"
2018-07-05 05:21:35,678 - octoprint.server.api.system - INFO - Performing command for core:restart: sudo service octoprint restart

# Fixed code
def __init__(self, fileManager, analysisQueue, printerProfileManager):
    from collections import deque

    self._logger = logging.getLogger(__name__)

    self._dict = (
        frozendict
        if settings().getBoolean(["devel", "useFrozenDictForPrinterState"])
        else dict
    )

    self._analysisQueue = analysisQueue
    self._fileManager = fileManager
    self._printerProfileManager = printerProfileManager

    # state
    # TODO do we really need to hold the temperature here?
    self._temp = None
    self._bedTemp = None
    self._targetTemp = None
    self._targetBedTemp = None
    self._temps = TemperatureHistory(
        cutoff=settings().getInt(["temperature", "cutoff"]) * 60
    )
    self._tempBacklog = []

    self._messages = deque([], 300)
    self._messageBacklog = []

    self._log = deque([], 300)
    self._logBacklog = []

    self._state = None

    self._currentZ = None

    self._printAfterSelect = False
    self._posAfterSelect = None

    # sd handling
    self._sdPrinting = False
    self._sdStreaming = False
    self._sdFilelistAvailable = threading.Event()
    self._streamingFinishedCallback = None
    self._streamingFailedCallback = None

    # job handling & estimation
    self._selectedFileMutex = threading.RLock()
    self._selectedFile = None

    self._estimator_factory = PrintTimeEstimator
    self._estimator = None
    analysis_queue_hooks = plugin_manager().get_hooks(
        "octoprint.printer.estimation.factory"
    )
    for name, hook in analysis_queue_hooks.items():
        try:
            estimator = hook()
            if estimator is not None:
                self._logger.info(
                    "Using print time estimator provided by {}".format(name)
                )
                self._estimator_factory = estimator
        except:
            self._logger.exception(
                "Error while processing analysis queues from {}".format(name)
            )

    # comm
    self._comm = None

    # callbacks
    self._callbacks = []

    # progress plugins
    self._lastProgressReport = None
    self._progressPlugins = plugin_manager().get_implementations(ProgressPlugin)

    self._stateMonitor = StateMonitor(
        interval=0.5,
        on_update=self._sendCurrentDataCallbacks,
        on_add_temperature=self._sendAddTemperatureCallbacks,
        on_add_log=self._sendAddLogCallbacks,
        on_add_message=self._sendAddMessageCallbacks,
        on_get_progress=self._updateProgressDataCallback,
    )
    self._stateMonitor.reset(
        state=self._dict(text=self.get_state_string(), flags=self._getStateFlags()),
        job_data=self._dict(
            file=self._dict(name=None, path=None, size=None, origin=None, date=None),
            estimatedPrintTime=None,
            lastPrintTime=None,
            filament=self._dict(length=None, volume=None),
            user=None,
        ),
        progress=self._dict(
            completion=None,
            filepos=None,
            printTime=None,
            printTimeLeft=None,
            printTimeOrigin=None,
        ),
        current_z=None,
        offsets=self._dict(),
    )

    eventManager().subscribe(
        Events.METADATA_ANALYSIS_FINISHED, self._on_event_MetadataAnalysisFinished
    )
    eventManager().subscribe(
        Events.METADATA_STATISTICS_UPDATED, self._on_event_MetadataStatisticsUpdated
    )