Beispiel #1
0
    def show_stack_icons(self, stack, current_win):
        self.stack = stack

        if not stack:
            logger.warning("Stack empty")
            clist.hide()
            return

        self.width = self.orig_width
        self.height = len(stack) * self.width

        offset = 0

        self.drawer.clear("000000")

        for client in stack:
            icon = self.get_window_icon(client)
            self.draw_icon(icon, offset)
            offset += self.width

        if current_win in stack:
            id = stack.index(current_win)
            self.drawer.set_source_rgb("00FFFF")
            self.drawer.rectangle(0, id * self.width, self.width, self.width)

        self.place()
        self.draw()
        self.unhide()
Beispiel #2
0
    def _check_colors(self):
        """
        dmenu needs colours to be in #rgb or #rrggbb format.

        Checks colour value, removes invalid values and adds # if missing.

        NB This should not be called in _Extension.__init__ as _Extension.global_defaults
        may not have been set at this point.
        """
        for c in [
                "background", "foreground", "selected_background",
                "selected_foreground"
        ]:
            col = getattr(self, c, None)
            if col is None:
                continue

            if not isinstance(col, str) or not RGB.match(col):
                logger.warning(f"Invalid extension '{c}' color: {col}. "
                               f"Must be #RGB or #RRGGBB string.")
                setattr(self, c, None)
                continue

            if not col.startswith("#"):
                col = f"#{col}"
                setattr(self, c, col)
Beispiel #3
0
    def find_batteries(self, *args):
        # Get all UPower devices that are named "battery"
        batteries = [
            b for b in self.upower.EnumerateDevices() if "battery" in b
        ]

        if not batteries:
            logger.warning("No batteries found. No icons will be displayed.")

        # Get DBus object for each battery
        self.batteries = [self.bus.get(UPOWER_INTERFACE, b) for b in batteries]

        # If user only wants named battery, get it here
        if self.battery_name:
            self.batteries = [
                b for b in self.batteries if b.NativePath == self.battery_name
            ]

            if not self.batteries:
                err = "No battery found matching {}.".format(self.battery_name)
                logger.warning(err)

        # Listen for change signals on DBus
        for battery in self.batteries:
            battery.onPropertiesChanged = self.battery_change
Beispiel #4
0
    def setup_images(self):
        for key, name in self.icons.items():
            try:
                path = os.path.join(self.theme_path, name)
                img = cairocffi.ImageSurface.create_from_png(path)
            except cairocffi.Error:
                self.theme_path = None
                logger.warning('Battery Icon switching to text mode')
                return
            input_width = img.get_width()
            input_height = img.get_height()

            sp = input_height / (self.bar.height - 1)

            width = input_width / sp
            if width > self.length:
                self.length = int(width) + self.actual_padding * 2

            imgpat = cairocffi.SurfacePattern(img)

            scaler = cairocffi.Matrix()

            scaler.scale(sp, sp)
            scaler.translate(self.actual_padding * -1, 0)
            imgpat.set_matrix(scaler)

            imgpat.set_filter(cairocffi.FILTER_BEST)
            self.surfaces[key] = imgpat
Beispiel #5
0
def getCmus(qtile:Optional[Qtile]=None, max_title_len:int=20):
    try:
        output = subprocess.check_output(['cmus-remote', '-Q']).decode()
    except subprocess.CalledProcessError as e:
        logger.warn("getMpd: {}".format(e))
        return getIcons()['error']
    else:
        output = re.findall(r'file (.*)|duration (\d+)|position (\d+)|tag title (.*)', output, re.MULTILINE)

    try:
        if len(output) > 3:
            title = output[3][-1].strip()
        else:
            title = output[0][0].split('/')[-1].split('.')[0].strip()
        title = title[:max_title_len-3] + '...' if len(title) > max_title_len else "{}{}".format(
            title, " "*(max_title_len-len(title)))
        total_time_m = int(output[1][1])//60
        total_time_s = int(output[1][1])%60
        time_m = int(output[2][2])//60
        time_s = int(output[2][2])%60

    except Exception as e:
        logger.warning("{} {}".format(e, output))
        return getIcons()['error']
    else:
        return "{} {}:{}/{}:{}".format(title, time_m, time_s, total_time_m, total_time_s)
