Example #1
0
    def _update(self, searchTuples, args, objectName):
        """
        A sub function that updates the object if it exists
        """

        obj = Object(self.cnx, objectName)
        commonName = self.common[objectName]
        results = obj.search(searchTuples)
        arguments = self.__parse_options(args)
        if results:
            if isinstance(results, list):
                results = results
            else:
                results = [results]
            if len(results) == 1:
                if obj.write(results, arguments):
                    return results[0]

                else:
                    raise EnvironmentError("We attempted to update a  " + \
                        + commonName + \
                        " , but failed.")
            else:
                string = ":"
                for obj in results:
                    string += str(obj) + ", "

                string += " Search: "
                for obj in searchTuples:
                    string += str(obj) + ", "

                raise ValueError("We preformed a search for a " + commonName + \
                    "and came back with a number greater than one." \
                    + string)
Example #2
0
    def _update_no_search(self, id, args, objectName):
        """
        To update an object when we already know the id
        """

        obj = Object(self.cnx, objectName)
        commonName = self.common[objectName]
        results = id
        arguments = self.__parse_options(args)
        if results:
            if isinstance(results, list):
                results = results
            else:
                results = [results]
            if len(results) == 1:
                if obj.write(results, arguments):
                    return results[0]

                else:
                    raise EnvironmentError("We attempted to update a  " + \
                        + commonName + \
                       " , but failed.")
            else:
                string = ""
                for obj in results:
                    string += obj

                raise ValueError("We preformed a search for a " + commonName + \
                                "and came back with a number greater than one." \
                                + string)
Example #3
0
def execute_import(filename,
                   connection,
                   separator=',',
                   transaction=False,
                   error_stop=False):
    """
    Read the file, and launched import_data
    """
    model = filename.split('/').pop().replace('.csv', '')
    if model.find('_') > 4:
        model = model[model.find('-') + 1:model.find('_')]
    else:
        model = model[model.find('-') + 1:]
    logger.debug('model: %s' % model)

    obj = Object(connection, model)

    logger.info('Read and analyse the file content')
    fp = open(filename, 'r')
    header = False
    lines = []
    count = 0
    reader = csv.reader(fp, delimiter=separator)
    for line in reader:
        count += 1
        if not header:
            header = line
            logger.debug('header: %s' % str(header))
            continue

        lines.append(line)
        logger.debug('line: %s' % str(line))
    logger.info('Read the file content is finished')

    logger.info('Start import the content in OpenERP (%d datas)' % len(lines))
    count = 0
    ctx = {
        'defer_parent_store_computation': True,
        'lang': opts.lang,
        'import': True,
    }
    if opts.inactive:
        ctx['active_test'] = False
    print ctx
    if transaction:
        try:
            logger.info('Import %s lines in one transaction' % len(lines))
            res = obj.import_data(header, lines, 'init', '', False, ctx)
            if res[0] == -1:
                logger.error('%s' % res[2])
                logger.error('%s' % str(res[1]))
            logger.info('End transaction import')
        except Exception, e:
            logger.error(str(e))
            if error_stop:
                raise StopError(str(e))
Example #4
0
    def readdir(self, path, offset):
        """
        Return content of a directory :
            - List models for root path
            - List records for a model
            - List attachments for a record
        We don't have to check for the path, because getattr already returns -ENOENT if the model/record/attachment doesn't exist
        """
        yield fuse.Direntry('.')
        yield fuse.Direntry('..')

        paths = path.split('/')[1:]
        # List models
        if path == '/':
            model_obj = Object(self.oerp_connection, 'ir.model')
            model_ids = model_obj.search([])
            for model_data in model_obj.read(model_ids, ['model']):
                yield fuse.Direntry(model_data['model'])
        # List records
        elif len(paths) == 1:
            element_obj = Object(self.oerp_connection, paths[0])
            element_ids = element_obj.search([])
            for element_data in element_obj.read(element_ids, ['id']):
                yield fuse.Direntry(str(element_data['id']))
        # List attachments
        else:
            attachment_obj = Object(self.oerp_connection, 'ir.attachment')
            attachment_ids = attachment_obj.search([('res_model', '=', paths[0]), ('res_id', '=', int(paths[1]))])
            for attachment_data in attachment_obj.read(attachment_ids, ['name']):
                yield fuse.Direntry('%d-%s' % (attachment_data['id'], attachment_data['name']))
Example #5
0
    def _exists(self, searchTuples, objectName):
        """
        Returns true if the search has a result.
        """

        obj = Object(self.cnx, objectName)
        try:
            if obj.search(searchTuples):
                return True
        except:
            return False
Example #6
0
 def read(self, path, size, offset):
     """
     Return the specified slide of a file
     Note : Only the beginning of the name is required (the ID of the attachment), we can put anything after the first '-', it will be ignored
     """
     paths = path.split('/')[1:]
     # TODO : Create a module that allows to read files by slides
     attachment_obj = Object(self.oerp_connection, 'ir.attachment')
     attachment_ids = attachment_obj.search([('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])), ('id', '=', self.id_from_label(paths[2]))])
     attachment_data = attachment_obj.read(attachment_ids, ['datas'])
     return base64.b64decode(attachment_data[0]['datas'])[offset:offset + size]
Example #7
0
    def _copy_with_args(self, searchTuples, searchExists, args, objectName):
        """
        Does a copy and then adds some extra information.
        """
        obj = Object(self.cnx, objectName)
        results = obj.search(searchTuples)
        new_id = obj.copy(results[0])

        if self._exists(searchExists, objectName):
            return True
        else:
            return self._update_no_search(new_id, args, objectName)
Example #8
0
    def _get_period(self, date):
        d = str(date.date())
        obj = Object(self.cnx, 'account.period')

        ids = obj.search([("date_start", "<=", d), ("date_stop", ">=", d),
            ("state", "=", "draft"), ("special", "=", False)])

        if len(ids) == 1:
            return ids[0]
        else:
            raise ValueError(
                "Did not find a single open period with that date, %s" % d)
Example #9
0
def execute_import(filename, connection, separator=',', transaction=False, error_stop=False):
    """
    Read the file, and launched import_data
    """
    model = filename.split('/').pop().replace('.csv', '')
    if model.find('_') > 4:
        model = model[model.find('-') + 1:model.find('_')]
    else:
        model = model[model.find('-') + 1:]
    logger.debug('model: %s' % model)

    obj = Object(connection, model)

    logger.info('Read and analyse the file content')
    fp = open(filename, 'r')
    header = False
    lines = []
    count = 0
    reader = csv.reader(fp, delimiter=separator)
    for line in reader:
        count += 1
        if not header:
            header = line
            logger.debug('header: %s' % str(header))
            continue

        lines.append(line)
        logger.debug('line: %s' %str(line))
    logger.info('Read the file content is finished')

    logger.info('Start import the content in OpenERP (%d datas)' % len(lines))
    count = 0
    ctx = {
        'defer_parent_store_computation': True,
        'lang': opts.lang,
        'import': True,
    }
    if opts.inactive:
        ctx['active_test'] = False
    print ctx
    if transaction:
        try:
            logger.info('Import %s lines in one transaction' % len(lines))
            res = obj.import_data(header, lines, 'init', '', False, ctx)
            if res[0] == -1:
                logger.error('%s' % res[2])
                logger.error('%s' % str(res[1]))
            logger.info('End transaction import')
        except Exception, e:
            logger.error(str(e))
            if error_stop:
                raise StopError(str(e))
Example #10
0
    def _get_attr(self, searchTuples, objectName, attribute):
        """
        returns value of the attribute
        """
        obj = Object(self.cnx, objectName)
        results = obj.search(searchTuples)

        if len(results) != 1:
            raise ValueError("We did not get a single " + \
                self.common[objectName] + " back. " + \
                str(results))
        else:
            return obj.read(results[0])[attribute]
Example #11
0
    def _get(self, searchTuples, objectName):
        """
        returns the object id as int iff the search returns a single result.
        """
        obj = Object(self.cnx, objectName)
        results = obj.search(searchTuples)

        if len(results) != 1:
            raise ValueError("We did not get a single " + \
                self.common[objectName] + " back. " + \
                str(results) + str(searchTuples))
        else:
            return results[0]
Example #12
0
 def read(self, path, size, offset):
     """
     Return the specified slide of a file
     Note : Only the beginning of the name is required (the ID of the attachment), we can put anything after the first '-', it will be ignored
     """
     paths = path.split('/')[1:]
     # TODO : Create a module that allows to read files by slides
     attachment_obj = Object(self.oerp_connection, 'ir.attachment')
     attachment_ids = attachment_obj.search([
         ('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])),
         ('id', '=', self.id_from_label(paths[2]))
     ])
     attachment_data = attachment_obj.read(attachment_ids, ['datas'])
     return base64.b64decode(attachment_data[0]['datas'])[offset:offset +
                                                          size]
Example #13
0
    def _create(self, args, objectName):
        """
        To create a new object, pass in a dictionary of objects and use the
        objectName to create the object.
        """

        arguments = self.__parse_options(args)

        obj = Object(self.cnx, objectName)

        objectCreated = obj.create(arguments)

        if objectCreated:
            return objectCreated
        else:
            raise EnvironmentError("We attempted to create a " + \
               self.common[objectName] + " but failed.")
Example #14
0
    def getattr(self, path):
        """
        Return attributes for the specified path :
            - Search for the model as first part
            - Search for an existing record as second part
            - Search for an existing attachment as third part
            - There cannot be more than 3 parts in the path
        """
        fakeStat = fuse.Stat()
        fakeStat.st_mode = stat.S_IFDIR | 0400
        fakeStat.st_nlink = 0

        if path == '/':
            return fakeStat

        paths = path.split('/')[1:]
        if len(paths) > 3:
            return -ENOENT

        # Check for model existence
        model_obj = Object(self.oerp_connection, 'ir.model')
        model_ids = model_obj.search([('model', '=', paths[0])])
        if not model_ids:
            return -ENOENT
        elif len(paths) == 1:
            return fakeStat

        # Check for record existence
        element_obj = Object(self.oerp_connection, paths[0])
        element_ids = element_obj.search([('id', '=', int(paths[1]))])
        if not element_ids:
            return -ENOENT
        elif len(paths) == 2:
            return fakeStat

        # Chech for attachement existence
        attachment_obj = Object(self.oerp_connection, 'ir.attachment')
        attachment_ids = attachment_obj.search([('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])), ('id', '=', self.id_from_label(paths[2]))])
        if not attachment_ids:
            return -ENOENT

        # Common stats
        fakeStat.st_mode = stat.S_IFREG | 0400
        fakeStat.st_nlink = 2

        # TODO : Read the file size from a dedicated field (created in a specific module)
        attachment_obj = Object(self.oerp_connection, 'ir.attachment')
        attachment_ids = attachment_obj.search([('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])), ('id', '=', self.id_from_label(paths[2]))])
        attachment_data = attachment_obj.read(attachment_ids, ['datas'])
        fakeStat.st_size = len(base64.b64decode(attachment_data[0]['datas']))
        return fakeStat
Example #15
0
    def release(self, path, fh):
        """
        Writing of the file is finished, import the contents into OpenERP
        """
        # FIXME : Don't know why it doesn't work without rebuilding the StringIO object...
        value = StringIO(self.files[path].getvalue())

        # Parse the CSV file contents
        csvFile = csv.reader(value)
        lines = list(csvFile)

        # Import data into OpenERP
        model = path.replace('.csv', '')[1:]
        oerpObject = Object(self.oerp_connection, model)
        oerpObject.import_data(lines[0], lines[1:], 'init', '', False, {'import': True})

        # Close StringIO and free memory
        self.files[path].close()
        del self.files[path]
        value.close()
        del value
        return True
Example #16
0
    def release(self, path, fh):
        """
        Writing of the file is finished, import the contents into OpenERP
        """
        # FIXME : Don't know why it doesn't work without rebuilding the StringIO object...
        value = StringIO(self.files[path].getvalue())

        # Parse the CSV file contents
        csvFile = csv.reader(value)
        lines = list(csvFile)

        # Import data into OpenERP
        model = path.replace('.csv', '')[1:]
        oerpObject = Object(self.oerp_connection, model)
        oerpObject.import_data(lines[0], lines[1:], 'init', '', False,
                               {'import': True})

        # Close StringIO and free memory
        self.files[path].close()
        del self.files[path]
        value.close()
        del value
        return True
logger.info('Field: %s' % (opts.field,))

try:
    logger.info('Open connection to "%s:%s" on "%s" with user "%s" ' % (opts.server, opts.port, opts.dbname, opts.user))
    cnx = Connection(
        server=opts.server,
        dbname=opts.dbname,
        login=opts.user,
        password=opts.passwd,
        port=opts.port)
except Exception, e:
    logger.error('Fail to connect to the server')
    logger.error('%s' % str(e))
    sys.exit(1)

model = Object(cnx, opts.model)
model_ids = model.search([])
model_lists = model.read(model_ids, [opts.field,'parent_left','parent_right'])
models = dict(map(lambda x: (x['id'],x), model_lists))
try:
    for a in model_lists:
        logger.debug('id: %d' % a['id'])
        if a[opts.field]:
            assert a['parent_left'] > models[a[opts.field][0]]['parent_left'], '%s > %s' % (a['parent_left'], models[a[opts.field][0]]['parent_left'])
            assert a['parent_right'] < models[a[opts.field][0]]['parent_right'], '%s > %s' % (a['parent_right'], models[a[opts.field][0]]['parent_right'])
        assert a['parent_left'] < a['parent_right']
        for a2 in model_lists:
            assert not ((a2['parent_right']>a['parent_left']) and 
                (a2['parent_left']<a['parent_left']) and 
                (a2['parent_right']<a['parent_right']))
            if a2[opts.field]==a['id']:
Example #18
0
                 default='',
                 help='Enter list of companies, seprate by a comma (,)')
parser.add_option_group(group)

opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server,
                     dbname=opts.dbname,
                     login=opts.user,
                     password=opts.passwd)
except Exception, e:
    print '%s' % str(e)
    exit(1)

user = Object(cnx, 'res.users')
multi = Object(cnx, 'res.company')

user_id = user.search([('login', '=', opts.user)])[0]
# save company_id to restore it after
curr = user.read(user_id, ['company_ids', 'company_id'])
c_save_id = curr['company_id']
print 'User: %d => %s (id %d)' % (user_id, c_save_id[1], c_save_id[0])

##
# If the company argument is missing, retrieve all companies in the user form
#
if opts.company:
    companies = opts.company.split(',')
else:
    companies = curr['company_ids']
Example #19
0
    def __init__(self, stdscr):
        """
        Initialize the sentinel program
        """
        # Read user configuration
        config = ConfigParser.SafeConfigParser(DEFAULT_CONFIG)
        config.read('.oerp_sentinelrc')

        # No configfile found, exit
        if not 'openerp' in config.sections():
            raise Exception('Config Error', 'Config file not found !')

        # Connection to the OpenERP Server
        self.connection = Connection(
            server=config.get('openerp', 'host'),
            dbname=config.get('openerp', 'database'),
            login=config.get('openerp', 'user'),
            password=config.get('openerp', 'password'),
            port=config.get('openerp', 'port'),
        )

        # Initialize translations
        context = Object(self.connection, 'res.users').context_get()
        lang = context.get('lang', I18N_DEFAULT)
        gettext.install(I18N_DOMAIN)
        try:
            language = gettext.translation(I18N_DOMAIN,
                                           I18N_DIR,
                                           languages=[lang])
        except:
            language = gettext.translation(I18N_DOMAIN,
                                           I18N_DIR,
                                           languages=[I18N_DEFAULT])
        language.install()

        # Initialize hardware
        self.hardware_obj = Object(self.connection, 'scanner.hardware')

        # Initialize window
        self.screen = stdscr
        self._set_screen_size()

        self._init_colors()

        # Get the informations for this material from server (identified by IP)
        self.hardware_code = ''
        self.scenario_id = False
        try:
            ssh_data = os.environ['SSH_CONNECTION'].split(' ')
            self.hardware_code = ssh_data[0]
            self.scenario_id = self.hardware_obj.scanner_check(
                self.hardware_code)
        except:
            self.hardware_code = self._input_text(
                _('Autoconfiguration failed !\nPlease enter terminal code'))
            self.scenario_id = self.hardware_obj.scanner_check(
                self.hardware_code)

        # Resize window to terminal screen size
        self._resize()

        # Reinit colors with values configured in OpenERP
        self._reinit_colors()

        # Initialize mouse events capture
        curses.mousemask(curses.BUTTON1_CLICKED
                         | curses.BUTTON1_DOUBLE_CLICKED)

        # Load the sentinel
        self.main_loop()
"""

import sys

sys.path.append("../")

from oobjlib.connection import Connection
from oobjlib.component import Object
from oobjlib.common import GetParser

parser = GetParser("Module List", "0.1")
opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user, password=opts.passwd, port=opts.port)
except Exception, e:
    print "%s" % str(e)
    exit(1)

modules = Object(cnx, "ir.module.module")
print "--[Connection Object]---------------------"
print "%s" % str(modules)

ids = modules.search([("state", "=", "installed")])
print "--[Module list]---------------------------"
for p in modules.read(ids, ["name"]):
    print "* %s" % p["name"]

print "--[End]-----------------------------------"
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
Example #21
0
try:
    cnx = Connection(server=opts.server,
                     dbname=opts.dbname,
                     login=opts.user,
                     password=opts.passwd,
                     port=opts.port)
except Exception, e:
    print '%s' % str(e)
    exit(1)

if not opts.service:
    print '--service argument is required!'
    exit(1)

jasper_obj = Object(cnx, 'jasper.document')
label_obj = Object(cnx, 'jasper.document.label')

root = Element(
    'jasperReport', {
        'name': 'to_be_defined',
        'language': 'groovy',
        'pageWidth': '595',
        'pageHeight': '842',
        'columnWidth': '555',
        'leftMargin': '20',
        'rightMargin': '20',
        'topMargin': '20',
        'bottomMargin': '20'
    })
#root.set('name', 'to_be_defined')
try:
    cnx = Connection(server=opts.server,
                     dbname=opts.dbname,
                     login=opts.user,
                     password=opts.passwd,
                     port=opts.port)
except Exception, e:
    print '%s' % str(e)
    exit(1)

if not opts.filename:
    print '--file argument is required!'
    exit(1)

jasper_obj = Object(cnx, 'jasper.document')
label_obj = Object(cnx, 'jasper.document.label')

fp = open(opts.filename, 'r')
reader = csv.DictReader(fp, delimiter=',')

service_cache = {}


def format_code(code):
    code = code.upper()
    code = code.replace(' ', '_')
    return code


for l in reader:
Example #23
0
    logger.error('%s' % str(e))
    sys.exit(1)


def normalize_name(name):
    """
    Replace all non alphanumeric characters by underscores
    """
    return re.sub(r'[^\w\d]', '_', name).lower()


resid = {}
opts.directory = os.path.expanduser(opts.directory)

# extract scenario
scenario_obj = Object(cnx, 'scanner.scenario')
model_obj = Object(cnx, 'ir.model')
warehouse_obj = Object(cnx, 'stock.warehouse')
user_obj = Object(cnx, 'res.users')
group_obj = Object(cnx, 'res.groups')
scen_read = scenario_obj.read(int(opts.scenario_id), [], '_classic_read',
                              {'active_test': False})
scen_read = scen_read and scen_read[0]
if not scen_read:
    logger.error('Scenario ID %s not found' % opts.scenario_id)
    sys.exit(1)
del scen_read['step_ids']

field_to_remove = [
    'create_uid', 'create_date', 'write_uid', 'write_date', '__last_update',
    'display_name'
    def __init__(self, stdscr):
        """
        Initialize the sentinel program
        """
        # Read user configuration
        config = ConfigParser.SafeConfigParser(DEFAULT_CONFIG)
        self.datadir = os.path.expanduser("~/")
        config.read([
            '.oerp_sentinelrc',
            '.openerp_sentinelrc',
            '.odoo_sentinelrc',
            os.path.join(self.datadir, '.oerp_sentinelrc'),
            os.path.join(self.datadir, '.openerp_sentinelrc'),
            os.path.join(self.datadir, '.odoo_sentinelrc'),
        ])

        # No configfile found, exit
        if 'openerp' not in config.sections():
            raise Exception('Config Error', 'Config file not found !')

        # Connection to the OpenERP Server
        self.connection = Connection(
            server=config.get('openerp', 'host'),
            dbname=config.get('openerp', 'database'),
            login=config.get('openerp', 'user'),
            password=config.get('openerp', 'password'),
            port=config.get('openerp', 'port'),
        )

        # Open the test file, if any
        test_file_name = config.get('openerp', 'test_file')
        self.test_file = None
        if test_file_name:
            self.test_file = open(test_file_name, 'r')

        # Initialize translations
        self.context = Object(self.connection, 'res.users').context_get()
        lang = self.context.get('lang', I18N_DEFAULT)
        gettext.install(I18N_DOMAIN)
        try:
            language = gettext.translation(
                I18N_DOMAIN, I18N_DIR, languages=[lang])
        except:
            language = gettext.translation(
                I18N_DOMAIN, I18N_DIR, languages=[I18N_DEFAULT])

        # Replace global dummy lambda by the translations gettext method
        # The install method of gettext doesn't replace the function if exists
        global _
        _ = language.gettext

        # Initialize hardware
        self.hardware_obj = Object(self.connection, 'scanner.hardware')
        self.scenario_obj = Object(self.connection, 'scanner.scenario')

        # Initialize window
        self.screen = stdscr
        self._set_screen_size()

        self._init_colors()

        # Get the informations for this material from server (identified by IP)
        self.hardware_code = ''
        self.scenario_id = False
        self.scenario_name = False
        try:
            ssh_data = os.environ['SSH_CONNECTION'].split(' ')
            self.hardware_code = ssh_data[0]
            self.scanner_check()
        except:
            self.hardware_code = self._input_text(
                _('Autoconfiguration failed !\nPlease enter terminal code'))
            self.scanner_check()

        # Resize window to terminal screen size
        self._resize()

        # Reinit colors with values configured in OpenERP
        self._reinit_colors()

        # Initialize mouse events capture
        curses.mousemask(
            curses.BUTTON1_CLICKED | curses.BUTTON1_DOUBLE_CLICKED)

        # Reinitialize to the main menu when using a test file (useful when
        # the last run has crashed before end)
        if test_file_name:
            self.oerp_call('end')

        # Load the sentinel
        self.main_loop()
                help='Indicate the version of OpenERP (5 or 6)')
parser.add_option_group(group)
opts, args = parser.parse_args()

try:
    cnx = Connection(
        server=opts.server,
        dbname=opts.dbname,
        login=opts.user,
        password=opts.passwd,
        port=opts.port)
except Exception, e:
    print '%s' % str(e)
    sys.exit(1)

mod = Object(cnx, 'ir.model')

if opts.oerp_version == '5':
    print 'version 5'
    model = mod.search([])
else:
    print 'version 6'
    model = mod.search([('osv_memory', '=', False)])


print 80 * '-'
print '| Model                                         | Search |  Read  | View XML |'
print 80 * '-'

footer = '--- FOOTER REPORT ---\n'
Example #26
0
    def getattr(self, path):
        """
        Return attributes for the specified path :
            - Search for the model as first part
            - Search for an existing record as second part
            - Search for an existing attachment as third part
            - There cannot be more than 3 parts in the path
        """
        fakeStat = fuse.Stat()
        fakeStat.st_mode = stat.S_IFDIR | 0400
        fakeStat.st_nlink = 0

        if path == '/':
            return fakeStat

        paths = path.split('/')[1:]
        if len(paths) > 3:
            return -ENOENT

        # Check for model existence
        model_obj = Object(self.oerp_connection, 'ir.model')
        model_ids = model_obj.search([('model', '=', paths[0])])
        if not model_ids:
            return -ENOENT
        elif len(paths) == 1:
            return fakeStat

        # Check for record existence
        element_obj = Object(self.oerp_connection, paths[0])
        element_ids = element_obj.search([('id', '=', int(paths[1]))])
        if not element_ids:
            return -ENOENT
        elif len(paths) == 2:
            return fakeStat

        # Chech for attachement existence
        attachment_obj = Object(self.oerp_connection, 'ir.attachment')
        attachment_ids = attachment_obj.search([
            ('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])),
            ('id', '=', self.id_from_label(paths[2]))
        ])
        if not attachment_ids:
            return -ENOENT

        # Common stats
        fakeStat.st_mode = stat.S_IFREG | 0400
        fakeStat.st_nlink = 2

        # TODO : Read the file size from a dedicated field (created in a specific module)
        attachment_obj = Object(self.oerp_connection, 'ir.attachment')
        attachment_ids = attachment_obj.search([
            ('res_model', '=', paths[0]), ('res_id', '=', int(paths[1])),
            ('id', '=', self.id_from_label(paths[2]))
        ])
        attachment_data = attachment_obj.read(attachment_ids, ['datas'])
        fakeStat.st_size = len(base64.b64decode(attachment_data[0]['datas']))
        return fakeStat
Example #27
0
except Exception, e:
    logger.error('Fail to connect to the server')
    logger.error('%s' % str(e))
    sys.exit(1)


class StopError(Exception):
    pass


filename = opts.filename
if not opts.filename:
    filename = '%s.csv' % opts.model

# recherche du mon de l'objet dans le nom du fichier sans l'extension
obj = Object(cnx, opts.model)

ctx = {'lang': opts.lang}
if opts.inactive:
    ctx['active_test'] = False

if not opts.ids:
    # Get all ids
    ids = obj.search([])
else:
    ids = [int(x.strip()) for x in opts.ids.split(',')]

if not opts.fields:
    # get all fields
    fields = obj.fields_get_keys()
else:
Example #28
0
    cnx = Connection(server=opts.server,
                     dbname=opts.dbname,
                     login=opts.user,
                     password=opts.passwd,
                     port=opts.port)
except Exception, e:
    print '%s' % str(e)
    exit(1)

print 80 * '*'
print '* A connection was established to %s on database %s with user %s ' % (
    opts.server, opts.dbname, opts.user)
print '* Use "cnx" variable for the current connection'
print "* To create a new object: eg x = Object(cnx, 'res.partner')"
print "* To call a method on this object just execute x.search([('field','operator','value')])"
print '*'

if opts.model:
    obj = Object(cnx, opts.model)
    print '* "obj" variable is affect to "%s" object' % opts.model
    print "* To call a method on this object just execute obj.search([('field','operator','value')])"
    print '*'

print 80 * '*'
print '* To exit: enter "exit()" or press "Ctrl + D"'
print 80 * '*'

code.interact(local=locals())

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
sys.path.append('../')

from oobjlib.connection import Connection
from oobjlib.component import Object
from oobjlib.common import GetParser

parser = GetParser('Module List', '0.1')
opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server,
                     dbname=opts.dbname,
                     login=opts.user,
                     password=opts.passwd,
                     port=opts.port)
except Exception, e:
    print '%s' % str(e)
    exit(1)

modules = Object(cnx, "ir.module.module")
print '--[Connection Object]---------------------'
print '%s' % str(modules)

ids = modules.search([('state', '=', 'installed')])
print '--[Module list]---------------------------'
for p in modules.read(ids, ['name']):
    print '* %s' % p['name']

print '--[End]-----------------------------------'
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
Example #30
0
logger.info('Field: %s' % (opts.field, ))

try:
    logger.info('Open connection to "%s:%s" on "%s" with user "%s" ' %
                (opts.server, opts.port, opts.dbname, opts.user))
    cnx = Connection(server=opts.server,
                     dbname=opts.dbname,
                     login=opts.user,
                     password=opts.passwd,
                     port=opts.port)
except Exception, e:
    logger.error('Fail to connect to the server')
    logger.error('%s' % str(e))
    sys.exit(1)

model = Object(cnx, opts.model)
model_ids = model.search([])
model_lists = model.read(model_ids,
                         [opts.field, 'parent_left', 'parent_right'])
models = dict(map(lambda x: (x['id'], x), model_lists))
try:
    for a in model_lists:
        logger.debug('id: %d' % a['id'])
        if a[opts.field]:
            assert a['parent_left'] > models[a[
                opts.field][0]]['parent_left'], '%s > %s' % (
                    a['parent_left'], models[a[opts.field][0]]['parent_left'])
            assert a['parent_right'] < models[a[
                opts.field][0]]['parent_right'], '%s > %s' % (
                    a['parent_right'],
                    models[a[opts.field][0]]['parent_right'])
from oobjlib.connection import Connection
from oobjlib.component import Object
from oobjlib.common import GetParser

parser = GetParser('Create Product', '0.1')
opts, args = parser.parse_args()

try:
    cnx = Connection(
        server=opts.server, 
        dbname=opts.dbname, 
        login=opts.user, 
        password=opts.passwd, 
        port=opts.port)
except Exception, e:
    print '%s' % str(e)
    exit(1)

product = Object(cnx, 'product.product')

args = {
    'name': 'Import Test',
    'default_code': 'ABCD-EFGH',
    'categ_id': 1,
}

print 'Product ID %d created !' % product.create(args)

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
logger.info('Language to import data: %s' % opts.lang)

try:
    logger.info('Open connection to "%s:%s" on "%s" with user "%s" ' % (opts.server, opts.port, opts.dbname, opts.user))
    cnx = Connection(
        server=opts.server,
        dbname=opts.dbname,
        login=opts.user,
        password=opts.passwd,
        port=opts.port)
except Exception, e:
    logger.error('Fail to connect to the server')
    logger.error('%s' % str(e))
    sys.exit(1)

model = Object(cnx, opts.model)

mod_count = model.search_count([])
logger.info('There are %d record to export' % mod_count)

fields = model.fields_get()
fields_name = fields.keys()

result = model.read(model.search([]))

from odf.opendocument import OpenDocumentSpreadsheet
from odf.style import Style, TextProperties, ParagraphProperties, TableColumnProperties
from odf.text import P
from odf.table import Table, TableColumn, TableRow, TableCell

textdoc = OpenDocumentSpreadsheet()
try:
    cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user, port=opts.port,
                     password=opts.passwd)
except Exception, e:
    print '%s' % str(e)
    exit(1)


def generate_tracking_message_id(openobject_id):
    """Returns a string that can be used in the Message-ID RFC822 header field so we
       can track the replies related to a given object thanks to the "In-Reply-To" or
       "References" fields that Mail User Agents will set.
    """
    s = hashlib.sha1()
    s.update(str(time.time()))
    return "<%s-openobject-%s@%s>" % (s.hexdigest(), openobject_id, 'syleam6.syleam.fr')


message = Object(cnx, 'mailgate.message')
message_ids = message.search([('model','=','project.issue'),('message_id','=', False)])

print '%d message to update' % len(message_ids)

for m in message.read(message_ids, ['name', 'res_id']):
    args = {'message_id': generate_tracking_message_id(m['res_id'])}
    message.write([m['id']], args)


# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
group.add_option('', '--follow-one2many', dest='one2many',
                 action='store_true',
                 default=False,
                 help='Follow the one2many child of this record')
parser.add_option_group(group)

opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user,
                     password=opts.passwd, port=opts.port)
except Exception, e:
    print '%s' % str(e)
    exit(1)

model = Object(cnx, opts.model)
model_data = Object(cnx, 'ir.model.data')

##
# Check if model exists and return all fields
#
try:
    fields = model.fields_get()
    f_list = []
    for i in fields:
        f_list.append(i)
    f_list.sort()
except Exception, e:
    print "Error object %s doesn't exists" % opts.model
    exit(2)
parser.add_option_group(group)

opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user,
                     password=opts.passwd, port=opts.port)
except Exception, e:
    print '%s' % str(e)
    exit(1)

if not opts.id:
    print '--id argument is required!'
    exit(1)

model_view = Object(cnx, 'ir.ui.view')
model_data = Object(cnx, 'ir.model.data')

def Ir_Model_Data(model, id):
    """
    Search if the record was previously register in ir_model_data
    """
    args = [
        ('model', '=', model),
        ('res_id', '=', id)
    ]
    ret = '%s_%d' % (model.replace('.', '_'), id)
    res = model_data.search(args)
    if res:
        r = model_data.read(res, ['module', 'name'])[0]
        ret = '%s.%s' % (r['module'], r['name'])
group.add_option('-l', '--legend', dest='legend',
                action="store_true",
                default=False,
                help='List the company by name and their ID')
parser.add_option_group(group)

opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user,
                     password=opts.passwd)
except Exception, e:
    print '%s' % str(e)
    exit(1)

user = Object(cnx, 'res.users')
rule = Object(cnx, 'ir.rule')

user_id = user.search([('login','=', opts.user)])[0]

if opts.legend:
    comp = Object(cnx, 'res.company')
    company_ids = comp.search([])
    print 'List all company'
    print 80 * '*'
    for compa in comp.read(company_ids, ['name']):
        print '%s -> %d' % (compa['name'].ljust(20), compa['id'])
    print 80 * '*'

company_id = user.read(user_id, ['company_id'])['company_id']
try:
sys.path.append('../')

from oobjlib.connection import Connection
from oobjlib.component import Object
from oobjlib.common import GetParser

parser = GetParser('Create Product', '0.1')
opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server,
                     dbname=opts.dbname,
                     login=opts.user,
                     password=opts.passwd,
                     port=opts.port)
except Exception, e:
    print '%s' % str(e)
    exit(1)

product = Object(cnx, 'product.product')

args = {
    'name': 'Import Test',
    'default_code': 'ABCD-EFGH',
    'categ_id': 1,
}

print 'Product ID %d created !' % product.create(args)

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
parser.add_option_group(group)

opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user,
                     password=opts.passwd, port=opts.port)
except Exception, e:
    print '%s' % str(e)
    exit(1)

if not opts.filename:
    print '--file argument is required!'
    exit(1)

jasper_obj = Object(cnx, 'jasper.document')
label_obj = Object(cnx, 'jasper.document.label')


fp = open(opts.filename, 'r')
reader = csv.DictReader(fp, delimiter=',')

service_cache = {}

def format_code(code):
    code = code.upper()
    code = code.replace(' ', '_')
    return code

for l in reader:
    #print l
Example #39
0
    def readdir(self, path, offset):
        """
        Return content of a directory :
            - List models for root path
            - List records for a model
            - List attachments for a record
        We don't have to check for the path, because getattr already returns -ENOENT if the model/record/attachment doesn't exist
        """
        yield fuse.Direntry('.')
        yield fuse.Direntry('..')

        paths = path.split('/')[1:]
        # List models
        if path == '/':
            model_obj = Object(self.oerp_connection, 'ir.model')
            model_ids = model_obj.search([])
            for model_data in model_obj.read(model_ids, ['model']):
                yield fuse.Direntry(model_data['model'])
        # List records
        elif len(paths) == 1:
            element_obj = Object(self.oerp_connection, paths[0])
            element_ids = element_obj.search([])
            for element_data in element_obj.read(element_ids, ['id']):
                yield fuse.Direntry(str(element_data['id']))
        # List attachments
        else:
            attachment_obj = Object(self.oerp_connection, 'ir.attachment')
            attachment_ids = attachment_obj.search([
                ('res_model', '=', paths[0]), ('res_id', '=', int(paths[1]))
            ])
            for attachment_data in attachment_obj.read(attachment_ids,
                                                       ['name']):
                yield fuse.Direntry(
                    '%d-%s' % (attachment_data['id'], attachment_data['name']))
parser.add_option_group(group)

opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user,
                     password=opts.passwd, port=opts.port)
except Exception, e:
    print '%s' % str(e)
    exit(1)

if not opts.service:
    print '--service argument is required!'
    exit(1)

jasper_obj = Object(cnx, 'jasper.document')
label_obj = Object(cnx, 'jasper.document.label')

root = Element('jasperReport', {'name': 'to_be_defined', 'language': 'groovy', 'pageWidth': '595',
                                'pageHeight': '842', 'columnWidth': '555', 'leftMargin': '20',
                                'rightMargin': '20', 'topMargin': '20', 'bottomMargin': '20'})
#root.set('name', 'to_be_defined')
#root.set('language', 'groovy')
#root.set('pageWidth', '595')
#root.set('pageHeight', '842')
#root.set('columnWidth', '555')
#root.set('leftMargin', '20')
#root.set('rightMargin', '20')
#root.set('topMargin', '20')
#root.set('bottomMargin', '20')
group.add_option('-c', '--company', dest='company',
                default='',
                help='Enter list of companies, seprate by a comma (,)')
parser.add_option_group(group)

opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user,
                     password=opts.passwd)
except Exception, e:
    print '%s' % str(e)
    exit(1)


user = Object(cnx, 'res.users')
multi = Object(cnx, 'res.company')

user_id = user.search([('login','=',opts.user)])[0]
# save company_id to restore it after 
curr = user.read(user_id, ['company_ids','company_id'])
c_save_id = curr['company_id']
print 'User: %d => %s (id %d)' % (user_id, c_save_id[1], c_save_id[0])

##
# If the company argument is missing, retrieve all companies in the user form
#
if opts.company:
    companies = opts.company.split(',')
else:
    companies = curr['company_ids']
Example #42
0
 def _return_object(self, objectName, id):
     obj = Object(self.cnx, objectName)
     r = obj.search([("id", "=", id)])
     return obj.read(r)[0]
Example #43
0
directories = []
opts.directory = os.path.expanduser(opts.directory)
if glob(opts.directory + '/scenario.xml'):
    directories.append(opts.directory)
if opts.recursive:
    for root, dirs, files in os.walk(opts.directory):
        for directory in dirs:
            if glob('%s/%s/scenario.xml' % (root, directory)):
                directories.append('%s/%s' % (root, directory))

for directory in directories:
    logger.info('Importing from : %s' % directory)

    # extract scenario
    scenario_obj = Object(cnx, 'scanner.scenario')
    model_obj = Object(cnx, 'ir.model')
    company_obj = Object(cnx, 'res.company')
    warehouse_obj = Object(cnx, 'stock.warehouse')
    step_obj = Object(cnx, 'scanner.scenario.step')
    trans_obj = Object(cnx, 'scanner.scenario.transition')
    xml_file = open('%s/scenario.xml' % directory, 'r')
    logger.info('Scenario file found, process reading!')
    scenario_xml = xml_file.read()
    xml_file.close()
    xml_doc = StringIO(scenario_xml)
    root = parse(xml_doc).getroot()

    step = []
    transition = []
    scen_vals = {}
Example #44
0
                 help='Follow the one2many child of this record')
parser.add_option_group(group)

opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server,
                     dbname=opts.dbname,
                     login=opts.user,
                     password=opts.passwd,
                     port=opts.port)
except Exception, e:
    print '%s' % str(e)
    exit(1)

model = Object(cnx, opts.model)
model_data = Object(cnx, 'ir.model.data')

##
# Check if model exists and return all fields
#
try:
    fields = model.fields_get()
    f_list = []
    for i in fields:
        f_list.append(i)
    f_list.sort()
except Exception, e:
    print "Error object %s doesn't exists" % opts.model
    exit(2)
class Sentinel(object):

    """
    Sentinel class
    Manages scanner terminals
    """

    def __init__(self, stdscr):
        """
        Initialize the sentinel program
        """
        # Read user configuration
        config = ConfigParser.SafeConfigParser(DEFAULT_CONFIG)
        self.datadir = os.path.expanduser("~/")
        config.read([
            '.oerp_sentinelrc',
            '.openerp_sentinelrc',
            '.odoo_sentinelrc',
            os.path.join(self.datadir, '.oerp_sentinelrc'),
            os.path.join(self.datadir, '.openerp_sentinelrc'),
            os.path.join(self.datadir, '.odoo_sentinelrc'),
        ])

        # No configfile found, exit
        if 'openerp' not in config.sections():
            raise Exception('Config Error', 'Config file not found !')

        # Connection to the OpenERP Server
        self.connection = Connection(
            server=config.get('openerp', 'host'),
            dbname=config.get('openerp', 'database'),
            login=config.get('openerp', 'user'),
            password=config.get('openerp', 'password'),
            port=config.get('openerp', 'port'),
        )

        # Open the test file, if any
        test_file_name = config.get('openerp', 'test_file')
        self.test_file = None
        if test_file_name:
            self.test_file = open(test_file_name, 'r')

        # Initialize translations
        self.context = Object(self.connection, 'res.users').context_get()
        lang = self.context.get('lang', I18N_DEFAULT)
        gettext.install(I18N_DOMAIN)
        try:
            language = gettext.translation(
                I18N_DOMAIN, I18N_DIR, languages=[lang])
        except:
            language = gettext.translation(
                I18N_DOMAIN, I18N_DIR, languages=[I18N_DEFAULT])

        # Replace global dummy lambda by the translations gettext method
        # The install method of gettext doesn't replace the function if exists
        global _
        _ = language.gettext

        # Initialize hardware
        self.hardware_obj = Object(self.connection, 'scanner.hardware')
        self.scenario_obj = Object(self.connection, 'scanner.scenario')

        # Initialize window
        self.screen = stdscr
        self._set_screen_size()

        self._init_colors()

        # Get the informations for this material from server (identified by IP)
        self.hardware_code = ''
        self.scenario_id = False
        self.scenario_name = False
        try:
            ssh_data = os.environ['SSH_CONNECTION'].split(' ')
            self.hardware_code = ssh_data[0]
            self.scanner_check()
        except:
            self.hardware_code = self._input_text(
                _('Autoconfiguration failed !\nPlease enter terminal code'))
            self.scanner_check()

        # Resize window to terminal screen size
        self._resize()

        # Reinit colors with values configured in OpenERP
        self._reinit_colors()

        # Initialize mouse events capture
        curses.mousemask(
            curses.BUTTON1_CLICKED | curses.BUTTON1_DOUBLE_CLICKED)

        # Reinitialize to the main menu when using a test file (useful when
        # the last run has crashed before end)
        if test_file_name:
            self.oerp_call('end')

        # Load the sentinel
        self.main_loop()

    def scanner_check(self):
        self.scenario_id = self.hardware_obj.scanner_check(
            self.hardware_code, self.context)
        if isinstance(self.scenario_id, list):
            self.scenario_id, self.scenario_name = self.scenario_id

    def _resize(self):
        """
        Resizes the window
        """
        # Asks for the hardware screen size
        (width, height) = self.oerp_call('screen_size')[1]
        self._set_screen_size(width, height)

    def _init_colors(self):
        """
        Initialize curses colors
        """
        # Declare all configured color pairs for curses
        for (the_id, front_color, back_color) in COLOR_PAIRS.values():
            curses.init_pair(
                the_id, COLOR_NAMES[front_color], COLOR_NAMES[back_color])

        # Set the default background color
        self.screen.bkgd(0, self._get_color('base'))

    def _reinit_colors(self):
        """
        Initializes the colors from Odoo configuration
        """
        # Asks for the hardware screen size
        colors = self.oerp_call('screen_colors')[1]
        COLOR_PAIRS['base'] = (1, colors['base'][0], colors['base'][1])
        COLOR_PAIRS['info'] = (2, colors['info'][0], colors['info'][1])
        COLOR_PAIRS['error'] = (3, colors['error'][0], colors['error'][1])
        self._init_colors()

    def _set_screen_size(self, width=18, height=6):
        self.window_width = width
        self.window_height = height
        self.screen.resize(height, width)

    def _get_color(self, name):
        """
        Get a curses color's code
        """
        return curses.color_pair(COLOR_PAIRS[name][0])

    def _read_from_file(self):
        """
        Emulates the getkey method of curses, reading from the supplied test
        file
        """
        key = self.test_file.read(1)
        if key == ':':
            # Truncate the trailing "new line" character
            key = self.test_file.readline()[:-1]

        # End of file reached, terminate the sentinel
        if not key:
            self.test_file.close()
            exit(0)

        return key

    def ungetch(self, value):
        """
        Put a value in the keyboard buffer
        """
        curses.ungetch(value)

    def getkey(self):
        """
        Get a user input and avoid Ctrl+C
        """
        if self.test_file:
            # Test file supplied, read from it
            key = self._read_from_file()
        else:
            # Get the pushed character
            key = self.screen.getkey()
        if key == '':
            # Escape key : Return back to the previous step
            raise SentinelBackException('Back')
        return key

    def _display(self, text='', x=0, y=0, clear=False, color='base',
                 bgcolor=False, modifier=curses.A_NORMAL, cursor=None,
                 height=None, scroll=False, title=None):
        """
        Display a line of text
        """
        # Clear the sceen if needed
        if clear:
            self.screen.clear()

        # Display the title, if any
        if title is not None:
            y += 1
            title = title.center(self.window_width)
            self._display(
                title, color='info',
                modifier=curses.A_REVERSE | curses.A_BOLD)

        # Compute the display modifiers
        color = self._get_color(color) | modifier
        # Set background to 'error' colors
        if bgcolor:
            self.screen.bkgd(0, color)

        # Normalize the text, because ncurses doesn't know UTF-8 with
        # python 2.x
        if isinstance(text, str):
            text = text.decode('utf-8')
        text = unicodedata.normalize(
            'NFKD', unicode(text)).encode('ascii', 'ignore')
        text = ''.join(
            [char not in ('\r', '\n') and
             curses.ascii.unctrl(char) or char for char in text])

        # Display the text
        if not scroll:
            self.screen.addstr(y, x, text, color)
        else:
            # Wrap the text to avoid splitting words
            text_lines = []
            for line in text.splitlines():
                text_lines.extend(
                    textwrap.wrap(line, self.window_width - x - 1) or [''])

            # Initialize variables
            first_line = 0
            if height is None:
                height = self.window_height

            (cursor_y, cursor_x) = cursor or (
                self.window_height - 1, self.window_width - 1)

            while True:
                # Display the menu
                self.screen.addstr(height - 1, x,
                                   (self.window_width - x - 1) * ' ', color)
                self.screen.addstr(
                    y, x, '\n'.join(
                        text_lines[first_line:first_line + height - y]),
                    color)

                # Display arrows
                if first_line > 0:
                    self.screen.addch(
                        y, self.window_width - 1, curses.ACS_UARROW)
                if first_line + height < len(text_lines):
                    self.screen.addch(
                        min(height + y - 1, self.window_height - 2),
                        self.window_width - 1, curses.ACS_DARROW)
                else:
                    self.screen.addch(
                        min(height + y - 1, self.window_height - 2),
                        self.window_width - 1, ' ')

                # Set the cursor position
                if height < len(text_lines):
                    scroll_height = len(text_lines) - height
                    position_percent = float(first_line) / scroll_height
                    position = y + min(
                        int(round((height - 1) * position_percent)),
                        self.window_height - 2)
                    self._display(
                        ' ', x=self.window_width - 1, y=position - 1,
                        color='info', modifier=curses.A_REVERSE)
                self.screen.move(cursor_y, cursor_x)

                # Get the pushed key
                key = self.getkey()

                if key == 'KEY_DOWN':
                    # Down key : Go down in the list
                    first_line += 1
                elif key == 'KEY_UP':
                    # Up key : Go up in the list
                    first_line -= 1
                else:
                    # Return the pressed key value
                    return key

                # Avoid going out of the list
                first_line = min(
                    max(0, first_line), max(0, len(text_lines) - height + 1))

    def main_loop(self):
        """
        Loops until the user asks for ending
        """
        code = False
        result = None
        value = None

        while True:
            try:
                try:
                    # No active scenario, select one
                    if not self.scenario_id:
                        (code, result, value) = self._select_scenario()
                    else:
                        # Search for a step title
                        title = None
                        title_key = '|'
                        if isinstance(result, (types.NoneType, bool)):
                            pass
                        elif (isinstance(result, dict) and
                              result.get(title_key, None)):
                            title = result[title_key]
                            del result[title_key]
                        elif (isinstance(result[0], (tuple, list)) and
                              result[0][0] == title_key):
                            title = result.pop(0)[1]
                        elif (isinstance(result[0], basestring) and
                              result[0].startswith(title_key)):
                            title = result.pop(0)[len(title_key):]

                        if title is None and self.scenario_name:
                            # If no title is defined, display the scenario name
                            title = self.scenario_name

                        if code == 'Q' or code == 'N':
                            # Quantity selection
                            quantity = self._select_quantity(
                                '\n'.join(result), '%g' % value,
                                integer=(code == 'N'), title=title)
                            (code, result, value) = self.oerp_call('action',
                                                                   quantity)
                        elif code == 'C':
                            # Confirmation query
                            confirm = self._confirm(
                                '\n'.join(result), title=title)
                            (code, result, value) = self.oerp_call('action',
                                                                   confirm)
                        elif code == 'T':
                            # Select arguments from value
                            default = ''
                            size = None
                            if isinstance(value, dict):
                                default = value.get('default', '')
                                size = value.get('size', None)
                            elif isinstance(value, str):
                                default = value

                            # Text input
                            text = self._input_text(
                                '\n'.join(result), default=default,
                                size=size, title=title)
                            (code, result, value) = self.oerp_call('action',
                                                                   text)
                        elif code == 'R':
                            # Critical error
                            self.scenario_id = False
                            self.scenario_name = False
                            self._display_error('\n'.join(result), title=title)
                        elif code == 'U':
                            # Unknown action : message with return back to the
                            # last state
                            self._display(
                                '\n'.join(result), clear=True, scroll=True,
                                title=title)
                            (code, result, value) = self.oerp_call('back')
                        elif code == 'E':
                            # Error message
                            self._display_error(
                                '\n'.join(result), title=title)
                            # Execute transition
                            if not value:
                                (code, result, value) = self.oerp_call(
                                    'action')
                            else:
                                # Back to the previous step required
                                (code, result, value) = self.oerp_call(
                                    'back')
                        elif code == 'M':
                            # Simple message
                            self._display(
                                '\n'.join(result), clear=True, scroll=True,
                                title=title)
                            # Execute transition
                            (code, result, value) = self.oerp_call('action',
                                                                   value)
                        elif code == 'L':
                            if result:
                                # Select a value in the list
                                choice = self._menu_choice(result, title=title)
                                # Send the result to Odoo
                                (code, result, value) = self.oerp_call(
                                    'action', choice)
                            else:
                                # Empty list supplied, display an error
                                (code, result, value) = (
                                    'E', [_('No value available')], True)

                            # Check if we are in a scenario (to retrieve the
                            # scenario name from a submenu)
                            self.scanner_check()
                            if not self.scenario_id:
                                self.scenario_id = True
                                self.scenario_name = False
                        elif code == 'F':
                            # End of scenario
                            self.scenario_id = False
                            self.scenario_name = False
                            self._display('\n'.join(result), clear=True,
                                          scroll=True, title=title)
                        else:
                            # Default call
                            (code, result, value) = self.oerp_call('restart')
                except SentinelBackException:
                    # Back to the previous step required
                    (code, result, value) = self.oerp_call('back')
                    # Do not display the termination message
                    if code == 'F':
                        self.ungetch(ord('\n'))
                    self.screen.bkgd(0, self._get_color('base'))
                except Exception:
                    # Generates log contents
                    log_contents = """%s
# %s
# Hardware code : %s
# ''Current scenario : %s (%s)
# Current values :
#\tcode : %s
#\tresult : %s
#\tvalue : %s
%s
%s
"""
                    log_contents = log_contents % (
                        '#' * 79, datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                        self.hardware_code, str(self.scenario_id),
                        self.scenario_name, code, repr(result), repr(value),
                        '#' * 79, reduce(
                            lambda x, y: x + y, traceback.format_exception(
                                sys.exc_info()[0],
                                sys.exc_info()[1],
                                sys.exc_info()[2])))

                    # Writes traceback in log file
                    logfile = open(self.datadir + 'oerp_sentinel.log', 'a')
                    logfile.write(log_contents)
                    logfile.close()

                    # Display error message
                    (code, result, value) = (
                        'E', [_('An error occured\n\nPlease contact your '
                                'administrator')], False)
            except KeyboardInterrupt:
                # If Ctrl+C, exit
                (code, result, value) = self.oerp_call('end')
                # Restore normal background colors
                self.screen.bkgd(0, self._get_color('base'))

    def _display_error(self, error_message, title=None):
        """
        Displays an error message, changing the background to red
        """
        # Display error message
        self._display(error_message, color='error', bgcolor=True, clear=True,
                      scroll=True, title=title)
        # Restore normal background colors
        self.screen.bkgd(0, self._get_color('base'))

    def oerp_call(self, action, message=False):
        """
        Calls a method from Odoo Server
        """
        return self.hardware_obj.scanner_call(
            self.hardware_code, action, message, 'keyboard', self.context)

    def _select_scenario(self):
        """
        Selects a scenario from the server
        """
        # Get the scenarios list from server
        values = self.oerp_call('menu')[1]

        # If no scenario available : return an error
        if not values:
            return ('R', [_('No scenario available !')], 0)

        # Select a scenario in the list
        choice = self._menu_choice(values, title=_('Scenarios'))
        ret = self.oerp_call('action', choice)

        # Store the scenario id and name
        self.scanner_check()
        if not self.scenario_id:
            self.scenario_id = True
            self.scenario_name = False

        # Send the result to OpenERP
        return ret

    def _confirm(self, message, title=None):
        """
        Allows the user to select quantity
        """
        confirm = False

        while True:
            # Clear the screen
            self._display(clear=True)

            # Compute Yes/No positions
            yes_start = 0
            yes_padding = int(math.floor(self.window_width / 2))
            yes_text = _('Yes').center(yes_padding)
            no_start = yes_padding
            no_padding = self.window_width - no_start - 1
            no_text = _('No').center(no_padding)

            if confirm:
                # Yes selected
                yes_modifier = curses.A_BOLD | curses.A_REVERSE
                no_modifier = curses.A_NORMAL
            else:
                # No selected
                yes_modifier = curses.A_NORMAL
                no_modifier = curses.A_BOLD | curses.A_REVERSE

            # Display Yes
            self._display(yes_text, x=yes_start, y=self.window_height - 1,
                          color='info', modifier=yes_modifier)
            # Display No
            self._display(no_text, x=no_start, y=self.window_height - 1,
                          color='info', modifier=no_modifier)

            # Display the confirmation message
            key = self._display(message, scroll=True,
                                height=self.window_height - 1, title=title)

            if key == '\n':
                # Return key : Validate the choice
                return confirm
            elif (key == 'KEY_DOWN' or
                  key == 'KEY_LEFT' or
                  key == 'KEY_UP' or
                  key == 'KEY_RIGHT'):
                # Arrow key : change value
                confirm = not confirm
            elif key.upper() == 'O' or key.upper() == 'Y':
                # O (oui) or Y (yes)
                confirm = True
            elif key.upper() == 'N':
                # N (No)
                confirm = False
            elif key == 'KEY_MOUSE':
                # Retrieve mouse event information
                mouse_info = curses.getmouse()

                # Set the selected entry
                confirm = mouse_info[1] < len(yes_text)

                # If we double clicked, auto-validate
                if mouse_info[4] & curses.BUTTON1_DOUBLE_CLICKED:
                    return confirm

    def _input_text(self, message, default='', size=None, title=None):
        """
        Allows the user to input random text
        """
        # Initialize variables
        value = default
        line = self.window_height - 1
        self.screen.move(line, 0)
        # Flush the input
        curses.flushinp()

        # While we do not validate, store characters
        while True:
            # Clear the screen
            self._display(clear=True)

            # Display the current value if echoing is needed
            display_value = ''.join(
                [curses.ascii.unctrl(char) for char in value])
            display_start = max(0, len(display_value) - self.window_width + 1)
            display_value = display_value[display_start:]
            self._display(' ' * (self.window_width - 1), 0, line)
            self._display(
                display_value, 0, line, color='info', modifier=curses.A_BOLD)
            key = self._display(
                message, scroll=True, height=self.window_height - 1,
                cursor=(line, min(len(value), self.window_width - 1)),
                title=title)

            # Printable character : store in value
            if len(key) == 1 and (curses.ascii.isprint(key) or ord(key) < 32):
                value += key
            # Backspace or del, remove the last character
            elif key == 'KEY_BACKSPACE' or key == 'KEY_DC':
                value = value[:-1]

            # Move cursor at end of the displayed value
            if key == '\n' or (size is not None and len(value) >= size):
                # Flush the input
                curses.flushinp()
                return value.strip()

    def _select_quantity(self, message, quantity='0', integer=False,
                         title=None):
        """
        Allows the user to select  quantity
        """
        # Erase the selected quantity on the first digit key press
        digit_key_pressed = False

        while True:
            # Clear the screen
            self._display(clear=True)
            # Diplays the selected quantity
            self._display(
                _('Selected : %s') % quantity, y=self.window_height - 1,
                color='info', modifier=curses.A_BOLD)

            # Display the message and get the key
            key = self._display(
                message, scroll=True, height=self.window_height - 1,
                title=title)

            if key == '\n':
                # Return key : Validate the choice
                return float(quantity)
            elif key.isdigit():
                if not digit_key_pressed:
                    quantity = '0'
                    digit_key_pressed = True

                # Digit : Add at end
                if quantity == '0':
                    quantity = key
                else:
                    quantity += key
            elif (not integer and
                  '.' not in quantity and
                  (key == '.' or key == ',' or key == '*')):
                # Decimal point
                quantity += '.'
            elif key == 'KEY_BACKSPACE' or key == 'KEY_DC':
                # Backspace : Remove last digit
                quantity = quantity[:-1]
                digit_key_pressed = True
            elif key == 'KEY_DOWN' or key == 'KEY_LEFT':
                # Down key : Decrease
                quantity = '%g' % (float(quantity) - 1)
            elif key == 'KEY_UP' or key == 'KEY_RIGHT':
                # Up key : Increase
                quantity = '%g' % (float(quantity) + 1)

            if not quantity:
                quantity = '0'

    def _menu_choice(self, entries, title=None):
        """
        Allows the user to choose a value in a list
        """
        # If a dict is passed, keep the keys
        keys = entries
        if isinstance(entries, dict):
            keys, entries = entries.items()
        elif isinstance(entries[0], (tuple, list)):
            keys, entries = map(list, zip(*entries))[:2]

        # Highlighted entry
        highlighted = 0
        first_column = 0
        max_length = max([len(value) for value in entries])

        # Add line numbers before text
        display = []
        index = 0
        nb_char = int(math.floor(math.log10(len(entries))) + 1)
        decal = nb_char + 3
        for value in entries:
            display.append(
                '%s: %s' % (str(index).rjust(nb_char),
                            value[:self.window_width - decal]))
            index += 1

        while True:
            # Display the menu
            self._menu_display(display, highlighted, title=title)

            # Get the pushed key
            key = self.getkey()
            digit_key = False

            if key == '\n':
                # Return key : Validate the choice
                return keys[highlighted]
            elif key.isdigit():
                # Digit : Add at end of index
                highlighted = highlighted * 10 + int(key)
                digit_key = True
            elif key == 'KEY_BACKSPACE' or key == 'KEY_DC':
                # Backspace : Remove last digit from index
                highlighted = int(math.floor(highlighted / 10))
            elif key == 'KEY_DOWN':
                # Down key : Go down in the list
                highlighted = highlighted + 1
            elif key == 'KEY_RIGHT':
                # Move display
                first_column = max(
                    0, min(first_column + 1,
                           max_length - self.window_width + decal))
                display = []
                index = 0
                for value in entries:
                    display.append(
                        '%s: %s' % (
                            str(index).rjust(nb_char),
                            value[first_column:
                                  self.window_width - decal + first_column]))
                    index += 1
            elif key == 'KEY_UP':
                # Up key : Go up in the list
                highlighted = highlighted - 1
            elif key == 'KEY_LEFT':
                # Move display
                first_column = max(0, first_column - 1)
                display = []
                index = 0
                for value in entries:
                    display.append(
                        '%s: %s' % (
                            str(index).rjust(nb_char),
                            value[first_column:
                                  self.window_width - decal + first_column]))
                    index += 1
            elif key == 'KEY_MOUSE':
                # First line to be displayed
                first_line = 0
                nb_lines = self.window_height - 1
                middle = int(math.floor(nb_lines / 2))

                # Change the first line if there is too much lines for the
                # screen
                if len(entries) > nb_lines and highlighted >= middle:
                    first_line = min(highlighted - middle,
                                     len(entries) - nb_lines)

                # Retrieve mouse event information
                mouse_info = curses.getmouse()

                # Set the selected entry
                highlighted = min(max(0, first_line + mouse_info[2]),
                                  len(entries) - 1)

                # If we double clicked, auto-validate
                if mouse_info[4] & curses.BUTTON1_DOUBLE_CLICKED:
                    return keys[highlighted]

            # Avoid going out of the list
            highlighted %= len(entries)

            # Auto validate if max number is reached
            current_nb_char = int(
                math.floor(math.log10(max(1, highlighted))) + 1)
            if highlighted and digit_key and current_nb_char >= nb_char:
                return keys[highlighted]

    def _menu_display(self, entries, highlighted, title=None):
        """
        Display a menu, highlighting the selected entry
        """
        # First line to be displayed
        first_line = 0
        nb_lines = self.window_height - 1
        if len(entries) > nb_lines:
            nb_lines -= 1
        middle = int(math.floor((nb_lines - 1) / 2))
        # Change the first line if there is too much lines for the screen
        if len(entries) > nb_lines and highlighted >= middle:
            first_line = min(highlighted - middle, len(entries) - nb_lines)

        # Display all entries, normal display
        self._display('\n'.join(entries[first_line:first_line + nb_lines]),
                      clear=True, title=title)
        # Highlight selected entry
        self._display(
            entries[highlighted].ljust(self.window_width - 1),
            y=highlighted - first_line,
            modifier=curses.A_REVERSE | curses.A_BOLD, title=title)

        # Display arrows
        if first_line > 0:
            self.screen.addch(0, self.window_width - 1, curses.ACS_UARROW)
        if first_line + nb_lines < len(entries):
            self.screen.addch(
                nb_lines, self.window_width - 1, curses.ACS_DARROW)

        # Diplays number of the selected entry
        self._display(_('Selected : %d') % highlighted, y=self.window_height-1,
                      color='info', modifier=curses.A_BOLD)

        # Set the cursor position
        if nb_lines < len(entries):
            position_percent = float(highlighted) / len(entries)
            position = int(round(nb_lines * position_percent))
            self._display(
                ' ', x=self.window_width - 1, y=position, color='info',
                modifier=curses.A_REVERSE)
        self.screen.move(self.window_height - 1, self.window_width - 1)
Example #46
0
                 default=False,
                 help='List the company by name and their ID')
parser.add_option_group(group)

opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server,
                     dbname=opts.dbname,
                     login=opts.user,
                     password=opts.passwd)
except Exception, e:
    print '%s' % str(e)
    exit(1)

user = Object(cnx, 'res.users')
rule = Object(cnx, 'ir.rule')

user_id = user.search([('login', '=', opts.user)])[0]

if opts.legend:
    comp = Object(cnx, 'res.company')
    company_ids = comp.search([])
    print 'List all company'
    print 80 * '*'
    for compa in comp.read(company_ids, ['name']):
        print '%s -> %d' % (compa['name'].ljust(20), compa['id'])
    print 80 * '*'

company_id = user.read(user_id, ['company_id'])['company_id']
try:
Example #47
0
                (opts.server, opts.port, opts.dbname, opts.user))
    cnx = Connection(server=opts.server,
                     dbname=opts.dbname,
                     login=opts.user,
                     password=opts.passwd,
                     port=opts.port)
except Exception, e:
    logger.error('Fail to connect to the server')
    logger.error('%s' % str(e))
    sys.exit(1)

resid = {}
opts.directory = os.path.expanduser(opts.directory)

# extract scenario
scenario_obj = Object(cnx, 'scanner.scenario')
model_obj = Object(cnx, 'ir.model')
warehouse_obj = Object(cnx, 'stock.warehouse')
scen_read = scenario_obj.read(int(opts.scenario_id), [],
                              {'active_test': False})
if not scen_read:
    logger.error('Scenario ID %s not found' % opts.scenario_id)
    sys.exit(1)
del scen_read['step_ids']
del scen_read['id']
# create node and attributs
root = Element('scenario')
for field in scen_read:
    node = SubElement(root, field)
    if field == 'model_id':
        if scen_read[field]:
opts, args = parser.parse_args()

try:
    cnx = Connection(server=opts.server, dbname=opts.dbname, login=opts.user, port=opts.port, password=opts.passwd)
except Exception, e:
    print "%s" % str(e)
    exit(1)


def generate_tracking_message_id(openobject_id):
    """Returns a string that can be used in the Message-ID RFC822 header field so we
       can track the replies related to a given object thanks to the "In-Reply-To" or
       "References" fields that Mail User Agents will set.
    """
    s = hashlib.sha1()
    s.update(str(time.time()))
    return "<%s-openobject-%s@%s>" % (s.hexdigest(), openobject_id, "syleam6.syleam.fr")


message = Object(cnx, "mailgate.message")
message_ids = message.search([("model", "=", "project.issue"), ("message_id", "=", False)])

print "%d message to update" % len(message_ids)

for m in message.read(message_ids, ["name", "res_id"]):
    args = {"message_id": generate_tracking_message_id(m["res_id"])}
    message.write([m["id"]], args)


# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: