tryton 7.0.20__py3-none-any.whl → 7.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tryton might be problematic. Click here for more details.
- tryton/__init__.py +1 -1
- tryton/cache.py +34 -0
- tryton/common/common.py +125 -69
- tryton/common/completion.py +2 -2
- tryton/common/domain_inversion.py +1 -2
- tryton/common/domain_parser.py +7 -17
- tryton/common/selection.py +6 -3
- tryton/common/tempfile.py +34 -0
- tryton/config.py +3 -2
- tryton/data/locale/bg/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/bg/LC_MESSAGES/tryton.po +28 -3
- tryton/data/locale/ca/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/ca/LC_MESSAGES/tryton.po +33 -5
- tryton/data/locale/cs/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/cs/LC_MESSAGES/tryton.po +28 -3
- tryton/data/locale/de/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/de/LC_MESSAGES/tryton.po +32 -4
- tryton/data/locale/es/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/es/LC_MESSAGES/tryton.po +32 -4
- tryton/data/locale/es_419/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/es_419/LC_MESSAGES/tryton.po +29 -4
- tryton/data/locale/et/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/et/LC_MESSAGES/tryton.po +32 -5
- tryton/data/locale/fa/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/fa/LC_MESSAGES/tryton.po +32 -6
- tryton/data/locale/fi/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/fi/LC_MESSAGES/tryton.po +28 -3
- tryton/data/locale/fr/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/fr/LC_MESSAGES/tryton.po +32 -4
- tryton/data/locale/hu/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/hu/LC_MESSAGES/tryton.po +32 -5
- tryton/data/locale/id/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/id/LC_MESSAGES/tryton.po +30 -3
- tryton/data/locale/it/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/it/LC_MESSAGES/tryton.po +31 -5
- tryton/data/locale/ja_JP/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/lo/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/lo/LC_MESSAGES/tryton.po +31 -5
- tryton/data/locale/lt/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/lt/LC_MESSAGES/tryton.po +32 -5
- tryton/data/locale/nl/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/nl/LC_MESSAGES/tryton.po +32 -4
- tryton/data/locale/pl/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/pl/LC_MESSAGES/tryton.po +32 -5
- tryton/data/locale/pt/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/pt/LC_MESSAGES/tryton.po +31 -5
- tryton/data/locale/ro/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/ro/LC_MESSAGES/tryton.po +43 -16
- tryton/data/locale/ru/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/ru/LC_MESSAGES/tryton.po +29 -5
- tryton/data/locale/sl/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/sl/LC_MESSAGES/tryton.po +32 -4
- tryton/data/locale/tr/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/tr/LC_MESSAGES/tryton.po +28 -3
- tryton/data/locale/uk/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/uk/LC_MESSAGES/tryton.po +32 -5
- tryton/data/locale/zh_CN/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/zh_CN/LC_MESSAGES/tryton.po +32 -4
- tryton/device_cookie.py +1 -1
- tryton/gui/main.py +3 -2
- tryton/gui/window/about.py +1 -1
- tryton/gui/window/dblogin.py +2 -2
- tryton/gui/window/email_.py +1 -1
- tryton/gui/window/form.py +4 -3
- tryton/gui/window/log.py +24 -2
- tryton/gui/window/view_form/model/field.py +56 -62
- tryton/gui/window/view_form/model/group.py +3 -1
- tryton/gui/window/view_form/model/record.py +55 -16
- tryton/gui/window/view_form/screen/screen.py +15 -12
- tryton/gui/window/view_form/view/calendar_gtk/calendar_.py +7 -12
- tryton/gui/window/view_form/view/form.py +4 -14
- tryton/gui/window/view_form/view/form_gtk/dictionary.py +33 -27
- tryton/gui/window/view_form/view/form_gtk/document.py +10 -9
- tryton/gui/window/view_form/view/form_gtk/many2many.py +17 -7
- tryton/gui/window/view_form/view/form_gtk/many2one.py +21 -13
- tryton/gui/window/view_form/view/form_gtk/one2many.py +25 -6
- tryton/gui/window/view_form/view/form_gtk/state_widget.py +6 -2
- tryton/gui/window/view_form/view/list.py +47 -56
- tryton/gui/window/view_form/view/list_gtk/widget.py +36 -23
- tryton/gui/window/view_form/view/screen_container.py +5 -3
- tryton/gui/window/win_export.py +1 -2
- tryton/gui/window/win_form.py +6 -8
- tryton/gui/window/wizard.py +11 -10
- tryton/jsonrpc.py +41 -27
- tryton/pyson.py +54 -4
- tryton/rpc.py +18 -0
- tryton/tests/test_common_domain_parser.py +0 -8
- {tryton-7.0.20.data → tryton-7.2.0.data}/scripts/tryton +1 -2
- {tryton-7.0.20.dist-info → tryton-7.2.0.dist-info}/METADATA +5 -5
- {tryton-7.0.20.dist-info → tryton-7.2.0.dist-info}/RECORD +93 -91
- {tryton-7.0.20.dist-info → tryton-7.2.0.dist-info}/WHEEL +1 -1
- {tryton-7.0.20.dist-info → tryton-7.2.0.dist-info}/LICENSE +0 -0
- {tryton-7.0.20.dist-info → tryton-7.2.0.dist-info}/top_level.txt +0 -0
tryton/gui/window/wizard.py
CHANGED
|
@@ -150,16 +150,17 @@ class Wizard(InfoBar):
|
|
|
150
150
|
|
|
151
151
|
def end(self, callback=None):
|
|
152
152
|
def end_callback(action):
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
callback
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
153
|
+
try:
|
|
154
|
+
self.destroy(action=action())
|
|
155
|
+
if callback:
|
|
156
|
+
callback()
|
|
157
|
+
except RPCException:
|
|
158
|
+
logger.warn(
|
|
159
|
+
"Unable to delete session %s of wizard %s",
|
|
160
|
+
self.session_id, self.action, exc_info=True)
|
|
161
|
+
RPCExecute(
|
|
162
|
+
'wizard', self.action, 'delete', self.session_id,
|
|
163
|
+
process_exception=False, callback=end_callback)
|
|
163
164
|
|
|
164
165
|
def clean(self):
|
|
165
166
|
for widget in self.widget.get_children():
|
tryton/jsonrpc.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import base64
|
|
4
4
|
import datetime
|
|
5
5
|
import errno
|
|
6
|
+
import gettext
|
|
6
7
|
import hashlib
|
|
7
8
|
import http.client
|
|
8
9
|
import json
|
|
@@ -11,17 +12,20 @@ import socket
|
|
|
11
12
|
import ssl
|
|
12
13
|
import threading
|
|
13
14
|
import xmlrpc.client
|
|
14
|
-
from collections import defaultdict
|
|
15
15
|
from contextlib import contextmanager
|
|
16
16
|
from decimal import Decimal
|
|
17
17
|
from functools import partial, reduce
|
|
18
18
|
from urllib.parse import quote, urljoin
|
|
19
19
|
|
|
20
|
+
from .cache import CacheDict
|
|
21
|
+
from .config import CONFIG
|
|
22
|
+
|
|
20
23
|
__all__ = ["ResponseError", "Fault", "ProtocolError", "Transport",
|
|
21
24
|
"ServerProxy", "ServerPool"]
|
|
22
25
|
CONNECT_TIMEOUT = 5
|
|
23
26
|
DEFAULT_TIMEOUT = None
|
|
24
27
|
logger = logging.getLogger(__name__)
|
|
28
|
+
_ = gettext.gettext
|
|
25
29
|
|
|
26
30
|
|
|
27
31
|
def deepcopy(obj):
|
|
@@ -193,34 +197,38 @@ class Transport(xmlrpc.client.SafeTransport):
|
|
|
193
197
|
ssl_ctx = ssl.create_default_context(cafile=self.__ca_certs)
|
|
194
198
|
|
|
195
199
|
def http_connection():
|
|
196
|
-
|
|
197
|
-
timeout=CONNECT_TIMEOUT)
|
|
198
|
-
self._connection
|
|
199
|
-
|
|
200
|
-
sock
|
|
201
|
-
sock
|
|
200
|
+
connection = http.client.HTTPConnection(
|
|
201
|
+
chost, timeout=CONNECT_TIMEOUT)
|
|
202
|
+
self._connection = host, connection
|
|
203
|
+
connection.connect()
|
|
204
|
+
sock = connection.sock
|
|
205
|
+
if sock:
|
|
206
|
+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
|
207
|
+
return connection
|
|
202
208
|
|
|
203
209
|
def https_connection(allow_http=False):
|
|
204
|
-
|
|
205
|
-
timeout=CONNECT_TIMEOUT, context=ssl_ctx)
|
|
210
|
+
connection = http.client.HTTPSConnection(
|
|
211
|
+
chost, timeout=CONNECT_TIMEOUT, context=ssl_ctx)
|
|
212
|
+
self._connection = host, connection
|
|
206
213
|
try:
|
|
207
|
-
|
|
208
|
-
sock =
|
|
209
|
-
sock
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
214
|
+
connection.connect()
|
|
215
|
+
sock = connection.sock
|
|
216
|
+
if sock:
|
|
217
|
+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
|
218
|
+
try:
|
|
219
|
+
peercert = sock.getpeercert(True)
|
|
220
|
+
except socket.error:
|
|
221
|
+
peercert = None
|
|
215
222
|
|
|
216
223
|
def format_hash(value):
|
|
217
224
|
return reduce(lambda x, y: x + y[1].upper()
|
|
218
225
|
+ ((y[0] % 2 and y[0] + 1 < len(value)) and ':' or ''),
|
|
219
226
|
enumerate(value), '')
|
|
220
|
-
return format_hash(
|
|
227
|
+
return connection, format_hash(
|
|
228
|
+
hashlib.sha1(peercert).hexdigest())
|
|
221
229
|
except (socket.error, ssl.SSLError, ssl.CertificateError):
|
|
222
230
|
if allow_http:
|
|
223
|
-
http_connection()
|
|
231
|
+
return http_connection(), None
|
|
224
232
|
else:
|
|
225
233
|
raise
|
|
226
234
|
|
|
@@ -228,17 +236,19 @@ class Transport(xmlrpc.client.SafeTransport):
|
|
|
228
236
|
if (self.__fingerprints is not None
|
|
229
237
|
and self.__fingerprints.exists(chost)):
|
|
230
238
|
if self.__fingerprints.get(chost):
|
|
231
|
-
fingerprint = https_connection()
|
|
239
|
+
connection, fingerprint = https_connection()
|
|
232
240
|
else:
|
|
233
|
-
http_connection()
|
|
241
|
+
connection = http_connection()
|
|
234
242
|
else:
|
|
235
|
-
fingerprint = https_connection(allow_http=True)
|
|
243
|
+
connection, fingerprint = https_connection(allow_http=True)
|
|
236
244
|
|
|
237
245
|
if self.__fingerprints is not None:
|
|
238
246
|
self.__fingerprints.set(chost, fingerprint)
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
247
|
+
connection.timeout = DEFAULT_TIMEOUT
|
|
248
|
+
sock = connection.sock
|
|
249
|
+
if sock:
|
|
250
|
+
sock.settimeout(DEFAULT_TIMEOUT)
|
|
251
|
+
return connection
|
|
242
252
|
|
|
243
253
|
@property
|
|
244
254
|
def encode_threshold(self):
|
|
@@ -302,7 +312,8 @@ class ServerProxy(xmlrpc.client.ServerProxy):
|
|
|
302
312
|
self.__transport.close()
|
|
303
313
|
raise
|
|
304
314
|
if response['id'] != id_:
|
|
305
|
-
raise ResponseError(
|
|
315
|
+
raise ResponseError(
|
|
316
|
+
_("Invalid response id (%s) expected %s") %
|
|
306
317
|
(response['id'], id_))
|
|
307
318
|
if response.get('error'):
|
|
308
319
|
raise Fault(*response['error'])
|
|
@@ -396,7 +407,10 @@ class ServerPool(object):
|
|
|
396
407
|
class _Cache:
|
|
397
408
|
|
|
398
409
|
def __init__(self):
|
|
399
|
-
|
|
410
|
+
cache_size = CONFIG['rpc.cache_size']
|
|
411
|
+
self.store = CacheDict(
|
|
412
|
+
cache_len=cache_size,
|
|
413
|
+
default_factory=lambda: CacheDict(cache_len=cache_size))
|
|
400
414
|
|
|
401
415
|
def cached(self, prefix):
|
|
402
416
|
return prefix in self.store
|
tryton/pyson.py
CHANGED
|
@@ -9,6 +9,8 @@ from dateutil.relativedelta import relativedelta
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class PYSON(object):
|
|
12
|
+
_operator = None
|
|
13
|
+
_binary_operator = None
|
|
12
14
|
|
|
13
15
|
def pyson(self):
|
|
14
16
|
raise NotImplementedError
|
|
@@ -81,8 +83,17 @@ class PYSON(object):
|
|
|
81
83
|
return In(k, self)
|
|
82
84
|
|
|
83
85
|
def __repr__(self):
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
params = self.__repr_params__
|
|
87
|
+
if self._operator and isinstance(params[0], PYSON):
|
|
88
|
+
return '%s.%s(%s)' % (
|
|
89
|
+
repr(params[0]), self._operator,
|
|
90
|
+
', '.join(map(repr, params[1:])))
|
|
91
|
+
elif self._binary_operator and isinstance(params[0], PYSON):
|
|
92
|
+
return '(%s %s %s)' % (
|
|
93
|
+
repr(params[0]), self._binary_operator, repr(params[1]))
|
|
94
|
+
else:
|
|
95
|
+
klass = self.__class__.__name__
|
|
96
|
+
return '%s(%s)' % (klass, ', '.join(map(repr, params)))
|
|
86
97
|
|
|
87
98
|
@property
|
|
88
99
|
def __repr_params__(self):
|
|
@@ -137,7 +148,10 @@ class Eval(PYSON):
|
|
|
137
148
|
|
|
138
149
|
@property
|
|
139
150
|
def __repr_params__(self):
|
|
140
|
-
|
|
151
|
+
params = (self._value,)
|
|
152
|
+
if self._default != '':
|
|
153
|
+
params += (self._default,)
|
|
154
|
+
return params
|
|
141
155
|
|
|
142
156
|
def pyson(self):
|
|
143
157
|
return {
|
|
@@ -183,6 +197,17 @@ class Not(PYSON):
|
|
|
183
197
|
v = bool(v)
|
|
184
198
|
self._value = v
|
|
185
199
|
|
|
200
|
+
def __repr__(self):
|
|
201
|
+
if (isinstance(self._value, Equal)
|
|
202
|
+
and isinstance(self._value._statement1, PYSON)):
|
|
203
|
+
return '(%s != %s)' % (
|
|
204
|
+
repr(self._value._statement1),
|
|
205
|
+
repr(self._value._statement2))
|
|
206
|
+
elif isinstance(self._value, PYSON):
|
|
207
|
+
return '~%s' % repr(self._value)
|
|
208
|
+
else:
|
|
209
|
+
return super().__repr__()
|
|
210
|
+
|
|
186
211
|
@property
|
|
187
212
|
def __repr_params__(self):
|
|
188
213
|
return (self._value,)
|
|
@@ -226,6 +251,8 @@ class Bool(PYSON):
|
|
|
226
251
|
|
|
227
252
|
|
|
228
253
|
class And(PYSON):
|
|
254
|
+
_pyson_class = 'And'
|
|
255
|
+
_binary_operator = '&'
|
|
229
256
|
|
|
230
257
|
def __init__(self, *statements, **kwargs):
|
|
231
258
|
super(And, self).__init__()
|
|
@@ -258,6 +285,7 @@ class And(PYSON):
|
|
|
258
285
|
|
|
259
286
|
|
|
260
287
|
class Or(And):
|
|
288
|
+
_binary_operator = '|'
|
|
261
289
|
|
|
262
290
|
def pyson(self):
|
|
263
291
|
res = super(Or, self).pyson()
|
|
@@ -270,6 +298,7 @@ class Or(And):
|
|
|
270
298
|
|
|
271
299
|
|
|
272
300
|
class Equal(PYSON):
|
|
301
|
+
_binary_operator = '=='
|
|
273
302
|
|
|
274
303
|
def __init__(self, s1, s2):
|
|
275
304
|
statement1, statement2 = s1, s2
|
|
@@ -332,6 +361,10 @@ class Greater(PYSON):
|
|
|
332
361
|
self._statement2 = statement2
|
|
333
362
|
self._equal = equal
|
|
334
363
|
|
|
364
|
+
@property
|
|
365
|
+
def _binary_operator(self):
|
|
366
|
+
return '<=' if self._equal else '<'
|
|
367
|
+
|
|
335
368
|
@property
|
|
336
369
|
def __repr_params__(self):
|
|
337
370
|
return (self._statement1, self._statement2, self._equal)
|
|
@@ -378,6 +411,10 @@ class Greater(PYSON):
|
|
|
378
411
|
|
|
379
412
|
class Less(Greater):
|
|
380
413
|
|
|
414
|
+
@property
|
|
415
|
+
def _binary_operator(self):
|
|
416
|
+
return '>=' if self._equal else '>'
|
|
417
|
+
|
|
381
418
|
def pyson(self):
|
|
382
419
|
res = super(Less, self).pyson()
|
|
383
420
|
res['__class__'] = 'Less'
|
|
@@ -440,6 +477,7 @@ class If(PYSON):
|
|
|
440
477
|
|
|
441
478
|
|
|
442
479
|
class Get(PYSON):
|
|
480
|
+
_operator = 'get'
|
|
443
481
|
|
|
444
482
|
def __init__(self, v, k, d=''):
|
|
445
483
|
obj, key, default = v, k, d
|
|
@@ -458,7 +496,10 @@ class Get(PYSON):
|
|
|
458
496
|
|
|
459
497
|
@property
|
|
460
498
|
def __repr_params__(self):
|
|
461
|
-
|
|
499
|
+
params = (self._obj, self._key)
|
|
500
|
+
if self._default != '':
|
|
501
|
+
params += (self._default,)
|
|
502
|
+
return params
|
|
462
503
|
|
|
463
504
|
def pyson(self):
|
|
464
505
|
return {
|
|
@@ -480,6 +521,7 @@ class Get(PYSON):
|
|
|
480
521
|
|
|
481
522
|
|
|
482
523
|
class In(PYSON):
|
|
524
|
+
_operator = 'in_'
|
|
483
525
|
|
|
484
526
|
def __init__(self, k, v):
|
|
485
527
|
key, obj = k, v
|
|
@@ -508,6 +550,14 @@ class In(PYSON):
|
|
|
508
550
|
self._key = key
|
|
509
551
|
self._obj = obj
|
|
510
552
|
|
|
553
|
+
def __repr__(self):
|
|
554
|
+
params = self.__repr_params__
|
|
555
|
+
if isinstance(params[1], PYSON):
|
|
556
|
+
return '%s.contains(%s)' % (
|
|
557
|
+
repr(params[1]), ', '.join(map(repr, params[:1] + params[2:])))
|
|
558
|
+
else:
|
|
559
|
+
return super().__repr__()
|
|
560
|
+
|
|
511
561
|
@property
|
|
512
562
|
def __repr_params__(self):
|
|
513
563
|
return (self._key, self._obj)
|
tryton/rpc.py
CHANGED
|
@@ -145,6 +145,24 @@ def logout():
|
|
|
145
145
|
_USER = None
|
|
146
146
|
|
|
147
147
|
|
|
148
|
+
def reset_password():
|
|
149
|
+
from tryton import common
|
|
150
|
+
host = CONFIG['login.host']
|
|
151
|
+
hostname = common.get_hostname(host)
|
|
152
|
+
port = common.get_port(host)
|
|
153
|
+
database = CONFIG['login.db']
|
|
154
|
+
username = CONFIG['login.login']
|
|
155
|
+
language = CONFIG['client.lang']
|
|
156
|
+
if not all([host, database, username]):
|
|
157
|
+
return
|
|
158
|
+
try:
|
|
159
|
+
connection = ServerProxy(hostname, port, database)
|
|
160
|
+
logger.info('common.db.reset_password(%s, %s)', (username, language))
|
|
161
|
+
connection.common.db.reset_password(username, language)
|
|
162
|
+
except Fault as exception:
|
|
163
|
+
logger.debug(exception.faultCode)
|
|
164
|
+
|
|
165
|
+
|
|
148
166
|
def execute(*args):
|
|
149
167
|
global CONNECTION, _USER
|
|
150
168
|
if CONNECTION is None:
|
|
@@ -592,8 +592,6 @@ class DomainParserTestCase(TestCase):
|
|
|
592
592
|
})
|
|
593
593
|
valid = ('name', '=', 'Doe')
|
|
594
594
|
invalid = ('surname', '=', 'John')
|
|
595
|
-
self.assertTrue(dom.stringable([]))
|
|
596
|
-
self.assertTrue(dom.stringable([[]]))
|
|
597
595
|
self.assertTrue(dom.stringable([valid]))
|
|
598
596
|
self.assertFalse(dom.stringable([invalid]))
|
|
599
597
|
self.assertTrue(dom.stringable(['AND', valid]))
|
|
@@ -681,15 +679,9 @@ class DomainParserTestCase(TestCase):
|
|
|
681
679
|
dom.string([('name', 'not ilike', '%Doe%')]), 'Name: !Doe')
|
|
682
680
|
self.assertEqual(
|
|
683
681
|
dom.string([('name', 'in', ['John', 'Jane'])]), 'Name: John;Jane')
|
|
684
|
-
self.assertEqual(
|
|
685
|
-
dom.string([('name', 'in', ['John', ''])]), 'Name: John;""')
|
|
686
|
-
self.assertEqual(
|
|
687
|
-
dom.string([('name', 'in', ['John'])]), 'Name: =John')
|
|
688
682
|
self.assertEqual(
|
|
689
683
|
dom.string([('name', 'not in', ['John', 'Jane'])]),
|
|
690
684
|
'Name: !John;Jane')
|
|
691
|
-
self.assertEqual(
|
|
692
|
-
dom.string([('name', 'not in', ['John'])]), 'Name: !=John')
|
|
693
685
|
self.assertEqual(
|
|
694
686
|
dom.string([
|
|
695
687
|
('name', 'ilike', '%Doe%'),
|
|
@@ -15,8 +15,7 @@ if hasattr(sys, 'frozen'):
|
|
|
15
15
|
share = os.path.join(prefix, 'share')
|
|
16
16
|
os.environ['GTK_EXE_PREFIX'] = prefix
|
|
17
17
|
os.environ['GTK_DATA_PREFIX'] = prefix
|
|
18
|
-
os.environ['EV_BACKENDS_DIR'] =
|
|
19
|
-
prefix, 'lib', 'evince', '4', 'backends')
|
|
18
|
+
os.environ['EV_BACKENDS_DIR'] = prefix
|
|
20
19
|
os.environ['XDG_DATA_DIRS'] = share
|
|
21
20
|
os.environ['GDK_PIXBUF_MODULE_FILE'] = os.path.join(
|
|
22
21
|
share, 'gtk-3.0', 'gdk-pixbuf.loaders')
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tryton
|
|
3
|
-
Version: 7.0
|
|
3
|
+
Version: 7.2.0
|
|
4
4
|
Summary: Tryton desktop client
|
|
5
5
|
Home-page: http://www.tryton.org/
|
|
6
|
-
Download-URL: http://downloads.tryton.org/7.
|
|
6
|
+
Download-URL: http://downloads.tryton.org/7.2/
|
|
7
7
|
Author: Tryton
|
|
8
8
|
Author-email: foundation@tryton.org
|
|
9
9
|
License: GPL-3
|
|
@@ -52,11 +52,11 @@ Requires-Python: >=3.8
|
|
|
52
52
|
License-File: LICENSE
|
|
53
53
|
Requires-Dist: pycairo
|
|
54
54
|
Requires-Dist: python-dateutil
|
|
55
|
-
Requires-Dist: PyGObject>=3.19
|
|
55
|
+
Requires-Dist: PyGObject >=3.19
|
|
56
56
|
Provides-Extra: calendar
|
|
57
|
-
Requires-Dist: GooCalendar>=0.7; extra ==
|
|
57
|
+
Requires-Dist: GooCalendar >=0.7 ; extra == 'calendar'
|
|
58
58
|
Provides-Extra: sound
|
|
59
|
-
Requires-Dist: playsound; extra ==
|
|
59
|
+
Requires-Dist: playsound ; extra == 'sound'
|
|
60
60
|
|
|
61
61
|
tryton
|
|
62
62
|
======
|