remove standalone
bzr revid: al@openerp.com-20121010172418-27stgsd4w71cbxv4
This commit is contained in:
parent
5775b402a7
commit
818fd9f67f
|
@ -1,6 +1,5 @@
|
|||
#!/usr/bin/python
|
||||
from . import http
|
||||
from . import nonliterals
|
||||
from . import release
|
||||
from . import session
|
||||
from . import xml2json
|
||||
|
|
|
@ -6,15 +6,18 @@ import ast
|
|||
import cgi
|
||||
import contextlib
|
||||
import functools
|
||||
import getpass
|
||||
import logging
|
||||
import mimetypes
|
||||
import os
|
||||
import pprint
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
import urllib
|
||||
import urlparse
|
||||
import uuid
|
||||
import xmlrpclib
|
||||
|
||||
|
@ -26,10 +29,10 @@ import werkzeug.utils
|
|||
import werkzeug.wrappers
|
||||
import werkzeug.wsgi
|
||||
|
||||
from . import nonliterals
|
||||
from . import session
|
||||
from . import openerplib
|
||||
import urlparse
|
||||
import openerp
|
||||
|
||||
import nonliterals
|
||||
import session
|
||||
|
||||
__all__ = ['Root', 'jsonrequest', 'httprequest', 'Controller',
|
||||
'WebRequest', 'JsonRequest', 'HttpRequest']
|
||||
|
@ -46,7 +49,6 @@ class WebRequest(object):
|
|||
|
||||
:param request: a wrapped werkzeug Request object
|
||||
:type request: :class:`werkzeug.wrappers.BaseRequest`
|
||||
:param config: configuration object
|
||||
|
||||
.. attribute:: httprequest
|
||||
|
||||
|
@ -58,10 +60,6 @@ class WebRequest(object):
|
|||
a :class:`~collections.Mapping` holding the HTTP session data for the
|
||||
current http session
|
||||
|
||||
.. attribute:: config
|
||||
|
||||
config parameter provided to the request object
|
||||
|
||||
.. attribute:: params
|
||||
|
||||
:class:`~collections.Mapping` of request parameters, not generally
|
||||
|
@ -85,11 +83,10 @@ class WebRequest(object):
|
|||
|
||||
``bool``, indicates whether the debug mode is active on the client
|
||||
"""
|
||||
def __init__(self, request, config):
|
||||
def __init__(self, request):
|
||||
self.httprequest = request
|
||||
self.httpresponse = None
|
||||
self.httpsession = request.session
|
||||
self.config = config
|
||||
|
||||
def init(self, params):
|
||||
self.params = dict(params)
|
||||
|
@ -98,7 +95,6 @@ class WebRequest(object):
|
|||
self.session = self.httpsession.get(self.session_id)
|
||||
if not self.session:
|
||||
self.httpsession[self.session_id] = self.session = session.OpenERPSession()
|
||||
self.session.config = self.config
|
||||
self.context = self.params.pop('context', None)
|
||||
self.debug = self.params.pop('debug', False) != False
|
||||
|
||||
|
@ -180,7 +176,7 @@ class JsonRequest(WebRequest):
|
|||
_logger.debug("--> %s.%s\n%s", controller.__class__.__name__, method.__name__, pprint.pformat(self.jsonrequest))
|
||||
response['id'] = self.jsonrequest.get('id')
|
||||
response["result"] = method(controller, self, **self.params)
|
||||
except openerplib.AuthenticationError:
|
||||
except session.AuthenticationError:
|
||||
error = {
|
||||
'code': 100,
|
||||
'message': "OpenERP Session Invalid",
|
||||
|
@ -238,8 +234,8 @@ def jsonrequest(f):
|
|||
beforehand)
|
||||
"""
|
||||
@functools.wraps(f)
|
||||
def json_handler(controller, request, config):
|
||||
return JsonRequest(request, config).dispatch(controller, f)
|
||||
def json_handler(controller, request):
|
||||
return JsonRequest(request).dispatch(controller, f)
|
||||
json_handler.exposed = True
|
||||
return json_handler
|
||||
|
||||
|
@ -325,8 +321,8 @@ def httprequest(f):
|
|||
and ``debug`` keys (which are stripped out beforehand)
|
||||
"""
|
||||
@functools.wraps(f)
|
||||
def http_handler(controller, request, config):
|
||||
return HttpRequest(request, config).dispatch(controller, f)
|
||||
def http_handler(controller, request):
|
||||
return HttpRequest(request).dispatch(controller, f)
|
||||
http_handler.exposed = True
|
||||
return http_handler
|
||||
|
||||
|
@ -425,6 +421,7 @@ def session_context(request, storage_path, session_cookie='httpsessionid'):
|
|||
mimetypes.add_type('application/font-woff', '.woff')
|
||||
mimetypes.add_type('application/vnd.ms-fontobject', '.eot')
|
||||
mimetypes.add_type('application/x-font-ttf', '.ttf')
|
||||
|
||||
class DisableCacheMiddleware(object):
|
||||
def __init__(self, app):
|
||||
self.app = app
|
||||
|
@ -449,45 +446,23 @@ class DisableCacheMiddleware(object):
|
|||
|
||||
class Root(object):
|
||||
"""Root WSGI application for the OpenERP Web Client.
|
||||
|
||||
:param options: mandatory initialization options object, must provide
|
||||
the following attributes:
|
||||
|
||||
``server_host`` (``str``)
|
||||
hostname of the OpenERP server to dispatch RPC to
|
||||
``server_port`` (``int``)
|
||||
RPC port of the OpenERP server
|
||||
``serve_static`` (``bool | None``)
|
||||
whether this application should serve the various
|
||||
addons's static files
|
||||
``storage_path`` (``str``)
|
||||
filesystem path where HTTP session data will be stored
|
||||
``dbfilter`` (``str``)
|
||||
only used in case the list of databases is requested
|
||||
by the server, will be filtered by this pattern
|
||||
"""
|
||||
def __init__(self, options):
|
||||
self.config = options
|
||||
|
||||
if not hasattr(self.config, 'connector'):
|
||||
if self.config.backend == 'local':
|
||||
self.config.connector = session.LocalConnector()
|
||||
else:
|
||||
self.config.connector = openerplib.get_connector(
|
||||
hostname=self.config.server_host, port=self.config.server_port)
|
||||
|
||||
def __init__(self):
|
||||
self.httpsession_cookie = 'httpsessionid'
|
||||
self.addons = {}
|
||||
|
||||
static_dirs = self._load_addons()
|
||||
if options.serve_static:
|
||||
app = werkzeug.wsgi.SharedDataMiddleware( self.dispatch, static_dirs)
|
||||
self.dispatch = DisableCacheMiddleware(app)
|
||||
app = werkzeug.wsgi.SharedDataMiddleware( self.dispatch, static_dirs)
|
||||
self.dispatch = DisableCacheMiddleware(app)
|
||||
|
||||
if options.session_storage:
|
||||
if not os.path.exists(options.session_storage):
|
||||
os.mkdir(options.session_storage, 0700)
|
||||
self.session_storage = options.session_storage
|
||||
try:
|
||||
username = getpass.getuser()
|
||||
except Exception:
|
||||
username = "unknown"
|
||||
self.session_storage = os.path.join(tempfile.gettempdir(), "oe-sessions-" + username)
|
||||
|
||||
if not os.path.exists(self.session_storage):
|
||||
os.mkdir(self.session_storage, 0700)
|
||||
_logger.debug('HTTP sessions stored in: %s', self.session_storage)
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
|
@ -512,7 +487,7 @@ class Root(object):
|
|||
response = werkzeug.exceptions.NotFound()
|
||||
else:
|
||||
with session_context(request, self.session_storage, self.httpsession_cookie) as session:
|
||||
result = handler( request, self.config)
|
||||
result = handler( request)
|
||||
|
||||
if isinstance(result, basestring):
|
||||
headers=[('Content-Type', 'text/html; charset=utf-8'), ('Content-Length', len(result))]
|
||||
|
@ -531,7 +506,7 @@ class Root(object):
|
|||
static URLs to the corresponding directories
|
||||
"""
|
||||
statics = {}
|
||||
for addons_path in self.config.addons_path:
|
||||
for addons_path in openerp.modules.module.ad_paths:
|
||||
for module in os.listdir(addons_path):
|
||||
if module not in addons_module:
|
||||
manifest_path = os.path.join(addons_path, module, '__openerp__.py')
|
||||
|
@ -579,28 +554,8 @@ class Root(object):
|
|||
ps = '/'
|
||||
return None
|
||||
|
||||
class Options(object):
|
||||
pass
|
||||
|
||||
def wsgi_postload():
|
||||
import openerp
|
||||
import tempfile
|
||||
import getpass
|
||||
_logger.info("embedded mode")
|
||||
o = Options()
|
||||
o.dbfilter = openerp.tools.config['dbfilter']
|
||||
o.server_wide_modules = openerp.conf.server_wide_modules or ['web']
|
||||
try:
|
||||
username = getpass.getuser()
|
||||
except Exception:
|
||||
username = "unknown"
|
||||
o.session_storage = os.path.join(tempfile.gettempdir(), "oe-sessions-" + username)
|
||||
o.addons_path = openerp.modules.module.ad_paths
|
||||
o.serve_static = True
|
||||
o.backend = 'local'
|
||||
|
||||
app = Root(o)
|
||||
openerp.wsgi.register_wsgi_handler(app)
|
||||
openerp.wsgi.register_wsgi_handler(Root())
|
||||
|
||||
|
||||
# vim:et:ts=4:sw=4:
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) Stephane Wirtel
|
||||
# Copyright (C) 2011 Nicolas Vanhoren
|
||||
# Copyright (C) 2011 OpenERP s.a. (<http://openerp.com>).
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from .main import *
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) Stephane Wirtel
|
||||
# Copyright (C) 2011 Nicolas Vanhoren
|
||||
# Copyright (C) 2011 OpenERP s.a. (<http://openerp.com>).
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import datetime
|
||||
|
||||
DEFAULT_SERVER_DATE_FORMAT = "%Y-%m-%d"
|
||||
DEFAULT_SERVER_TIME_FORMAT = "%H:%M:%S"
|
||||
DEFAULT_SERVER_DATETIME_FORMAT = "%s %s" % (
|
||||
DEFAULT_SERVER_DATE_FORMAT,
|
||||
DEFAULT_SERVER_TIME_FORMAT)
|
||||
|
||||
def str_to_datetime(str):
|
||||
"""
|
||||
Converts a string to a datetime object using OpenERP's
|
||||
datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
|
||||
No timezone information is added, the datetime is a naive instance, but
|
||||
according to OpenERP 6.1 specification the timezone is always UTC.
|
||||
"""
|
||||
if not str:
|
||||
return str
|
||||
return datetime.datetime.strptime(str, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
def str_to_date(str):
|
||||
"""
|
||||
Converts a string to a date object using OpenERP's
|
||||
date string format (exemple: '2011-12-01').
|
||||
"""
|
||||
if not str:
|
||||
return str
|
||||
return datetime.datetime.strptime(str, DEFAULT_SERVER_DATE_FORMAT).date()
|
||||
|
||||
def str_to_time(str):
|
||||
"""
|
||||
Converts a string to a time object using OpenERP's
|
||||
time string format (exemple: '15:12:35').
|
||||
"""
|
||||
if not str:
|
||||
return str
|
||||
return datetime.datetime.strptime(str, DEFAULT_SERVER_TIME_FORMAT).time()
|
||||
|
||||
def datetime_to_str(obj):
|
||||
"""
|
||||
Converts a datetime object to a string using OpenERP's
|
||||
datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
|
||||
The datetime instance should not have an attached timezone and be in UTC.
|
||||
"""
|
||||
if not obj:
|
||||
return False
|
||||
return obj.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
def date_to_str(obj):
|
||||
"""
|
||||
Converts a date object to a string using OpenERP's
|
||||
date string format (exemple: '2011-12-01').
|
||||
"""
|
||||
if not obj:
|
||||
return False
|
||||
return obj.strftime(DEFAULT_SERVER_DATE_FORMAT)
|
||||
|
||||
def time_to_str(obj):
|
||||
"""
|
||||
Converts a time object to a string using OpenERP's
|
||||
time string format (exemple: '15:12:35').
|
||||
"""
|
||||
if not obj:
|
||||
return False
|
||||
return obj.strftime(DEFAULT_SERVER_TIME_FORMAT)
|
||||
|
|
@ -1,311 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) Stephane Wirtel
|
||||
# Copyright (C) 2011 Nicolas Vanhoren
|
||||
# Copyright (C) 2011 OpenERP s.a. (<http://openerp.com>).
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
OpenERP Client Library
|
||||
|
||||
Home page: http://pypi.python.org/pypi/openerp-client-lib
|
||||
Code repository: https://code.launchpad.net/~niv-openerp/openerp-client-lib/trunk
|
||||
"""
|
||||
|
||||
import xmlrpclib
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
def _getChildLogger(logger, subname):
|
||||
return logging.getLogger(logger.name + "." + subname)
|
||||
|
||||
class Connector(object):
|
||||
"""
|
||||
The base abstract class representing a connection to an OpenERP Server.
|
||||
"""
|
||||
|
||||
__logger = _getChildLogger(_logger, 'connector')
|
||||
|
||||
def get_service(self, service_name):
|
||||
"""
|
||||
Returns a Service instance to allow easy manipulation of one of the services offered by the remote server.
|
||||
|
||||
:param service_name: The name of the service.
|
||||
"""
|
||||
return Service(self, service_name)
|
||||
|
||||
class XmlRPCConnector(Connector):
|
||||
"""
|
||||
A type of connector that uses the XMLRPC protocol.
|
||||
"""
|
||||
PROTOCOL = 'xmlrpc'
|
||||
|
||||
__logger = _getChildLogger(_logger, 'connector.xmlrpc')
|
||||
|
||||
def __init__(self, hostname, port=8069):
|
||||
"""
|
||||
Initialize by specifying the hostname and the port.
|
||||
:param hostname: The hostname of the computer holding the instance of OpenERP.
|
||||
:param port: The port used by the OpenERP instance for XMLRPC (default to 8069).
|
||||
"""
|
||||
self.url = 'http://%s:%d/xmlrpc' % (hostname, port)
|
||||
|
||||
def send(self, service_name, method, *args):
|
||||
url = '%s/%s' % (self.url, service_name)
|
||||
service = xmlrpclib.ServerProxy(url)
|
||||
return getattr(service, method)(*args)
|
||||
|
||||
class XmlRPCSConnector(XmlRPCConnector):
|
||||
"""
|
||||
A type of connector that uses the secured XMLRPC protocol.
|
||||
"""
|
||||
PROTOCOL = 'xmlrpcs'
|
||||
|
||||
__logger = _getChildLogger(_logger, 'connector.xmlrpcs')
|
||||
|
||||
def __init__(self, hostname, port=8069):
|
||||
super(XmlRPCSConnector, self).__init__(hostname, port)
|
||||
self.url = 'https://%s:%d/xmlrpc' % (hostname, port)
|
||||
|
||||
class Service(object):
|
||||
"""
|
||||
A class to execute RPC calls on a specific service of the remote server.
|
||||
"""
|
||||
def __init__(self, connector, service_name):
|
||||
"""
|
||||
:param connector: A valid Connector instance.
|
||||
:param service_name: The name of the service on the remote server.
|
||||
"""
|
||||
self.connector = connector
|
||||
self.service_name = service_name
|
||||
self.__logger = _getChildLogger(_getChildLogger(_logger, 'service'),service_name or "")
|
||||
|
||||
def __getattr__(self, method):
|
||||
"""
|
||||
:param method: The name of the method to execute on the service.
|
||||
"""
|
||||
self.__logger.debug('method: %r', method)
|
||||
def proxy(*args):
|
||||
"""
|
||||
:param args: A list of values for the method
|
||||
"""
|
||||
self.__logger.debug('args: %r', args)
|
||||
result = self.connector.send(self.service_name, method, *args)
|
||||
self.__logger.debug('result: %r', result)
|
||||
return result
|
||||
return proxy
|
||||
|
||||
class Connection(object):
|
||||
"""
|
||||
A class to represent a connection with authentication to an OpenERP Server.
|
||||
It also provides utility methods to interact with the server more easily.
|
||||
"""
|
||||
__logger = _getChildLogger(_logger, 'connection')
|
||||
|
||||
def __init__(self, connector,
|
||||
database=None,
|
||||
login=None,
|
||||
password=None,
|
||||
user_id=None):
|
||||
"""
|
||||
Initialize with login information. The login information is facultative to allow specifying
|
||||
it after the initialization of this object.
|
||||
|
||||
:param connector: A valid Connector instance to send messages to the remote server.
|
||||
:param database: The name of the database to work on.
|
||||
:param login: The login of the user.
|
||||
:param password: The password of the user.
|
||||
:param user_id: The user id is a number identifying the user. This is only useful if you
|
||||
already know it, in most cases you don't need to specify it.
|
||||
"""
|
||||
self.connector = connector
|
||||
|
||||
self.set_login_info(database, login, password, user_id)
|
||||
self.user_context = None
|
||||
|
||||
def set_login_info(self, database, login, password, user_id=None):
|
||||
"""
|
||||
Set login information after the initialisation of this object.
|
||||
|
||||
:param connector: A valid Connector instance to send messages to the remote server.
|
||||
:param database: The name of the database to work on.
|
||||
:param login: The login of the user.
|
||||
:param password: The password of the user.
|
||||
:param user_id: The user id is a number identifying the user. This is only useful if you
|
||||
already know it, in most cases you don't need to specify it.
|
||||
"""
|
||||
self.database, self.login, self.password = database, login, password
|
||||
|
||||
self.user_id = user_id
|
||||
|
||||
def check_login(self, force=True):
|
||||
"""
|
||||
Checks that the login information is valid. Throws an AuthenticationError if the
|
||||
authentication fails.
|
||||
|
||||
:param force: Force to re-check even if this Connection was already validated previously.
|
||||
Default to True.
|
||||
"""
|
||||
if self.user_id and not force:
|
||||
return
|
||||
|
||||
if not self.database or not self.login or self.password is None:
|
||||
raise AuthenticationError("Credentials not provided")
|
||||
|
||||
# TODO use authenticate instead of login
|
||||
self.user_id = self.get_service("common").login(self.database, self.login, self.password)
|
||||
if not self.user_id:
|
||||
raise AuthenticationError("Authentication failure")
|
||||
self.__logger.debug("Authenticated with user id %s", self.user_id)
|
||||
|
||||
def get_user_context(self):
|
||||
"""
|
||||
Query the default context of the user.
|
||||
"""
|
||||
if not self.user_context:
|
||||
self.user_context = self.get_model('res.users').context_get()
|
||||
return self.user_context
|
||||
|
||||
def get_model(self, model_name):
|
||||
"""
|
||||
Returns a Model instance to allow easy remote manipulation of an OpenERP model.
|
||||
|
||||
:param model_name: The name of the model.
|
||||
"""
|
||||
return Model(self, model_name)
|
||||
|
||||
def get_service(self, service_name):
|
||||
"""
|
||||
Returns a Service instance to allow easy manipulation of one of the services offered by the remote server.
|
||||
Please note this Connection instance does not need to have valid authentication information since authentication
|
||||
is only necessary for the "object" service that handles models.
|
||||
|
||||
:param service_name: The name of the service.
|
||||
"""
|
||||
return self.connector.get_service(service_name)
|
||||
|
||||
class AuthenticationError(Exception):
|
||||
"""
|
||||
An error thrown when an authentication to an OpenERP server failed.
|
||||
"""
|
||||
pass
|
||||
|
||||
class Model(object):
|
||||
"""
|
||||
Useful class to dialog with one of the models provided by an OpenERP server.
|
||||
An instance of this class depends on a Connection instance with valid authentication information.
|
||||
"""
|
||||
|
||||
def __init__(self, connection, model_name):
|
||||
"""
|
||||
:param connection: A valid Connection instance with correct authentication information.
|
||||
:param model_name: The name of the model.
|
||||
"""
|
||||
self.connection = connection
|
||||
self.model_name = model_name
|
||||
self.__logger = _getChildLogger(_getChildLogger(_logger, 'object'), model_name or "")
|
||||
|
||||
def __getattr__(self, method):
|
||||
"""
|
||||
Provides proxy methods that will forward calls to the model on the remote OpenERP server.
|
||||
|
||||
:param method: The method for the linked model (search, read, write, unlink, create, ...)
|
||||
"""
|
||||
def proxy(*args, **kw):
|
||||
"""
|
||||
:param args: A list of values for the method
|
||||
"""
|
||||
self.connection.check_login(False)
|
||||
self.__logger.debug(args)
|
||||
result = self.connection.get_service('object').execute_kw(
|
||||
self.connection.database,
|
||||
self.connection.user_id,
|
||||
self.connection.password,
|
||||
self.model_name,
|
||||
method,
|
||||
args, kw)
|
||||
if method == "read":
|
||||
if isinstance(result, list) and len(result) > 0 and "id" in result[0]:
|
||||
index = {}
|
||||
for r in result:
|
||||
index[r['id']] = r
|
||||
result = [index[x] for x in args[0] if x in index]
|
||||
self.__logger.debug('result: %r', result)
|
||||
return result
|
||||
return proxy
|
||||
|
||||
def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, context=None):
|
||||
"""
|
||||
A shortcut method to combine a search() and a read().
|
||||
|
||||
:param domain: The domain for the search.
|
||||
:param fields: The fields to extract (can be None or [] to extract all fields).
|
||||
:param offset: The offset for the rows to read.
|
||||
:param limit: The maximum number of rows to read.
|
||||
:param order: The order to class the rows.
|
||||
:param context: The context.
|
||||
:return: A list of dictionaries containing all the specified fields.
|
||||
"""
|
||||
record_ids = self.search(domain or [], offset, limit or False, order or False, context or {})
|
||||
if not record_ids: return []
|
||||
records = self.read(record_ids, fields or [], context or {})
|
||||
return records
|
||||
|
||||
def get_connector(hostname=None, protocol="xmlrpc", port="auto"):
|
||||
"""
|
||||
A shortcut method to easily create a connector to a remote server using XMLRPC.
|
||||
|
||||
:param hostname: The hostname to the remote server.
|
||||
:param protocol: The name of the protocol, must be "xmlrpc" or "xmlrpcs".
|
||||
:param port: The number of the port. Defaults to auto.
|
||||
"""
|
||||
if port == 'auto':
|
||||
port = 8069
|
||||
if protocol == "xmlrpc":
|
||||
return XmlRPCConnector(hostname, port)
|
||||
elif protocol == "xmlrpcs":
|
||||
return XmlRPCSConnector(hostname, port)
|
||||
else:
|
||||
raise ValueError("You must choose xmlrpc or xmlrpcs")
|
||||
|
||||
def get_connection(hostname=None, protocol="xmlrpc", port='auto', database=None,
|
||||
login=None, password=None, user_id=None):
|
||||
"""
|
||||
A shortcut method to easily create a connection to a remote OpenERP server.
|
||||
|
||||
:param hostname: The hostname to the remote server.
|
||||
:param protocol: The name of the protocol, must be "xmlrpc" or "xmlrpcs".
|
||||
:param port: The number of the port. Defaults to auto.
|
||||
:param connector: A valid Connector instance to send messages to the remote server.
|
||||
:param database: The name of the database to work on.
|
||||
:param login: The login of the user.
|
||||
:param password: The password of the user.
|
||||
:param user_id: The user id is a number identifying the user. This is only useful if you
|
||||
already know it, in most cases you don't need to specify it.
|
||||
"""
|
||||
return Connection(get_connector(hostname, protocol, port), database, login, password, user_id)
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
name = 'openerp-web'
|
||||
version = '7.0alpha'
|
||||
description = "OpenERP Web"
|
||||
long_description = "OpenERP Web is the web interface of OpenERP, an Open Source Business Application Suite"
|
||||
author = "OpenERP SA"
|
||||
author_email = "info@openerp.com"
|
||||
support_email = 'support@openerp.com'
|
||||
url = "http://www.openerp.com/"
|
||||
download_url = ''
|
||||
license = "AGPL"
|
|
@ -4,70 +4,58 @@ import babel
|
|||
import dateutil.relativedelta
|
||||
import logging
|
||||
import time
|
||||
import traceback
|
||||
import sys
|
||||
import xmlrpclib
|
||||
|
||||
import openerplib
|
||||
import openerp
|
||||
|
||||
from . import nonliterals
|
||||
import nonliterals
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
#----------------------------------------------------------
|
||||
# openerplib local connector
|
||||
#----------------------------------------------------------
|
||||
class LibException(Exception):
|
||||
""" Base of all client lib exceptions """
|
||||
def __init__(self,code=None,message=None):
|
||||
self.code = code
|
||||
self.message = message
|
||||
|
||||
class ApplicationError(LibException):
|
||||
""" maps to code: 1, server side: Exception or openerp.exceptions.DeferredException"""
|
||||
|
||||
class Warning(LibException):
|
||||
""" maps to code: 2, server side: openerp.exceptions.Warning"""
|
||||
|
||||
class AccessError(LibException):
|
||||
""" maps to code: 3, server side: openerp.exceptions.AccessError"""
|
||||
|
||||
class AccessDenied(LibException):
|
||||
""" maps to code: 4, server side: openerp.exceptions.AccessDenied"""
|
||||
|
||||
class LocalConnector(openerplib.Connector):
|
||||
"""
|
||||
A type of connector that uses the XMLRPC protocol.
|
||||
"""
|
||||
PROTOCOL = 'local'
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def send(self, service_name, method, *args):
|
||||
import openerp
|
||||
import traceback
|
||||
import xmlrpclib
|
||||
code_string = "warning -- %s\n\n%s"
|
||||
try:
|
||||
return openerp.netsvc.dispatch_rpc(service_name, method, args)
|
||||
except openerp.osv.osv.except_osv, e:
|
||||
# TODO change the except to raise LibException instead of their emulated xmlrpc fault
|
||||
raise xmlrpclib.Fault(code_string % (e.name, e.value), '')
|
||||
except openerp.exceptions.Warning, e:
|
||||
raise xmlrpclib.Fault(code_string % ("Warning", e), '')
|
||||
except openerp.exceptions.AccessError, e:
|
||||
raise xmlrpclib.Fault(code_string % ("AccessError", e), '')
|
||||
except openerp.exceptions.AccessDenied, e:
|
||||
raise xmlrpclib.Fault('AccessDenied', str(e))
|
||||
except openerp.exceptions.DeferredException, e:
|
||||
formatted_info = "".join(traceback.format_exception(*e.traceback))
|
||||
raise xmlrpclib.Fault(openerp.tools.ustr(e.message), formatted_info)
|
||||
except Exception, e:
|
||||
formatted_info = "".join(traceback.format_exception(*(sys.exc_info())))
|
||||
raise xmlrpclib.Fault(openerp.tools.exception_to_unicode(e), formatted_info)
|
||||
|
||||
#----------------------------------------------------------
|
||||
# OpenERPSession RPC openerp backend access
|
||||
#----------------------------------------------------------
|
||||
class AuthenticationError(Exception):
|
||||
pass
|
||||
|
||||
class Service(object):
|
||||
def __init__(self, session, service_name):
|
||||
self.session = session
|
||||
self.service_name = service_name
|
||||
|
||||
def __getattr__(self, method):
|
||||
def proxy_method(*args):
|
||||
result = self.session.send(self.service_name, method, *args)
|
||||
return result
|
||||
return proxy_method
|
||||
|
||||
class Model(object):
|
||||
def __init__(self, session, model):
|
||||
self.session = session
|
||||
self.model = model
|
||||
self.proxy = self.session.proxy('object')
|
||||
|
||||
def __getattr__(self, method):
|
||||
def proxy(*args, **kw):
|
||||
result = self.proxy.execute_kw(self.session._db, self.session._uid, self.session._password, self.model, method, args, kw)
|
||||
# reorder read
|
||||
if method == "read":
|
||||
if isinstance(result, list) and len(result) > 0 and "id" in result[0]:
|
||||
index = {}
|
||||
for r in result:
|
||||
index[r['id']] = r
|
||||
result = [index[x] for x in args[0] if x in index]
|
||||
return result
|
||||
return proxy
|
||||
|
||||
def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, context=None):
|
||||
record_ids = self.search(domain or [], offset, limit or False, order or False, context or {})
|
||||
if not record_ids: return []
|
||||
records = self.read(record_ids, fields or [], context or {})
|
||||
return records
|
||||
|
||||
class OpenERPSession(object):
|
||||
"""
|
||||
An OpenERP RPC session, a given user can own multiple such sessions
|
||||
|
@ -87,7 +75,6 @@ class OpenERPSession(object):
|
|||
"""
|
||||
def __init__(self):
|
||||
self._creation_time = time.time()
|
||||
self.config = None
|
||||
self._db = False
|
||||
self._uid = False
|
||||
self._login = False
|
||||
|
@ -98,19 +85,27 @@ class OpenERPSession(object):
|
|||
self.domains_store = {}
|
||||
self.jsonp_requests = {} # FIXME use a LRU
|
||||
|
||||
def __getstate__(self):
|
||||
state = dict(self.__dict__)
|
||||
if "config" in state:
|
||||
del state['config']
|
||||
return state
|
||||
|
||||
def build_connection(self):
|
||||
conn = openerplib.Connection(self.config.connector, database=self._db, login=self._login,
|
||||
user_id=self._uid, password=self._password)
|
||||
return conn
|
||||
def send(self, service_name, method, *args):
|
||||
code_string = "warning -- %s\n\n%s"
|
||||
try:
|
||||
return openerp.netsvc.dispatch_rpc(service_name, method, args)
|
||||
except openerp.osv.osv.except_osv, e:
|
||||
raise xmlrpclib.Fault(code_string % (e.name, e.value), '')
|
||||
except openerp.exceptions.Warning, e:
|
||||
raise xmlrpclib.Fault(code_string % ("Warning", e), '')
|
||||
except openerp.exceptions.AccessError, e:
|
||||
raise xmlrpclib.Fault(code_string % ("AccessError", e), '')
|
||||
except openerp.exceptions.AccessDenied, e:
|
||||
raise xmlrpclib.Fault('AccessDenied', str(e))
|
||||
except openerp.exceptions.DeferredException, e:
|
||||
formatted_info = "".join(traceback.format_exception(*e.traceback))
|
||||
raise xmlrpclib.Fault(openerp.tools.ustr(e.message), formatted_info)
|
||||
except Exception, e:
|
||||
formatted_info = "".join(traceback.format_exception(*(sys.exc_info())))
|
||||
raise xmlrpclib.Fault(openerp.tools.exception_to_unicode(e), formatted_info)
|
||||
|
||||
def proxy(self, service):
|
||||
return self.build_connection().get_service(service)
|
||||
return Service(self, service)
|
||||
|
||||
def bind(self, db, uid, login, password):
|
||||
self._db = db
|
||||
|
@ -119,7 +114,6 @@ class OpenERPSession(object):
|
|||
self._password = password
|
||||
|
||||
def authenticate(self, db, login, password, env=None):
|
||||
# TODO use the openerplib API once it exposes authenticate()
|
||||
uid = self.proxy('common').authenticate(db, login, password, env)
|
||||
self.bind(db, uid, login, password)
|
||||
|
||||
|
@ -130,7 +124,12 @@ class OpenERPSession(object):
|
|||
"""
|
||||
Ensures this session is valid (logged into the openerp server)
|
||||
"""
|
||||
self.build_connection().check_login(force)
|
||||
if self._uid and not force:
|
||||
return
|
||||
# TODO use authenticate instead of login
|
||||
uid = self.proxy("common").login(self._db, self._login, self._password)
|
||||
if not uid:
|
||||
raise AuthenticationError("Authentication failure")
|
||||
|
||||
def ensure_valid(self):
|
||||
if self._uid:
|
||||
|
@ -141,7 +140,7 @@ class OpenERPSession(object):
|
|||
|
||||
def execute(self, model, func, *l, **d):
|
||||
self.assert_valid()
|
||||
model = self.build_connection().get_model(model)
|
||||
model = self.model(model)
|
||||
r = getattr(model, func)(*l, **d)
|
||||
return r
|
||||
|
||||
|
@ -157,7 +156,8 @@ class OpenERPSession(object):
|
|||
:type model: str
|
||||
:rtype: a model object
|
||||
"""
|
||||
return self.build_connection().get_model(model)
|
||||
|
||||
return Model(self, model)
|
||||
|
||||
def get_context(self):
|
||||
""" Re-initializes the current user's session context (based on
|
||||
|
@ -167,7 +167,7 @@ class OpenERPSession(object):
|
|||
:returns: the new context
|
||||
"""
|
||||
assert self._uid, "The user needs to be logged-in to initialize his context"
|
||||
self.context = self.build_connection().get_user_context() or {}
|
||||
self.context = self.model('res.users').context_get() or {}
|
||||
self.context['uid'] = self._uid
|
||||
self._fix_lang(self.context)
|
||||
return self.context
|
||||
|
|
|
@ -27,6 +27,8 @@ try:
|
|||
except ImportError:
|
||||
xlwt = None
|
||||
|
||||
import openerp
|
||||
|
||||
from .. import common
|
||||
openerpweb = common.http
|
||||
|
||||
|
@ -135,7 +137,7 @@ def db_list(req):
|
|||
dbs = proxy.list()
|
||||
h = req.httprequest.environ['HTTP_HOST'].split(':')[0]
|
||||
d = h.split('.')[0]
|
||||
r = req.config.dbfilter.replace('%h', h).replace('%d', d)
|
||||
r = openerp.tools.config['dbfilter'].replace('%h', h).replace('%d', d)
|
||||
dbs = [i for i in dbs if re.match(r, i)]
|
||||
return dbs
|
||||
|
||||
|
@ -227,11 +229,12 @@ def module_installed_bypass_session(dbname):
|
|||
return sorted_modules
|
||||
|
||||
def module_boot(req):
|
||||
return [m for m in req.config.server_wide_modules if m in openerpweb.addons_manifest]
|
||||
server_wide_modules = openerp.conf.server_wide_modules or ['web']
|
||||
return [m for m in server_wide_modules if m in openerpweb.addons_manifest]
|
||||
# TODO the following will be enabled once we separate the module code and translation loading
|
||||
serverside = []
|
||||
dbside = []
|
||||
for i in req.config.server_wide_modules:
|
||||
for i in server_wide_modules:
|
||||
if i in openerpweb.addons_manifest:
|
||||
serverside.append(i)
|
||||
# if only one db load every module at boot
|
||||
|
@ -507,7 +510,7 @@ def parse_domain(domain, session):
|
|||
:param domain: the domain to parse, if the domain is not a string it
|
||||
is assumed to be a literal domain and is returned as-is
|
||||
:param session: Current OpenERP session
|
||||
:type session: openerpweb.openerpweb.OpenERPSession
|
||||
:type session: openerpweb.OpenERPSession
|
||||
"""
|
||||
if not isinstance(domain, basestring):
|
||||
return domain
|
||||
|
@ -524,7 +527,7 @@ def parse_context(context, session):
|
|||
:param context: the context to parse, if the context is not a string it
|
||||
is assumed to be a literal domain and is returned as-is
|
||||
:param session: Current OpenERP session
|
||||
:type session: openerpweb.openerpweb.OpenERPSession
|
||||
:type session: openerpweb.OpenERPSession
|
||||
"""
|
||||
if not isinstance(context, basestring):
|
||||
return context
|
||||
|
@ -612,7 +615,6 @@ class Home(openerpweb.Controller):
|
|||
def login(self, req, db, login, key):
|
||||
return login_and_redirect(req, db, login, key)
|
||||
|
||||
|
||||
class WebClient(openerpweb.Controller):
|
||||
_cp_path = "/web/webclient"
|
||||
|
||||
|
@ -746,7 +748,7 @@ class WebClient(openerpweb.Controller):
|
|||
@openerpweb.jsonrequest
|
||||
def version_info(self, req):
|
||||
return {
|
||||
"version": common.release.version
|
||||
"version": openerp.release.version
|
||||
}
|
||||
|
||||
class Proxy(openerpweb.Controller):
|
||||
|
@ -862,12 +864,10 @@ class Session(openerpweb.Controller):
|
|||
@openerpweb.jsonrequest
|
||||
def authenticate(self, req, db, login, password, base_location=None):
|
||||
wsgienv = req.httprequest.environ
|
||||
release = common.release
|
||||
env = dict(
|
||||
base_location=base_location,
|
||||
HTTP_HOST=wsgienv['HTTP_HOST'],
|
||||
REMOTE_ADDR=wsgienv['REMOTE_ADDR'],
|
||||
user_agent="%s / %s" % (release.name, release.version),
|
||||
)
|
||||
req.session.authenticate(db, login, password, env)
|
||||
|
||||
|
|
Loading…
Reference in New Issue