Rasa FormAction doens't get the values - python

I have been working with rasa, and there are things of the formAction that I still do not understand very well, my question today is why? my formAction is activated but it does not store any slotvalue, if I am using it incorrectly?
Here's my code:
class HotelForm(FormAction):
def name(self):
# type: () -> Text
return "formaejemplo"
#staticmethod
def required_slots(tracker):
return ["tipo_habitacion"]
def slot_mappings(self):
return {'tipo_habitacion':[self.from_entity(entity='tipo_habitacion',intent=['gethabitacion','peticion_habitacion'])]}
#staticmethod
def habitaciones_db():
return ["individual","doble","suite","suite doble"]
def submit(self, dispatcher, tracker, domain):
dispatcher.utter_template('utter_listo', tracker)
return []
def validate(self,dispatcher: CollectingDispatcher,tracker: Tracker,domain: Dict[Text, Any]) -> List[Dict]:
slot_values = self.extract_other_slots(dispatcher, tracker, domain)
print('slot values:',slot_values)
slot_to_fill = tracker.get_slot(REQUESTED_SLOT)
if slot_to_fill:
print('slot values:',slot_values)
slot_values.update(self.extract_requested_slot(dispatcher,tracker, domain))
if not slot_values:
try:
return super().validate(dispatcher, tracker, domain)
except ActionExecutionRejection as e:
# could not extract entity
dispatcher.utter_message(
"Sorry, I could not parse the value correctly. \n"
"Please double check your entry otherwise I will ask you this forever"
)
return []
for slot, value in slot_values.items():
print('Slot: ',slot)
print('valor: ',values)
if slot == 'tipo_habitacion':
if value.lower() not in self.habitaciones_db():
dispatcher.utter_template('utter_wrong_tipo_habitacion', tracker)
# validation failed, set slot to None
slot_values[slot] = None
# validation succeed, set the slots values to the extracted values
return [SlotSet(slot, value) for slot, value in slot_values.items()]
when i print the values (slotvalues) on the console it always empty.

when you print('slot values:',slot_values) the first time, it's only collected extra slots (entities for required slots that it didn't ask for, but picked up anyway). You shouldn't have any of these since you only have one required slot.
As for the second time you print('slot values:',slot_values), you're doing it before slot_values.update(self.extract_requested_slot(dispatcher,tracker, domain)), so it's exactly the same values as before. Try printing it after the updating happens. If you didn't run into the if not slot_values logic, then it should correctly print if you move it to after the update.
Did it correctly print when you did these lines?
print('Slot: ',slot)
print('valor: ',values)

Related

python function to try/except assigning variables

