internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: hpcaitech/ColossalAI

Issue:
[tensor] fix some unittests

[tensor] fix some unittests

[tensor] fix some unittests



Discussion:

Resolving patch:
diff --git a/extensions/pybind/inference/inference_ops_cuda.py b/extensions/pybind/inference/inference_ops_cuda.py
--- a/extensions/pybind/inference/inference_ops_cuda.py
+++ b/extensions/pybind/inference/inference_ops_cuda.py
@@ -17,6 +17,7 @@ def sources_files(self):
                 "kernel/cuda/rms_layernorm_kernel.cu",
                 "kernel/cuda/get_cos_and_sin_kernel.cu",
                 "kernel/cuda/flash_decoding_attention_kernel.cu",
+                "kernel/cuda/convert_fp8_kernel.cu",
             ]
         ] + [self.pybind_abs_path("inference/inference.cpp")]
         return ret


Test patch:
diff --git a/tests/test_infer/test_kernels/cuda/test_convert_fp8.py b/tests/test_infer/test_kernels/cuda/test_convert_fp8.py
new file mode 100644
--- /dev/null
+++ b/tests/test_infer/test_kernels/cuda/test_convert_fp8.py
@@ -0,0 +1,57 @@
+import random
+
+import pytest
+import torch
+
+from colossalai.kernel.kernel_loader import InferenceOpsLoader
+from colossalai.utils import get_current_device
+
+inference_ops = InferenceOpsLoader().load()
+
+DTYPES = [torch.half, torch.bfloat16, torch.float]
+NUM_TOKENS = [42]  # Arbitrary values for testing
+NUM_LAYERS = [1]  # Arbitrary values for testing
+NUM_HEADS = [8]  # Arbitrary values for testing
+HEAD_SIZES = [64, 80, 96, 112, 128, 256]
+BLOCK_SIZES = [8, 16, 32]
+
+
+@pytest.mark.skipif(True, reason="FP8 conversion still needs improvement, now we skip it's relative test!")
+@pytest.mark.parametrize("num_heads", [8])
+@pytest.mark.parametrize("head_size", [64, 80, 96, 112, 128, 256])
+@pytest.mark.parametrize("block_size", [8, 16, 32])
+@pytest.mark.parametrize("num_blocks", [1024, 10000])
+@pytest.mark.parametrize("dtype", [torch.half, torch.bfloat16, torch.float])
+@pytest.mark.parametrize("seed", [0])
+@torch.inference_mode()
+def test_fp8_conversion(
+    num_heads: int,
+    head_size: int,
+    block_size: int,
+    num_blocks: int,
+    dtype: torch.dtype,
+    seed: int,
+) -> None:
+    random.seed(seed)
+    torch.random.manual_seed(seed)
+    torch.cuda.manual_seed(seed)
+
+    device = get_current_device()
+
+    low = -224.0
+    high = 224.0
+    shape = (num_blocks, num_heads, head_size, block_size)
+    cache = torch.empty(shape, dtype=dtype, device=device)
+    cache.uniform_(low, high)
+
+    cache_fp8 = torch.empty_like(cache, dtype=torch.uint8)
+    inference_ops.convert_fp8(cache, cache_fp8)
+
+    converted_cache = torch.empty_like(cache)
+    inference_ops.convert_fp8(cache_fp8, converted_cache)
+
+    assert torch.allclose(cache, converted_cache, atol=0.001, rtol=0.1)
+
+
+if __name__ == "__main__":
+    test_fp8_conversion(8, 64, 8, 1024, torch.half, 0)
Repository: hpcaitech/ColossalAI

Issue:
[tensor] fix some unittests

[tensor] fix some unittests

[tensor] fix some unittests



Discussion:

Resolving patch:
diff --git a/colossalai/lazy/pretrained.py b/colossalai/lazy/pretrained.py
--- a/colossalai/lazy/pretrained.py
+++ b/colossalai/lazy/pretrained.py
@@ -1,3 +1,4 @@
+import copy
 import os
 from typing import Callable, Optional, Union
 
