localstack-snapshot 0.3.1__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/PKG-INFO +1 -1
- localstack_snapshot-0.3.2/localstack_snapshot/__init__.py +1 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/snapshots/prototype.py +22 -9
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot.egg-info/PKG-INFO +1 -1
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/pyproject.toml +1 -1
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/tests/test_snapshots.py +62 -0
- localstack_snapshot-0.3.1/localstack_snapshot/__init__.py +0 -1
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/LICENSE +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/README.md +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/pytest/__init__.py +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/pytest/snapshot.py +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/snapshots/__init__.py +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/snapshots/report.py +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/snapshots/transformer.py +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/snapshots/transformer_utility.py +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/util/__init__.py +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/util/encoding.py +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot.egg-info/SOURCES.txt +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot.egg-info/dependency_links.txt +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot.egg-info/requires.txt +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot.egg-info/top_level.txt +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/setup.cfg +0 -0
- {localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/tests/test_transformer.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.2"
|
{localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/snapshots/prototype.py
RENAMED
|
@@ -2,7 +2,9 @@ import io
|
|
|
2
2
|
import json
|
|
3
3
|
import logging
|
|
4
4
|
import os
|
|
5
|
+
from collections.abc import Iterator
|
|
5
6
|
from datetime import datetime, timezone
|
|
7
|
+
from enum import Enum
|
|
6
8
|
from json import JSONDecodeError
|
|
7
9
|
from pathlib import Path
|
|
8
10
|
from re import Pattern
|
|
@@ -169,16 +171,27 @@ class SnapshotSession:
|
|
|
169
171
|
def match_object(self, key: str, obj: object) -> None:
|
|
170
172
|
def _convert_object_to_dict(obj_):
|
|
171
173
|
if isinstance(obj_, dict):
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
174
|
+
# Serialize the values of the dictionary, while skipping any private keys (starting with '_')
|
|
175
|
+
return {
|
|
176
|
+
key_: _convert_object_to_dict(obj_[key_])
|
|
177
|
+
for key_ in obj_
|
|
178
|
+
if not key_.startswith("_")
|
|
179
|
+
}
|
|
180
|
+
elif isinstance(obj_, (list, Iterator)):
|
|
181
|
+
return [_convert_object_to_dict(val) for val in obj_]
|
|
182
|
+
elif isinstance(obj_, Enum):
|
|
183
|
+
return obj_.value
|
|
180
184
|
elif hasattr(obj_, "__dict__"):
|
|
181
|
-
|
|
185
|
+
# This is an object - let's try to convert it to a dictionary
|
|
186
|
+
# A naive approach would be to use the '__dict__' object directly, but that only lists the attributes
|
|
187
|
+
# In order to also serialize the properties, we use the __dir__() method
|
|
188
|
+
# Filtering by everything that is not a method gives us both attributes and properties
|
|
189
|
+
# We also (still) skip private attributes/properties, so everything that starts with an underscore
|
|
190
|
+
return {
|
|
191
|
+
k: _convert_object_to_dict(getattr(obj_, k))
|
|
192
|
+
for k in obj_.__dir__()
|
|
193
|
+
if not k.startswith("_") and type(getattr(obj_, k, "")).__name__ != "method"
|
|
194
|
+
}
|
|
182
195
|
return obj_
|
|
183
196
|
|
|
184
197
|
return self.match(key, _convert_object_to_dict(obj))
|
|
@@ -7,7 +7,7 @@ name = "localstack-snapshot"
|
|
|
7
7
|
authors = [
|
|
8
8
|
{ name = "LocalStack Contributors", email = "info@localstack.cloud" }
|
|
9
9
|
]
|
|
10
|
-
version = "0.3.
|
|
10
|
+
version = "0.3.2"
|
|
11
11
|
description = "Extracted snapshot testing lib for LocalStack"
|
|
12
12
|
dependencies = [
|
|
13
13
|
"jsonpath-ng>1.6",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import io
|
|
2
|
+
from enum import Enum
|
|
2
3
|
|
|
3
4
|
import pytest
|
|
4
5
|
|
|
@@ -75,6 +76,67 @@ class TestSnapshotManager:
|
|
|
75
76
|
sm.match_object("key_a", CustomObject(name="myname"))
|
|
76
77
|
sm._assert_all()
|
|
77
78
|
|
|
79
|
+
def test_match_object_lists_and_iterators(self):
|
|
80
|
+
class CustomObject:
|
|
81
|
+
def __init__(self, name):
|
|
82
|
+
self.name = name
|
|
83
|
+
self.my_list = [9, 8, 7, 6, 5]
|
|
84
|
+
self.my_iterator = (x for x in range(5))
|
|
85
|
+
|
|
86
|
+
sm = SnapshotSession(scope_key="A", verify=True, base_file_path="", update=False)
|
|
87
|
+
sm.recorded_state = {
|
|
88
|
+
"key_a": {"name": "myname", "my_iterator": [0, 1, 2, 3, 4], "my_list": [9, 8, 7, 6, 5]}
|
|
89
|
+
}
|
|
90
|
+
sm.match_object("key_a", CustomObject(name="myname"))
|
|
91
|
+
sm._assert_all()
|
|
92
|
+
|
|
93
|
+
def test_match_object_include_properties(self):
|
|
94
|
+
class CustomObject:
|
|
95
|
+
def __init__(self, name):
|
|
96
|
+
self.name = name
|
|
97
|
+
self._internal = "n/a"
|
|
98
|
+
|
|
99
|
+
def some_method(self):
|
|
100
|
+
# method should not be serialized
|
|
101
|
+
return False
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def some_prop(self):
|
|
105
|
+
# properties should be serialized
|
|
106
|
+
return True
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def some_iterator(self):
|
|
110
|
+
for i in range(3):
|
|
111
|
+
yield i
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def _private_prop(self):
|
|
115
|
+
# private properties should be ignored
|
|
116
|
+
return False
|
|
117
|
+
|
|
118
|
+
sm = SnapshotSession(scope_key="A", verify=True, base_file_path="", update=False)
|
|
119
|
+
sm.recorded_state = {
|
|
120
|
+
"key_a": {"name": "myname", "some_prop": True, "some_iterator": [0, 1, 2]}
|
|
121
|
+
}
|
|
122
|
+
sm.match_object("key_a", CustomObject(name="myname"))
|
|
123
|
+
sm._assert_all()
|
|
124
|
+
|
|
125
|
+
def test_match_object_enums(self):
|
|
126
|
+
class TestEnum(Enum):
|
|
127
|
+
value1 = "Value 1"
|
|
128
|
+
value2 = "Value 2"
|
|
129
|
+
|
|
130
|
+
class CustomObject:
|
|
131
|
+
def __init__(self, name):
|
|
132
|
+
self.name = name
|
|
133
|
+
self.my_enum = TestEnum.value2
|
|
134
|
+
|
|
135
|
+
sm = SnapshotSession(scope_key="A", verify=True, base_file_path="", update=False)
|
|
136
|
+
sm.recorded_state = {"key_a": {"name": "myname", "my_enum": "Value 2"}}
|
|
137
|
+
sm.match_object("key_a", CustomObject(name="myname"))
|
|
138
|
+
sm._assert_all()
|
|
139
|
+
|
|
78
140
|
def test_match_object_change(self):
|
|
79
141
|
class CustomObject:
|
|
80
142
|
def __init__(self, name):
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.3.1"
|
|
File without changes
|
|
File without changes
|
{localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/pytest/__init__.py
RENAMED
|
File without changes
|
{localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/pytest/snapshot.py
RENAMED
|
File without changes
|
{localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/snapshots/__init__.py
RENAMED
|
File without changes
|
{localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/snapshots/report.py
RENAMED
|
File without changes
|
{localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/snapshots/transformer.py
RENAMED
|
File without changes
|
|
File without changes
|
{localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/util/__init__.py
RENAMED
|
File without changes
|
{localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot/util/encoding.py
RENAMED
|
File without changes
|
{localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot.egg-info/requires.txt
RENAMED
|
File without changes
|
{localstack_snapshot-0.3.1 → localstack_snapshot-0.3.2}/localstack_snapshot.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|