I want to assign variables like this:
Title = 'Lord of the Rings'
The issue here is that the value isn't always available, sometimes the server doesn't respond well and I get error that crashes my code.
And I have a lot of variables to assign.
So I decided to create a function that uses try and except:
def try_this(identificator, value):
try:
identificator = value
print(identificator,': ',value)
except:
traceback.print_exc
for item in items:
try_this(ebay_Title, item.title)
try_this(ebay_Price, item.currentPrice.value)
#etc...
Expected behavior:
ebay_title : 'Lord of the rings'
Actual behavior:
'Lord of the rings' : 'Lord of the rings'
Any errors in your code will occur at the point when you try to read item.title or item.currentPrice.value. So your proposed solution will still crash just before calling try_this.
When you call a function, Python first computes the values of the arguments, then assigns those values to variables in the function. So Python will try to read item.title or item.currentPrice.value before it calls try_this, then it will load try_this and assign the value it got to the local value variable inside the function. After that, there is no possibility of an error: you can always assign value to another variable.
So you need to wrap the reference to item.title or item.currentPrice.value in a try/except block.
This is the most straightforward way to do that:
try:
ebay_Title = item.title
except:
# handle error here, e.g., assign a default value
traceback.print_exc()
try:
ebay_Price = item.currentPrice.value
except:
# handle error here, e.g., assign a default value
traceback.print_exc()
As you've seen, this can get tedious. In your case, the error always occurs when you try to read an attribute, so you could write code specifically to handle that:
def get_attr(obj, attr_name, default_value=None):
try:
return getattr(obj, attr_name)
except:
# handle any errors here
traceback.print_exc()
return default_value
ebay_Title = get_attr(item, 'title')
# handle missing value (optional)
if ebay_Title is None:
...
ebay_Price = get_attr(get_attr(item, 'currentPrice'), 'value')
# handle missing value (optional)
if ebay_Price is None:
...
Note that get_attr is very similar to the built-in getattr function, but it will catch any kind of error that occurs when trying to read the attribute, not just missing-attribute errors.
If you don't like the get_attr(get_attr(item, 'currentPrice'), 'value') syntax, you could have get_attr accept a dot-separated attribute list like this:
def get_attr(obj, attr_name, default_value=None):
try:
val = obj
for attr in attr_name.split('.'):
val = getattr(val, attr)
return val
except:
# handle any errors here
traceback.print_exc()
return default_value
ebay_Title = get_attr(item, 'title')
ebay_Price = get_attr(item, 'currentPrice.value')
As said before, you really don't want to do this but here is how you can.
def try_this(identificator, value):
try:
globals()[identificator] = value
print(identificator,': ',value)
except:
traceback.print_exc
for item in items:
try_this("ebay_Title", item.title)
try_this("ebay_Price", item.currentPrice.value)
It would be better to use a predeclared object like:
itemDict = {
"ebay_Title": "",
"ebay_Price": ""
}
def try_this(identificator, value):
try:
itemDict[identificator] = value
print(identificator,': ',value)
except:
traceback.print_exc
for item in items:
try_this("ebay_Title", item.title)
try_this("ebay_Price", item.currentPrice.value)
In the comments thread, the OP stated:
It's a server side error, the actual function I use is a bit more complex: for item in response.reply.searchResult.item: And sometimes the server says there's not searchResult in response.reply The the code crushes – V-cash 28 mins ago
To deal with searchResult not existing, I would do this in that portion:
for item in getattr(response.reply, 'searchResult', []):
...
If searchResult does not exist in response.reply, it will return an empty list, preventing an error and making the loop do nothing.

Function does not return expected instance

I have a very specific problem in my code and I just can't figure it out why.
select_desire_tool() returns None.
It seems that when it arrives at return self._associated_instance(value), somehow it finishes some process in the else statement of the for loop and the supposed returned instance is lost.
why is that?
Return specific instance
def _associated_instance(self, argument):
if RegionConstants.SETTINGS == argument:
return Settings()
else:
test.fail("No such instance found.")
raise
## Clicks on desired map tools option
# #param[in] self The self object pointer.
# #param[in] value Map tools option to be selected
# #return specific class instance class instance
def select_desire_tool(self, value):
items_from_list = self.items
for item in items_from_list:
if item.name == value:
while True:
try:
item.click_button()
return self._associated_instance(value)
except LookupError:
Base().Scrollbar().scroll_down()
else:
if not Base().Scrollbar().at_y_end:
Base().Scrollbar().scroll_down()
self.select_desire_tool(value)
else:
test.fail("Option was not found in map tools")
raise

Pyqt and general python, can this be considered a correct approach for coding?