Beispiel #6
0
def clickMpd(qtile:Optional[Qtile]=None, button:int=1):
    keys = {
        # Left mouse button
        "toggle": 1,
        # Right mouse button
        "stop": 3,
        # Scroll up
        "previous": 4,
        # Scroll down
        "next": 5,
        # User defined command
        "command": None
    }
    cmd = ['mpc']
    if button == keys["toggle"]:
        cmd.append('toggle')
    elif button == keys["stop"]:
        cmd.append('stop')
    elif button == keys["previous"]:
        cmd.append('prev')
    elif button == keys["next"]:
        cmd.append('next')
    try:
        subprocess.run(cmd)
    except subprocess.CalledProcessError as e:
        logger.warning(e.output.decode().strip())
Beispiel #7
0
 def _on_destroy(self, _listener, _data):
     logger.debug("Signal: window destroy")
     if self.mapped:
         logger.warning("Window destroyed before unmap event.")
         self.mapped = False
     self.qtile.unmanage(self.wid)
     self.finalize()
Beispiel #8
0
def get_bar_text(qtile):
    """Primary function to be run from config with
    import tts
    lazy.function(tts.get_text)
    """
    try:
        text = ""
        for i, s in enumerate(qtile.screens):
            text += "Screen number " + str(i) + ". "
            for pos in ["top", "bottom", "left", "right"]:
                if hasattr(s, pos):
                    bar = getattr(s, pos)  # can return None
                    if bar:
                        text += bar.cmd_info()["position"].capitalize() + " bar. "
                        for w in bar.widgets:
                            #text += w.__class__.__name__ + " widget. "
                            text += _parse_widget(w)
        log_test(text)
        """Sending the text to the TTS engine may take awhile so mp
        is to ensure that qtile doesn't freeze during that time
        NOTE CURRENTLY NOT WORKING?
        """
        p = Process(target=_play_audio, args=(text,), daemon=True)
        p.start()
        p.join()
        #log_test(p.is_alive())
        #log_test("finished")
    except Exception as e:
        log_test(e)
        logger.warning(f"TTS failed: {e}")
Beispiel #9
0
 def remove_rule(self, rule_id):
     rule = self.rules_map.get(rule_id)
     if rule:
         self.rules.remove(rule)
         del self.rules_map[rule_id]
     else:
         logger.warning('Rule "%s" not found', rule_id)
Beispiel #10
0
    def setup_images(self):
        for key, name in self.icons.items():
            try:
                path = os.path.join(self.theme_path, name)
                img = cairocffi.ImageSurface.create_from_png(path)
            except (cairocffi.Error, FileNotFoundError):
                self.theme_path = None
                logger.warning('VolumeIcons wrong icons path')
                return
            input_width = img.get_width()
            input_height = img.get_height()

            size = self.fontsize
            sp = input_height / size

            width = input_width / sp
            if width > self.length:
                # cast to `int` only after handling all potentially-float values
                self.length = int(width + self.actual_padding * 2)

            imgpat = cairocffi.SurfacePattern(img)

            scaler = cairocffi.Matrix()
            scaler.scale(sp, sp)

            translate_y = (self.bar.height - size) // 2
            scaler.translate(self.actual_padding * -1, -translate_y)

            imgpat.set_matrix(scaler)

            imgpat.set_filter(cairocffi.FILTER_BEST)
            self.surfaces[key] = imgpat
Beispiel #11
0
def startup_once():
    import glob
    prog_files = glob.glob(home + "/.config/autostart/*.desktop")
    progs = []

    for prog in prog_files:
        try:
            executable = ""
            with open(prog, "r") as prog_f:
                for line in prog_f:
                    if line.startswith("Exec="):
                        executable = line[5:].strip()
                        break
            if executable != "":
                progs.append(executable)
        except:
            logger.warning("qtile: can't open " + prog)

    for prog in progs:
        runInBackground(prog)

    runInBackground("/usr/lib/polkit-kde-authentication-agent-1",
                    "authentication agent polkit-kde-agent")

    runInBackground("udiskie --smart-tray",
                    "udisks2 automounter (mount helper)")

    runInBackground(
        "xss-lock -- " + screen_locker,
        "xss-lock subscribes to the systemd-events suspend, hibernate")
Beispiel #12
0
 def register(self, callback):
     if not self.service:
         logger.warning(
             'Registering %s without any dbus connection existing',
             callback.__name__,
         )
     self.callbacks.append(callback)
