-
Notifications
You must be signed in to change notification settings - Fork 61
Fix: Support iteration and indexing for ModelSimple list responses #109
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -462,6 +462,31 @@ def get(self, name, default=None): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def __getitem__(self, name): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """get the value of an attribute using square-bracket notation: `instance[attr]`""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Support numeric indexing for simple models that wrap a list-like | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # value (for example response models that have `value: [Item]`). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Iteration (for x in model) falls back to __getitem__ with integer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # indices if __iter__ is not present, so accept ints and slices here. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if isinstance(name, (int, slice)): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| v = self.__dict__['_data_store'].get('value') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| except Exception: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| v = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if v is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ApiAttributeError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "{0} has no attribute '{1}'".format( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type(self).__name__, name), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [e for e in [self._path_to_item, name] if e] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+475
to
+479
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return v[name] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| except Exception: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # normalize to attribute error expected by callers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ApiAttributeError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "{0} has no attribute '{1}'".format( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type(self).__name__, name), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [e for e in [self._path_to_item, name] if e] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+480
to
+489
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | |
| return v[name] | |
| except Exception: | |
| # normalize to attribute error expected by callers | |
| raise ApiAttributeError( | |
| "{0} has no attribute '{1}'".format( | |
| type(self).__name__, name), | |
| [e for e in [self._path_to_item, name] if e] | |
| ) | |
| if isinstance(v, (list, tuple)): | |
| try: | |
| return v[name] | |
| except Exception: | |
| # normalize to attribute error expected by callers | |
| raise ApiAttributeError( | |
| "{0} has no attribute '{1}'".format( | |
| type(self).__name__, name), | |
| [e for e in [self._path_to_item, name] if e] | |
| ) | |
| if isinstance(name, slice): | |
| return [v][name] | |
| if name in (0, -1): | |
| return v | |
| raise ApiAttributeError( | |
| "{0} has no attribute '{1}'".format( | |
| type(self).__name__, name), | |
| [e for e in [self._path_to_item, name] if e] | |
| ) |
Copilot
AI
Apr 12, 2026
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.
Adding __len__ changes truthiness for ModelSimple instances (Python will use __len__ for bool(model) when __bool__ is not defined). For list-based responses this means empty responses become falsy, which can be a backward-incompatible behavioral change. If that’s not intended, consider defining __bool__ to preserve prior truthiness, or documenting this as a behavior change.
Copilot
AI
Apr 12, 2026
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 __len__ docstring says “otherwise 0”, but the implementation returns 1 for non-(list, tuple) values (treating them as a single item). Update the docstring to match the actual behavior.
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,38 @@ | ||||
| import pytest | ||||
|
||||
| import pytest |
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 new changelog entry is indented with an extra leading space (
- fix(model): ...), which will render as a nested list item in Markdown. Align it with the other bullets under Bug fixes: (no leading space before-).