Skip to content

Commit cd18bb3

Browse files
committed
fix: Prevent reassignment of base value when retrieving None.
1 parent f77960b commit cd18bb3

File tree

3 files changed

+28
-14
lines changed

3 files changed

+28
-14
lines changed

nyan/nyan_tool.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@ int test_parser(const std::string &base_path, const std::string &filename) {
2727

2828
std::shared_ptr<View> root = db->new_view();
2929

30+
Object test = root->get_object("test.Test");
3031
Object second = root->get_object("test.Second");
3132
Object first = root->get_object("test.First");
3233

3334
std::cout << "before change: First.member == "
3435
<< *root->get_object("test.First").get<Int>("member")
3536
<< std::endl;
3637

37-
std::optional<std::shared_ptr<Object>> optional_wat3 = first.get_optional<Object>("wat3", 0);
38-
39-
if (optional_wat3.has_value()) {
40-
if ((*optional_wat3)->get_name() != "test.Second") {
38+
std::optional<std::shared_ptr<Object>> wat3_first = first.get_optional<Object>("wat3", 0);
39+
if (wat3_first.has_value()) {
40+
if ((*wat3_first)->get_name() != "test.Second") {
4141
std::cout << "First.wat3 has wrong value at t=0" << std::endl;
4242
return 1;
4343
}
@@ -47,6 +47,19 @@ int test_parser(const std::string &base_path, const std::string &filename) {
4747
return 1;
4848
}
4949

50+
std::optional<std::shared_ptr<Object>> wat3_second = second.get_optional<Object, true>("wat3", 0);
51+
if (wat3_second.has_value()) {
52+
std::cout << "Second.wat3 should be None" << std::endl;
53+
return 1;
54+
}
55+
56+
std::optional<std::shared_ptr<Object>> wat3_test = test.get_optional<Object, true>("wat3", 0);
57+
if (wat3_test.has_value()) {
58+
std::cout << "Test.wat3 should be None" << std::endl;
59+
return 1;
60+
}
61+
62+
5063
Object patch = root->get_object("test.FirstPatch");
5164
for (int i = 0; i < 3; i++) {
5265
Transaction tx = root->new_transaction();
@@ -56,8 +69,8 @@ int test_parser(const std::string &base_path, const std::string &filename) {
5669
}
5770
}
5871

59-
optional_wat3 = first.get_optional<Object>("wat3");
60-
if (optional_wat3.has_value()) {
72+
wat3_first = first.get_optional<Object>("wat3");
73+
if (wat3_first.has_value()) {
6174
std::cout << "First.wat3 should be None by patch" << std::endl;
6275
return 1;
6376
}
@@ -250,7 +263,6 @@ std::pair<flags_t, params_t> argparse(int argc, char** argv) {
250263

251264

252265
int main(int argc, char **argv) {
253-
254266
auto args = nyan::argparse(argc, argv);
255267
nyan::flags_t flags = args.first;
256268
nyan::params_t params = args.second;

nyan/object.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2016-2023 the nyan authors, LGPLv3+. See copying.md for legal info.
1+
// Copyright 2016-2024 the nyan authors, LGPLv3+. See copying.md for legal info.
22

33
#include "object.h"
44

@@ -170,15 +170,16 @@ ValueHolder Object::calculate_value(const memberid_t &member, order_t t) const {
170170
ValueHolder result = base_value->copy();
171171

172172
// walk back and apply the value changes
173-
while (true) {
174-
const Member *change = parents[defined_by]->get(member);
173+
174+
// skip the parent that assigns the value
175+
// this prevents reassignment errors e.g. from assigning None
176+
int parent_idx = defined_by - 1;
177+
while (parent_idx >= 0) {
178+
const Member *change = parents[parent_idx]->get(member);
175179
if (change != nullptr) {
176180
result->apply(*change);
177181
}
178-
if (defined_by == 0) {
179-
break;
180-
}
181-
defined_by -= 1;
182+
parent_idx -= 1;
182183
}
183184

184185
return result;

test/test.nyan

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Second(First):
2828
member *= 5.5
2929
First.nice_member = False
3030
# nap : int
31+
wat3 = None
3132

3233
NestingBase(First):
3334

0 commit comments

Comments
 (0)