@@ -74,6 +75,24 @@ def new_from_pretrained(
     subfolder = kwargs.pop("subfolder", "")
     commit_hash = kwargs.pop("_commit_hash", None)
     variant = kwargs.pop("variant", None)
+
+    kwargs.pop("state_dict", None)
+    kwargs.pop("from_tf", False)
+    kwargs.pop("from_flax", False)
+    kwargs.pop("output_loading_info", False)
+    kwargs.pop("trust_remote_code", None)
+    kwargs.pop("low_cpu_mem_usage", None)
+    kwargs.pop("device_map", None)
+    kwargs.pop("max_memory", None)
+    kwargs.pop("offload_folder", None)
+    kwargs.pop("offload_state_dict", False)
+    kwargs.pop("load_in_8bit", False)
+    kwargs.pop("load_in_4bit", False)
+    kwargs.pop("quantization_config", None)
+    kwargs.pop("adapter_kwargs", {})
+    kwargs.pop("adapter_name", "default")
+    kwargs.pop("use_flash_attention_2", False)
+
     use_safetensors = kwargs.pop("use_safetensors", None if is_safetensors_available() else False)
 
     if len(kwargs) > 0:
@@ -108,6 +127,10 @@ def new_from_pretrained(
             **kwargs,
         )
     else:
+        config = copy.deepcopy(config)
+        kwarg_attn_imp = kwargs.pop("attn_implementation", None)
+        if kwarg_attn_imp is not None and config._attn_implementation != kwarg_attn_imp:
+            config._attn_implementation = kwarg_attn_imp
         model_kwargs = kwargs
 
     if commit_hash is None:


Test patch:
Repository: hpcaitech/ColossalAI

Issue:
[tensor] fix some unittests

[tensor] fix some unittests

[tensor] fix some unittests



Discussion:

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -111,7 +111,6 @@ def get_version() -> str:
             "tests",
             "scripts",
             "requirements",
-            "extensions",
             "*.egg-info",
         ),
     ),


Test patch:
Repository: hpcaitech/ColossalAI

Issue:
[tensor] fix some unittests

[tensor] fix some unittests

[tensor] fix some unittests



Discussion:

Resolving patch:
diff --git a/colossalai/inference/core/engine.py b/colossalai/inference/core/engine.py
--- a/colossalai/inference/core/engine.py
+++ b/colossalai/inference/core/engine.py
@@ -1,6 +1,6 @@
 import time
 from itertools import count
-from typing import Dict, List, Optional, Tuple, Union
+from typing import Dict, List, Optional, Tuple, Type, Union
 
 import numpy as np
 import torch
@@ -64,7 +64,7 @@ def __init__(
         tokenizer: Union[PreTrainedTokenizer, PreTrainedTokenizerFast],
         inference_config: InferenceConfig,
         verbose: bool = False,
-        model_policy: Policy = None,
+        model_policy: Union[Policy, Type[Policy]] = None,
     ) -> None:
         self.inference_config = inference_config
         self.dtype = inference_config.dtype
