Skip to content

Commit 559fc82

Browse files
wouterdbbartv
authored andcommitted
Issue/747 entity origin (#752)
* Track all locations where an instance has been created. (fixes #747)
1 parent fc4d0a6 commit 559fc82

File tree

7 files changed

+99
-7
lines changed

7 files changed

+99
-7
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,4 @@ docs/moduleguides
4545
.mypy
4646
.mypy_cache
4747
mypy
48-
types
48+
types

src/inmanta/ast/entity.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ def get_instance(self,
319319
Return an instance of the class defined in this entity
320320
"""
321321
out = Instance(self, resolver, queue)
322-
out.location = location
322+
out.set_location(location)
323323
for k, v in attributes.items():
324324
out.set_attribute(k, v, location)
325325

src/inmanta/ast/statements/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def copy_location(self, statement: Locatable) -> None:
4444
"""
4545
Copy the location of this statement in the given statement
4646
"""
47-
statement.location = self.location
47+
statement.set_location(self.location)
4848

4949
def get_namespace(self) -> "Namespace":
5050
return self.namespace

src/inmanta/ast/statements/generator.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,13 +290,12 @@ def execute(self, requires: Dict[object, ResultVariable], resolver: Resolver, qu
290290
raise Exception("Inconsistent indexes detected!")
291291

292292
object_instance = first
293+
self.copy_location(object_instance)
293294
for k, v in attributes.items():
294295
object_instance.set_attribute(k, v, self.location)
295-
296296
else:
297297
# create the instance
298298
object_instance = type_class.get_instance(attributes, resolver, queue, self.location)
299-
self.copy_location(object_instance)
300299

301300
# deferred execution for indirect attributes
302301
for attributename, valueexpression in self._indirect_attributes.items():

src/inmanta/execute/runtime.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from inmanta.ast import RuntimeException, NotFoundException, DoubleSetException, OptionalValueException, AttributeException, \
2222
Locatable, Location
2323
from inmanta.ast.type import Type
24-
from typing import Dict, Any
24+
from typing import List, Dict, Any
2525

2626

2727
class ResultCollector(object):
@@ -636,6 +636,8 @@ def __init__(self, mytype, resolver, queue):
636636
# see inmanta.ast.execute.scheduler.QueueScheduler
637637
self.trackers = []
638638

639+
self.locations = []
640+
639641
def get_type(self):
640642
return self.type
641643

@@ -657,7 +659,7 @@ def __repr__(self):
657659
return "%s %02x" % (self.type, self.sid)
658660

659661
def __str__(self):
660-
return "%s (instantiated at %s)" % (self.type, self.location)
662+
return "%s (instantiated at %s)" % (self.type, ",".join([str(l) for l in self.get_locations()]))
661663

662664
def add_implementation(self, impl):
663665
if impl in self.implemenations:
@@ -709,5 +711,12 @@ def verify_done(self):
709711
return False
710712
return True
711713

714+
def set_location(self, location: Location):
715+
Locatable.set_location(self, location)
716+
self.locations.append(location)
717+
712718
def get_location(self) -> Location:
713719
return self.location
720+
721+
def get_locations(self) -> List[Location]:
722+
return self.locations

tests/test_compilation.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2682,6 +2682,30 @@ def test_lazy_attibutes3(snippetcompiler):
26822682
assert "5" == root.lookup("a").get_value().lookup("value").get_value().lookup("value").get_value()
26832683

26842684

2685+
def test_747_entity_multi_location(snippetcompiler):
2686+
snippetcompiler.setup_for_snippet("""
2687+
entity Alpha:
2688+
string name
2689+
end
2690+
2691+
implementation none for Alpha:
2692+
end
2693+
implement Alpha using none
2694+
2695+
index Alpha(name)
2696+
2697+
a= Alpha(name="A")
2698+
b= Alpha(name="A")
2699+
c= Alpha(name="A")
2700+
""", autostd=False)
2701+
(_, scopes) = compiler.do_compile()
2702+
2703+
root = scopes.get_child("__config__")
2704+
a = root.lookup("a").get_value()
2705+
assert len(a.get_locations()) == 3
2706+
assert sorted([l.lnr for l in a.get_locations()]) == [12, 13, 14]
2707+
2708+
26852709
def test_749_is_unknown(snippetcompiler):
26862710
snippetcompiler.setup_for_snippet("""
26872711
import tests

tests/test_compiler_errors.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,3 +440,63 @@ def test_672_missing_type(snippetcompiler):
440440
""",
441441
"could not find type Testt in namespace __config__"
442442
" (reported in Implementation(test) ({dir}/main.cf:5))")
443+
444+
445+
def test_747_index_collisions(snippetcompiler):
446+
snippetcompiler.setup_for_error(
447+
"""
448+
entity Test:
449+
string name
450+
string value
451+
end
452+
453+
implementation none for Test:
454+
end
455+
456+
implement Test using none
457+
458+
index Test(name)
459+
Test(name="A", value="a")
460+
Test(name="A", value="b")
461+
462+
""",
463+
"""Could not set attribute `value` on instance `__config__::Test (instantiated at {dir}/main.cf:13,{dir}/main.cf:14)` (reported in Construct(Test) ({dir}/main.cf:14))
464+
caused by:
465+
value set twice:
466+
\told value: a
467+
\t\tset at {dir}/main.cf:13
468+
\tnew value: b
469+
\t\tset at {dir}/main.cf:14
470+
(reported in Construct(Test) ({dir}/main.cf:14))""" # nopep8
471+
)
472+
473+
474+
def test_747_index_collisions_invisible(snippetcompiler):
475+
snippetcompiler.setup_for_error(
476+
"""
477+
entity Test:
478+
string name
479+
string value
480+
end
481+
482+
implementation none for Test:
483+
end
484+
485+
implement Test using none
486+
487+
index Test(name)
488+
489+
for v in ["a","b"]:
490+
Test(name="A", value=v)
491+
end
492+
493+
""",
494+
"""Could not set attribute `value` on instance `__config__::Test (instantiated at {dir}/main.cf:15,{dir}/main.cf:15)` (reported in Construct(Test) ({dir}/main.cf:15))
495+
caused by:
496+
value set twice:
497+
\told value: a
498+
\t\tset at {dir}/main.cf:15:34
499+
\tnew value: b
500+
\t\tset at {dir}/main.cf:15:34
501+
(reported in Construct(Test) ({dir}/main.cf:15))""" # nopep8
502+
)

0 commit comments

Comments
 (0)