Beispiel #13
0
    def cmd_hide_show_bar(self, position="all"):
        """Toggle visibility of a given bar

        Parameters
        ==========
        position :
            one of: "top", "bottom", "left", "right", or "all" (default: "all")
        """
        if position in ["top", "bottom", "left", "right"]:
            bar = getattr(self.current_screen, position)
            if bar:
                bar.show(not bar.is_show())
                self.current_group.layout_all()
            else:
                logger.warning(
                    "Not found bar in position '%s' for hide/show." % position)
        elif position == "all":
            screen = self.current_screen
            is_show = None
            for bar in [screen.left, screen.right, screen.top, screen.bottom]:
                if bar:
                    if is_show is None:
                        is_show = not bar.is_show()
                    bar.show(is_show)
            if is_show is not None:
                self.current_group.layout_all()
            else:
                logger.warning("Not found bar for hide/show.")
        else:
            logger.error("Invalid position value:{0:s}".format(position))
Beispiel #14
0
def setMute(mute=2, refresh=False):
    '''
    Sets active sink mute state

    Args:
    mute:int        - 0-unmute, 1-mute, 2-toggle
    refresh:boolean - Re-fetches current data from pulse audio

    returns True is succeeded, False if error
    '''
    global active_sink, sinks
    if refresh or not active_sink:
        sinks, active_sink = _getSinks()
    if not active_sink:
        logger.warning(f'Audio/toggleMuted: no active sink: {active_sink}')
        return False
    cmd = 'toggle' if mute == 2 else str(mute)
    muteCmd = f'pactl set-sink-mute {active_sink["index"]} {cmd}'.split()

    try:
        Popen(muteCmd)
    except CalledProcessError as err:
        logger.warning("SetMute error : {}".format(err))
        return False

    return True
Beispiel #15
0
 def update(self, theme):
     widgets = set()
     for prop_name, value in theme.items():
         widgets |= self.set(prop_name, value)
     logger.warning("{} WIDGETS TO DRAW".format(len(widgets)))
     for widget in widgets:
         widget.draw()
Beispiel #16
0
def setupMonitors():
    try:
        o = subprocess.check_output(['xrandr']).decode()
    except subprocess.CalledProcessError as e:
        logger.warning(e.output.decode().strip())
        return

    cmd = ["xrandr"]
    x = 0
    monitors = []
    for i, e in enumerate(o.split('\n')):
        if not 'connected' in e:
            continue

        name = e.strip().split()[0]
        if ' connected' in e:
            res = o.split('\n')[i+1].strip().split()[0]
            cmd += ['--output', name, '--mode', res,
                    '--pos', "{}x{}".format(x, 0), '--rotate', 'normal']
            x += int(res.split('x')[0])
            monitors.append(name)
        elif 'disconnected' in e:
            cmd += ['--output', name, '--off']

    try:
        subprocess.run(cmd)
    except subprocess.CalledProcessError as e:
        logger.warning(e.output.decode().strip())
    else:
        return monitors
Beispiel #17
0
    def _configure(self, qtile, bar):
        base._Widget._configure(self, qtile, bar)
        self.img = None

        if not self.filename:
            logger.warning("Image filename not set!")
            return

        self.filename = os.path.expanduser(self.filename)

        if not os.path.exists(self.filename):
            logger.warning("Image does not exist: {}".format(self.filename))
            return

        img = Img.from_path(self.filename)
        self.img = img
        img.theta = self.rotate
        if not self.scale:
            return
        if self.bar.horizontal:
            new_height = self.bar.height - (self.margin_y * 2)
            img.resize(height=new_height)
        else:
            new_width = self.bar.width - (self.margin_x * 2)
            img.resize(width=new_width)
Beispiel #18
0
def configure_device(device: InputDevice, configs: dict[str,
                                                        InputConfig]) -> None:
    if not configs:
        return

    # Find a matching InputConfig
    name = device.name
    if name == " " or not name.isprintable():
        name = "_"
    identifier = "%d:%d:%s" % (device.vendor, device.product, name)
    type_key = "type:" + device.device_type.name.lower()

    if type_key == "type:pointer":
        # This checks whether the pointer is a touchpad.
        handle = device.libinput_get_device_handle()
        if handle and libinput.libinput_device_config_tap_get_finger_count(
                handle) > 0:
            type_key = "type:touchpad"

    if identifier in configs:
        conf = configs[identifier]
    elif type_key in configs:
        conf = configs[type_key]
    elif "*" in configs:
        conf = configs["*"]
    else:
        return

    if device.device_type == input_device.InputDeviceType.POINTER:
        _configure_pointer(device, conf, name)
    elif device.device_type == input_device.InputDeviceType.KEYBOARD:
        _configure_keyboard(device, conf)
    else:
        logger.warning("Device not configured. Type '%s' not recognised.",
                       device.device_type)
