##// END OF EJS Templates
py3: conditionalize test-demandimport.py for Python 3...
py3: conditionalize test-demandimport.py for Python 3 The Python 3 lazy importer uses the LazyLoader that is part of importlib. On Python 3 and later, LazyLoader is implemented using a custom module type that defines a __getattribute__ which triggers module loading. Furthermore, there are additional differences as well. For example, it appears that Python 3 will return an existing sys.modules entry instead of constructing a new module object. This commit adds additional test coverage for lazy importing behavior to cover the differences between Python 2 and 3. This reveals that the test and some lazy import functionality is kinda busted. For example, the test assumes "contextlib" will be lazy. But in reality an import before it has already imported contextlib! There's definitely room to improve the behavior of the demand importer code, both for Python 2 and 3. But at least the test passes on Python 3 now. Differential Revision: https://phab.mercurial-scm.org/D5796

File last commit:

r41092:0a7f582f default
r41647:3e89736b default
Show More
proto.py
198 lines | 7.4 KiB | text/x-python | PythonLexer
various
hgext: add largefiles extension...
r15168 # Copyright 2011 Fog Creek Software
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
liscju
py3: make largefiles/proto.py use absolute_import
r29312 from __future__ import absolute_import
various
hgext: add largefiles extension...
r15168
import os
Mads Kiilerich
largefiles: make the protocol hack for replacing heads with lheads more precise...
r19917 import re
various
hgext: add largefiles extension...
r15168
from mercurial.i18n import _
liscju
py3: make largefiles/proto.py use absolute_import
r29312 from mercurial import (
error,
Matt Harbison
largefiles: port wrapped functions to exthelper...
r41092 exthelper,
liscju
py3: make largefiles/proto.py use absolute_import
r29312 httppeer,
util,
Gregory Szorc
wireproto: introduce type for raw byte responses (API)...
r36091 wireprototypes,
Gregory Szorc
wireproto: move version 1 peer functionality to standalone module (API)...
r37632 wireprotov1peer,
Matt Harbison
largefiles: port wrapped functions to exthelper...
r41092 wireprotov1server,
liscju
py3: make largefiles/proto.py use absolute_import
r29312 )
from . import (
lfutil,
)
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 urlerr = util.urlerr
urlreq = util.urlreq
Greg Ward
largefiles: cosmetics, whitespace, code style...
r15255 LARGEFILES_REQUIRED_MSG = ('\nThis repository uses the largefiles extension.'
'\n\nPlease enable it in your Mercurial config '
'file.\n')
various
hgext: add largefiles extension...
r15168
Matt Harbison
largefiles: port wrapped functions to exthelper...
r41092 eh = exthelper.exthelper()
Bryan O'Sullivan
largefiles: quiet (and document) undefined name errors (issue3886)...
r18922 # these will all be replaced by largefiles.uisetup
ssholdcallstream = None
httpoldcallstream = None
various
hgext: add largefiles extension...
r15168 def putlfile(repo, proto, sha):
Mads Kiilerich
largefiles: add some docstrings
r28576 '''Server command for putting a largefile into a repository's local store
and into the user cache.'''
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 with proto.mayberedirectstdio() as output:
path = lfutil.storepath(repo, sha)
util.makedirs(os.path.dirname(path))
tmpfp = util.atomictempfile(path, createmode=repo.store.createmode)
hlian
largefiles: in putlfile, ensure tempfile's directory exists prior to creation...
r16594
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 try:
Joerg Sonnenberger
wireproto: allow direct stream processing for unbundle...
r37432 for p in proto.getpayload():
tmpfp.write(p)
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 tmpfp._fp.seek(0)
if sha != lfutil.hexsha1(tmpfp._fp):
raise IOError(0, _('largefile contents do not match hash'))
tmpfp.close()
lfutil.linktousercache(repo, sha)
except IOError as e:
repo.ui.warn(_('largefiles: failed to put %s into store: %s\n') %
(sha, e.strerror))
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.pushres(
1, output.getvalue() if output else '')
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 finally:
tmpfp.discard()
various
hgext: add largefiles extension...
r15168
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.pushres(0, output.getvalue() if output else '')
various
hgext: add largefiles extension...
r15168
def getlfile(repo, proto, sha):
Mads Kiilerich
largefiles: add some docstrings
r28576 '''Server command for retrieving a largefile from the repository-local
cache or user cache.'''
various
hgext: add largefiles extension...
r15168 filename = lfutil.findfile(repo, sha)
if not filename:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('requested largefile %s not present in cache')
% sha)
various
hgext: add largefiles extension...
r15168 f = open(filename, 'rb')
length = os.fstat(f.fileno())[6]
Greg Ward
largefiles: improve comments, internal docstrings...
r15252
# Since we can't set an HTTP content-length header here, and
# Mercurial core provides no way to give the length of a streamres
# (and reading the entire file into RAM would be ill-advised), we
# just send the length on the first line of the response, like the
# ssh proto does for string responses.
various
hgext: add largefiles extension...
r15168 def generator():
yield '%d\n' % length
Mads Kiilerich
largefiles: use filechunkiter for iterating largefile when serving getlfile...
r19009 for chunk in util.filechunkiter(f):
various
hgext: add largefiles extension...
r15168 yield chunk
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.streamreslegacy(gen=generator())
various
hgext: add largefiles extension...
r15168
def statlfile(repo, proto, sha):
Mads Kiilerich
largefiles: add some docstrings
r28576 '''Server command for checking if a largefile is present - returns '2\n' if
the largefile is missing, '0\n' if it seems to be in good condition.
Mads Kiilerich
largefiles: don't verify largefile hashes on servers when processing statlfile...
r18488
The value 1 is reserved for mismatched checksum, but that is too expensive
to be verified on every stat and must be caught be running 'hg verify'
server side.'''
various
hgext: add largefiles extension...
r15168 filename = lfutil.findfile(repo, sha)
if not filename:
Gregory Szorc
wireproto: introduce type for raw byte responses (API)...
r36091 return wireprototypes.bytesresponse('2\n')
return wireprototypes.bytesresponse('0\n')
various
hgext: add largefiles extension...
r15168
def wirereposetup(ui, repo):
class lfileswirerepository(repo.__class__):
def putlfile(self, sha, fd):
# unfortunately, httprepository._callpush tries to convert its
# input file-like into a bundle before sending it, so we can't use
# it ...
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 if issubclass(self.__class__, httppeer.httppeer):
Mads Kiilerich
largefiles: don't mute and obfuscate http errors when putlfile fails...
r26825 res = self._call('putlfile', data=fd, sha=sha,
Augie Fackler
largefiles: headers and values need to be sysstrs, add r prefixes...
r36674 headers={r'content-type': r'application/mercurial-0.1'})
various
hgext: add largefiles extension...
r15168 try:
Kevin Gessner
largefiles: display remote errors from putlfile (issue3123) (issue3149)
r15778 d, output = res.split('\n', 1)
for l in output.splitlines(True):
Mads Kiilerich
largefiles: don't add extra \n when displaying remote messages in putlfile
r19949 self.ui.warn(_('remote: '), l) # assume l ends with \n
Kevin Gessner
largefiles: display remote errors from putlfile (issue3123) (issue3149)
r15778 return int(d)
Mads Kiilerich
largefiles: don't mute and obfuscate http errors when putlfile fails...
r26825 except ValueError:
Mads Kiilerich
largefiles: fix 'unexpected response' warning newlines...
r19947 self.ui.warn(_('unexpected putlfile response: %r\n') % res)
various
hgext: add largefiles extension...
r15168 return 1
# ... but we can't use sshrepository._call because the data=
# argument won't get sent, and _callpush does exactly what we want
# in this case: send the data straight through
else:
try:
ret, output = self._callpush("putlfile", fd, sha=sha)
if ret == "":
raise error.ResponseError(_('putlfile failed:'),
output)
return int(ret)
except IOError:
return 1
except ValueError:
raise error.ResponseError(
_('putlfile failed (unexpected response):'), ret)
def getlfile(self, sha):
Mads Kiilerich
largefiles: move protocol conversion into getlfile and make it an iterable...
r19004 """returns an iterable with the chunks of the file with sha sha"""
various
hgext: add largefiles extension...
r15168 stream = self._callstream("getlfile", sha=sha)
length = stream.readline()
try:
length = int(length)
except ValueError:
Matt Mackall
largefiles: fix over-long lines
r15170 self._abort(error.ResponseError(_("unexpected response:"),
length))
Mads Kiilerich
largefiles: move protocol conversion into getlfile and make it an iterable...
r19004
Mads Kiilerich
largefiles: drop limitreader, use filechunkiter limit...
r19005 # SSH streams will block if reading more than length
Mads Kiilerich
util: increase filechunkiter size to 128k...
r30181 for chunk in util.filechunkiter(stream, limit=length):
Mads Kiilerich
largefiles: move protocol conversion into getlfile and make it an iterable...
r19004 yield chunk
Mads Kiilerich
largefiles: getlfile must hit end of HTTP chunked streams to reuse connections...
r19006 # HTTP streams must hit the end to process the last empty
# chunk of Chunked-Encoding so the connection can be reused.
if issubclass(self.__class__, httppeer.httppeer):
chunk = stream.read(1)
if chunk:
self._abort(error.ResponseError(_("unexpected response:"),
chunk))
various
hgext: add largefiles extension...
r15168
Gregory Szorc
wireproto: move version 1 peer functionality to standalone module (API)...
r37632 @wireprotov1peer.batchable
various
hgext: add largefiles extension...
r15168 def statlfile(self, sha):
Gregory Szorc
wireproto: move version 1 peer functionality to standalone module (API)...
r37632 f = wireprotov1peer.future()
Na'Tosha Bard
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)...
r17127 result = {'sha': sha}
yield result, f
various
hgext: add largefiles extension...
r15168 try:
Na'Tosha Bard
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)...
r17127 yield int(f.value)
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 except (ValueError, urlerr.httperror):
Greg Ward
largefiles: improve comments, internal docstrings...
r15252 # If the server returns anything but an integer followed by a
various
hgext: add largefiles extension...
r15168 # newline, newline, it's not speaking our language; if we get
# an HTTP error, we can't be sure the largefile is present;
Greg Ward
largefiles: improve comments, internal docstrings...
r15252 # either way, consider it missing.
Na'Tosha Bard
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)...
r17127 yield 2
various
hgext: add largefiles extension...
r15168
repo.__class__ = lfileswirerepository
# advertise the largefiles=serve capability
Matt Harbison
largefiles: port wrapped functions to exthelper...
r41092 @eh.wrapfunction(wireprotov1server, '_capabilities')
Matt Harbison
largefiles: modernize how capabilities are added to the wire protocol...
r35523 def _capabilities(orig, repo, proto):
'''announce largefile server capability'''
caps = orig(repo, proto)
caps.append('largefiles=serve')
return caps
various
hgext: add largefiles extension...
r15168
Gregory Szorc
largefiles: wrap heads command handler more directly...
r37502 def heads(orig, repo, proto):
Mads Kiilerich
largefiles: add some docstrings
r28576 '''Wrap server command - largefile capable clients will know to call
lheads instead'''
various
hgext: add largefiles extension...
r15168 if lfutil.islfilesrepo(repo):
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.ooberror(LARGEFILES_REQUIRED_MSG)
Gregory Szorc
largefiles: wrap heads command handler more directly...
r37502
return orig(repo, proto)
various
hgext: add largefiles extension...
r15168
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 def sshrepocallstream(self, cmd, **args):
various
hgext: add largefiles extension...
r15168 if cmd == 'heads' and self.capable('largefiles'):
cmd = 'lheads'
if cmd == 'batch' and self.capable('largefiles'):
Pulkit Goyal
py3: handle keyword arguments correctly in hgext/largefiles/...
r35349 args[r'cmds'] = args[r'cmds'].replace('heads ', 'lheads ')
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 return ssholdcallstream(self, cmd, **args)
various
hgext: add largefiles extension...
r15168
Augie Fackler
largefiles: mark headre as bytes regex...
r36330 headsre = re.compile(br'(^|;)heads\b')
Mads Kiilerich
largefiles: make the protocol hack for replacing heads with lheads more precise...
r19917
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 def httprepocallstream(self, cmd, **args):
various
hgext: add largefiles extension...
r15168 if cmd == 'heads' and self.capable('largefiles'):
cmd = 'lheads'
if cmd == 'batch' and self.capable('largefiles'):
Pulkit Goyal
py3: handle keyword arguments correctly in hgext/largefiles/...
r35349 args[r'cmds'] = headsre.sub('lheads', args[r'cmds'])
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 return httpoldcallstream(self, cmd, **args)