I have a dialog window containing check-boxes, when each of them is checked a particular class needs to be instantiated and a run a a task on a separated thread (one for each check box). I have 14 check-boxes to check the .isChecked() property and is comprehensible checking the returned Boolean for each of them is not efficient and requires a lot more coding.
Hence I decided to get all the children items corresponding to check-box element, get just those that are checked, appending their names to list and loop through them matching their name to d dictionary which key is the name of the check box and the value is the corresponding class to instantiate.
EXAMPLE:
# class dictionary
self.summary_runnables = {'dupStreetCheckBox': [DupStreetDesc(),0],
'notStreetEsuCheckBox': [StreetsNoEsuDesc(),1],
'notType3CheckBox': [Type3Desc(False),2],
'incFootPathCheckBox': [Type3Desc(True),2],
'dupEsuRefCheckBox': [DupEsuRef(True),3],
'notEsuStreetCheckBox': [NoLinkEsuStreets(),4],
'invCrossRefCheckBox': [InvalidCrossReferences()],
'startEndCheckBox': [CheckStartEnd(tol=10),8],
'tinyEsuCheckBox': [CheckTinyEsus("esu",1)],
'notMaintReinsCheckBox': [CheckMaintReins()],
'asdStartEndCheckBox': [CheckAsdCoords()],
'notMaintPolysCheckBox': [MaintNoPoly(),16],
'notPolysMaintCheckBox': [PolyNoMaint()],
'tinyPolysCheckBox': [CheckTinyEsus("rd_poly",1)]}
# looping through list
self.long_task = QThreadPool(None).globalInstance()
self.long_task.setMaxThreadCount(1)
start_report = StartReport(val_file_path)
end_report = EndReport()
# start_report.setAutoDelete(False)
# end_report.setAutoDelete(False)
end_report.signals.result.connect(self.log_progress)
end_report.signals.finished.connect(self.show_finished)
# end_report.setAutoDelete(False)
start_report.signals.result.connect(self.log_progress)
self.long_task.start(start_report)
# print str(self.check_boxes_names)
for check_box_name in self.check_boxes_names:
run_class = self.summary_runnables[check_box_name]
if run_class[0].__class__.__name__ is 'CheckStartEnd':
run_class[0].tolerance = tolerance
runnable = run_class[0]()
runnable.signals.result.connect(self.log_progress)
self.long_task.start(runnable)
self.long_task.start(end_report)
example of a runnable (even if some of them use different global functions)
I can't post the global functions that write content to file as they are too many and not all 14 tasks execute the same type function. arguments of these functions are int keys to other dictionaries that contain the report static content and the SQL queries to return report main dynamic contents.
class StartReport(QRunnable):
def __init__(self, file_path):
super(StartReport,self).__init__()
# open the db connection in thread
db.open()
self.signals = GeneralSignals()
# self.simple_signal = SimpleSignal()
# print self.signals.result
self.file_path = file_path
self.task = "Starting Report"
self.progress = 1
self.org_name = org_name
self.user = user
self.report_title = "Validation Report"
print "instantiation of start report "
def run(self):
self.signals.result.emit(self.task, self.progress)
if self.file_path is None:
print "I started and found file none "
return
else:
global report_file
# create the file and prints the header
report_file = open(self.file_path, 'wb')
report_file.write(str(self.report_title) + ' for {0} \n'.format(self.org_name))
report_file.write('Created on : {0} at {1} By : {2} \n'.format(datetime.today().strftime("%d/%m/%Y"),
datetime.now().strftime("%H:%M"),
str(self.user)))
report_file.write(
"------------------------------------------------------------------------------------------ \n \n \n \n")
report_file.flush()
os.fsync(report_file.fileno())
class EndReport(QRunnable):
def __init__(self):
super(EndReport,self).__init__()
self.signals = GeneralSignals()
self.task = "Finishing report"
self.progress = 100
def run(self):
self.signals.result.emit(self.task, self.progress)
if report_file is not None:
# write footer and close file
report_file.write("\n \n \n")
report_file.write("---------- End of Report -----------")
report_file.flush()
os.fsync(report_file.fileno())
report_file.close()
self.signals.finished.emit()
# TODO: checking whether opening a db connection in thread might affect the db on the GUI
# if db.isOpen():
# db.close()
else:
return
class DupStreetDesc(QRunnable):
"""
duplicate street description report section creation
:return: void if the report is to text
list[string] if the report is to screen
"""
def __init__(self):
super(DupStreetDesc,self).__init__()
self.signals = GeneralSignals()
self.task = "Checking duplicate street descriptions..."
self.progress = 16.6
def run(self):
self.signals.result.emit(self.task,self.progress)
if report_file is None:
print "report file is none "
# items_list = write_content(0, 0, 0, 0)
# for item in items_list:
# self.signals.list.emit(item)
else:
write_content(0, 0, 0, 0)
Now, I used this approach before and it has always worked fine without using multiprocessing. In this case it works good to some extent, I can run the tasks the first time but if I try to run for the second time I get the following Python Error :
self.long_task.start(run_class[0])
RuntimeError: wrapped C/C++ object of type DupStreetDesc has been deleted
I tried to use run_class[0].setAutoDelete(False) before running them in the loop but pyQt crashes with a minidump error (I am running the code in QGIS) and I the programs exists with few chances to understand what has happened.
On the other hand, if I run my classes separately, checking with an if else statement each check-box, then it works fine, I can run the tasks again and the C++ classes are not deleted, but it isn't a nice coding approach, at least from my very little experience.
Is there anyone else out there who can advise a different approach in order to make this run smoothly without using too many lines of code? Or knows whether there is a more efficient pattern to handle this problem, which I think must be quite common?
It seems that you should create a new instance of each runnable, and allow Qt to automatically delete it. So your dictionary entries could look like this:
'dupStreetCheckBox': [lambda: DupStreetDesc(), 0],
and then you can do:
for check_box_name in self.check_boxes_names:
run_class = self.summary_runnables[check_box_name]
runnable = run_class[0]()
runnable.signals.result.connect(self.log_progress)
self.long_task.start(runnable)
I don't know why setAutoDelete does not work (assuming you are calling it before starting the threadpool). I suppose there might be a bug, but it's impossible to be sure without having a fully-working example to test.

Use of arguments with property.deleter

I'm trying to define a property deleter with a parameter for an attribute of Character class as follows:
class Character(object):
_status = None
#property
def status(self):
""" Return _status if it exists or False if not."""
return self._status
#status.setter
def status(self, status_value):
"""
Receive the status and the duration(continous or not) and add
it for the _status.
"""
if not self._status:
self._status = []
self._status.append(status_value)
#status.deleter
def status(self, status_value):
"""
Delete the specified object from the _status list.
"""
status = [value for value in self._status
if status_value in value.keys()]
if status:
self._status.remove(self._status.index(status[0]))
I'm trying to delete a specific object from the status.
>>>a = Character()
>>>a.status = 'Test'
Would return a list with 1 element:
>>>a.status
['Test']
If i set the status again, the old value persists and new one is added to the list:
>>>a.status = 'Dazed'
>>>a.status
['Test', 'Dazed']
As well I want to delete only a specific value from the list:
>>>del a.status('Dazed')
And the expected result should be:
>>> a.status
['Test']
The problem is that hen I try:
del a.status('Dazed')
The following error occurs:
SyntaxError: can't delete function call
Is there any way to use arguments with a property.deleter?
This is odd behaviour you are trying to create, and would likely trip up users of your class. I certainly wouldn't expect:
self.status = "happy"
to add the new string to an existing list.
As far as I'm aware there is no way to pass an argument to a #property.deleter.
A better approach might be to make the character.status a set (I am assuming that you meant this to be an instance attribute, but this all stands for class attributes too):
class Character(object):
def __init__(self, ..., status=None):
if status is None:
self.status = set()
else:
self.status = set(status)
...
conan = Character(..., status=("happy", "cold"))
conan.status.add("tired")
conan.status.remove("happy")
One advantage of a set is that it prevents duplicates. Also, it provides for very fast membership tests (e.g. if "warm" in conan.status:) and you can find out if two Character instances have any of the same status easily:
if conan.status.intersection(other_character.status):

Any tips for a more pythonic way to implement state machine behavior?