Beispiel #19
0
async def _notify(title, message, urgency, timeout, id):
    notification = [
        "qtile",  # Application name
        id,  # id
        "",  # icon
        title,  # summary
        message,  # body
        [""],  # actions
        {
            "urgency": Variant("y", urgency)
        },  # hints
        timeout
    ]  # timeout

    bus, msg = await _send_dbus_message(True, MessageType.METHOD_CALL,
                                        "org.freedesktop.Notifications",
                                        "org.freedesktop.Notifications",
                                        "/org/freedesktop/Notifications",
                                        "Notify", "susssasa{sv}i",
                                        notification)

    if msg.message_type == MessageType.ERROR:
        logger.warning("Unable to send notification. "
                       "Is a notification server running?")

    # a new bus connection is made each time a notification is sent so
    # we disconnect when the notification is done
    bus.disconnect()
Beispiel #20
0
    def setup_images(self):
        for key, name in self.icons.items():
            try:
                path = os.path.join(self.theme_path, name)
                img = cairocffi.ImageSurface.create_from_png(path)
            except cairocffi.Error:
                self.theme_path = None
                logger.warning('Battery Icon switching to text mode')
                return
            input_width = img.get_width()
            input_height = img.get_height()

            sp = input_height / (self.bar.height - 1)

            width = input_width / sp
            if width > self.length:
                self.length = int(width) + self.actual_padding * 2

            imgpat = cairocffi.SurfacePattern(img)

            scaler = cairocffi.Matrix()

            scaler.scale(sp, sp)
            scaler.translate(self.actual_padding * -1, 0)
            imgpat.set_matrix(scaler)

            imgpat.set_filter(cairocffi.FILTER_BEST)
            self.surfaces[key] = imgpat
Beispiel #21
0
    async def _server_callback(self, reader: asyncio.StreamReader,
                               writer: asyncio.StreamWriter) -> None:
        """Callback when a connection is made to the server

        Read the data sent from the client, execute the requested command, and
        send the reply back to the client.
        """
        try:
            logger.debug("Connection made to server")
            data = await reader.read()
            logger.debug("EOF received by server")

            req, is_json = _IPC.unpack(data)
        except IPCError:
            logger.warning("Invalid data received, closing connection")
        else:
            rep = self.handler(req)

            result = _IPC.pack(rep, is_json=is_json)

            logger.debug("Sending result on receive EOF")
            writer.write(result)
            logger.debug("Closing connection on receive EOF")
            writer.write_eof()
        finally:
            writer.close()
            await writer.wait_closed()
Beispiel #22
0
def send_notification(title, message, urgent=False, timeout=10000, id=None):
    """
    Send a notification.

    The id argument, if passed, requests the notification server to replace a visible
    notification with the same ID. An ID is returned for each call; this would then be
    passed when calling this function again to replace that notification. See:
    https://developer.gnome.org/notification-spec/
    """
    if not has_dbus:
        logger.warning(
            "dbus-next is not installed. Unable to send notifications.")
        return -1

    id = randint(10, 1000) if id is None else id
    urgency = 2 if urgent else 1

    try:
        loop = asyncio.get_running_loop()
    except RuntimeError:
        logger.warning("Eventloop has not started. Cannot send notification.")
    else:
        loop.create_task(_notify(title, message, urgency, timeout, id))

    return id
Beispiel #23
0
    def get_max(self):
        "Read the max brightness level for the device"

        maxval = self._read(self.max_path)
        if not maxval:
            logger.warning("Max value was not read. "
                           "Module may behave unexpectedly.")
        return maxval
Beispiel #24
0
    async def _config_async(self):
        subscribed = await add_signal_receiver(self._signal_received,
                                               session_bus=True,
                                               signal_name="layoutChanged",
                                               dbus_interface="ru.gentoo.kbdd")

        if not subscribed:
            logger.warning("Could not subscribe to kbdd signal.")
Beispiel #25
0
    def _get_data(self, queue=None):
        try:
            data = self.tvh.get_upcoming()
        except TVHTimeOut:
            logger.warning("Couldn't connect to TVH server")
            data = []

        return data
Beispiel #26
0
def getNumScreens():
    try:
        o = subprocess.check_output(['xrandr']).decode()
    except subprocess.CalledProcessError as e:
        logger.warning(e.output.decode().strip())
        return 1
    else:
        return len(re.findall(r'\w+ connected \w+', o))
