Skip to content

Commit 5110d82

Browse files
committed
Fix the deparse method and add unit tests
1 parent 1f597e8 commit 5110d82

2 files changed

Lines changed: 215 additions & 104 deletions

File tree

rivescript/rivescript.py

Lines changed: 48 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from __future__ import unicode_literals
99
from six import text_type
10+
import copy
1011
import sys
1112
import os
1213
import re
@@ -109,7 +110,7 @@ def __init__(self, debug=False, strict=True, depth=50, log=None,
109110
"sub": {},
110111
"person": {},
111112
}
112-
113+
113114
# Initialize the session manager.
114115
if session_manager is None:
115116
session_manager = MemorySessionStorage(warn=self._warn)
@@ -298,13 +299,9 @@ def deparse(self):
298299
"sub": {},
299300
"person": {},
300301
"array": {},
301-
"triggers": {},
302-
"that": {},
302+
"triggers": [],
303303
},
304-
"topic": {},
305-
"that": {},
306-
"inherit": {},
307-
"include": {},
304+
"topics": {},
308305
}
309306

310307
# Populate the config fields.
@@ -322,48 +319,29 @@ def deparse(self):
322319

323320
# Topic Triggers.
324321
for topic in self._topics:
325-
dest = {} # Where to place the topic info
322+
dest = None # Where to place the topic info
326323

327324
if topic == "__begin__":
328325
# Begin block.
329-
dest = result["begin"]["triggers"]
326+
dest = result["begin"]
330327
else:
331328
# Normal topic.
332-
if topic not in result["topic"]:
333-
result["topic"][topic] = {}
334-
dest = result["topic"][topic]
329+
if topic not in result["topics"]:
330+
result["topics"][topic] = {
331+
"triggers": [],
332+
"includes": {},
333+
"inherits": {},
334+
}
335+
dest = result["topics"][topic]
335336

336337
# Copy the triggers.
337-
for trig, data in self._topics[topic].iteritems():
338-
dest[trig] = self._copy_trigger(trig, data)
339-
340-
# %Previous's.
341-
for topic in self._thats:
342-
dest = {} # Where to place the topic info
338+
for trig in self._topics[topic]:
339+
dest["triggers"].append(copy.deepcopy(trig))
343340

344-
if topic == "__begin__":
345-
# Begin block.
346-
dest = result["begin"]["that"]
347-
else:
348-
# Normal topic.
349-
if topic not in result["that"]:
350-
result["that"][topic] = {}
351-
dest = result["that"][topic]
352-
353-
# The "that" structure is backwards: bot reply, then trigger, then info.
354-
for previous, pdata in self._thats[topic].iteritems():
355-
for trig, data in pdata.iteritems():
356-
dest[trig] = self._copy_trigger(trig, data, previous)
357-
358-
# Inherits/Includes.
359-
for topic, data in self._lineage.iteritems():
360-
result["inherit"][topic] = []
361-
for inherit in data:
362-
result["inherit"][topic].append(inherit)
363-
for topic, data in self._includes.iteritems():
364-
result["include"][topic] = []
365-
for include in data:
366-
result["include"][topic].append(include)
341+
# Inherits/Includes.
342+
for label, mapping in {"inherits": self._lineage, "includes": self._includes}.items():
343+
if topic in mapping and len(mapping[topic]):
344+
dest[label] = mapping[topic].copy()
367345

368346
return result
369347

