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 | |||||