Beispiel #27
0
    def get_current(self):
        "Read the current brightness level for the device"

        current = self._read(self.bright_path)
        if not current:
            logger.warning("Current value was not read. "
                           "Module may behave unexpectedly.")
        return current
Beispiel #28
0
 def wrapper(*args, **kwargs):
     return_value = return_on_exception
     try:
         return_value = func(*args, **kwargs)
     except excepts as err:
         logger.warning(str(err))
         warnings.warn(str(err), warning)
     return return_value
Beispiel #29
0
 def register(self, callback, capabilities=None):
     if not self.service:
         logger.warning(
             'Registering %s without any dbus connection existing',
             callback.__name__,
         )
     self.callbacks.append(callback)
     if capabilities:
         self._service.register_capabilities(capabilities)
Beispiel #30
0
 def set_keymap(self, layout: Optional[str],
                options: Optional[str]) -> None:
     """
     Set the keymap for the current keyboard.
     """
     if self.keyboards:
         self.keyboards[-1].set_keymap(layout, options)
     else:
         logger.warning("Could not set keymap: no keyboards set up.")
Beispiel #31
0
    async def start(self):
        # Create a proxy object connecting for the item.
        introspection = await self.bus.introspect(self.service, self.path)

        try:
            obj = self.bus.get_proxy_object(self.service, self.path,
                                            introspection)
        except InvalidBusNameError:
            return False

        # Try to connect to the bus object and verify there's a valid
        # interface available
        # TODO: This may not ever fail given we've specified the underying
        # schema so dbus-next has not attempted any introspection.
        interface_found = False
        for interface in ITEM_INTERFACES:
            try:
                self.item = obj.get_interface(interface)
                interface_found = True
                break
            except InterfaceNotFoundError:
                continue

        if not interface_found:
            logger.warning(f"Unable to find StatusNotifierItem"
                           f"interface on {self.service}")
            return False

        # Default to XDG icon:
        icon_name = await self.item.get_icon_name()

        try:
            icon_path = await self.item.get_icon_theme_path()
            self.icon = self._get_custom_icon(icon_name, icon_path)
        except (AttributeError, DBusError):
            pass

        if not self.icon:
            self.icon = self._get_xdg_icon(icon_name)

        # If there's no XDG icon, try to use icon provided by application
        if self.icon is None:

            # Get initial application icons:
            for icon in ["Icon", "Attention", "Overlay"]:
                await self._get_icon(icon)

            # Attach listeners for when the icon is updated
            self.item.on_new_icon(self._new_icon)
            self.item.on_new_attention_icon(self._new_attention_icon)
            self.item.on_new_overlay_icon(self._new_overlay_icon)

        if not self.has_icons:
            logger.warning("Cannot find icon in current theme and "
                           "no icon provided by StatusNotifierItem.")

        return True
Beispiel #32
0
    def setup_images(self):
        """ Create image structures for each icon files. """
        for img_name, iconfile in self.icons_files.items():
            if iconfile is None:
                logger.warning(
                    'No icon found for application "%s" (%s) switch to text mode',
                    img_name, iconfile)
                # if no icon is found and no default icon was set, we just
                # print the name, based on a textbox.
                textbox = base._TextBox()
                textbox._configure(self.qtile, self.bar)
                textbox.layout = self.drawer.textlayout(
                    textbox.text,
                    textbox.foreground,
                    textbox.font,
                    textbox.fontsize,
                    textbox.fontshadow,
                    markup=textbox.markup,
                )
                # the name will be displayed
                textbox.text = img_name
                textbox.calculate_length()
                self.icons_widths[img_name] = textbox.width
                self.surfaces[img_name] = textbox
                continue
            else:
                try:
                    img = cairocffi.ImageSurface.create_from_png(iconfile)
                except cairocffi.Error:
                    logger.exception('Error loading icon for application "%s" (%s)',
                        img_name, iconfile)
                    return

            input_width = img.get_width()
            input_height = img.get_height()

            sp = input_height / (self.bar.height - 4)
            width = int(input_width / sp)

            imgpat = cairocffi.SurfacePattern(img)
            scaler = cairocffi.Matrix()
            scaler.scale(sp, sp)
            scaler.translate(self.padding * -1, -2)
            imgpat.set_matrix(scaler)

            imgpat.set_filter(cairocffi.FILTER_BEST)
            self.surfaces[img_name] = imgpat
            self.icons_widths[img_name] = width
Beispiel #33
0
 def __init__(self, **config):
     _Graph.__init__(self, **config)
     self.add_defaults(NetGraph.defaults)
     if self.interface == "auto":
         try:
             self.interface = self.get_main_iface()
         except RuntimeError:
             logger.warning(
                 "NetGraph - Automatic interface detection failed, "
                 "falling back to 'eth0'"
             )
             self.interface = "eth0"
     if self.bandwidth_type != "down" and self.bandwidth_type != "up":
         raise ValueError("bandwidth type {} not known!".format(self.bandwidth_type))
     self.bytes = 0
     self.bytes = self._get_values()
Beispiel #34
0
 def __init__(self, **config):
     _Graph.__init__(self, **config)
     self.add_defaults(NetGraph.defaults)
     if self.interface == "auto":
         try:
             self.interface = self.get_main_iface()
         except RuntimeError:
             logger.warning(
                 "NetGraph - Automatic interface detection failed, "
                 "falling back to 'eth0'"
             )
             self.interface = "eth0"
     self.filename = '/sys/class/net/{interface}/statistics/{type}'.format(
         interface=self.interface,
         type=self.bandwidth_type == 'down' and 'rx_bytes' or 'tx_bytes'
     )
     self.bytes = 0
     self.bytes = self._getValues()
Beispiel #35
0
        def on_done(future):
            try:
                result = future.result()
            except Exception:
                logger.exception('poll() raised exceptions, not rescheduling')

            if result is not None:
                try:
                    self.update(result)

                    if self.update_interval is not None:
                        self.timeout_add(self.update_interval, self.timer_setup)
                    else:
                        self.timer_setup()

                except Exception:
                    logger.exception('Failed to reschedule.')
            else:
                logger.warning('poll() returned None, not rescheduling')
Beispiel #36
0
def safe_import(module_name, class_name):
    """
    try to import a module, and if it fails because an ImporError
    it logs on WARNING, and logs the traceback on DEBUG level
    """
    if type(class_name) is list:
        for name in class_name:
            safe_import(module_name, name)
        return
    package = __package__
    # python 3.2 don't set __package__
    if not package:
        package = __name__
    try:
        module = importlib.import_module(module_name, package)
        globals()[class_name] = getattr(module, class_name)
    except ImportError as error:
        logger.warning("Can't Import Widget: '%s.%s', %s", module_name, class_name, error)
        logger.debug("%s", traceback.format_exc())
Beispiel #37
0
    def connect(self, quiet=False):
        if self.connected:
            return True

        try:
            self.client.connect(host=self.host, port=self.port)
        except Exception:
            if not quiet:
                logger.exception('Failed to connect to mpd')
            return False

        if self.password:
            try:
                self.client.password(self.password)
            except Exception:
                logger.warning('Authentication failed.  Disconnecting')
                try:
                    self.client.disconnect()
                except Exception:
                    pass

        self.connected = True
        return True
Beispiel #38
0
    def __init__(self, fname=None, is_restart=False):
        if not fname:
            config_directory = os.path.expandvars('$XDG_CONFIG_HOME')
            if config_directory == '$XDG_CONFIG_HOME':
                # if variable wasn't set
                config_directory = os.path.expanduser("~/.config")
            fname = os.path.join(config_directory, "qtile", "config.py")

        # We delay importing here to avoid a circular import issue when
        # testing.
        from .resources import default_config

        if fname == "default":
            config = default_config
        elif os.path.isfile(fname):
            try:
                sys.path.insert(0, os.path.dirname(fname))
                config = __import__(os.path.basename(fname)[:-3])
            except Exception as v:

                tb = traceback.format_exc()

                # On restart, user potentially has some windows open, but they
                # screwed up their config. So as not to lose their apps, we
                # just load the default config here.
                if is_restart:
                    logger.warning(
                        'Caught exception in configuration:\n\n'
                        '%s\n\n'
                        'Qtile restarted with default config', tb)
                    config = None
                else:
                    raise ConfigError(tb)
        else:
            config = None

        # if you add something here, be sure to add a reasonable default value
        # to resources/default_config.py
        config_options = [
            "keys",
            "mouse",
            "groups",
            "dgroups_key_binder",
            "dgroups_app_rules",
            "follow_mouse_focus",
            "focus_on_window_activation",
            "cursor_warp",
            "layouts",
            "floating_layout",
            "screens",
            "main",
            "auto_fullscreen",
            "widget_defaults",
            "bring_front_click",
            "wmname",
            "extentions",
        ]

        for option in config_options:
            if hasattr(config, option):
                v = getattr(config, option)
            else:
                v = getattr(default_config, option)
            if not hasattr(self, option):
                setattr(self, option, v)