-
-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Recursive assignment of fields in settings.py to the app.settings object #78
Merged
dotchetter
merged 7 commits into
Hashmap-Software-Agency:develop
from
RadarJam:Recursive-assignment-of-fields-in-settings.py-to-the-app.settings-object
Sep 25, 2023
Merged
Changes from 6 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
8938922
Test cases
RadarJam 483f5ff
Dot notation can be used to read dicts in settings.py
RadarJam 480cdc3
Removed Reduntant class
RadarJam 6242f9b
Renamed method and set it as a class method
RadarJam b30d1ab
Test suite is now using pytest test fixtures
RadarJam a9c4328
Test Fixture generates MockSettings
RadarJam 3056976
Fixed memory leak and renamed method
RadarJam File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,9 @@ | |
from dataclasses import dataclass, field | ||
from datetime import datetime | ||
from typing import Any | ||
import json | ||
from collections import UserDict | ||
|
||
|
||
import pyttman | ||
from pyttman.core.containers import MessageMixin, Reply | ||
|
@@ -32,7 +35,6 @@ def depr_graceful(message: str, version: str): | |
out = f"{message} - This was deprecated in version {version}." | ||
warnings.warn(out, DeprecationWarning) | ||
|
||
|
||
class Settings: | ||
""" | ||
Dataclass holding settings configured in the settings.py | ||
|
@@ -48,7 +50,8 @@ class Settings: | |
aren't valid settings. | ||
""" | ||
|
||
def __init__(self, **kwargs): | ||
def __init__(self, dictionary={}, **kwargs): | ||
self.__dict__.update(dictionary) | ||
self.APPEND_LOG_FILES: bool = True | ||
self.MIDDLEWARE: dict | None = None | ||
self.ABILITIES: list | None = None | ||
|
@@ -60,14 +63,27 @@ def __init__(self, **kwargs): | |
self.LOG_FORMAT: str | None = None | ||
self.LOG_TO_STDOUT: bool = False | ||
|
||
[setattr(self, k, v) for k, v in kwargs.items() | ||
[self.__set_attr(k, v) for k, v in kwargs.items() | ||
if not inspect.ismodule(v) | ||
and not inspect.isfunction(v)] | ||
|
||
def __getitem__(self, item): | ||
return self.__dict__[item] | ||
|
||
def __set_attr(self, k, v): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to PEP-8, single |
||
tmp = v | ||
if isinstance(v, dict): | ||
tmp = Settings._dict_to_object(v) | ||
|
||
setattr(self, k, tmp) | ||
|
||
def __repr__(self): | ||
_attrs = {name: value for name, value in self.__dict__.items()} | ||
return f"Settings({_attrs})" | ||
|
||
@staticmethod | ||
def _dict_to_object(dictionary): | ||
return json.loads(json.dumps(dictionary), object_hook=Settings) | ||
|
||
def _generate_name(name): | ||
""" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
from tests.module_helper import PyttmanInternalBaseTestCase | ||
from pyttman.core.internals import Settings | ||
|
||
from importlib import import_module | ||
import pytest | ||
|
||
@pytest.fixture | ||
def mockSettings(): | ||
|
||
mock_settings = { | ||
"d":{ | ||
"k1":"v1", | ||
"k2":{ | ||
"a":"a", | ||
"b":"b" | ||
} | ||
}, | ||
"foo":"bar" | ||
} | ||
|
||
return Settings(**mock_settings) | ||
|
||
def test_read_settings_with_dictionary(mockSettings): | ||
assert mockSettings.d.k2.a == "a" | ||
assert mockSettings.d["k2"].a == "a" | ||
assert mockSettings.d["k2"]["a"] == "a" | ||
|
||
assert mockSettings.d.k1 == "v1" | ||
assert mockSettings.d["k1"] == "v1" | ||
|
||
assert mockSettings.foo == "bar" | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that in Python, default keyword arguments are parsed once, not for each call.
The argument default
dictionary={}
statement, is creating one dictionary used over and over again for every call. The same is true for anything non-primitive. It could cause serious implications where multiple instances of this class will share the samedictionary
memory reference.An example
If you create multiple instances of a class with this syntax, this is the result of the leak:
For an example, see this stack overflow post
To fix this, use the default argument
None
as: