[FIX] *: werkzeug 1.0 compat (and some other deprecation warnings)
Some more leftover deprecation warnings I missed in odoo/odoo#44164, which turned into errors when Werkzeug 1.0 was released, as well as a few other issues. closes odoo/odoo#45931 Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This commit is contained in:
@@ -8,7 +8,7 @@ import hmac
|
||||
import threading
|
||||
|
||||
from hashlib import sha1
|
||||
from werkzeug import url_encode
|
||||
from werkzeug.urls import url_encode
|
||||
|
||||
from odoo import api, models, tools
|
||||
|
||||
|
||||
@@ -269,7 +269,9 @@ class IrHttp(models.AbstractModel):
|
||||
for url, endpoint, routing in cls._generate_routing_rules(mods, converters=cls._get_converters()):
|
||||
xtra_keys = 'defaults subdomain build_only strict_slashes redirect_to alias host'.split()
|
||||
kw = {k: routing[k] for k in xtra_keys if k in routing}
|
||||
routing_map.add(werkzeug.routing.Rule(url, endpoint=endpoint, methods=routing['methods'], **kw))
|
||||
rule = werkzeug.routing.Rule(url, endpoint=endpoint, methods=routing['methods'], **kw)
|
||||
rule.merge_slashes = False
|
||||
routing_map.add(rule)
|
||||
cls._routing_map[key] = routing_map
|
||||
return cls._routing_map[key]
|
||||
|
||||
|
||||
+11
-7
@@ -30,15 +30,17 @@ from datetime import datetime, date
|
||||
import passlib.utils
|
||||
import psycopg2
|
||||
import json
|
||||
import werkzeug.contrib.sessions
|
||||
import werkzeug.datastructures
|
||||
import werkzeug.exceptions
|
||||
import werkzeug.local
|
||||
import werkzeug.routing
|
||||
import werkzeug.wrappers
|
||||
import werkzeug.wsgi
|
||||
from werkzeug import urls
|
||||
from werkzeug.wsgi import wrap_file
|
||||
try:
|
||||
from werkzeug.middleware.shared_data import SharedDataMiddleware
|
||||
except ImportError:
|
||||
from werkzeug.wsgi import SharedDataMiddleware
|
||||
|
||||
try:
|
||||
import psutil
|
||||
@@ -53,7 +55,7 @@ from .sql_db import flush_env
|
||||
from .tools.func import lazy_property
|
||||
from .tools import ustr, consteq, frozendict, pycompat, unique, date_utils
|
||||
from .tools.mimetypes import guess_mimetype
|
||||
|
||||
from .tools._vendor import sessions
|
||||
from .modules.module import module_manifest
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
@@ -957,7 +959,7 @@ class AuthenticationError(Exception):
|
||||
class SessionExpiredException(Exception):
|
||||
pass
|
||||
|
||||
class OpenERPSession(werkzeug.contrib.sessions.Session):
|
||||
class OpenERPSession(sessions.Session):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.inited = False
|
||||
self.modified = False
|
||||
@@ -1258,7 +1260,7 @@ class Root(object):
|
||||
# Setup http sessions
|
||||
path = odoo.tools.config.session_dir
|
||||
_logger.debug('HTTP sessions stored in: %s', path)
|
||||
return werkzeug.contrib.sessions.FilesystemSessionStore(
|
||||
return sessions.FilesystemSessionStore(
|
||||
path, session_class=OpenERPSession, renew_missing=True)
|
||||
|
||||
@lazy_property
|
||||
@@ -1266,7 +1268,9 @@ class Root(object):
|
||||
_logger.info("Generating nondb routing")
|
||||
routing_map = werkzeug.routing.Map(strict_slashes=False, converters=None)
|
||||
for url, endpoint, routing in odoo.http._generate_routing_rules([''] + odoo.conf.server_wide_modules, True):
|
||||
routing_map.add(werkzeug.routing.Rule(url, endpoint=endpoint, methods=routing['methods']))
|
||||
rule = werkzeug.routing.Rule(url, endpoint=endpoint, methods=routing['methods'])
|
||||
rule.merge_slashes = False
|
||||
routing_map.add(rule)
|
||||
return routing_map
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
@@ -1301,7 +1305,7 @@ class Root(object):
|
||||
|
||||
if statics:
|
||||
_logger.info("HTTP Configuring static files")
|
||||
app = werkzeug.wsgi.SharedDataMiddleware(self.dispatch, statics, cache_timeout=STATIC_CACHE)
|
||||
app = SharedDataMiddleware(self.dispatch, statics, cache_timeout=STATIC_CACHE)
|
||||
self.dispatch = DisableCacheMiddleware(app)
|
||||
|
||||
def setup_session(self, httprequest):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import ast
|
||||
import collections
|
||||
import collections.abc
|
||||
import importlib
|
||||
import inspect
|
||||
import itertools
|
||||
@@ -260,7 +260,7 @@ def load_information_from_description_file(module, mod_path=None):
|
||||
# auto_install: [] to always auto_install a module regardless of its
|
||||
# dependencies
|
||||
auto_install = info.get('auto_install', info.get('active', False))
|
||||
if isinstance(auto_install, collections.Iterable):
|
||||
if isinstance(auto_install, collections.abc.Iterable):
|
||||
info['auto_install'] = set(auto_install)
|
||||
non_dependencies = info['auto_install'].difference(info['depends'])
|
||||
assert not non_dependencies,\
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ def init_logger():
|
||||
logging.setLogRecordFactory(record_factory)
|
||||
|
||||
# enable deprecation warnings (disabled by default)
|
||||
warnings.filterwarnings('once', category=DeprecationWarning)
|
||||
warnings.filterwarnings('default', category=DeprecationWarning)
|
||||
# ignore deprecation warnings from invalid escape (there's a ton and it's
|
||||
# pretty likely a super low-value signal)
|
||||
warnings.filterwarnings('ignore', r'^invalid escape sequence \\.', category=DeprecationWarning)
|
||||
|
||||
@@ -113,7 +113,7 @@ Finally, to instruct OpenERP to really use the unaccent function, you have to
|
||||
start the server specifying the ``--unaccent`` flag.
|
||||
|
||||
"""
|
||||
import collections
|
||||
import collections.abc
|
||||
|
||||
import logging
|
||||
import traceback
|
||||
@@ -958,7 +958,7 @@ class expression(object):
|
||||
op2 = (TERM_OPERATORS_NEGATION[operator]
|
||||
if operator in NEGATIVE_TERM_OPERATORS else operator)
|
||||
ids2 = [x[0] for x in comodel.name_search(right, domain or [], op2, limit=None)]
|
||||
elif isinstance(right, collections.Iterable):
|
||||
elif isinstance(right, collections.abc.Iterable):
|
||||
ids2 = right
|
||||
else:
|
||||
ids2 = [right]
|
||||
@@ -1018,7 +1018,7 @@ class expression(object):
|
||||
op2 = (TERM_OPERATORS_NEGATION[operator]
|
||||
if operator in NEGATIVE_TERM_OPERATORS else operator)
|
||||
ids2 = [x[0] for x in comodel.name_search(right, domain or [], op2, limit=None)]
|
||||
elif isinstance(right, collections.Iterable):
|
||||
elif isinstance(right, collections.abc.Iterable):
|
||||
ids2 = right
|
||||
else:
|
||||
ids2 = [right]
|
||||
|
||||
@@ -17,7 +17,6 @@ from xmlrpc import client as xmlrpclib
|
||||
import werkzeug.exceptions
|
||||
import werkzeug.wrappers
|
||||
import werkzeug.serving
|
||||
import werkzeug.contrib.fixers
|
||||
|
||||
import odoo
|
||||
from odoo.tools import config
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
r"""
|
||||
Vendored copy of https://github.com/pallets/werkzeug/blob/2b2c4c3dd3cf7389e9f4aa06371b7332257c6289/src/werkzeug/contrib/sessions.py
|
||||
|
||||
werkzeug.contrib was removed from werkzeug 1.0. sessions (and secure
|
||||
cookies) were moved to the secure-cookies package. Problem is distros
|
||||
are starting to update werkzeug to 1.0 without having secure-cookies
|
||||
(e.g. Arch has done so, Debian has updated python-werkzeug in
|
||||
"experimental"), which will be problematic once that starts trickling
|
||||
down onto more stable distros and people start deploying that.
|
||||
|
||||
Edited some to fix imports and remove some compatibility things
|
||||
(mostly PY2) and the unnecessary (to us) SessionMiddleware
|
||||
|
||||
:copyright: 2007 Pallets
|
||||
:license: BSD-3-Clause
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import tempfile
|
||||
from hashlib import sha1
|
||||
from os import path
|
||||
from pickle import dump
|
||||
from pickle import HIGHEST_PROTOCOL
|
||||
from pickle import load
|
||||
from time import time
|
||||
|
||||
from werkzeug.datastructures import CallbackDict
|
||||
from werkzeug.posixemulation import rename
|
||||
|
||||
_sha1_re = re.compile(r"^[a-f0-9]{40}$")
|
||||
|
||||
|
||||
def generate_key(salt=None):
|
||||
if salt is None:
|
||||
salt = repr(salt).encode("ascii")
|
||||
return sha1(b"".join([salt, str(time()).encode("ascii"), os.urandom(30)])).hexdigest()
|
||||
|
||||
|
||||
class ModificationTrackingDict(CallbackDict):
|
||||
__slots__ = ("modified",)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
def on_update(self):
|
||||
self.modified = True
|
||||
|
||||
self.modified = False
|
||||
CallbackDict.__init__(self, on_update=on_update)
|
||||
dict.update(self, *args, **kwargs)
|
||||
|
||||
def copy(self):
|
||||
"""Create a flat copy of the dict."""
|
||||
missing = object()
|
||||
result = object.__new__(self.__class__)
|
||||
for name in self.__slots__:
|
||||
val = getattr(self, name, missing)
|
||||
if val is not missing:
|
||||
setattr(result, name, val)
|
||||
return result
|
||||
|
||||
def __copy__(self):
|
||||
return self.copy()
|
||||
|
||||
|
||||
class Session(ModificationTrackingDict):
|
||||
"""Subclass of a dict that keeps track of direct object changes. Changes
|
||||
in mutable structures are not tracked, for those you have to set
|
||||
`modified` to `True` by hand.
|
||||
"""
|
||||
|
||||
__slots__ = ModificationTrackingDict.__slots__ + ("sid", "new")
|
||||
|
||||
def __init__(self, data, sid, new=False):
|
||||
ModificationTrackingDict.__init__(self, data)
|
||||
self.sid = sid
|
||||
self.new = new
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s %s%s>" % (
|
||||
self.__class__.__name__,
|
||||
dict.__repr__(self),
|
||||
"*" if self.should_save else "",
|
||||
)
|
||||
|
||||
@property
|
||||
def should_save(self):
|
||||
"""True if the session should be saved.
|
||||
|
||||
.. versionchanged:: 0.6
|
||||
By default the session is now only saved if the session is
|
||||
modified, not if it is new like it was before.
|
||||
"""
|
||||
return self.modified
|
||||
|
||||
|
||||
class SessionStore(object):
|
||||
"""Baseclass for all session stores. The Werkzeug contrib module does not
|
||||
implement any useful stores besides the filesystem store, application
|
||||
developers are encouraged to create their own stores.
|
||||
|
||||
:param session_class: The session class to use. Defaults to
|
||||
:class:`Session`.
|
||||
"""
|
||||
|
||||
def __init__(self, session_class=None):
|
||||
if session_class is None:
|
||||
session_class = Session
|
||||
self.session_class = session_class
|
||||
|
||||
def is_valid_key(self, key):
|
||||
"""Check if a key has the correct format."""
|
||||
return _sha1_re.match(key) is not None
|
||||
|
||||
def generate_key(self, salt=None):
|
||||
"""Simple function that generates a new session key."""
|
||||
return generate_key(salt)
|
||||
|
||||
def new(self):
|
||||
"""Generate a new session."""
|
||||
return self.session_class({}, self.generate_key(), True)
|
||||
|
||||
def save(self, session):
|
||||
"""Save a session."""
|
||||
|
||||
def save_if_modified(self, session):
|
||||
"""Save if a session class wants an update."""
|
||||
if session.should_save:
|
||||
self.save(session)
|
||||
|
||||
def delete(self, session):
|
||||
"""Delete a session."""
|
||||
|
||||
def get(self, sid):
|
||||
"""Get a session for this sid or a new session object. This method
|
||||
has to check if the session key is valid and create a new session if
|
||||
that wasn't the case.
|
||||
"""
|
||||
return self.session_class({}, sid, True)
|
||||
|
||||
|
||||
#: used for temporary files by the filesystem session store
|
||||
_fs_transaction_suffix = ".__wz_sess"
|
||||
|
||||
|
||||
class FilesystemSessionStore(SessionStore):
|
||||
"""Simple example session store that saves sessions on the filesystem.
|
||||
This store works best on POSIX systems and Windows Vista / Windows
|
||||
Server 2008 and newer.
|
||||
|
||||
.. versionchanged:: 0.6
|
||||
`renew_missing` was added. Previously this was considered `True`,
|
||||
now the default changed to `False` and it can be explicitly
|
||||
deactivated.
|
||||
|
||||
:param path: the path to the folder used for storing the sessions.
|
||||
If not provided the default temporary directory is used.
|
||||
:param filename_template: a string template used to give the session
|
||||
a filename. ``%s`` is replaced with the
|
||||
session id.
|
||||
:param session_class: The session class to use. Defaults to
|
||||
:class:`Session`.
|
||||
:param renew_missing: set to `True` if you want the store to
|
||||
give the user a new sid if the session was
|
||||
not yet saved.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
path=None,
|
||||
filename_template="werkzeug_%s.sess",
|
||||
session_class=None,
|
||||
renew_missing=False,
|
||||
mode=0o644,
|
||||
):
|
||||
SessionStore.__init__(self, session_class)
|
||||
if path is None:
|
||||
path = tempfile.gettempdir()
|
||||
self.path = path
|
||||
assert not filename_template.endswith(_fs_transaction_suffix), (
|
||||
"filename templates may not end with %s" % _fs_transaction_suffix
|
||||
)
|
||||
self.filename_template = filename_template
|
||||
self.renew_missing = renew_missing
|
||||
self.mode = mode
|
||||
|
||||
def get_session_filename(self, sid):
|
||||
# out of the box, this should be a strict ASCII subset but
|
||||
# you might reconfigure the session object to have a more
|
||||
# arbitrary string.
|
||||
return path.join(self.path, self.filename_template % sid)
|
||||
|
||||
def save(self, session):
|
||||
fn = self.get_session_filename(session.sid)
|
||||
fd, tmp = tempfile.mkstemp(suffix=_fs_transaction_suffix, dir=self.path)
|
||||
f = os.fdopen(fd, "wb")
|
||||
try:
|
||||
dump(dict(session), f, HIGHEST_PROTOCOL)
|
||||
finally:
|
||||
f.close()
|
||||
try:
|
||||
rename(tmp, fn)
|
||||
os.chmod(fn, self.mode)
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
|
||||
def delete(self, session):
|
||||
fn = self.get_session_filename(session.sid)
|
||||
try:
|
||||
os.unlink(fn)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def get(self, sid):
|
||||
if not self.is_valid_key(sid):
|
||||
return self.new()
|
||||
try:
|
||||
f = open(self.get_session_filename(sid), "rb")
|
||||
except IOError:
|
||||
if self.renew_missing:
|
||||
return self.new()
|
||||
data = {}
|
||||
else:
|
||||
try:
|
||||
try:
|
||||
data = load(f)
|
||||
except Exception:
|
||||
data = {}
|
||||
finally:
|
||||
f.close()
|
||||
return self.session_class(data, sid, False)
|
||||
|
||||
def list(self):
|
||||
"""Lists all sessions in the store.
|
||||
|
||||
.. versionadded:: 0.6
|
||||
"""
|
||||
before, after = self.filename_template.split("%s", 1)
|
||||
filename_re = re.compile(
|
||||
r"%s(.{5,})%s$" % (re.escape(before), re.escape(after))
|
||||
)
|
||||
result = []
|
||||
for filename in os.listdir(self.path):
|
||||
#: this is a session that is still being saved.
|
||||
if filename.endswith(_fs_transaction_suffix):
|
||||
continue
|
||||
match = filename_re.match(filename)
|
||||
if match is not None:
|
||||
result.append(match.group(1))
|
||||
return result
|
||||
+1
-1
@@ -40,7 +40,7 @@ requests==2.21.0
|
||||
zeep==3.2.0
|
||||
python-stdnum==1.8
|
||||
vobject==0.9.6.1
|
||||
Werkzeug==0.14.1
|
||||
Werkzeug==0.16.1
|
||||
XlsxWriter==1.1.2
|
||||
xlwt==1.3.*
|
||||
xlrd==1.1.0
|
||||
|
||||
Reference in New Issue
Block a user