Extract matchdate from util.py to utils/dateutil.py
After this commit, util.py losed 313 lines
lothiraldan |
hg-reviewers |
Extract matchdate from util.py to utils/dateutil.py
After this commit, util.py losed 313 lines
Lint Skipped |
Unit Tests Skipped |
Path | Packages | |||
---|---|---|---|---|
M | hgext/churn.py (4 lines) | |||
M | mercurial/cmdutil.py (2 lines) | |||
M | mercurial/debugcommands.py (2 lines) | |||
M | mercurial/revset.py (3 lines) | |||
M | mercurial/util.py (81 lines) | |||
M | mercurial/utils/dateutil.py (75 lines) |
Status | Author | Revision | |
---|---|---|---|
Abandoned | lothiraldan | ||
Abandoned | durin42 | D2056 util: extract matchdate | |
Abandoned | durin42 | D2055 util: extract parsedate | |
Abandoned | durin42 | D2054 util: extract strdate | |
Abandoned | durin42 | ||
Abandoned | durin42 | D2052 util: extract shortdate | |
Abandoned | durin42 | D2051 util: extract datestr | |
Abandoned | durin42 | D2050 util: extract makedate | |
Abandoned | durin42 | ||
Abandoned | lothiraldan | ||
Abandoned | durin42 |
from mercurial.i18n import _ | from mercurial.i18n import _ | ||||
from mercurial import ( | from mercurial import ( | ||||
cmdutil, | cmdutil, | ||||
encoding, | encoding, | ||||
patch, | patch, | ||||
pycompat, | pycompat, | ||||
registrar, | registrar, | ||||
scmutil, | scmutil, | ||||
util, | |||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
cmdtable = {} | cmdtable = {} | ||||
command = registrar.command(cmdtable) | command = registrar.command(cmdtable) | ||||
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | ||||
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | ||||
# be specifying the version(s) of Mercurial they are tested with, or | # be specifying the version(s) of Mercurial they are tested with, or | ||||
# leave the attribute unspecified. | # leave the attribute unspecified. | ||||
testedwith = 'ships-with-hg-core' | testedwith = 'ships-with-hg-core' | ||||
ui.pushbuffer() | ui.pushbuffer() | ||||
tmpl.show(ctx) | tmpl.show(ctx) | ||||
return ui.popbuffer() | return ui.popbuffer() | ||||
state = {'count': 0} | state = {'count': 0} | ||||
rate = {} | rate = {} | ||||
df = False | df = False | ||||
if opts.get('date'): | if opts.get('date'): | ||||
df = util.matchdate(opts['date']) | df = dateutil.matchdate(opts['date']) | ||||
m = scmutil.match(repo[None], pats, opts) | m = scmutil.match(repo[None], pats, opts) | ||||
def prep(ctx, fns): | def prep(ctx, fns): | ||||
rev = ctx.rev() | rev = ctx.rev() | ||||
if df and not df(ctx.date()[0]): # doesn't match date format | if df and not df(ctx.date()[0]): # doesn't match date format | ||||
return | return | ||||
key = getkey(ctx).strip() | key = getkey(ctx).strip() |
meta = marker.metadata().copy() | meta = marker.metadata().copy() | ||||
meta.pop('date', None) | meta.pop('date', None) | ||||
fm.write('metadata', '{%s}', fm.formatdict(meta, fmt='%r: %r', sep=', ')) | fm.write('metadata', '{%s}', fm.formatdict(meta, fmt='%r: %r', sep=', ')) | ||||
fm.plain('\n') | fm.plain('\n') | ||||
def finddate(ui, repo, date): | def finddate(ui, repo, date): | ||||
"""Find the tipmost changeset that matches the given date spec""" | """Find the tipmost changeset that matches the given date spec""" | ||||
df = util.matchdate(date) | df = dateutil.matchdate(date) | ||||
m = scmutil.matchall(repo) | m = scmutil.matchall(repo) | ||||
results = {} | results = {} | ||||
def prep(ctx, fns): | def prep(ctx, fns): | ||||
d = ctx.date() | d = ctx.date() | ||||
if df(d[0]): | if df(d[0]): | ||||
results[ctx.rev()] = d | results[ctx.rev()] = d | ||||
"""parse and display a date""" | """parse and display a date""" | ||||
if opts[r"extended"]: | if opts[r"extended"]: | ||||
d = dateutil.parsedate(date, util.extendeddateformats) | d = dateutil.parsedate(date, util.extendeddateformats) | ||||
else: | else: | ||||
d = dateutil.parsedate(date) | d = dateutil.parsedate(date) | ||||
ui.write(("internal: %s %s\n") % d) | ui.write(("internal: %s %s\n") % d) | ||||
ui.write(("standard: %s\n") % dateutil.datestr(d)) | ui.write(("standard: %s\n") % dateutil.datestr(d)) | ||||
if range: | if range: | ||||
m = util.matchdate(range) | m = dateutil.matchdate(range) | ||||
ui.write(("match: %s\n") % m(d[0])) | ui.write(("match: %s\n") % m(d[0])) | ||||
@command('debugdeltachain', | @command('debugdeltachain', | ||||
cmdutil.debugrevlogopts + cmdutil.formatteropts, | cmdutil.debugrevlogopts + cmdutil.formatteropts, | ||||
_('-c|-m|FILE'), | _('-c|-m|FILE'), | ||||
optionalrepo=True) | optionalrepo=True) | ||||
def debugdeltachain(ui, repo, file_=None, **opts): | def debugdeltachain(ui, repo, file_=None, **opts): | ||||
"""dump information about delta chains in a revlog | """dump information about delta chains in a revlog |
pycompat, | pycompat, | ||||
registrar, | registrar, | ||||
repoview, | repoview, | ||||
revsetlang, | revsetlang, | ||||
scmutil, | scmutil, | ||||
smartset, | smartset, | ||||
util, | util, | ||||
) | ) | ||||
from .utils import dateutil | |||||
# helpers for processing parsed tree | # helpers for processing parsed tree | ||||
getsymbol = revsetlang.getsymbol | getsymbol = revsetlang.getsymbol | ||||
getstring = revsetlang.getstring | getstring = revsetlang.getstring | ||||
getinteger = revsetlang.getinteger | getinteger = revsetlang.getinteger | ||||
getboolean = revsetlang.getboolean | getboolean = revsetlang.getboolean | ||||
getlist = revsetlang.getlist | getlist = revsetlang.getlist | ||||
getrange = revsetlang.getrange | getrange = revsetlang.getrange | ||||
condrepr=('<converted %r>', rev)) | condrepr=('<converted %r>', rev)) | ||||
@predicate('date(interval)', safe=True, weight=10) | @predicate('date(interval)', safe=True, weight=10) | ||||
def date(repo, subset, x): | def date(repo, subset, x): | ||||
"""Changesets within the interval, see :hg:`help dates`. | """Changesets within the interval, see :hg:`help dates`. | ||||
""" | """ | ||||
# i18n: "date" is a keyword | # i18n: "date" is a keyword | ||||
ds = getstring(x, _("date requires a string")) | ds = getstring(x, _("date requires a string")) | ||||
dm = util.matchdate(ds) | dm = dateutil.matchdate(ds) | ||||
return subset.filter(lambda x: dm(repo[x].date()[0]), | return subset.filter(lambda x: dm(repo[x].date()[0]), | ||||
condrepr=('<date %r>', ds)) | condrepr=('<date %r>', ds)) | ||||
@predicate('desc(string)', safe=True, weight=10) | @predicate('desc(string)', safe=True, weight=10) | ||||
def desc(repo, subset, x): | def desc(repo, subset, x): | ||||
"""Search commit message for string. The match is case-insensitive. | """Search commit message for string. The match is case-insensitive. | ||||
Pattern matching is supported for `string`. See | Pattern matching is supported for `string`. See |
nbytes = min(limit, size) | nbytes = min(limit, size) | ||||
s = nbytes and f.read(nbytes) | s = nbytes and f.read(nbytes) | ||||
if not s: | if not s: | ||||
break | break | ||||
if limit: | if limit: | ||||
limit -= len(s) | limit -= len(s) | ||||
yield s | yield s | ||||
def matchdate(date): | |||||
"""Return a function that matches a given date match specifier | |||||
Formats include: | |||||
'{date}' match a given date to the accuracy provided | |||||
'<{date}' on or before a given date | |||||
'>{date}' on or after a given date | |||||
>>> p1 = dateutil.parsedate(b"10:29:59") | |||||
>>> p2 = dateutil.parsedate(b"10:30:00") | |||||
>>> p3 = dateutil.parsedate(b"10:30:59") | |||||
>>> p4 = dateutil.parsedate(b"10:31:00") | |||||
>>> p5 = dateutil.parsedate(b"Sep 15 10:30:00 1999") | |||||
>>> f = matchdate(b"10:30") | |||||
>>> f(p1[0]) | |||||
False | |||||
>>> f(p2[0]) | |||||
True | |||||
>>> f(p3[0]) | |||||
True | |||||
>>> f(p4[0]) | |||||
False | |||||
>>> f(p5[0]) | |||||
False | |||||
""" | |||||
def lower(date): | |||||
d = {'mb': "1", 'd': "1"} | |||||
return dateutil.parsedate(date, extendeddateformats, d)[0] | |||||
def upper(date): | |||||
d = {'mb': "12", 'HI': "23", 'M': "59", 'S': "59"} | |||||
for days in ("31", "30", "29"): | |||||
try: | |||||
d["d"] = days | |||||
return dateutil.parsedate(date, extendeddateformats, d)[0] | |||||
except Abort: | |||||
pass | |||||
d["d"] = "28" | |||||
return dateutil.parsedate(date, extendeddateformats, d)[0] | |||||
date = date.strip() | |||||
if not date: | |||||
raise Abort(_("dates cannot consist entirely of whitespace")) | |||||
elif date[0] == "<": | |||||
if not date[1:]: | |||||
raise Abort(_("invalid day spec, use '<DATE'")) | |||||
when = upper(date[1:]) | |||||
return lambda x: x <= when | |||||
elif date[0] == ">": | |||||
if not date[1:]: | |||||
raise Abort(_("invalid day spec, use '>DATE'")) | |||||
when = lower(date[1:]) | |||||
return lambda x: x >= when | |||||
elif date[0] == "-": | |||||
try: | |||||
days = int(date[1:]) | |||||
except ValueError: | |||||
raise Abort(_("invalid day spec: %s") % date[1:]) | |||||
if days < 0: | |||||
raise Abort(_("%s must be nonnegative (see 'hg help dates')") | |||||
% date[1:]) | |||||
when = dateutil.makedate()[0] - days * 3600 * 24 | |||||
return lambda x: x >= when | |||||
elif " to " in date: | |||||
a, b = date.split(" to ") | |||||
start, stop = lower(a), upper(b) | |||||
return lambda x: x >= start and x <= stop | |||||
else: | |||||
start, stop = lower(date), upper(date) | |||||
return lambda x: x >= start and x <= stop | |||||
def stringmatcher(pattern, casesensitive=True): | def stringmatcher(pattern, casesensitive=True): | ||||
""" | """ | ||||
accepts a string, possibly starting with 're:' or 'literal:' prefix. | accepts a string, possibly starting with 're:' or 'literal:' prefix. | ||||
returns the matcher name, pattern, and matcher function. | returns the matcher name, pattern, and matcher function. | ||||
missing or unknown prefixes are treated as literal matches. | missing or unknown prefixes are treated as literal matches. | ||||
helper for tests: | helper for tests: | ||||
>>> def test(pattern, *tests): | >>> def test(pattern, *tests): | ||||
return dateutil.strdate(*args, **kwargs) | return dateutil.strdate(*args, **kwargs) | ||||
def parsedate(*args, **kwargs): | def parsedate(*args, **kwargs): | ||||
msg = ("'util.parsedate' is deprecated, " | msg = ("'util.parsedate' is deprecated, " | ||||
"use 'utils.dateutil.parsedate'") | "use 'utils.dateutil.parsedate'") | ||||
nouideprecwarn(msg, "4.6") | nouideprecwarn(msg, "4.6") | ||||
return dateutil.parsedate(*args, **kwargs) | return dateutil.parsedate(*args, **kwargs) | ||||
def matchdate(*args, **kwargs): | |||||
msg = ("'util.matchdate' is deprecated, " | |||||
"use 'utils.dateutil.matchdate'") | |||||
nouideprecwarn(msg, "4.6") | |||||
return dateutil.matchdate(*args, **kwargs) |
# current 32-bit linux runtimes. timezones go from UTC-12 | # current 32-bit linux runtimes. timezones go from UTC-12 | ||||
# to UTC+14 | # to UTC+14 | ||||
if when < -0x80000000 or when > 0x7fffffff: | if when < -0x80000000 or when > 0x7fffffff: | ||||
raise error.ParseError(_('date exceeds 32 bits: %d') % when) | raise error.ParseError(_('date exceeds 32 bits: %d') % when) | ||||
if offset < -50400 or offset > 43200: | if offset < -50400 or offset > 43200: | ||||
raise error.ParseError(_('impossible time zone offset: %d') % offset) | raise error.ParseError(_('impossible time zone offset: %d') % offset) | ||||
return when, offset | return when, offset | ||||
def matchdate(date): | |||||
"""Return a function that matches a given date match specifier | |||||
Formats include: | |||||
'{date}' match a given date to the accuracy provided | |||||
'<{date}' on or before a given date | |||||
'>{date}' on or after a given date | |||||
>>> p1 = parsedate(b"10:29:59") | |||||
>>> p2 = parsedate(b"10:30:00") | |||||
>>> p3 = parsedate(b"10:30:59") | |||||
>>> p4 = parsedate(b"10:31:00") | |||||
>>> p5 = parsedate(b"Sep 15 10:30:00 1999") | |||||
>>> f = matchdate(b"10:30") | |||||
>>> f(p1[0]) | |||||
False | |||||
>>> f(p2[0]) | |||||
True | |||||
>>> f(p3[0]) | |||||
True | |||||
>>> f(p4[0]) | |||||
False | |||||
>>> f(p5[0]) | |||||
False | |||||
""" | |||||
def lower(date): | |||||
d = {'mb': "1", 'd': "1"} | |||||
return parsedate(date, extendeddateformats, d)[0] | |||||
def upper(date): | |||||
d = {'mb': "12", 'HI': "23", 'M': "59", 'S': "59"} | |||||
for days in ("31", "30", "29"): | |||||
try: | |||||
d["d"] = days | |||||
return parsedate(date, extendeddateformats, d)[0] | |||||
except error.Abort: | |||||
pass | |||||
d["d"] = "28" | |||||
return parsedate(date, extendeddateformats, d)[0] | |||||
date = date.strip() | |||||
if not date: | |||||
raise error.Abort(_("dates cannot consist entirely of whitespace")) | |||||
elif date[0] == "<": | |||||
if not date[1:]: | |||||
raise error.Abort(_("invalid day spec, use '<DATE'")) | |||||
when = upper(date[1:]) | |||||
return lambda x: x <= when | |||||
elif date[0] == ">": | |||||
if not date[1:]: | |||||
raise error.Abort(_("invalid day spec, use '>DATE'")) | |||||
when = lower(date[1:]) | |||||
return lambda x: x >= when | |||||
elif date[0] == "-": | |||||
try: | |||||
days = int(date[1:]) | |||||
except ValueError: | |||||
raise error.Abort(_("invalid day spec: %s") % date[1:]) | |||||
if days < 0: | |||||
raise error.Abort(_("%s must be nonnegative (see 'hg help dates')") | |||||
% date[1:]) | |||||
when = makedate()[0] - days * 3600 * 24 | |||||
return lambda x: x >= when | |||||
elif " to " in date: | |||||
a, b = date.split(" to ") | |||||
start, stop = lower(a), upper(b) | |||||
return lambda x: x >= start and x <= stop | |||||
else: | |||||
start, stop = lower(date), upper(date) | |||||
return lambda x: x >= start and x <= stop |