Repository: rochacbruno/dynaconf (python)

Issue:
[bug] dict-like iteration seems broken (when using example from Home page)
**Describe the bug**

When I try to run the example from section https://www.dynaconf.com/#initialize-dynaconf-on-your-project ("Using Python only") and try to use the dict-like iteration from section https://www.dynaconf.com/#reading-settings-variables then the assertions pass but it returns a TypeError trying to iterate over the settings object.

**To Reproduce**

Run the following `dynaconf_settings.py` file in Python 3.7 (with Dynaconf 3.0.0) with the following `settings.toml` file (copied and edited from Home page).

1. Having the following folder structure

<details>
<summary> Project structure </summary>

```bash
$ tree -v
.
├── SCRIMMAGE_1.md
├── curio_examples.py
├── dynaconf_settings.py
├── ini2json.py
├── settings.toml
├── trio_cancel.py
├── trio_rib.py
└── watchservers.sh

0 directories, 8 files
```
</details>

2. Having the following config files:

<details>
<summary> Config files </summary>

**settings.toml**
```toml
key = "value"
a_boolean = false
number = 789  # had to edit this to match assertion above; previous value: 1234
a_float = 56.8
a_list = [1, 2, 3, 4]
a_dict = {hello="world"}

[a_dict.nested]
other_level = "nested value"
```

</details>

3. Having the following app code:

<details>
<summary> Code </summary>

**dynaconf_settings.py**
```python
from dynaconf import Dynaconf

settings = Dynaconf(
    settings_files=["settings.toml"],
)

assert settings.key == "value"
assert settings.number == 789
assert settings.a_dict.nested.other_level == "nested value"
assert settings['a_boolean'] is False
assert settings.get("DONTEXIST", default=1) == 1

for key, value in settings:                   # dict like iteration
    print(key, value)
```

</details>

4. Executing under the following environment

<details>
<summary> Execution </summary>

```bash
$ python3 --version
Python 3.7.7
$ python3 dynaconf_settings.py
Traceback (most recent call last):
  File "dynaconf_settings.py", line 15, in <module>
    for key, value in settings:                   # dict like iteration
  File "/usr/local/lib/python3.7/site-packages/dynaconf/base.py", line 285, in __getitem__
    value = self.get(item, default=empty)
  File "/usr/local/lib/python3.7/site-packages/dynaconf/utils/parse_conf.py", line 195, in evaluate
    value = f(settings, *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/dynaconf/base.py", line 377, in get
    if "." in key and dotted_lookup:
TypeError: argument of type 'int' is not iterable
```

</details>

**Expected behavior**
No exception thrown when looping over dictionary.

**Environment (please complete the following information):**
 - OS: Mac OS 10.14
 - Dynaconf Version 3.0.0 (via pip3)


Pull request:
Fix #379 dict like iteration
Fix #379 

Patch:
diff --git a/docs/index.md b/docs/index.md
index fa7c80e..88486be 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -562,7 +562,7 @@ settings['databases.schema'] == "main"        # Nested items traversing
 settings.get("nonexisting", "default value")  # Default values just like a dict
 settings("number", cast=int)                  # customizable forcing of casting
 
-for key, value in settings:                   # dict like iteration
+for key, value in settings.items():           # dict like iteration
     print(key, value)
 ```
 
diff --git a/dynaconf/base.py b/dynaconf/base.py
index b5bde7c..9f54507 100644
--- a/dynaconf/base.py
+++ b/dynaconf/base.py
@@ -304,6 +304,14 @@ class Settings(object):
             + list(self.keys())
         )
 
+    def __iter__(self):
+        """Redirects to store object"""
+        yield from self._store
+
+    def items(self):
+        """Redirects to store object"""
+        return self._store.items()
+
     def keys(self):
         """Redirects to store object"""
         return self.store.keys()
diff --git a/example/issues/379_dict_like_iteration/app.py b/example/issues/379_dict_like_iteration/app.py
new file mode 100644
index 0000000..3e53d82
--- /dev/null
+++ b/example/issues/379_dict_like_iteration/app.py
@@ -0,0 +1,17 @@
+from dynaconf import Dynaconf
+
+settings = Dynaconf(settings_files=["settings.toml"],)
+
+assert settings.key == "value"
+assert settings.number == 789
+assert settings.a_dict.nested.other_level == "nested value"
+assert settings["a_boolean"] is False
+assert settings.get("DONTEXIST", default=1) == 1
+
+
+for item in settings:
+    print(item)
+
+
+for key, value in settings.items():  # dict like iteration
+    print(key, value)
diff --git a/example/issues/379_dict_like_iteration/settings.toml b/example/issues/379_dict_like_iteration/settings.toml
new file mode 100644
index 0000000..a5aaff2
--- /dev/null
+++ b/example/issues/379_dict_like_iteration/settings.toml
@@ -0,0 +1,9 @@
+key = "value"
+a_boolean = false
+number = 789  # had to edit this to match assertion above; previous value: 1234
+a_float = 56.8
+a_list = [1, 2, 3, 4]
+a_dict = {hello="world"}
+
+[a_dict.nested]
+other_level = "nested value"


Test patch:
diff --git a/tests/test_base.py b/tests/test_base.py
index a803c7a..ea233bb 100644
--- a/tests/test_base.py
+++ b/tests/test_base.py
@@ -820,3 +820,23 @@ def test_lowercase_read_mode(tmpdir):
     results = dir(settings.databases)
     assert "default" in results
     assert "DEFAULT" in results
+
+
+def test_settings_dict_like_iteration(tmpdir):
+    """Settings can be iterated just like a dict"""
+    data = {
+        "foo": "bar",
+        "hello": "world",
+        "default": 1,
+        "databases": {"default": {"port": 8080}},
+    }
+    toml_loader.write(str(tmpdir.join("settings.toml")), data)
+
+    # settings_files mispelled.. should be `settings_file`
+    settings = LazySettings(settings_files="settings.toml")
+
+    for key in settings:
+        assert key in settings._store
+
+    for key, value in settings.items():
+        assert settings._store[key] == value