@@ -104,7 +104,7 @@ def __init__(
 
         self._verify_args()
 
-    def init_model(self, model_or_path: Union[nn.Module, str], model_policy: Policy = None):
+    def init_model(self, model_or_path: Union[nn.Module, str], model_policy: Union[Policy, Type[Policy]] = None):
         """
         Shard model or/and Load weight
 
@@ -149,11 +149,17 @@ def init_model(self, model_or_path: Union[nn.Module, str], model_policy: Policy
             )
 
         if model_policy is None:
-            if self.inference_config.pad_input:
-                model_type = "padding_" + self.model_config.model_type
-            else:
-                model_type = "nopadding_" + self.model_config.model_type
-            model_policy = model_policy_map[model_type]()
+            prefix = "nopadding" if not self.inference_config.pad_input else "padding"
+            model_policy_key = f"{prefix}_{getattr(self.model_config, 'model_type', None)}"
+            model_policy = model_policy_map.get(model_policy_key)
+
+        if not isinstance(model_policy, Policy):
+            try:
+                model_policy = model_policy()
+            except Exception as e:
+                raise ValueError(f"Unable to instantiate model policy: {e}")
+
+        assert isinstance(model_policy, Policy), f"Invalid type of model policy: {type(model_policy)}"
         pg_mesh = ProcessGroupMesh(self.inference_config.pp_size, self.inference_config.tp_size)
         tp_group = pg_mesh.get_group_along_axis(TP_AXIS)
 


Test patch:
Repository: hpcaitech/ColossalAI

Issue:
[tensor] fix some unittests

[tensor] fix some unittests

[tensor] fix some unittests



Discussion:

Resolving patch:
diff --git a/colossalai/zero/gemini/gemini_mgr.py b/colossalai/zero/gemini/gemini_mgr.py
--- a/colossalai/zero/gemini/gemini_mgr.py
+++ b/colossalai/zero/gemini/gemini_mgr.py
@@ -42,7 +42,9 @@ def __init__(
         self._mem_stats_collector = (
             ChunkMemStatsCollector(chunk_manager, self._memstats) if policy_cls.need_mem_stats else None
         )
-        self._placement_policy = policy_cls(self, chunk_manager, self._mem_stats_collector, **placement_kwargs)
+        self._placement_policy = policy_cls(
+            chunk_manager=chunk_manager, mem_stats_collector=self._mem_stats_collector, **placement_kwargs
+        )
         self._compute_list: List[Tuple[Chunk, ...]] = []
         self._compute_idx: int = -1
         self._async_works: Dict[Chunk, dist.Work] = {}


Test patch:
Repository: hpcaitech/ColossalAI

Issue:
[tensor] fix some unittests

[tensor] fix some unittests

[tensor] fix some unittests



Discussion:

Resolving patch:
diff --git a/colossalai/kernel/triton/flash_decoding.py b/colossalai/kernel/triton/flash_decoding.py
--- a/colossalai/kernel/triton/flash_decoding.py
+++ b/colossalai/kernel/triton/flash_decoding.py
@@ -111,10 +111,10 @@ def _flash_decoding_fwd_kernel(
     m = tl.max(S_ij, 0)
     S_ij -= m
     p_ij_hat = tl.exp(S_ij)
-    l = tl.sum(p_ij_hat, 0)
+    l_i = tl.sum(p_ij_hat, 0)
     p_ij_hat = p_ij_hat.to(v_cur_block.type.element_ty)
     acc += tl.sum(v_cur_block * p_ij_hat[:, None], 0)
-    acc = acc / l
+    acc = acc / l_i
 
     offsets_mid_o = (
         cur_token_idx * stride_mid_ot
@@ -126,8 +126,8 @@ def _flash_decoding_fwd_kernel(
     offsets_mid_o_lse = (
         cur_token_idx * stride_mid_o_lset + cur_head_idx * stride_mid_o_lseh + block_start_kv * stride_mid_o_lseb
     )
-    # logsumexp L^(j) = m^(j) + log(l^(j))
-    tl.store(mid_o_lse + offsets_mid_o_lse, m + tl.log(l))
+    # logsumexp l_i^(j) = m^(j) + log(l_i^(j))
+    tl.store(mid_o_lse + offsets_mid_o_lse, m + tl.log(l_i))
 
 
 # Triton 2.1.0
@@ -234,10 +234,10 @@ def _alibi_flash_decoding_fwd_kernel(
     m = tl.max(S_ij, 0)
     S_ij -= m
     p_ij_hat = tl.exp(S_ij)
-    l = tl.sum(p_ij_hat, 0)
+    l_i = tl.sum(p_ij_hat, 0)
     p_ij_hat = p_ij_hat.to(v_cur_block.type.element_ty)
     acc += tl.sum(v_cur_block * p_ij_hat[:, None], 0)
-    acc = acc / l
+    acc = acc / l_i
 
     offsets_mid_o = (
         cur_token_idx * stride_mid_ot
@@ -249,8 +249,8 @@ def _alibi_flash_decoding_fwd_kernel(
     offsets_mid_o_lse = (
         cur_token_idx * stride_mid_o_lset + cur_head_idx * stride_mid_o_lseh + block_start_kv * stride_mid_o_lseb
     )
-    # logsumexp L^(j) = m^(j) + log(l^(j))
-    tl.store(mid_o_lse + offsets_mid_o_lse, m + tl.log(l))
+    # logsumexp l_i^(j) = m^(j) + log(l_i^(j))
+    tl.store(mid_o_lse + offsets_mid_o_lse, m + tl.log(l_i))
 
 
 # Triton 2.1.0
@@ -290,7 +290,7 @@ def _flash_decoding_fwd_reduce_kernel(
     # BLOCK_KV == BLOCK_SIZE for now. We might want to decrease the number of blocks of kv splitted.
     kv_split_num = (cur_kv_seq_len + BLOCK_KV - 1) // BLOCK_KV
     m_i = float("-inf")  # max logic
-    l = 0.0  # sum exp
+    l_i = 0.0  # sum exp
     acc = tl.zeros([HEAD_DIM], dtype=tl.float32)
 
     offsets_mid_o = cur_token_idx * stride_mid_ot + cur_head_idx * stride_mid_oh + offsets_dmodel
@@ -304,10 +304,10 @@ def _flash_decoding_fwd_reduce_kernel(
         lse -= m_ij
         exp_logic = tl.exp(lse)
         acc += exp_logic * mid_o_block
-        l = scale * l + exp_logic
+        l_i = scale * l_i + exp_logic
         m_i = m_ij
 
-    acc = acc / l
+    acc = acc / l_i
     offsets_O = cur_token_idx * stride_ot + cur_head_idx * stride_oh + offsets_dmodel
     tl.store(O + offsets_O, acc.to(O.type.element_ty))
     return


Test patch:
Repository: qtile/qtile

Issue:
TreeLayout works bad with two screens
Left panel does not move between screens.
(will probably fix myself, just to not to forget)



Discussion:

Resolving patch:
diff --git a/libqtile/layout/tree.py b/libqtile/layout/tree.py
--- a/libqtile/layout/tree.py
+++ b/libqtile/layout/tree.py
@@ -278,7 +278,10 @@ def focus(self, win):
         self._focused = win
 
     def blur(self):
-        self._focused = None
+        # Does not clear current window, will change if new one
+        # will be focused. This works better when floating window
+        # will be next focused one
+        pass
 
     def add(self, win):
         if self._focused:
@@ -309,6 +312,16 @@ def _create_panel(self):
         hook.subscribe.window_name_change(self.draw_panel)
         hook.subscribe.focus_change(self.draw_panel)
 
+    def _show_panel(self):
+        self._panel.place(
+            self.group.screen.dx,
+            self.group.screen.dy,
+            self.panel_width,
+            self.group.screen.dheight,
+            0,
+            None)
+        self._panel.unhide()
+
     def _panel_Expose(self, e):
         self.draw_panel()
 
@@ -347,7 +360,7 @@ def info(self):
     def show(self):
         if not self._panel:
             self._create_panel()
-        self._panel.unhide()
+        self._show_panel()
         self.draw_panel()
 
     def hide(self):


Test patch:
Repository: qtile/qtile

Issue:
using Qtile.cmd_{info, debug} doesn't switch logging level
It seems that critical, warning, and error do all work, though.



Discussion:
It does change which messages are printed to stdout/err (I don't know which one exactly is used)

I think the problem is that the the log level of the log handler handling the file logging is manually set to WARNING, which overrides the log level set for the logger.


Resolving patch:
diff --git a/libqtile/log_utils.py b/libqtile/log_utils.py
--- a/libqtile/log_utils.py
+++ b/libqtile/log_utils.py
@@ -43,7 +43,6 @@ def format(self, record):
 def init_log(log_level=logging.WARNING, logger='qtile'):
     handler = logging.FileHandler(
         os.path.expanduser('~/.%s.log' % logger))
-    handler.setLevel(logging.WARNING)
     handler.setFormatter(
         logging.Formatter(
             "%(asctime)s %(levelname)s %(funcName)s:%(lineno)d %(message)s"))


Test patch:
Repository: qtile/qtile

Issue:
lib*.so references in pangocffi.py
When upgrading from 0.9.1 to 0.10.1, I needed to modify the following references for my system (Ubuntu Vivid) in libqtile/pangocffi.py

gobject = ffi.dlopen('libgobject-2.0.so')
pango = ffi.dlopen('libpango-1.0.so')
pangocairo = ffi.dlopen('libpangocairo-1.0.so')



Discussion:
On Mon, Aug 03, 2015 at 11:39:14PM -0700, jsqliu wrote:

> When upgrading from 0.9.1 to 0.10.1, I needed to modify the following references for my system (Ubuntu Vivid) in libqtile/pangocffi.py
> 
> gobject = ffi.dlopen('libgobject-2.0.so')
> pango = ffi.dlopen('libpango-1.0.so')
> pangocairo = ffi.dlopen('libpangocairo-1.0.so')

Sorry, what's the bug here? My copy of the tree has those in it as
well. Can you post a patch of your modifications?

On my system two of the .so filenames are slightly different so I'm using

```
pango = ffi.dlopen('libpango-1.0.so.0')
pangocairo = ffi.dlopen('libpangocairo-1.0.so.0')
```

libpango and libpangocairo should have been installed through apt.  I used `dpkg -L libpango-1.0-0:amd64` and `dpkg -L libpangocairo-1.0-0:amd64` to locate these files.

I'm not sure if this counts as a bug or if there is a more system independent way to write this, but it's a step beyond the documented installation instructions I had to take.

On Tue, Aug 04, 2015 at 09:29:42AM -0700, jsqliu wrote:

> On my system two of the .so filenames are slightly different so I'm using
> 
> ```
> pango = ffi.dlopen('libpango-1.0.so.0')
> pangocairo = ffi.dlopen('libpangocairo-1.0.so.0')
> ```
> 
> libpango and libpangocairo should have been installed through apt.  I used `dpkg -L libpango-1.0-0:amd64` and `dpkg -L libpangocairo-1.0-0:amd64` to locate these files.
> 
> I'm not sure if this counts as a bug or if there is a more system independent way to write this, but it's a step beyond the documented installation instructions I had to take.

Oh, no, you're right, I think qtile is wrong here. It looks like the
raw libpango-1.0.so is provided by libpango1.0-dev, which we don't
(well, shouldn't) require as a dependency. I'll try to send a patch
soon, thanks!

> ---
> 
> Reply to this email directly or view it on GitHub:
> https://github.com/qtile/qtile/issues/734#issuecomment-127666304


Resolving patch:
diff --git a/libqtile/pangocffi.py b/libqtile/pangocffi.py
--- a/libqtile/pangocffi.py
+++ b/libqtile/pangocffi.py
@@ -54,9 +54,9 @@
 except ImportError:
     from libqtile.ffi_build import pango_ffi as ffi
 
-gobject = ffi.dlopen('libgobject-2.0.so')
-pango = ffi.dlopen('libpango-1.0.so')
-pangocairo = ffi.dlopen('libpangocairo-1.0.so')
+gobject = ffi.dlopen('libgobject-2.0.so.0')
+pango = ffi.dlopen('libpango-1.0.so.0')
+pangocairo = ffi.dlopen('libpangocairo-1.0.so.0')
 
 
 def CairoContext(cairo_t):


Test patch:
Repository: qtile/qtile

Issue:
EWMH window focus
It looks likes switching focus via EWMH is not working. 
For example:

```
$ wmctrl -l
0x0220000d  1 bunion VulK@bunion: ~
0x0140000d  1 bunion VulK@bunion: wmctrl -l
0x0400000d  0 bunion VulK@bunion: mutt
$ wmctrl -i -a 0x0220000d
```

Does nothing.



Discussion:

Resolving patch:
diff --git a/libqtile/confreader.py b/libqtile/confreader.py
--- a/libqtile/confreader.py
+++ b/libqtile/confreader.py
@@ -80,6 +80,7 @@ def __init__(self, fname=None, is_restart=False):
             "dgroups_key_binder",
             "dgroups_app_rules",
             "follow_mouse_focus",
+            "focus_on_window_activation",
             "cursor_warp",
             "layouts",
             "floating_layout",
diff --git a/libqtile/resources/default_config.py b/libqtile/resources/default_config.py
--- a/libqtile/resources/default_config.py
+++ b/libqtile/resources/default_config.py
@@ -139,6 +139,7 @@
 cursor_warp = False
 floating_layout = layout.Floating()
 auto_fullscreen = True
+focus_on_window_activation = "urgent"
 
 # XXX: Gasp! We're lying here. In fact, nobody really uses or cares about this
 # string besides java UI toolkits; you can see several discussions on the
diff --git a/libqtile/window.py b/libqtile/window.py
--- a/libqtile/window.py
+++ b/libqtile/window.py
@@ -1152,6 +1152,23 @@ def handle_ClientMessage(self, event):
                     current_state ^= set([prop])  # toggle :D
 
             self.window.set_property('_NET_WM_STATE', list(current_state))
+        elif atoms["_NET_ACTIVE_WINDOW"] == opcode:
+            source = data.data32[0]
+            if source == 2:  # XCB_EWMH_CLIENT_SOURCE_TYPE_NORMAL
+                logger.info("Focusing window by pager")
+                self.qtile.currentScreen.setGroup(self.group)
+                self.group.focus(self)
+            else:  # XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER
+                focus_behavior = self.qtile.config.focus_on_window_activation
+                if focus_behavior == "focus" or (focus_behavior == "smart" and self.group.screen):
+                    logger.info("Focusing window")
+                    self.qtile.currentScreen.setGroup(self.group)
+                    self.group.focus(self)
+                elif focus_behavior == "urgent" or (focus_behavior == "smart" and not self.group.screen):
+                    logger.info("Setting urgent flag for window")
+                    self.urgent = True
+                else:
+                    logger.info("Ignoring focus request")
 
     def handle_PropertyNotify(self, e):
         name = self.qtile.conn.atoms.get_name(e.atom)


Test patch:
Repository: qtile/qtile

Issue:
Typo in ratiotile.py
https://github.com/qtile/qtile/blob/95919912b11eabedb59ad3215747544c48c522f9/libqtile/layout/ratiotile.py#L307

cmd_upn -> cmd_up


Discussion:

Resolving patch:
diff --git a/libqtile/layout/ratiotile.py b/libqtile/layout/ratiotile.py
--- a/libqtile/layout/ratiotile.py
+++ b/libqtile/layout/ratiotile.py
@@ -304,7 +304,7 @@ def shuffle(self, function):
             self.group.layoutAll()
 
     cmd_down = _SimpleLayoutBase.previous
-    cmd_upn = _SimpleLayoutBase.next
+    cmd_up = _SimpleLayoutBase.next
 
     cmd_previous = _SimpleLayoutBase.previous
     cmd_next = _SimpleLayoutBase.next


Test patch:
Repository: qtile/qtile

Issue:
Fake screens
[This part of the documentation](https://github.com/qtile/qtile/blob/ed7198a5fb5438110f81a8c6ecc0e6289676c057/libqtile/config.py#L231-L232) mentions "fake screens", and the term is also found [in the code](https://github.com/qtile/qtile/blob/7c2a88fba68bdcf6f25dfb5494a74afc475d674e/libqtile/manager.py#L357-L373).

What are they? How to use them?

We need to document answers to those questions, and then make sure they work correctly.

See #1192 for this last point.


Discussion:
@mattharrison @flacjacket can you help on this?
In my opinion they are very helphul, if one usese a 4k-Screen and wants to split it up to multiple fake screens.
@kes31 do you still know how it would work and could you give a simple example on how to configure fakescreens (assuming they work)?
I can probably spend some time to configure them for my widescreen monitor next week and create a documentation, if noone else is looking into it at moment.
@Melkor333 What I remember the following points:
- My problem was, that I could not overwrite the screen-setting which was detected from x11. Basically all my manual settings to screens were ignored.
- I found in code theses fakescreens, which basically overwrite the x11 setup. They were prepared to work, except this small patch in code.
- When I configured in my config the fakescreens variable, the x11 screen setup was ignored and my configured screens were used instead. In this way it was possible to create two screens on one  monitor.

Solemnly I decided to switch to awesomwm so I do not have an example anymore.

Resolving patch:
diff --git a/libqtile/confreader.py b/libqtile/confreader.py
--- a/libqtile/confreader.py
+++ b/libqtile/confreader.py
@@ -66,6 +66,7 @@ def __init__(self, **settings):
                 value = getattr(self, key, default[key])
             setattr(self, key, value)
         self._init_deprecated(**settings)
+        self._init_fake_screens(**settings)
 
     def _init_deprecated(self, extensions=None, **settings):
         "Initialize deprecated settings."
@@ -75,6 +76,14 @@ def _init_deprecated(self, extensions=None, **settings):
                           "'extension_defaults'", DeprecationWarning)
             self.extension_defaults.update(extensions.get('dmenu', {}))
 
+    def _init_fake_screens(self, **settings):
+        " Initiaize fake_screens if they are set."
+        try:
+            value = settings['fake_screens']
+            setattr(self, 'fake_screens', value)
+        except KeyError:
+            pass
+
     @classmethod
     def from_file(cls, path):
         "Create a Config() object from the python file located at path."


Test patch: