Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • scs/ipaaca
  • ramin.yaghoubzadeh/ipaaca
2 results
Show changes
Showing
with 1064 additions and 212 deletions
......@@ -4,7 +4,7 @@
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2014 Social Cognitive Systems Group
# Copyright (c) 2009-2022 Social Cognitive Systems Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
......@@ -37,6 +37,9 @@ import copy
import threading
import uuid
import six
import ipaaca.ipaaca_pb2
import ipaaca.converter
import ipaaca.exception
import ipaaca.misc
......@@ -103,18 +106,18 @@ class IUInterface(object):
self._links = collections.defaultdict(set)
def __str__(self):
s = unicode(self.__class__)+"{ "
s = str(self.__class__)+"{ "
s += "category="+("<None>" if self._category is None else self._category)+" "
s += "uid="+self._uid+" "
s += "(buffer="+(self.buffer.unique_name if self.buffer is not None else "<None>")+") "
s += "owner_name=" + ("<None>" if self.owner_name is None else self.owner_name) + " "
s += "payload={ "
for k,v in self.payload.items():
s += k+":'"+unicode(v)+"', "
s += k+":'"+str(v)+"', "
s += "} "
s += "links={ "
for t,ids in self.get_all_links().items():
s += t+":'"+unicode(ids)+"', "
for t, ids in self.get_all_links().items():
s += t+":'"+str(ids)+"', "
s += "} "
s += "}"
return s
......@@ -134,13 +137,13 @@ class IUInterface(object):
def add_links(self, type, targets, writer_name=None):
'''Attempt to add links if the conditions are met
and send an update message. Then call the local setter.'''
if not hasattr(targets, '__iter__'): targets=[targets]
if isinstance(targets, six.string_types) and hasattr(targets, '__iter__'): targets=[targets]
self._modify_links(is_delta=True, new_links={type:targets}, links_to_remove={}, writer_name=writer_name)
self._add_and_remove_links( add={type:targets}, remove={} )
def remove_links(self, type, targets, writer_name=None):
'''Attempt to remove links if the conditions are met
and send an update message. Then call the local setter.'''
if not hasattr(targets, '__iter__'): targets=[targets]
if isinstance(targets, six.string_types) and hasattr(targets, '__iter__'): targets=[targets]
self._modify_links(is_delta=True, new_links={}, links_to_remove={type:targets}, writer_name=writer_name)
self._add_and_remove_links( add={}, remove={type:targets} )
def modify_links(self, add, remove, writer_name=None):
......@@ -172,9 +175,9 @@ class IUInterface(object):
if self._buffer is None:
self._payload_type = type
else:
raise IpaacaException('The IU is already in a buffer, cannot change payload type anymore.')
raise ipaaca.exception.IpaacaError('The IU is already in a buffer, cannot change payload type anymore.')
payload_type = property(
fget=_get_payload_type,
fget=_get_payload_type,
fset=_set_payload_type,
doc='Type of the IU payload')
......@@ -208,7 +211,7 @@ class IUInterface(object):
return self._buffer
def _set_buffer(self, buffer):
if self._buffer is not None:
raise IpaacaException('The IU is already in a buffer, cannot move it.')
raise ipaaca.exception.IpaacaError('The IU is already in a buffer, cannot move it.')
self._buffer = buffer
buffer = property(
fget=_get_buffer,
......@@ -219,7 +222,7 @@ class IUInterface(object):
return self._owner_name
def _set_owner_name(self, owner_name):
if self._owner_name is not None:
raise Exception('The IU already has an owner name, cannot change it.')
raise ipaaca.exception.IpaacaError('The IU already has an owner name, cannot change it.')
self._owner_name = owner_name
owner_name = property(
fget=_get_owner_name,
......@@ -240,7 +243,9 @@ class IU(IUInterface):
self._payload = ipaaca.payload.Payload(iu=self)
def _modify_links(self, is_delta=False, new_links={}, links_to_remove={}, writer_name=None):
if self.committed:
if self._retracted:
raise ipaaca.exception.IURetractedError(self)
if self._committed:
raise ipaaca.exception.IUCommittedError(self)
with self.revision_lock:
# modify links locally
......@@ -257,7 +262,9 @@ class IU(IUInterface):
def _modify_payload(self, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
"""Modify the payload: add or remove items from this payload locally and send update."""
if self.committed:
if self._retracted:
raise ipaaca.exception.IURetractedError(self)
if self._committed:
raise ipaaca.exception.IUCommittedError(self)
with self.revision_lock:
# set item locally
......@@ -278,23 +285,33 @@ class IU(IUInterface):
self._revision += 1
def _internal_commit(self, writer_name=None):
if self.committed:
raise ipaaca.exception.IUCommittedError(self)
if self._committed:
return
if self._retracted:
raise ipaaca.exception.IURetractedError(self)
with self.revision_lock:
if not self._committed:
self._increase_revision_number()
self._committed = True
if self.buffer is not None:
self.buffer._send_iu_commission(self, writer_name=writer_name)
self._increase_revision_number()
self._committed = True
if self.buffer is not None:
self.buffer._send_iu_commission(self, writer_name=writer_name)
def commit(self):
"""Commit to this IU."""
return self._internal_commit()
def retract(self):
if self._buffer:
self._buffer.remove(self)
self._buffer = None
else:
self._retracted = True
def _get_payload(self):
return self._payload
def _set_payload(self, new_pl, writer_name=None):
if self.committed:
if self._retracted:
raise ipaaca.exception.IURetractedError(self)
if self._committed:
raise ipaaca.exception.IUCommittedError(self)
with self.revision_lock:
self._increase_revision_number()
......@@ -315,7 +332,7 @@ class IU(IUInterface):
def _set_buffer(self, buffer):
if self._buffer is not None:
raise Exception('The IU is already in a buffer, cannot move it.')
raise ipaaca.exception.IpaacaError('The IU is already in a buffer, cannot move it.')
self._buffer = buffer
self.owner_name = buffer.unique_name
self._payload.owner_name = buffer.unique_name
......@@ -363,7 +380,9 @@ class Message(IU):
if self.is_published:
LOGGER.info('Info: modifying a Message after sending has no global effects')
else:
if self.committed:
if self._retracted:
raise ipaaca.exception.IURetractedError(self)
if self._committed:
raise ipaaca.exception.IUCommittedError(self)
with self.revision_lock:
self._increase_revision_number()
......@@ -384,7 +403,7 @@ class Message(IU):
def _set_buffer(self, buffer):
if self._buffer is not None:
raise Exception('The IU is already in a buffer, cannot move it.')
raise ipaaca.exception.IpaacaError('The IU is already in a buffer, cannot move it.')
self._buffer = buffer
self.owner_name = buffer.unique_name
self._payload.owner_name = buffer.unique_name
......@@ -413,7 +432,6 @@ class RemoteMessage(IUInterface):
self._category = category
self.owner_name = owner_name
self._committed = committed
self._retracted = False
# NOTE Since the payload is an already-existant Payload which we didn't modify ourselves,
# don't try to invoke any modification checks or network updates ourselves either.
# We are just receiving it here and applying the new data.
......@@ -480,7 +498,6 @@ class RemotePushIU(IUInterface):
self._category = category
self.owner_name = owner_name
self._committed = committed
self._retracted = False
# NOTE Since the payload is an already-existant Payload which we didn't modify ourselves,
# don't try to invoke any modification checks or network updates ourselves either.
# We are just receiving it here and applying the new data.
......@@ -489,9 +506,11 @@ class RemotePushIU(IUInterface):
def _modify_links(self, is_delta=False, new_links={}, links_to_remove={}, writer_name=None):
"""Modify the links: add or remove item from this payload remotely and send update."""
if self.committed:
if self._retracted:
raise ipaaca.exception.IURetractedError(self)
if self._committed:
raise ipaaca.exception.IUCommittedError(self)
if self.read_only:
if self._read_only:
raise ipaaca.exception.IUReadOnlyError(self)
requested_update = ipaaca.converter.IULinkUpdate(
uid=self.uid,
......@@ -509,9 +528,11 @@ class RemotePushIU(IUInterface):
def _modify_payload(self, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
"""Modify the payload: add or remove item from this payload remotely and send update."""
if self.committed:
if self._retracted:
raise ipaaca.exception.IURetractedError(self)
if self._committed:
raise ipaaca.exception.IUCommittedError(self)
if self.read_only:
if self._read_only:
raise ipaaca.exception.IUReadOnlyError(self)
requested_update = ipaaca.converter.IUPayloadUpdate(
uid=self.uid,
......@@ -530,30 +551,32 @@ class RemotePushIU(IUInterface):
def commit(self):
"""Commit to this IU."""
if self.read_only:
raise ipaaca.exception.IUReadOnlyError(self)
if self._committed:
# ignore commit requests when already committed
return
if self._retracted:
raise ipaaca.exception.IURetractedError(self)
if self._read_only:
raise ipaaca.exception.IUReadOnlyError(self)
commission_request = ipaaca.ipaaca_pb2.IUCommission()
commission_request.uid = self.uid
commission_request.revision = self.revision
commission_request.writer_name = self.buffer.unique_name
remote_server = self.buffer._get_remote_server(self)
new_revision = remote_server.commit(commission_request)
if new_revision == 0:
raise ipaaca.exception.IUUpdateFailedError(self)
else:
commission_request = ipaaca_pb2.IUCommission()
commission_request.uid = self.uid
commission_request.revision = self.revision
commission_request.writer_name = self.buffer.unique_name
remote_server = self.buffer._get_remote_server(self)
new_revision = remote_server.commit(commission_request)
if new_revision == 0:
raise ipaaca.exception.IUUpdateFailedError(self)
else:
self._revision = new_revision
self._committed = True
self._revision = new_revision
self._committed = True
def _get_payload(self):
return self._payload
def _set_payload(self, new_pl):
if self.committed:
if self._retracted:
raise ipaaca.exception.IURetractedError(self)
if self._committed:
raise ipaaca.exception.IUCommittedError(self)
if self.read_only:
if self._read_only:
raise ipaaca.exception.IUReadOnlyError(self)
requested_update = ipaaca.converter.IUPayloadUpdate(
uid=self.uid,
......
......@@ -4,7 +4,7 @@
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2014 Social Cognitive Systems Group
# Copyright (c) 2009-2022 Social Cognitive Systems Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
......@@ -35,10 +35,10 @@ from __future__ import division, print_function
import argparse
import logging
import sys
import ipaaca.defaults
__all__ = [
'enum',
'IpaacaArgumentParser',
......@@ -54,6 +54,7 @@ def enum(*sequential, **named):
"""
enums = dict(zip(sequential, range(len(sequential))), **named)
enums['_choices'] = enums.keys()
enums['_values'] = enums.values() # RY e.g. see if raw int is valid
return type('Enum', (object,), enums)
......@@ -69,6 +70,21 @@ class IpaacaLoggingHandler(logging.Handler):
msg = str(record.msg.format(record.args))
print(meta + msg)
class RSBLoggingHandler(logging.Handler):
'''A logging handler that prints to stdout, RSB version.'''
def __init__(self, prefix='IPAACA', level=logging.NOTSET):
logging.Handler.__init__(self, level)
self._prefix = prefix
def emit(self, record):
meta = '[%s: %s] ' % (self._prefix, str(record.levelname))
try:
msg = str(record.msg % record.args)
except:
msg = str(record.msg) + ' WITH ARGS: ' + str(record.args)
print(meta + msg)
class GenericNoLoggingHandler(logging.Handler):
'''A logging handler that produces no output'''
......@@ -80,21 +96,21 @@ def get_library_logger():
return logging.getLogger(ipaaca.defaults.IPAACA_LOGGER_NAME)
__IPAACA_LOGGING_HANDLER = IpaacaLoggingHandler('IPAACA')
__GENERIC_NO_LOG_HANDLER = GenericNoLoggingHandler()
_IPAACA_LOGGING_HANDLER = IpaacaLoggingHandler('IPAACA')
_GENERIC_NO_LOG_HANDLER = GenericNoLoggingHandler()
# By default, suppress library logging
# - for IPAACA
get_library_logger().addHandler(__GENERIC_NO_LOG_HANDLER)
get_library_logger().addHandler(_GENERIC_NO_LOG_HANDLER)
# - for RSB
logging.getLogger('rsb').addHandler(__GENERIC_NO_LOG_HANDLER)
logging.getLogger('rsb').addHandler(_GENERIC_NO_LOG_HANDLER)
def enable_logging(level=None):
'''Enable ipaaca's 'library-wide logging.'''
ipaaca_logger = get_library_logger()
ipaaca_logger.addHandler(__IPAACA_LOGGING_HANDLER)
ipaaca_logger.removeHandler(__GENERIC_NO_LOG_HANDLER)
ipaaca_logger.addHandler(_IPAACA_LOGGING_HANDLER)
ipaaca_logger.removeHandler(_GENERIC_NO_LOG_HANDLER)
ipaaca_logger.setLevel(level=level if level is not None else
ipaaca.defaults.IPAACA_DEFAULT_LOGGING_LEVEL)
......@@ -120,10 +136,30 @@ class IpaacaArgumentParser(argparse.ArgumentParser):
def __call__(self, parser, namespace, values, option_string=None):
rsb_logger = logging.getLogger('rsb')
rsb_logger.addHandler(IpaacaLoggingHandler('RSB'))
rsb_logger.removeHandler(__GENERIC_NO_LOG_HANDLER)
rsb_logger.addHandler(RSBLoggingHandler('RSB'))
rsb_logger.removeHandler(_GENERIC_NO_LOG_HANDLER)
rsb_logger.setLevel(level=values)
class IpaacaRSBHost(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
ipaaca.defaults.IPAACA_DEFAULT_RSB_HOST = values
class IpaacaRSBPort(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
ipaaca.defaults.IPAACA_DEFAULT_RSB_PORT = values
class IpaacaRSBTransport(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
ipaaca.defaults.IPAACA_DEFAULT_RSB_TRANSPORT = values
class IpaacaRSBSocketServer(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
ipaaca.defaults.IPAACA_DEFAULT_RSB_SOCKET_SERVER = values
def __init__(self, prog=None, usage=None, description=None, epilog=None,
parents=[], formatter_class=argparse.HelpFormatter,
prefix_chars='-', fromfile_prefix_chars=None,
......@@ -136,6 +172,7 @@ class IpaacaArgumentParser(argparse.ArgumentParser):
conflict_handler=conflict_handler, add_help=add_help)
def _add_ipaaca_lib_arguments(self):
# CMD-arguments for ipaaca
ipaacalib_group = self.add_argument_group('IPAACA library arguments')
ipaacalib_group.add_argument(
'--ipaaca-payload-type',
......@@ -157,6 +194,7 @@ class IpaacaArgumentParser(argparse.ArgumentParser):
choices=['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'],
dest='_ipaaca_logging_level_',
help="enable IPAACA logging with threshold")
# CMD-arguments for rsb
rsblib_group = self.add_argument_group('RSB library arguments')
rsblib_group.add_argument(
'--rsb-enable-logging',
......@@ -164,6 +202,36 @@ class IpaacaArgumentParser(argparse.ArgumentParser):
choices=['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'],
dest='_ipaaca_rsb_enable_logging_',
help="enable RSB logging with threshold")
rsblib_group.add_argument(
'--rsb-host',
action=self.IpaacaRSBHost,
default=None,
dest='_ipaaca_rsb_set_host_',
metavar='HOST',
help="set RSB host")
rsblib_group.add_argument(
'--rsb-port',
action=self.IpaacaRSBPort,
default=None,
dest='_ipaaca_rsb_set_port_',
metavar='PORT',
help="set RSB port")
rsblib_group.add_argument(
'--rsb-transport',
action=self.IpaacaRSBTransport,
default=None,
dest='_ipaaca_rsb_set_transport_',
choices=['spread', 'socket'],
metavar='TRANSPORT',
help="set RSB transport")
rsblib_group.add_argument(
'--rsb-socket-server',
action=self.IpaacaRSBSocketServer,
default=None,
dest='_ipaaca_rsb_set_socket_server_',
choices=['0', '1', 'auto'],
metavar='server',
help="act as server (only when --rsb-transport=socket)")
def parse_args(self, args=None, namespace=None):
self._add_ipaaca_lib_arguments() # Add ipaaca-args just before parsing
......
......@@ -4,7 +4,7 @@
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2014 Social Cognitive Systems Group
# Copyright (c) 2009-2022 Social Cognitive Systems Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
......@@ -30,7 +30,7 @@
# Forschungsgemeinschaft (DFG) in the context of the German
# Excellence Initiative.
from __future__ import division, print_function
import threading
import time
......@@ -53,12 +53,12 @@ class Payload(dict):
def __init__(self, iu, writer_name=None, new_payload=None, omit_init_update_message=False, update_timeout=_DEFAULT_PAYLOAD_UPDATE_TIMEOUT):
self.iu = iu
_pl = {}
for k, v in ({} if new_payload is None else new_payload).iteritems():
_pl[unicode(k, 'utf8') if type(k) == str else k] = unicode(v, 'utf8') if type(v) == str else v
for k, v in ({} if new_payload is None else new_payload).items():
_pl[str(k) if type(k) == str else k] = str(v) if type(v) == str else v
# NOTE omit_init_update_message is necessary to prevent checking for
# exceptions and sending updates in the case where we just receive
# a whole new payload from the remote side and overwrite it locally.
for k, v in _pl.iteritems():
for k, v in _pl.items():
dict.__setitem__(self, k, v)
if (not omit_init_update_message) and (self.iu.buffer is not None):
self.iu._modify_payload(
......@@ -85,8 +85,8 @@ class Payload(dict):
def __setitem__(self, k, v, writer_name=None):
with self._batch_update_lock:
k = unicode(k, 'utf8') if type(k) == str else k
v = unicode(v, 'utf8') if type(v) == str else v
k = str(k) if type(k) == str else k
v = str(v) if type(v) == str else v
if self._update_on_every_change:
self.iu._modify_payload(
is_delta=True,
......@@ -96,11 +96,13 @@ class Payload(dict):
else: # Collect additions/modifications
self._batch_update_writer_name = writer_name
self._collected_modifications[k] = v
# revoke deletion of item since a new version has been added
self._collected_removals = [i for i in self._collected_removals if i!=k]
return dict.__setitem__(self, k, v)
def __delitem__(self, k, writer_name=None):
with self._batch_update_lock:
k = unicode(k, 'utf8') if type(k) == str else k
k = str(k) if type(k) == str else k
if self._update_on_every_change:
self.iu._modify_payload(
is_delta=True,
......@@ -110,6 +112,8 @@ class Payload(dict):
else: # Collect additions/modifications
self._batch_update_writer_name = writer_name
self._collected_removals.append(k)
# revoke older update of item since more recent changes take precedence
if k in self._collected_modifications: del self._collected_modifications[k]
return dict.__delitem__(self, k)
# Context-manager based batch updates, not thread-safe (on remote updates)
......@@ -132,9 +136,9 @@ class Payload(dict):
def merge(self, payload, writer_name=None):
with self._batch_update_lock:
for k, v in payload.iteritems():
k = unicode(k, 'utf8') if type(k) == str else k
v = unicode(v, 'utf8') if type(v) == str else v
for k, v in payload.items():
k = str(k) if type(k) == str else k
v = str(v) if type(v) == str else v
self.iu._modify_payload(
is_delta=True,
new_items=payload,
......@@ -144,11 +148,11 @@ class Payload(dict):
def _remotely_enforced_setitem(self, k, v):
"""Sets an item when requested remotely."""
return dict.__setitem__(self, k, v)
dict.__setitem__(self, k, v)
def _remotely_enforced_delitem(self, k):
"""Deletes an item when requested remotely."""
return dict.__delitem__(self, k)
if k in self: dict.__delitem__(self, k)
def _wait_batch_update_lock(self, timeout):
# wait lock with time-out http://stackoverflow.com/a/8393033
......@@ -216,18 +220,22 @@ class PayloadItemDictProxy(PayloadItemProxy, dict):
value = self.content.get(key, default)
return self._create_proxy(value, key)
def items(self):
return [(key, value) for key, value in self.iteritems()]
# py3port: were these used at all?
# def items(self):
# return [(key, value) for key, value in self.items()]
def iteritems(self):
for key, value in self.content.iteritems():
# py3port: was iteritems
def items(self):
for key, value in self.content.items():
yield key, self._create_proxy(value, key)
def values(self):
return [value for value in self.itervalues()]
# py3port: were these used at all?
# def values(self):
# return [value for value in self.values()]
def itervalues(self):
for key, value in self.content.iteritems():
# py3port: was itervalues
def values(self):
for key, value in self.content.items():
yield self._create_proxy(value, key)
def pop(self, key, *args):
......
......@@ -4,7 +4,7 @@
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2014 Social Cognitive Systems Group
# Copyright (c) 2009-2022 Social Cognitive Systems Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
......@@ -32,4 +32,4 @@
from __future__ import division, print_function
from notifier import ComponentNotifier
from .notifier import ComponentNotifier
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of IPAACA, the
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2022 Social Cognitive Systems Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
# http://purl.org/net/ipaaca
#
# This file may be licensed under the terms of of the
# GNU Lesser General Public License Version 3 (the ``LGPL''),
# or (at your option) any later version.
#
# Software distributed under the License is distributed
# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
# express or implied. See the LGPL for the specific language
# governing rights and limitations.
#
# You should have received a copy of the LGPL along with this
# program. If not, go to http://www.gnu.org/licenses/lgpl.html
# or write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The development of this software was supported by the
# Excellence Cluster EXC 277 Cognitive Interaction Technology.
# The Excellence Cluster EXC 277 is a grant of the Deutsche
# Forschungsgemeinschaft (DFG) in the context of the German
# Excellence Initiative.
from __future__ import division, print_function
import datetime
import subprocess
import sys
import threading
import time
import traceback
import uuid
import ipaaca
import ipaaca.misc
import six
__all__ = [
'logger_send_ipaaca_logs',
'logger_set_log_filename',
'logger_set_module_name',
'logger_set_log_level',
'LOG_DEBUG',
'LOG_INFO',
'LOG_WARN',
'LOG_WARNING',
'LOG_ERROR',
]
LogLevel = ipaaca.misc.enum(
DEBUG = 0,
INFO = 1,
WARN = 2,
ERROR = 3,
SILENT = 4,
)
LOG_LEVEL_FROM_STRING_DICT = {
'DEBUG': LogLevel.DEBUG,
'INFO': LogLevel.INFO,
'WARN': LogLevel.WARN,
'WARNING': LogLevel.WARN,
'ERROR': LogLevel.ERROR,
'NONE': LogLevel.SILENT,
'SILENT': LogLevel.SILENT,
}
CURRENT_LOG_LEVEL = LogLevel.DEBUG
LOGGER_LOCK = threading.RLock()
MODULE_NAME = sys.argv[0]
SEND_IPAACA_LOGS = True
OUTPUT_BUFFER = None
STANDARD_LOG_FILE_EXTENSION = '.log'
LOG_MODES = ['append', 'timestamp', 'overwrite']
def logger_set_log_filename(filename, existing=None):
global OUTPUT_BUFFER
if existing is not None and not existing in LOG_MODES:
raise Exception('Invalid log mode {mode} given. '
'Valid options are {options}.'.format(
mode=existing,
options=', '.join(LOG_MODES)))
with LOGGER_LOCK:
if OUTPUT_BUFFER is None:
OUTPUT_BUFFER = ipaaca.OutputBuffer('LogSender')
msg = ipaaca.Message('logcontrol')
msg.payload = {
'cmd': 'open_log_file',
'filename': filename}
if existing is not None:
msg.payload['existing'] = existing
OUTPUT_BUFFER.add(msg)
def logger_set_module_name(name):
global MODULE_NAME
with LOGGER_LOCK:
MODULE_NAME = name
def logger_send_ipaaca_logs(flag=True):
global SEND_IPAACA_LOGS
with LOGGER_LOCK:
SEND_IPAACA_LOGS = flag
def logger_set_log_level(level=LogLevel.DEBUG):
global CURRENT_LOG_LEVEL
with LOGGER_LOCK:
if level in LogLevel._values:
CURRENT_LOG_LEVEL = level
elif isinstance(level, six.string_types) and level.upper() in LOG_LEVEL_FROM_STRING_DICT:
CURRENT_LOG_LEVEL = LOG_LEVEL_FROM_STRING_DICT[level.upper()]
else:
pass # leave previous setting untouched
def LOG_IPAACA(lvl, text, now=0.0, fn='???', thread='???'):
global OUTPUT_BUFFER
uid = str(uuid.uuid4())[0:8]
with LOGGER_LOCK:
if OUTPUT_BUFFER is None:
OUTPUT_BUFFER = ipaaca.OutputBuffer('LogSender')
msg = ipaaca.Message('log')
msg.payload = {
'module': MODULE_NAME,
'function': fn,
'level': lvl,
'time':' %.3f'%now,
'thread': thread,
'uuid': uid,
'text': text,}
try:
OUTPUT_BUFFER.add(msg)
except Exception as e:
LOG_ERROR('Caught an exception while logging via ipaaca. '
+ ' str(e); '
+ traceback.format_exc())
def LOG_CONSOLE(lvlstr, msg, fn_markup='', msg_markup='', now=0.0, fn='???', thread='???'):
if isinstance(msg, six.string_types):
lines = msg.split('\n')
else:
lines = [msg]
for line in lines:
text = lvlstr+' '+thread+' '+fn_markup+fn+'\033[m'+' '+msg_markup+str(line)+'\033[m'
print(text)
fn = ' '*len(fn)
def LOG_ERROR(msg, now=None):
if CURRENT_LOG_LEVEL > LogLevel.ERROR: return
now = time.time() if now is None else now
f = sys._getframe(1)
classprefix = (f.f_locals['self'].__class__.__name__+'.') if 'self' in f.f_locals else ''
fn = classprefix + f.f_code.co_name
thread = threading.current_thread().getName()
with LOGGER_LOCK:
if SEND_IPAACA_LOGS: LOG_IPAACA('ERROR', msg, now=now, fn=fn, thread=thread)
LOG_CONSOLE('\033[38;5;9;1;4m[ERROR]\033[m', msg, fn_markup='\033[38;5;203m', msg_markup='\033[38;5;9;1;4m', now=now, fn=fn, thread=thread)
def LOG_WARN(msg, now=None):
if CURRENT_LOG_LEVEL > LogLevel.WARN: return
now = time.time() if now is None else now
f = sys._getframe(1)
classprefix = (f.f_locals['self'].__class__.__name__+'.') if 'self' in f.f_locals else ''
fn = classprefix + f.f_code.co_name
thread = threading.current_thread().getName()
with LOGGER_LOCK:
if SEND_IPAACA_LOGS: LOG_IPAACA('WARN', msg, now=now, fn=fn, thread=thread)
LOG_CONSOLE('\033[38;5;208;1m[WARN]\033[m ', msg, fn_markup='\033[38;5;214m', msg_markup='\033[38;5;208;1m', now=now, fn=fn, thread=thread)
LOG_WARNING = LOG_WARN
def LOG_INFO(msg, now=None):
if CURRENT_LOG_LEVEL > LogLevel.INFO: return
now = time.time() if now is None else now
f = sys._getframe(1)
classprefix = (f.f_locals['self'].__class__.__name__+'.') if 'self' in f.f_locals else ''
fn = classprefix + f.f_code.co_name
thread = threading.current_thread().getName()
with LOGGER_LOCK:
if SEND_IPAACA_LOGS: LOG_IPAACA('INFO', msg, now=now, fn=fn, thread=thread)
LOG_CONSOLE('[INFO] ', msg, now=now, fn=fn, thread=thread)
def LOG_DEBUG(msg, now=None):
if CURRENT_LOG_LEVEL > LogLevel.DEBUG: return
now = time.time() if now is None else now
f = sys._getframe(1)
classprefix = (f.f_locals['self'].__class__.__name__+'.') if 'self' in f.f_locals else ''
fn = classprefix + f.f_code.co_name
thread = threading.current_thread().getName()
with LOGGER_LOCK:
if SEND_IPAACA_LOGS: LOG_IPAACA('DEBUG', msg, now=now, fn=fn, thread=thread)
LOG_CONSOLE('\033[2m[DEBUG]\033[m', msg, fn_markup='\033[38;5;144m', msg_markup='\033[38;5;248m', now=now, fn=fn, thread=thread)
class LoggerComponent(object):
def __init__(self, filename, log_mode='append'):
self.ib = ipaaca.InputBuffer('Logger', ['log', 'logcontrol'])
self.ib.register_handler(self._logger_handle_iu_event)
self.logfile = None
self.log_mode = log_mode
self.open_logfile(filename)
if self.logfile is None:
print('Logging to console only ...')
print('Press Ctrl-C at any time to terminate the logger.')
def open_logfile(self, filename):
with LOGGER_LOCK:
if filename is None or filename.strip() == '':
print('No log file name specified, not opening one.')
self.close_logfile()
else:
new_logfile = None
try:
# create dir first
ret = subprocess.call(
'mkdir -p `dirname ' + filename + '`',
shell=True)
# proceed with dir+file
if self.log_mode == 'timestamp':
t = datetime.datetime.now().strftime('%Y-%m-%d-%H%M%S')
if filename.endswith(STANDARD_LOG_FILE_EXTENSION):
# insert timestamp between filename and extension
# (only for standard extension)
filename = filename.replace(
STANDARD_LOG_FILE_EXTENSION,
'.' + t + STANDARD_LOG_FILE_EXTENSION)
else: # prepend timestamp
filename = t + '_' + filename
append_if_exist = not (self.log_mode == 'overwrite' or
self.log_mode == 'timestamp')
new_logfile = open(filename, 'a' if append_if_exist else 'w')
if self.logfile is not None:
text = u'Will now continue logging in log file ' + str(filename)
uid = str(uuid.uuid4())[0:8]
tim = time.time()
record = {
'uuid': uid,
'time': tim,
'level': u'INFO',
'text': text,
'module': u'logger',
'function': u'LoggerComponent.open_logfile',
'thread': '-',
'logreceivedtime': tim}
self.logfile.write(str(record)+'\n')
self.logfile.close()
self.logfile = new_logfile
print('Logging to console and {filename} ...'.format(filename=filename))
except Exception as e:
print('Failed to open logfile {filename} for writing! Keeping previous configuration'.format(filename=filename))
def close_logfile(self):
if self.logfile is not None:
text = u'Closing of log file requested.'
uid = str(uuid.uuid4())[0:8]
tim = str(time.time())
record = {
'uuid': uid,
'time': tim,
'level': u'INFO',
'text': text,
'module': u'logger',
'function': u'LoggerComponent.close_logfile',
'thread': u'-',
'logreceivedtime': tim}
self.logfile.write(str(record)+'\n')
self.logfile.close()
print('Closed current log file.')
self.logfile = None
def _logger_handle_iu_event(self, iu, event_type, own):
received_time = "%.3f" % time.time()
with LOGGER_LOCK:
try:
if iu.category == 'log':
pl = iu.payload
message = pl['text'] if 'text' in pl else '(No message.)'
uid = '????????' if 'uuid' not in pl else pl['uuid']
tim = '???' if 'time' not in pl else pl['time']
module = '???' if 'module' not in pl else pl['module']
function = '???' if 'function' not in pl else pl['function']
thread = '???' if 'thread' not in pl else pl['thread']
level = 'INFO' if 'level' not in pl else pl['level']
# dump to console
if level=='WARN':
level='WARNING'
if level not in ['DEBUG','INFO','WARNING','ERROR']:
level = 'INFO'
try:
print('%s %-8s {%s} {%s} {%s} %s'%(tim, ('['+level+']'), thread, module, function, message))
except:
print('Failed to format a string for printing!')
if self.logfile is not None:
try:
record = {
'uuid': uid,
'time': tim,
'level': level,
'text': message,
'module': module,
'function': function,
'thread': thread,
'logreceivedtime': received_time}
self.logfile.write(str(record) + '\n')
except:
print('Failed to write to logfile!')
elif iu.category == 'logcontrol':
cmd = iu.payload['cmd'] if 'cmd' in iu.payload else 'undef'
if cmd == 'open_log_file':
filename = iu.payload['filename'] if 'filename' in iu.payload else ''
if 'existing' in iu.payload:
log_mode_ = iu.payload['existing'].lower()
if log_mode_ not in LOG_MODES:
LOG_WARN(u'Value of "existing" should be "append", "timestamp", or "overwrite", continuing with mode {mode}'.format(mode=self.log_mode))
else:
self.log_mode = log_mode_
self.open_logfile(filename)
elif cmd == 'close_log_file':
self.close_logfile()
else:
LOG_WARN(u'Received unknown logcontrol command: '+str(cmd))
except Exception as e:
print('Exception while logging!') # TODO write to file as well?
print(u' '+str(traceback.format_exc()))
......@@ -4,7 +4,7 @@
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2014 Social Cognitive Systems Group
# Copyright (c) 2009-2022 Social Cognitive Systems Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
......@@ -33,9 +33,9 @@
from __future__ import division, print_function
import os
import threading
import ipaaca.buffer
import ipaaca.iu
import ipaaca.misc
......@@ -64,11 +64,16 @@ class ComponentError(Exception):
class ComponentNotifier(object):
NOTIFY_CATEGORY = "componentNotify"
CONTROL_CATEGORY = "componentControl"
SEND_CATEGORIES = "send_categories"
RECEIVE_CATEGORIES = "recv_categories"
CMD = "cmd"
STATE = "state"
NAME = "name"
WHO = "who" # list of names (or empty)
FUNCTION = "function"
PID = "pid"
CMD_REPORT = "report"
def __init__(self, component_name, component_function, send_categories, receive_categories, out_buffer=None, in_buffer=None):
self.component_name = component_name
......@@ -116,14 +121,23 @@ class ComponentNotifier(object):
self.out_buffer.add(notify_iu)
def _handle_iu_event(self, iu, event_type, local):
if iu.payload[ComponentNotifier.NAME] == self.component_name:
return
with self.notification_handler_lock:
for h in self.notification_handlers:
h(iu, event_type, local)
if iu.payload[ComponentNotifier.STATE] == "new":
#print("submitting")
self._submit_notify(False)
if iu.category == ComponentNotifier.NOTIFY_CATEGORY:
if iu.payload[ComponentNotifier.NAME] == self.component_name:
return
with self.notification_handler_lock:
for h in self.notification_handlers:
h(iu, event_type, local)
if iu.payload[ComponentNotifier.STATE] == "new":
#print("submitting")
self._submit_notify(False)
elif iu.category == ComponentNotifier.CONTROL_CATEGORY:
cmd = iu.payload[ComponentNotifier.CMD]
if cmd=='report':
# Request to report (by component controller)
who = iu.payload[ComponentNotifier.WHO]
# If we are named specifically or it's a broadcast
if len(who)==0 or self.component_name in who:
self._submit_notify(False)
def add_notification_handler(self, handler):
with self.notification_handler_lock:
......@@ -155,12 +169,14 @@ class ComponentNotifier(object):
if (not self.initialized):
self.timesync_slave = ipaaca.util.timesync.TimesyncSlave(component_name=self.component_name, timing_handler=self.launch_timesync_slave_handlers)
self.timesync_master = ipaaca.util.timesync.TimesyncMaster(component_name=self.component_name, timing_handler=self.launch_timesync_master_handlers)
self.in_buffer.register_handler(self._handle_iu_event, ipaaca.iu.IUEventType.MESSAGE, ComponentNotifier.NOTIFY_CATEGORY)
self.in_buffer.register_handler(self._handle_iu_event, ipaaca.iu.IUEventType.MESSAGE, [ComponentNotifier.NOTIFY_CATEGORY, ComponentNotifier.CONTROL_CATEGORY])
self._submit_notify(True)
self.initialized = True
def __enter__(self):
self.initialize()
return self
def __exit__(self, t, v, tb):
self.terminate()
return self
......@@ -4,7 +4,7 @@
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2014 Social Cognitive Systems Group
# Copyright (c) 2009-2022 Social Cognitive Systems Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
......@@ -32,6 +32,7 @@
from __future__ import division, print_function
import threading
import time
import ipaaca.buffer
......@@ -45,7 +46,7 @@ class TimesyncMaster(object):
# component name to report (None => use buffer name)
self.component_name = component_name if component_name is not None else self.ob.unique_name
#
self.ob.register_handler(self.handle_timesync_master)
#self.ob.register_handler(self.handle_timesync_master)
self.ib.register_handler(self.handle_timesync_master)
# master_t1 is identical for all slaves
self.master_t1 = None
......@@ -63,7 +64,7 @@ class TimesyncMaster(object):
self.timing_handler = timing_handler
def send_master_timesync(self):
iu = ipaaca.iu.IU('timesyncRequest')
iu = ipaaca.iu.Message('timesyncRequest')
self.master_t1 = self.get_time()
iu.payload = {
'stage':'0',
......@@ -71,47 +72,48 @@ class TimesyncMaster(object):
'master':self.component_name,
}
self.ob.add(iu)
print('Sent a stage 0 timesync as master '+self.component_name)
def handle_timesync_master(self, iu, event_type, own):
master = iu.payload['master']
if not own and master == self.component_name:
if self.component_name == master:
# reply to our own initial IU
slave = iu.payload['slave']
stage = iu.payload['stage']
if stage=='1':
print('Received stage 1 from slave '+slave)
# initial reply by slave
t1 = iu.payload['slave_t1']
self.slave_t1s[slave] = float(t1)
t2 = self.master_t2s[slave] = self.get_time()
iu.payload.merge({'master_t2': str(t2), 'stage':'2'})
latency1 = t2 - self.master_t1
self.latencies[slave] = latency1
#print('Latency of round-trip 1: %.3f' % latency1)
elif stage=='3':
print('Received stage 3 from slave '+slave)
# second reply by slave
t2 = iu.payload['slave_t2']
self.slave_t2s[slave] = float(t2)
t_final = self.get_time()
latency1 = self.latencies[slave]
latency2 = t_final - self.master_t2s[slave]
latency = self.latencies[slave] = (latency1+latency2)/2.0
offset1 = (self.slave_t1s[slave]-self.master_t1)-latency/2.0
offset2 = (self.slave_t2s[slave]-self.master_t2s[slave])-latency/2.0
offset = (offset1+offset2)/2.0
iu.payload.merge({'stage':'4', 'latency': str(latency), 'offset':str(offset)})
if self.timing_handler is None:
print('Determined timing of timesync slave '+slave)
print(' Avg round-trip latency: %.3f s'%latency)
print(' Offset of their clock: %.3f s'%offset)
if event_type == ipaaca.IUEventType.ADDED or event_type == ipaaca.IUEventType.UPDATED:
if self.component_name == master:
# reply to our own initial IU
slave = iu.payload['slave']
stage = iu.payload['stage']
if stage=='1':
# initial reply by slave
t1 = iu.payload['slave_t1']
self.slave_t1s[slave] = float(t1)
t2 = self.master_t2s[slave] = self.get_time()
iu.payload.merge({'master_t2': str(t2), 'stage':'2'})
latency1 = t2 - self.master_t1
#print('Before stage 1 for '+slave+': '+str(self.latencies))
self.latencies[slave] = latency1
#print('After stage 1 for '+slave+': '+str(self.latencies))
#print('Latency of round-trip 1: %.3f' % latency1)
elif stage=='3':
#print('At stage 3 for '+slave+': '+str(self.latencies))
# second reply by slave
t2 = iu.payload['slave_t2']
self.slave_t2s[slave] = float(t2)
t_final = self.get_time()
latency1 = self.latencies[slave]
latency2 = t_final - self.master_t2s[slave]
latency = self.latencies[slave] = (latency1+latency2)/2.0
offset1 = (self.slave_t1s[slave]-self.master_t1)-latency/2.0
offset2 = (self.slave_t2s[slave]-self.master_t2s[slave])-latency/2.0
offset = (offset1+offset2)/2.0
iu.payload.merge({'stage':'4', 'latency': str(latency), 'offset':str(offset)})
if self.timing_handler is None:
print('Determined timing of timesync slave '+slave)
print(' Avg round-trip latency: %.3f s'%latency)
print(' Offset of their clock: %.3f s'%offset)
else:
self.timing_handler(self.component_name, slave, latency, offset)
else:
self.timing_handler(self.component_name, slave, latency, offset)
else:
# other stages are handled by time slave handler
pass
# other stages are handled by time slave handler
pass
def get_time(self):
return time.time() + self.debug_offset
......@@ -129,7 +131,6 @@ class TimesyncSlave(object):
#self.master_t2 = None
#self.master = None
self.latency = None
self.my_iu = None
#
self.debug_offset = debug_offset
#
......@@ -142,30 +143,23 @@ class TimesyncSlave(object):
master = iu.payload['master']
stage = iu.payload['stage']
if self.component_name != master:
if not own:
if not own and stage=='0':
# reply only to IUs from others
if stage=='0':
#print('Received stage 0 from master '+master)
# initial reply to master
self.my_iu = ipaaca.iu.IU('timesyncReply')
# TODO: add grounded_in link too?
t1 = self.get_time()
self.my_iu.payload = iu.payload
self.my_iu.payload['slave'] = self.component_name
self.my_iu.payload['slave_t1'] = str(t1)
self.my_iu.payload['stage'] = '1'
#self.my_iu.payload.merge({
# 'slave':self.component_name,
# 'slave_t1':str(t1),
# 'stage':'1',
# })
self.ob.add(self.my_iu)
else:
#print('Received stage 0 from master '+master)
# initial reply to master
myiu = ipaaca.iu.IU('timesyncReply')
# TODO: add grounded_in link too?
t1 = self.get_time()
myiu.payload = iu.payload
myiu.payload['slave'] = self.component_name
myiu.payload['slave_t1'] = str(t1)
myiu.payload['stage'] = '1'
self.ob.add(myiu)
elif iu.payload['slave'] == self.component_name:
if stage=='2':
#print('Received stage 2 from master '+master)
t2 = self.get_time()
self.my_iu.payload.merge({
iu.payload.merge({
'slave_t2':str(t2),
'stage':'3',
})
......
......@@ -4,7 +4,7 @@
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2013 Sociable Agents Group
# Copyright (c) 2009-2022 Sociable Agents Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
......@@ -32,7 +32,6 @@
import time
import logging
import ipaaca
iu_to_write = None
......@@ -69,8 +68,8 @@ while True:
else:
iu.payload = {'a': 'reset'}
except ipaaca.IUUpdateFailedError, e:
ipaaca.logger.warning("Payload update failed (IU changed in the mean time)")
except ipaaca.IUUpdateFailedError as e:
print("Payload update failed (IU changed in the mean time)")
time.sleep(0.1)
exit(0)
......@@ -2,5 +2,5 @@
import ipaaca
print "{this is the IpaacaPython run.py doing nothing at all}"
print("{this is the IpaacaPython run.py doing nothing at all}")
......@@ -2,7 +2,7 @@
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2013 Sociable Agents Group
# Copyright (c) 2009-2022 Sociable Agents Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
......
......@@ -2,7 +2,7 @@
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2013 Sociable Agents Group
# Copyright (c) 2009-2022 Sociable Agents Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
......
......@@ -2,7 +2,7 @@
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2013 Sociable Agents Group
# Copyright (c) 2009-2022 Sociable Agents Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
......
......@@ -2,7 +2,7 @@
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2013 Sociable Agents Group
# Copyright (c) 2009-2022 Sociable Agents Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
......
......@@ -2,7 +2,7 @@
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2013 Sociable Agents Group
# Copyright (c) 2009-2022 Sociable Agents Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of IPAACA, the
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2015 Social Cognitive Systems Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
# http://purl.org/net/ipaaca
#
# This file may be licensed under the terms of of the
# GNU Lesser General Public License Version 3 (the ``LGPL''),
# or (at your option) any later version.
#
# Software distributed under the License is distributed
# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
# express or implied. See the LGPL for the specific language
# governing rights and limitations.
#
# You should have received a copy of the LGPL along with this
# program. If not, go to http://www.gnu.org/licenses/lgpl.html
# or write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The development of this software was supported by the
# Excellence Cluster EXC 277 Cognitive Interaction Technology.
# The Excellence Cluster EXC 277 is a grant of the Deutsche
# Forschungsgemeinschaft (DFG) in the context of the German
# Excellence Initiative.
from __future__ import division, print_function
import sys
import ipaaca
import traceback
import io
def pretty_printed_time(t):
if t<0:
t = -t
sign = '-'
else:
sign = ' '
s = float(t)
h = int(s/3600)
m = int(s/60) - h*60
s -= h*3600 + m*60
ms = int((s-int(s))*1000)
return sign+'%01d:%02d:%02d.%03d'%(h, m, int(s), ms)
REPLACEMENT_COLORS={
'30': 'black',
'31': 'red',
'32': 'green',
'33': 'cyan',
'34': 'blue',
'35': 'brown',
'36': 'magenta',
'37': 'grey',
'248': 'lightgray',
# should add more colors
}
def replace_ansi_html(s):
r = u''
in_esc = False
last_color = u''
#skip_one_double_wide_bar = False
for c in s:
if in_esc:
if c=='m':
in_esc = False
itms = last_color.replace('[','').replace(']','').split(';')
col = None
bold = False
if itms[0]=='':
r += '</code></font><code>'
else:
for i in itms:
if i=='1':
bold = True
elif i in REPLACEMENT_COLORS:
col = REPLACEMENT_COLORS[i]
if col is None:
if bold:
col = 'grey'
else:
col = 'black'
print('Warning: unknown colors '+str(itms))
r += '</code><font color="'+col+'"><code>'
else:
last_color += c
else:
#if c in u'▁▂▃▄▅▆▇█':
# if skip_one_double_wide_bar:
# skip_one_double_wide_bar = False
# else:
# r += c
# skip_one_double_wide_bar = True
#el
if c=='':
in_esc = True
last_color = ''
else:
r += c
return r
def print_header(formt, fields):
s = u''
if formt=='html':
s += '<html><head><meta charset="UTF-8"><title>flexdiam log view</title></head>\n<body>\n<table width="100%" border="1" bordercolor="lightgray" style="white-space:pre">\n<tr>'
for f in fields:
s+='<th>'+f+'</th>'
s += '</tr>'
return s
def print_footer(formt):
s = u''
if formt=='html':
s += '</tr>\n</body>\n</html>'
return s
def print_record(data, delimiter, formt):
if formt=='html':
s = u'<tr>'
for d in data:
d2 = d.replace('<', '&lt;').replace('>', '&gt;').replace('\n', '<br/>').replace('"', '&quot;')
d3 = replace_ansi_html(d2)
#s += u'<td><code>' + d2.replace('<', '&lt;').replace('>', '&gt;').replace('\n', '<br/>') + u'</code></td>'
s += u'<td><code>' + d3 + u'</code></td>'
s += u'</tr>'
return s
else:
return delimiter.join(data)
def modify(key, value, strip=False, pretty_printed_times=False, time_offset=0.0):
if key=='time':
f = float(value.strip()) - time_offset
return pretty_printed_time(f) if pretty_printed_times else str(f)
else:
return value.strip() if strip else value
if __name__=='__main__':
try:
iap = ipaaca.IpaacaArgumentParser('ipaaca-logcat')
iap.add_argument(
'-s', '--strip-fields',
dest='strip', action='store_true',
default=False,
help='Strip leading/trailing whitespace from all fields')
iap.add_argument(
'-p', '--pretty-printed-times',
dest='pretty_printed_times', action='store_true',
default=False,
help='Print human-readable times (hh:mm:ss.ms) instead of float seconds')
iap.add_argument(
'--format',
dest='format', nargs=1,
default=['plain'],
help='output format (plain, html) (default plain)')
iap.add_argument(
'-o', '--output-file',
dest='output_file', nargs=1,
default=['-'],
help='output file name (default \'-\' -> standard terminal output)')
iap.add_argument(
'-d', '--delimiter',
dest='delimiter', nargs=1,
default=['\t'],
help='field delimiter, interpreted as python unicode string (default \'\\t\')')
iap.add_argument(
'-t', '--align-times',
dest='align_times', nargs=2,
default=['0', '0'],
help='Calculate relative output timestamps (default: 0 0 => keep)\nFirst argument is a reference event timestamp from the log file\nSecond argument is the new output time for that same event')
iap.add_argument(
'-f', '--fields',
dest='fields', default=['time', 'text'], nargs='+',
help='fields to print (defaults: \'time\' \'text\')')
arguments = iap.parse_args()
delimiter = eval("u'"+arguments.delimiter[0]+"'", {"__builtins__":None}, {} )
ref_t, out_t = float(arguments.align_times[0]), float(arguments.align_times[1])
time_offset = ref_t - out_t
#print(arguments); sys.exit(1)
#modify = (lambda s: s.strip()) if arguments.strip else (lambda s: s)
#modify = lambda s: type(s).__name__
fil = sys.stdout
if arguments.output_file[0] != '-':
fil = io.open(arguments.output_file[0], 'w', encoding='utf8')
fil.write(print_header(arguments.format[0], arguments.fields)+'\n')
for line in sys.stdin:
record = eval(line.strip(), {"__builtins__":None}, {} )
data = [modify(f, unicode(record[f]), arguments.strip, arguments.pretty_printed_times, time_offset) for f in arguments.fields]
u = print_record(data, delimiter, arguments.format[0])
res = u'{}'.format(u) #.decode('utf-8')
fil.write(u''+res+'\n' )
fil.write(print_footer(arguments.format[0])+'\n')
if fil != sys.stdout: fil.close()
except (KeyboardInterrupt, SystemExit):
pass # ret below
except Exception, e:
print(u'Exception: '+unicode(traceback.format_exc()))
ipaaca.exit(1)
ipaaca.exit(0)
......@@ -31,7 +31,7 @@
# Forschungsgemeinschaft (DFG) in the context of the German
# Excellence Initiative.
from __future__ import division, print_function
#from __future__ import division, print_function
import itertools
import os
......@@ -43,7 +43,10 @@ import ipaaca
def iu_update_handler(iu, event_type, local):
print(event_type + ': ' + str(iu))
try:
print(event_type + ': ' + str(iu))
except:
print(u"An error occurred printing an IU for an event of type "+event_type)
parser = ipaaca.IpaacaArgumentParser(description='Ipaaca IU Injector -- Sent ipaaca messages or IUs from the command line')
......@@ -83,22 +86,24 @@ parser.add_argument(
if __name__ == '__main__':
arguments = parser.parse_args()
print('BackEnd is '+str(ipaaca.backend.get_default_backend().name))
ob = ipaaca.OutputBuffer('IpaacaIUInjector')
ob.register_handler(iu_update_handler)
iu = ipaaca.Message(arguments.category) if arguments.iu_type == 'Message' else ipaaca.IU(arguments.category)
if arguments.json_payload:
# Treat payload values as Python expressions
iu.payload = {k: eval(v) for (k, v) in itertools.izip_longest(arguments.payload[::2], arguments.payload[1::2])}
iu.payload = {k: eval(v) for (k, v) in itertools.zip_longest(arguments.payload[::2], arguments.payload[1::2])}
else:
iu.payload = {k: v for (k, v) in itertools.izip_longest(arguments.payload[::2], arguments.payload[1::2])}
iu.payload = {k: v for (k, v) in itertools.zip_longest(arguments.payload[::2], arguments.payload[1::2])}
ob.add(iu)
print(
'Sent {iu_type} with category "{category}" and payload {{'.format(**vars(arguments)),
u'Sent {iu_type} with category "{category}" and payload {{'.format(**vars(arguments)),
end='\n' if len(iu.payload) > 0 else '')
for k, v in iu.payload.items():
print(" '{key}': {value},".format(key=k, value=v))
print('}.')
print(u" '{key}': {value},".format(key=k, value=v))
print(u'}.')
# Wait for updates to the IU
try:
......@@ -109,8 +114,7 @@ if __name__ == '__main__':
time.sleep(0.1)
except KeyboardInterrupt:
pass
if platform.system() == 'Windows':
os._exit(0)
else:
sys.exit(0)
except Exception as e:
print(u'Exception: '+str(traceback.format_exc()))
ipaaca.exit(1)
ipaaca.exit(0)
......@@ -31,7 +31,7 @@
# Forschungsgemeinschaft (DFG) in the context of the German
# Excellence Initiative.
from __future__ import division, print_function
#from __future__ import division, print_function
import logging
import os
......@@ -51,20 +51,23 @@ def event_type_color(typ):
'MESSAGE': '34;1',
'COMMITTED': '35;1',
'LINKSUPDATED': '36;1',
'RETRACTED': '37;1',
'RETRACTED': '37',
}
return colors.get(typ, '1')
def highlight_if_color(s, c='1'):
return s if not arguments.color else '[' + c + 'm' + s +''
return s if arguments.color else '[' + c + 'm' + s +''
def pretty_printed_dict(d):
s='{\n'
for k, v in d.items():
v = str(v)
if isinstance(v, str) or isinstance(v, str):
v = "'"+str(v)+"'"
else:
v = str(v)
v2 = v if len(v) <= arguments.max_size else v[:arguments.max_size] + '<excess length omitted>'
v2.replace('\\','\\\\').replace('\n', highlight_if_color('\\n'))
s += "\t '%s': '%s',\n" % (highlight_if_color(unicode(k),'1'), unicode(v2))
s += "\t '%s': %s,\n" % (highlight_if_color(str(k),'1'), str(v2))
s+='}'
return s
......@@ -75,7 +78,8 @@ def pretty_printed_iu_event(iu, event_type, local):
s += highlight_if_color('%.3f' % t, '1')
s += ' %02d:%02d:%02d' % (lt.tm_hour, lt.tm_min, lt.tm_sec)
s += ' ' + highlight_if_color('%-9s' % event_type, event_type_color(event_type))
s += ' category=' + highlight_if_color(iu.category,event_type_color(event_type))
s += ' category=' + highlight_if_color(iu.category,event_type_color(event_type))
s += ' channel=' + iu.buffer._channel
s += ' uid=' + iu.uid
s += ' owner=' + iu.owner_name
if event_type is not 'MESSAGE':
......@@ -83,7 +87,7 @@ def pretty_printed_iu_event(iu, event_type, local):
s += '\npayload=' + pretty_printed_dict(iu.payload)
return s
def my_update_handler(iu, event_type, local):
def iu_event_handler(iu, event_type, local):
if arguments.regex:
for cat in arguments.categories: # actually now regexs, not categories
if re.match(cat, iu.category):
......@@ -92,19 +96,14 @@ def my_update_handler(iu, event_type, local):
return
print(pretty_printed_iu_event(iu, event_type, local), end='\n\n')
def exit(code):
ipaaca.exit(code)
#if platform.system() == 'Windows':
# os._exit(code)
#else:
# sys.exit(code)
parser = ipaaca.IpaacaArgumentParser(description='Ipaaca IU Sniffer -- Selectively listen to IPAACA traffic')
parser.add_argument(
'-r', '--regex',
action='store_true',
dest='regex',
help='match categories by regular expressions')
parser.add_argument(
'-c', '--color',
action='store_true',
dest='color',
help='colorize output')
parser.add_argument(
'--channels',
dest='channels',
......@@ -113,12 +112,29 @@ parser.add_argument(
nargs='+',
help="set the channels to listen on (otherwise 'default')")
parser.add_argument(
'--categories',
'-c', '--categories',
default=[''],
dest='categories',
metavar='CATEGORY',
nargs='+',
help='set categories (or regex patterns) to be matched')
parser.add_argument(
'-e', '--event-types',
default=None,
dest='event_types',
metavar='EVENT-TYPE',
nargs='+',
help='set event types ({})'.format(' '.join(ipaaca.iu.IUEventType._choices)))
parser.add_argument(
'-r', '--regex',
action='store_true',
dest='regex',
help='match categories by regular expressions')
parser.add_argument(
'--no-color',
action='store_true',
dest='color',
help='do not colorize output')
parser.add_argument(
'--size-limit',
default=2048,
......@@ -130,37 +146,61 @@ parser.add_argument(
if __name__ == '__main__':
arguments = parser.parse_args()
buffers = {}
backend_name = str(ipaaca.backend.get_default_backend().name)
print('BackEnd is '+backend_name)
universal_listener_category = ''
if backend_name == 'mqtt':
universal_listener_category = '#'
if arguments.categories == ['']: arguments.categories = ['#']
elif backend_name == 'ros':
if arguments.categories == [''] or arguments.regex:
print('ATTENTION: listening to all categories not implemented for ROS back-end!')
print(' (By extension, the same goes for filtering all categories by regex.)')
print(' !! You will receive nothing, please provide fixed category names. !!')
# Create one input buffer for each channel we are listening on
for channel in arguments.channels:
buffers[channel] = ipaaca.InputBuffer(
'IpaacaIUSniffer',
category_interests=arguments.categories if not arguments.regex else [''],
category_interests=arguments.categories if not arguments.regex else [universal_listener_category],
channel=channel,
resend_active=True)
buffers[channel].register_handler(my_update_handler)
channellist = 's ' if len(arguments.channels) > 1 else ' '
channellist += ', '.join(arguments.channels)
print('Listening on channel' + channellist + ' for IU events of ', end='')
if arguments.categories == ['']:
print('any category ...')
# Check whether the specified event_types are valid
if arguments.event_types is not None:
for et in arguments.event_types:
if et.upper() not in ipaaca.iu.IUEventType._choices:
print('ERROR: "{et}" is not a valid IPAACA event type.'.format(et=et.upper()))
exit(code=1)
buffers[channel].register_handler(
iu_event_handler,
for_event_types=[et.upper() for et in arguments.event_types] if arguments.event_types is not None else None)
# Tell user what we are doing
print('ipaaca-iu-sniffer listening')
print(' * on channel(s): ' + ', '.join(arguments.channels))
print(' * for event type(s): ', end='')
if arguments.event_types is None:
print('any')
else:
print(', '.join([highlight_if_color(et.upper(), event_type_color(et.upper())) for et in arguments.event_types]))
print(' * for category/ies', end='')
if arguments.categories == [universal_listener_category]:
print(': any')
else:
if arguments.regex:
print('whose category matches one of the regexes:')
else:
print('categories:')
print('\t' + ', '.join(arguments.categories))
print('')
print(' that match the regex', end='')
print(': ' + ', '.join(arguments.categories))
# Wait for the user to kill the sniffer
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
if platform.system() == 'Windows':
os._exit(0)
else:
sys.exit(0)
\ No newline at end of file
except Exception as e:
print(u'Exception: '+str(traceback.format_exc()))
ipaaca.exit(1)
ipaaca.exit(0)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of IPAACA, the
# "Incremental Processing Architecture
# for Artificial Conversational Agents".
#
# Copyright (c) 2009-2015 Social Cognitive Systems Group
# CITEC, Bielefeld University
#
# http://opensource.cit-ec.de/projects/ipaaca/
# http://purl.org/net/ipaaca
#
# This file may be licensed under the terms of of the
# GNU Lesser General Public License Version 3 (the ``LGPL''),
# or (at your option) any later version.
#
# Software distributed under the License is distributed
# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
# express or implied. See the LGPL for the specific language
# governing rights and limitations.
#
# You should have received a copy of the LGPL along with this
# program. If not, go to http://www.gnu.org/licenses/lgpl.html
# or write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The development of this software was supported by the
# Excellence Cluster EXC 277 Cognitive Interaction Technology.
# The Excellence Cluster EXC 277 is a grant of the Deutsche
# Forschungsgemeinschaft (DFG) in the context of the German
# Excellence Initiative.
from __future__ import division, print_function
import sys
import time
import ipaaca
import ipaaca.util.logger as ipaacalog
def main(log_mode, filename=None):
ipaacalog.logger_send_ipaaca_logs(False)
il = ipaacalog.LoggerComponent(filename, log_mode)
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
il.close_logfile()
print('Logging-Component closed by keyboard interrupt.')
if __name__ == '__main__':
import traceback
try:
iap = ipaaca.IpaacaArgumentParser(
'ipaaca-logger')
iap.add_argument(
'-m', '--log-mode', dest='log_mode',
choices=ipaacalog.LOG_MODES,
default='append',
help="set what to do when logfile exists "
"(default: 'append'; 'timestamp' adds timestamp in any case)")
iap.add_argument(
'filename', nargs='?',
metavar='FILE',
help='set name of logfile')
arguments = iap.parse_args()
main(arguments.log_mode, arguments.filename)
except KeyboardInterrupt:
pass
except Exception, e:
print(u'Exception: '+unicode(traceback.format_exc()))
ipaaca.exit(1)
ipaaca.exit(0)
#!/usr/bin/env python
import ipaaca
import time
class PingSender(object):
def __init__(self):
self.pings = []
self.times = []
self.ob = ipaaca.OutputBuffer('IpaacaPing')
self.ob.register_handler(self.iu_event_handler)
def iu_event_handler(self, iu, event_type, local):
recv_t = time.time()
if event_type=='UPDATED':
print('OK')
send_t = float(iu.payload['sender_local_t'])
receiver_recv_t = float(iu.payload['receiver_local_t'])
round_trip_t = recv_t - send_t
locally_estimated_receiver_recv_t = (recv_t + send_t) / 2
estimated_clock_skew = receiver_recv_t - locally_estimated_receiver_recv_t
self.times.append(estimated_clock_skew)
average_clock_difference = sum(self.times) / len(self.times)
self.pings.append(500.0 * round_trip_t)
average_estimated_single_trip = sum(self.pings) / len(self.pings)
print('Received ping reply')
print(' measured round trip time [ms]: %0.3f'%(1000.0 * round_trip_t))
print(' estimated single trip [ms]: %0.3f'%(500.0 * round_trip_t))
print(' averaged single trip [ms]: %0.3f'%(average_estimated_single_trip))
print(' estimated system clock difference [s]: %0.3f'%(average_clock_difference))
def send_ping(self):
t = time.time()
iu = ipaaca.IU('ipaacaPing')
iu.payload['sender_local_t'] = t
self.ob.add(iu)
iap = ipaaca.IpaacaArgumentParser('ipaaca-ping')
arguments = iap.parse_args()
ps = PingSender()
while True:
ps.send_ping()
time.sleep(1)
#!/usr/bin/env python
import ipaaca
import time
def iu_event_handler(iu, event_type, local):
if event_type=='ADDED':
iu.payload['receiver_local_t'] = time.time()
print('Sent IPAACA ping reply')
iap = ipaaca.IpaacaArgumentParser('ipaaca-pong')
arguments = iap.parse_args()
ib = ipaaca.InputBuffer('IpaacaPong', ['ipaacaPing'])
ib.register_handler(iu_event_handler)
while True:
time.sleep(1)