import-checker: don't treat modules as relative one if not found
The previous patch ensures all module names are recorded in `imports`
as absolute names, so we no longer need to treat modules as ones
imported relatively from the target source if they appear to not be
from the stdlib.
import-checker: make imported_modules yield absolute dotted_name_of_path
This patch makes `imported_modules()` always yield absolute
`dotted_name_of_path()`-ed name by strict detection with
`fromlocal()`.
This change improves circular detection in some points:
- locally defined modules, of which name collides against one of
standard library, can be examined correctly
For example, circular import related to `commands` is overlooked
before this patch.
- names not useful for circular detection are ignored
Names below are also yielded before this patch:
- module names of standard library (= not locally defined one)
- non-module names (e.g. `node.nullid` of `from node import nullid`)
These redundant names decrease performance of circular detection.
For example, with files at
1ef96a3b8b89, average loops per file in
`checkmod()` is reduced from 165 to 109.
- `__init__` can be handled correctly in `checkmod()`
For example, current implementation has problems below:
- `from xxx import yyy` doesn't recognize `xxx.__init__` as imported
- `xxx.__init__` imported via `import xxx` is treated as `xxx`,
and circular detection is aborted, because `key` of such
module name is not `xxx` but `xxx.__init__`
- it is easy to enhance for `from . import xxx` style or so (in the
future)
Module name detection in `imported_modules()` can use information
in `ast.ImportFrom` fully.
It is assumed that all locally defined modules are correctly specified
to `import-checker.py` at once.
Strictly speaking, when `from foo.bar.baz import module1` imports
`foo.bar.baz.module1` module, current `imported_modules()` yields only
`foo.bar.baz.__init__`, even though also `foo.__init__` and
`foo.bar.__init__` should be yielded to detect circular import
exactly.
But this limitation is reasonable one for improvement in this patch,
because current `__init__` files in Mercurial seems to be implemented
carefully.
import-checker: add utility to examine what module is imported easily
`fromlocalfunc()` uses:
- `modulename` (of the target source) to compose absolute module
name imported relatively from it
It is assumed that `modulename` is an `dotted_name_of_path()`-ed
source file, which may have `.__init__` at the end of it.
This assumption makes composing `prefix` of relative name easy.
- `localmods` to examine whether there is a locally defined (=
Mercurial specific) module matching against the specified name
It is assumed that module names not existing in `localmods` are
ones of Python standard library.
subrepo: further replacement of try/except with 'next'
Burn StopIteration, Burn!
parsers: use 'next' instead of try/except
This get rid of another StopIteration abomination. The change in self.current
value is supposed to not matter as nobody should be calling '_advance' after
that (as per Matt wisdom).
dagparser: use 'next' instead of try/except for default value
"Ich liebe es wenn ein Plan funktioniert."
getlogrevs: rewrite a loop to get read of try/except
Get rid of the 'except StopIteration' abomination.
_makelogrevset: replace try/except with 'next' usage
More readable without the 'except StopIteration' abomination.
ignore: move readpatternfile to match.py
In preparation for adding 'include:' rule support to match.py, let's move the
pattern file reader function to match.py
ignore: rename readignorefile to readpatternfile
A future commit will move the readignorefile logic into match.py so it can be
used from general match rules. Let's rename the function to represent this new
behavior.
ignore: combine readignorefile and _ignorefile
_ignorefile did nothing except open the file. Let's combine it with
readignorefile for simplicity. This will make it easier to rename and move to
match.py in upcoming patches.
ignore: move bad file handling out of readignorefile
In preparation for moving readignorefile to match.py to make it more generally
usable, let's move the bad ignore file handling up to the ignore specific logic.