For brevity, I'm just showing what can/must occur in states. I haven't run into any oddities in the state machine framework itself.
Here is a specific question:
Do you find it confusing that we have to return StateChange(...) and StateMachineComplete(...) whereas some of the of the other actions like some_action_1(...) and some_action_2(...) need not be returned - they're just direct method invocations?
I think that StateChange(...) needs to return because otherwise code beyond the StateChange(...) call will be executed. This isn't how a state machine should work! For example see the implementation of event1 in the ExampleState below
import abc
class State(metaclass=abc.ABCMeta):
# =====================================================================
# == events the state optionally or must implement ====================
# =====================================================================
# optional: called when the state becomes active.
def on_state_entry(self): pass
# optional: called when we're about to transition away from this state.
def on_state_exit(self): pass
#abc.abstractmethod
def event1(self,x,y,z): pass
#abc.abstractmethod
def event2(self,a,b): pass
#abc.abstractmethod
def event3(self): pass
# =====================================================================
# == actions the state may invoke =====================================
# =====================================================================
def some_action_1(self,c,d,e):
# implementation omitted for brevity
pass
def some_action_2(self,f):
# implementation omitted for brevity
pass
class StateChange:
def __init__(self,new_state_type):
# implementation omitted for brevity
pass
class StateMachineComplete: pass
class ExampleState(State):
def on_state_entry(self):
some_action_1("foo","bar","baz")
def event1(self,x,y,z):
if x == "asdf":
return StateChange(ExampleState2)
else:
return StateChange(ExampleState3)
print("I think it would be confusing if we ever got here. Therefore the StateChange calls above are return")
def event2(self,a,b):
if a == "asdf":
return StateMachineComplete()
print("As with the event above, the return above makes it clear that we'll never get here.")
def event3(self):
# Notice that we're not leaving the state. Therefore this can just be a method call, nothing need be returned.
self.some_action_1("x","y","z")
# In fact we might need to do a few things here. Therefore a return call again doesn't make sense.
self.some_action_2("z")
# Notice we don't implement on_state_exit(). This state doesn't care about that.
When I need a state machine in Python, I store it as a dictionary of functions. The indices into the dictionary are the current states, and the functions do what they need to and return the next state (which may be the same state) and outputs. Turning the crank on the machine is simply:
state, outputs = machine_states[state](inputs)
By putting the outgoing state changes in code you're obfuscating the whole process. A state machine should be driven by a simple set of tables. One axis is the current state, and the other is the possible events. You have two or three tables:
The "next-state" table that determines the exit state
The "action" table that determines what action to take
The "read" table that determines whether you stay on the current input event or move on to the next.
The third table may or may not be needed depending on the complexity of the input "grammar".
There are more esoteric variations, but I've never found a need for more than this.
I also struggled to find a good state_machine solution in python. So I wrote state_machine
It works like the following
#acts_as_state_machine
class Person():
name = 'Billy'
sleeping = State(initial=True)
running = State()
cleaning = State()
run = Event(from_states=sleeping, to_state=running)
cleanup = Event(from_states=running, to_state=cleaning)
sleep = Event(from_states=(running, cleaning), to_state=sleeping)
#before('sleep')
def do_one_thing(self):
print "{} is sleepy".format(self.name)
#before('sleep')
def do_another_thing(self):
print "{} is REALLY sleepy".format(self.name)
#after('sleep')
def snore(self):
print "Zzzzzzzzzzzz"
#after('sleep')
def big_snore(self):
print "Zzzzzzzzzzzzzzzzzzzzzz"
person = Person()
print person.current_state == person.sleeping # True
print person.is_sleeping # True
print person.is_running # False
person.run()
print person.is_running # True
person.sleep()
# Billy is sleepy
# Billy is REALLY sleepy
# Zzzzzzzzzzzz
# Zzzzzzzzzzzzzzzzzzzzzz
print person.is_sleeping # True

Categories

Resources