@@ -380,11 +358,11 @@ def write(self, fh, deparsed=None):
380358
by a user interface for editing RiveScript without writing the code
381359
directly).
382360
383-
:param fh: Either a file name ``str`` or a file handle object of a file
384-
opened in write mode.
385-
:param optional dict deparsed: A data structure in the same format as
386-
what ``deparse()`` returns. If not passed, this value will come from
387-
the current in-memory data from ``deparse()``.
361+
Parameters:
362+
fh (str or file): a string or a file-like object.
363+
deparsed (dict): a data structure in the same format as what
364+
``deparse()`` returns. If not passed, this value will come from
365+
the current in-memory data from ``deparse()``.
388366
"""
389367

390368
# Passed a string instead of a file handle?
@@ -432,101 +410,67 @@ def write(self, fh, deparsed=None):
432410
fh.write("\n")
433411

434412
# Begin block.
435-
if len(deparsed["begin"]["triggers"].keys()):
413+
if len(deparsed["begin"]["triggers"]):
436414
fh.write("> begin\n\n")
437415
self._write_triggers(fh, deparsed["begin"]["triggers"], indent="\t")
438416
fh.write("< begin\n\n")
439417

440418
# The topics. Random first!
441419
topics = ["random"]
442-
topics.extend(sorted(deparsed["topic"].keys()))
420+
topics.extend(sorted(deparsed["topics"].keys()))
443421
done_random = False
444422
for topic in topics:
445-
if topic not in deparsed["topic"]: continue
423+
if topic not in deparsed["topics"]: continue
446424
if topic == "random" and done_random: continue
447425
if topic == "random": done_random = True
448426

449427
tagged = False # Used > topic tag
450428

451-
if topic != "random" or topic in deparsed["include"] or topic in deparsed["inherit"]:
429+
data = deparsed["topics"][topic]
430+
431+
if topic != "random" or len(data["includes"]) or len(data["inherits"]):
452432
tagged = True
453433
fh.write("> topic " + topic)
454434

455-
if topic in deparsed["inherit"]:
456-
fh.write(" inherits " + " ".join(deparsed["inherit"][topic]))
457-
if topic in deparsed["include"]:
458-
fh.write(" includes " + " ".join(deparsed["include"][topic]))
435+
if data["inherits"]:
436+
fh.write(" inherits " + " ".join(sorted(data["inherits"].keys())))
437+
if data["includes"]:
438+
fh.write(" includes " + " ".join(sorted(data["includes"].keys())))
459439

460440
fh.write("\n\n")
461441

462442
indent = "\t" if tagged else ""
463-
self._write_triggers(fh, deparsed["topic"][topic], indent=indent)
464-
465-
# Any %Previous's?
466-
if topic in deparsed["that"]:
467-
self._write_triggers(fh, deparsed["that"][topic], indent=indent)
443+
self._write_triggers(fh, data["triggers"], indent=indent)
468444

469445
if tagged:
470446
fh.write("< topic\n\n")
471447

472448
return True
473449

474-
def _copy_trigger(self, trig, data, previous=None):
475-
"""Make copies of all data below a trigger.
476-
477-
:param str trig: The trigger key.
478-
:param dict data: The data under that trigger.
479-
:param previous: The ``%Previous`` for the trigger.
480-
"""
481-
# Copied data.
482-
dest = {}
483-
484-
if previous:
485-
dest["previous"] = previous
486-
487-
if "redirect" in data and data["redirect"]:
488-
# @Redirect
489-
dest["redirect"] = data["redirect"]
490-
491-
if "condition" in data and len(data["condition"].keys()):
492-
# *Condition
493-
dest["condition"] = []
494-
for i in sorted(data["condition"].keys()):
495-
dest["condition"].append(data["condition"][i])
496-
497-
if "reply" in data and len(data["reply"].keys()):
498-
# -Reply
499-
dest["reply"] = []
500-
for i in sorted(data["reply"].keys()):
501-
dest["reply"].append(data["reply"][i])
502-
503-
return dest
504-
505450
def _write_triggers(self, fh, triggers, indent=""):
506451
"""Write triggers to a file handle.
507452
508-
:param fh: The file handle.
509-
:param dict triggers: The triggers to write to the file.
510-
:param str indent: The indentation (spaces) to prefix each line with.
453+
Parameters:
454+
fh (file): file object.
455+
triggers (list): list of triggers to write.
456+
indent (str): indentation for each line.
511457
"""
512458

513-
for trig in sorted(triggers.keys()):
514-
fh.write(indent + "+ " + self._write_wrapped(trig, indent=indent) + "\n")
515-
d = triggers[trig]
459+
for trig in triggers:
460+
fh.write(indent + "+ " + self._write_wrapped(trig["trigger"], indent=indent) + "\n")
461+
d = trig
516462

517-
if "previous" in d:
463+
if d.get("previous"):
518464
fh.write(indent + "% " + self._write_wrapped(d["previous"], indent=indent) + "\n")
519465

520-
if "condition" in d:
521-
for cond in d["condition"]:
522-
fh.write(indent + "* " + self._write_wrapped(cond, indent=indent) + "\n")
466+
for cond in d["condition"]:
467+
fh.write(indent + "* " + self._write_wrapped(cond, indent=indent) + "\n")
523468

524-
if "redirect" in d:
469+
if d.get("redirect"):
525470
fh.write(indent + "@ " + self._write_wrapped(d["redirect"], indent=indent) + "\n")
526471

527-
if "reply" in d:
528-
for reply in d["reply"]:
529-
fh.write(indent + "- " + self._write_wrapped(reply, indent=indent) + "\n")
472+
for reply in d["reply"]:
473+
fh.write(indent + "- " + self._write_wrapped(reply, indent=indent) + "\n")
530474

531475
fh.write("\n")
532476

0 commit comments

Comments
 (0)