Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/i18n.py @ 37060:2ec1fb9de638
wireproto: add request IDs to frames
One of my primary goals with the new wire protocol is to make
operations faster and enable both client and server-side
operations to scale to multiple CPU cores.
One of the ways we make server interactions faster is by reducing
the number of round trips to that server.
With the existing wire protocol, the "batch" command facilitates
executing multiple commands from a single request payload. The way
it works is the requests for multiple commands are serialized. The
server executes those commands sequentially then serializes all
their results. As an optimization for reducing round trips, this
is very effective. The technical implementation, however, is pretty
bad and suffers from a number of deficiencies. For example, it
creates a new place where authorization to run a command must be
checked. (The lack of this checking in older Mercurial releases
was CVE-2018-1000132.)
The principles behind the "batch" command are sound. However, the
execution is not. Therefore, I want to ditch "batch" in the
new wire protocol and have protocol level support for issuing
multiple requests in a single round trip.
This commit introduces support in the frame-based wire protocol to
facilitate this. We do this by adding a "request ID" to each frame.
If a server sees frames associated with different "request IDs," it
handles them as separate requests. All of this happening possibly
as part of the same message from client to server (the same request
body in the case of HTTP).
We /could/ model the exchange the way pipelined HTTP requests do,
where the server processes requests in order they are issued and
received. But this artifically constrains scalability. A better
model is to allow multi-requests to be executed concurrently and
for responses to be sent and handled concurrently. So the
specification explicitly allows this. There is some work to be done
around specifying dependencies between multi-requests. We take
the easy road for now and punt on this problem, declaring that
if order is important, clients must not issue the request until
responses to dependent requests have been received.
This commit focuses on the boilerplate of implementing the request
ID. The server reactor still can't manage multiple, in-flight
request IDs. This will be addressed in a subsequent commit.
Because the wire semantics have changed, we bump the version of the
media type.
Differential Revision: https://phab.mercurial-scm.org/D2869
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Wed, 14 Mar 2018 16:51:34 -0700 |
parents | 5bc7ff103081 |
children | 79dd61a4554f |
rev | line source |
---|---|
8226
8b2cd04a6e97
put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents:
8225
diff
changeset
|
1 # i18n.py - internationalization support for mercurial |
8b2cd04a6e97
put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents:
8225
diff
changeset
|
2 # |
8b2cd04a6e97
put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents:
8225
diff
changeset
|
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com> |
8b2cd04a6e97
put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents:
8225
diff
changeset
|
4 # |
8b2cd04a6e97
put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents:
8225
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
10263 | 6 # GNU General Public License version 2 or any later version. |
1400
cf9a1233738a
i18n first part: make '_' available for files who need it
Benoit Boissinot <benoit.boissinot@ens-lyon.org
parents:
diff
changeset
|
7 |
25955
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
8 from __future__ import absolute_import |
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
9 |
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
10 import gettext as gettextmod |
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
11 import locale |
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
12 import os |
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
13 import sys |
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
14 |
30050
d229be12e256
py3: convert to unicode to pass into encode()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30035
diff
changeset
|
15 from . import ( |
d229be12e256
py3: convert to unicode to pass into encode()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30035
diff
changeset
|
16 encoding, |
d229be12e256
py3: convert to unicode to pass into encode()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30035
diff
changeset
|
17 pycompat, |
d229be12e256
py3: convert to unicode to pass into encode()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30035
diff
changeset
|
18 ) |
7650
85ae7aaf08e9
i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents:
3888
diff
changeset
|
19 |
85ae7aaf08e9
i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents:
3888
diff
changeset
|
20 # modelled after templater.templatepath: |
14975
b64538363dbe
i18n: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents:
13849
diff
changeset
|
21 if getattr(sys, 'frozen', None) is not None: |
30672
10b17ed9b591
py3: replace sys.executable with pycompat.sysexecutable
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30644
diff
changeset
|
22 module = pycompat.sysexecutable |
7650
85ae7aaf08e9
i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents:
3888
diff
changeset
|
23 else: |
31091
2912b06905dc
py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30672
diff
changeset
|
24 module = pycompat.fsencode(__file__) |
7650
85ae7aaf08e9
i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents:
3888
diff
changeset
|
25 |
28674
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
26 try: |
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
27 unicode |
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
28 except NameError: |
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
29 unicode = str |
7650
85ae7aaf08e9
i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents:
3888
diff
changeset
|
30 |
21987
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
31 _languages = None |
34645 | 32 if (pycompat.iswindows |
30035
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
33 and 'LANGUAGE' not in encoding.environ |
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
34 and 'LC_ALL' not in encoding.environ |
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
35 and 'LC_MESSAGES' not in encoding.environ |
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
36 and 'LANG' not in encoding.environ): |
21987
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
37 # Try to detect UI language by "User Interface Language Management" API |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
38 # if no locale variables are set. Note that locale.getdefaultlocale() |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
39 # uses GetLocaleInfo(), which may be different from UI language. |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
40 # (See http://msdn.microsoft.com/en-us/library/dd374098(v=VS.85).aspx ) |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
41 try: |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
42 import ctypes |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
43 langid = ctypes.windll.kernel32.GetUserDefaultUILanguage() |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
44 _languages = [locale.windows_locale[langid]] |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
45 except (ImportError, AttributeError, KeyError): |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
46 # ctypes not found or unknown langid |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
47 pass |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
48 |
22638
0d0350cfc7ab
i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents:
21987
diff
changeset
|
49 _ugettext = None |
0d0350cfc7ab
i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents:
21987
diff
changeset
|
50 |
0d0350cfc7ab
i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents:
21987
diff
changeset
|
51 def setdatapath(datapath): |
30314
8321b083a83d
py3: make util.datapath a bytes variable
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30085
diff
changeset
|
52 datapath = pycompat.fsdecode(datapath) |
36843
5bc7ff103081
py3: use r'' instead of sysstr('') to get around code transformer
Yuya Nishihara <yuya@tcha.org>
parents:
36717
diff
changeset
|
53 localedir = os.path.join(datapath, r'locale') |
36717
aeaf9c7f7528
py3: make gettext domain a system string
Yuya Nishihara <yuya@tcha.org>
parents:
34660
diff
changeset
|
54 t = gettextmod.translation(r'hg', localedir, _languages, fallback=True) |
22638
0d0350cfc7ab
i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents:
21987
diff
changeset
|
55 global _ugettext |
28674
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
56 try: |
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
57 _ugettext = t.ugettext |
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
58 except AttributeError: |
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
59 _ugettext = t.gettext |
7651
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
60 |
34660
d00ec62d156f
i18n: cache translated messages per encoding
Yuya Nishihara <yuya@tcha.org>
parents:
34645
diff
changeset
|
61 _msgcache = {} # encoding: {message: translation} |
23031
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
62 |
7651
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
63 def gettext(message): |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
64 """Translate message. |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
65 |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
66 The message is looked up in the catalog to get a Unicode string, |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
67 which is encoded in the local encoding before being returned. |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
68 |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
69 Important: message is restricted to characters in the encoding |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
70 given by sys.getdefaultencoding() which is most likely 'ascii'. |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
71 """ |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
72 # If message is None, t.ugettext will return u'None' as the |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
73 # translation whereas our callers expect us to return None. |
22638
0d0350cfc7ab
i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents:
21987
diff
changeset
|
74 if message is None or not _ugettext: |
7651
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
75 return message |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
76 |
34660
d00ec62d156f
i18n: cache translated messages per encoding
Yuya Nishihara <yuya@tcha.org>
parents:
34645
diff
changeset
|
77 cache = _msgcache.setdefault(encoding.encoding, {}) |
d00ec62d156f
i18n: cache translated messages per encoding
Yuya Nishihara <yuya@tcha.org>
parents:
34645
diff
changeset
|
78 if message not in cache: |
23031
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
79 if type(message) is unicode: |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
80 # goofy unicode docstrings in test |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
81 paragraphs = message.split(u'\n\n') |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
82 else: |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
83 paragraphs = [p.decode("ascii") for p in message.split('\n\n')] |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
84 # Be careful not to translate the empty string -- it holds the |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
85 # meta data of the .po file. |
29415
47fb4beb992b
i18n: use unicode literal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28674
diff
changeset
|
86 u = u'\n\n'.join([p and _ugettext(p) or u'' for p in paragraphs]) |
23031
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
87 try: |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
88 # encoding.tolocal cannot be used since it will first try to |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
89 # decode the Unicode string. Calling u.decode(enc) really |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
90 # means u.encode(sys.getdefaultencoding()).decode(enc). Since |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
91 # the Python encoding defaults to 'ascii', this fails if the |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
92 # translated string use non-ASCII characters. |
30050
d229be12e256
py3: convert to unicode to pass into encode()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30035
diff
changeset
|
93 encodingstr = pycompat.sysstr(encoding.encoding) |
34660
d00ec62d156f
i18n: cache translated messages per encoding
Yuya Nishihara <yuya@tcha.org>
parents:
34645
diff
changeset
|
94 cache[message] = u.encode(encodingstr, "replace") |
23031
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
95 except LookupError: |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
96 # An unknown encoding results in a LookupError. |
34660
d00ec62d156f
i18n: cache translated messages per encoding
Yuya Nishihara <yuya@tcha.org>
parents:
34645
diff
changeset
|
97 cache[message] = message |
d00ec62d156f
i18n: cache translated messages per encoding
Yuya Nishihara <yuya@tcha.org>
parents:
34645
diff
changeset
|
98 return cache[message] |
7651
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
99 |
13849
9f97de157aad
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents:
11403
diff
changeset
|
100 def _plain(): |
30035
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
101 if ('HGPLAIN' not in encoding.environ |
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
102 and 'HGPLAINEXCEPT' not in encoding.environ): |
13849
9f97de157aad
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents:
11403
diff
changeset
|
103 return False |
30035
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
104 exceptions = encoding.environ.get('HGPLAINEXCEPT', '').strip().split(',') |
13849
9f97de157aad
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents:
11403
diff
changeset
|
105 return 'i18n' not in exceptions |
9f97de157aad
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents:
11403
diff
changeset
|
106 |
9f97de157aad
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents:
11403
diff
changeset
|
107 if _plain(): |
10455
40dfd46d098f
ui: add HGPLAIN environment variable for easier scripting
Brodie Rao <me+hg@dackz.net>
parents:
10263
diff
changeset
|
108 _ = lambda message: message |
40dfd46d098f
ui: add HGPLAIN environment variable for easier scripting
Brodie Rao <me+hg@dackz.net>
parents:
10263
diff
changeset
|
109 else: |
40dfd46d098f
ui: add HGPLAIN environment variable for easier scripting
Brodie Rao <me+hg@dackz.net>
parents:
10263
diff
changeset
|
110 _ = gettext |