Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 28 additions & 33 deletions moodle/utils/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,41 @@
T = TypeVar("T")


def to_dict(data: Any, name: str = "") -> Any:
def to_dict(data: dict, name: str = "") -> dict:
"""Properly format query string for webservice request
The passed object itself must be a dict, but the returned value will be
flattened to a dict with keys like `name[key]` or `name[index][key]`.

Args:
data (Any): Query to be formated
data (dict): Query to be formated
name (str, optional): The key of the data. Defaults to "".

Returns:
Any: Formated data
dict: Formated data
"""
if not data:
return data
if isinstance(data, list):
out = {}
for idx, val in enumerate(data):
val = to_dict(val)
if isinstance(val, dict):
for key, value in val.items():
out[f"{name}[{idx}][{key}]"] = val[key]
else:
out_key = name
# Check if data required name prefix
if hasattr(data, "name"):
out_key += f"[{getattr(data, 'name')}]"
out_key += f"[{idx}]"
out[out_key] = val
return out
if isinstance(data, dict):
out = {}
for key, value in data.items():
if isinstance(value, list):
out.update(to_dict(value, key))
else:
out[key] = value
return out
if has(data):
return asdict_attr(data)
if isinstance(data, datetime):
return datetime.timestamp(data)
return data

result = {}
def inner(prefix: str, data: Any) -> dict:
pairs = None
if isinstance(data, list):
pairs = enumerate(data)
elif isinstance(data, dict):
pairs = data.items()
elif has(data):
pairs = asdict_attr(data).items()

if pairs is not None:
for key, value in pairs:
inner(f"{prefix}[{key}]", value)
else:
if isinstance(data, datetime):
data = datetime.timestamp(data)
result[prefix] = data

for key, value in data.items():
inner(key, value)

return result


def fromtimestamp(d: str):
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def domain() -> str:
@fixture
def moodle(domain: str) -> Moodle:
username = "manager"
password = "moodle2024"
password = "moodle25"
return Moodle.login(domain, username, password)


Expand Down
2 changes: 1 addition & 1 deletion tests/test_core/test_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def test_get_calendar_event_by_id(self, moodle):
pass

def test_get_calendar_events(self, moodle):
events = moodle.core.calendar.get_calendar_events()
events = moodle.core.calendar.get_calendar_events(options=Events.Options(userevents=1))
assert isinstance(events, Events)

def test_get_calendar_monthly_view(self, moodle):
Expand Down
Empty file added tests/test_utils/__init__.py
Empty file.
61 changes: 61 additions & 0 deletions tests/test_utils/test_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import attr
from datetime import datetime

from moodle.utils.helper import to_dict

class TestHelper:
def test_to_dict(self):
# empty dict
result = to_dict(dict())
assert result == {}

# dict with simple values
result = to_dict(dict(a=1, b=2))
assert result == { 'a': 1, 'b': 2 }

# dict with lists
result = to_dict(dict(a=[1], b=[2, 3]))
assert result == { 'a[0]': 1, 'b[0]': 2, 'b[1]': 3 }

# dict with lists of dicts
result = to_dict(dict(a=[dict(x=1), dict(x=2)], b=[dict(y=2, z=3)]))
assert result == { 'a[0][x]': 1, 'a[1][x]': 2, 'b[0][y]': 2, 'b[0][z]': 3 }

# dict with nested dicts
result = to_dict(dict(a=dict(x=1, y=2), b=dict(z=3)))
assert result == { 'a[x]': 1, 'a[y]': 2, 'b[z]': 3 }

# dict with lists of lists
result = to_dict(dict(a=[[1, 2], [3, 4]], b=[[5], [6, 7]]))
assert result == {
'a[0][0]': 1, 'a[0][1]': 2, 'a[1][0]': 3, 'a[1][1]': 4,
'b[0][0]': 5, 'b[1][0]': 6, 'b[1][1]': 7,
}

# dict with list of nested dicts
result = to_dict(dict(a=[dict(x=1, nested=dict(y=2))]))
assert result == { 'a[0][x]': 1, 'a[0][nested][y]': 2 }

@attr.s
class MyAttrClass:
x = attr.ib()
y = attr.ib()

# attr class
# result = to_dict(MyAttrClass(x=1, y=2))
# assert result == { 'x': 1, 'y': 2 }

# dict with attr class
result = to_dict(dict(a=MyAttrClass(x=1, y=2)))
assert result == { 'a[x]': 1, 'a[y]': 2 }

# dict with datetime
result = to_dict(dict(a=datetime(2025, 1, 1)))
assert result == { 'a': datetime(2025, 1, 1).timestamp() }

# dict with list of datetimes
result = to_dict(dict(a=[datetime(2025, 1, 1)]))
assert result == { 'a[0]': datetime(2025, 1, 1).timestamp() }

def test_fromtimestamp(self):
pass