Skip to content

Commit

Permalink
Kill --quick-and-dirty (#6078)
Browse files Browse the repository at this point in the history
It has been deprecated for two mypy releases. Users should really use dmypy instead.

Closes #5728.
  • Loading branch information
gvanrossum committed Dec 17, 2018
1 parent d2a9f9d commit b922266
Show file tree
Hide file tree
Showing 9 changed files with 8 additions and 771 deletions.
17 changes: 0 additions & 17 deletions docs/source/command_line.rst
Original file line number Diff line number Diff line change
Expand Up @@ -451,23 +451,6 @@ beyond what incremental mode can offer, try running mypy in
By default, mypy will ignore cache data generated by a different
version of mypy. This flag disables that behavior.

.. _quick-mode:

``--quick-and-dirty``
This flag enables a **deprecated**, unsafe variant of incremental mode.
Quick mode is faster than regular incremental mode because it only
re-checks modules that were modified since their cache file was
last written: regular incremental mode also re-checks all modules
that depend on one or more modules that were re-checked.

Quick mode is unsafe because it may miss problems caused by a change
in a dependency. Quick mode updates the cache, but regular incremental
mode ignores cache files written by quick mode.

We recommend that you try using the :ref:`mypy_daemon` before
attempting to use this feature.
Quick mode is deprecated and will soon be removed.

.. _advanced-flags:

Advanced flags
Expand Down
3 changes: 0 additions & 3 deletions docs/source/config_file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,6 @@ section of the command line docs.
Makes mypy use incremental cache data even if it was generated by a
different version of mypy. (By default, mypy will perform a version
check and regenerate the cache if it was written by older versions of mypy.)

``quick_and_dirty`` (bool, default False)
Enables :ref:`quick mode <quick-mode>`. **Deprecated.**


Configuring error messages
Expand Down
2 changes: 1 addition & 1 deletion docs/source/extending_mypy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ During different phases of analyzing the code (first in semantic analysis,
and then in type checking) mypy calls plugin methods such as
``get_type_analyze_hook()`` on user plugins. This particular method for example
can return a callback that mypy will use to analyze unbound types with given
full name. See full plugin hook methods list :ref:`below <plugin-hooks>`.
full name. See full plugin hook methods list :ref:`below <plugin_hooks>`.

Mypy maintains a list of plugins it gets from the config file plus the default
(built-in) plugin that is always enabled. Mypy calls a method once for each
Expand Down
32 changes: 4 additions & 28 deletions mypy/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -898,9 +898,6 @@ def find_cache_meta(id: str, path: str, manager: BuildManager) -> Optional[Cache
# Note that it's fine to mutilate cached_options since it's only used here.
cached_options = m.options
current_options = manager.options.clone_for_module(id).select_options_affecting_cache()
if manager.options.quick_and_dirty:
# In quick_and_dirty mode allow non-quick_and_dirty cache files.
cached_options['quick_and_dirty'] = True
if manager.options.skip_version_check:
# When we're lax about version we're also lax about platform.
cached_options['platform'] = current_options['platform']
Expand Down Expand Up @@ -1598,7 +1595,6 @@ def fix_cross_refs(self) -> None:
# We need to set quick_and_dirty when doing a fine grained
# cache load because we need to gracefully handle missing modules.
fixup_module(self.tree, self.manager.modules,
self.manager.options.quick_and_dirty or
self.options.use_fine_grained_cache)

def patch_dependency_parents(self) -> None:
Expand Down Expand Up @@ -1866,10 +1862,7 @@ def write_cache(self) -> None:
or self.options.cache_dir == os.devnull
or self.options.fine_grained_incremental):
return
if self.manager.options.quick_and_dirty:
is_errors = self.manager.errors.is_errors_for_file(self.path)
else:
is_errors = self.transitive_error
is_errors = self.transitive_error
if is_errors:
delete_cache(self.id, self.path, self.manager)
self.meta = None
Expand Down Expand Up @@ -2431,8 +2424,7 @@ def process_graph(graph: Graph, manager: BuildManager) -> None:
deps.update(graph[id].dependencies)
deps -= ascc
stale_deps = {id for id in deps if id in graph and not graph[id].is_interface_fresh()}
if not manager.options.quick_and_dirty:
fresh = fresh and not stale_deps
fresh = fresh and not stale_deps
undeps = set()
if fresh:
# Check if any dependencies that were suppressed according
Expand Down Expand Up @@ -2466,9 +2458,7 @@ def process_graph(graph: Graph, manager: BuildManager) -> None:
manager.trace(" %5s %.0f %s" % (key, graph[id].xmeta.data_mtime, id))
# If equal, give the benefit of the doubt, due to 1-sec time granularity
# (on some platforms).
if manager.options.quick_and_dirty and stale_deps:
fresh_msg = "fresh(ish)"
elif oldest_in_scc < newest_in_deps:
if oldest_in_scc < newest_in_deps:
fresh = False
fresh_msg = "out of date by %.0f seconds" % (newest_in_deps - oldest_in_scc)
else:
Expand Down Expand Up @@ -2608,19 +2598,7 @@ def process_stale_scc(graph: Graph, scc: List[str], manager: BuildManager) -> No
Exception: If quick_and_dirty is set, use the cache for fresh modules.
"""
if manager.options.quick_and_dirty:
fresh = [id for id in scc if graph[id].is_fresh()]
fresh_set = set(fresh) # To avoid running into O(N**2)
stale = [id for id in scc if id not in fresh_set]
if fresh:
manager.log(" Fresh ids: %s" % (", ".join(fresh)))
if stale:
manager.log(" Stale ids: %s" % (", ".join(stale)))
else:
fresh = []
stale = scc
for id in fresh:
graph[id].load_tree()
stale = scc
for id in stale:
# We may already have parsed the module, or not.
# If the former, parse_file() is a no-op.
Expand All @@ -2633,8 +2611,6 @@ def process_stale_scc(graph: Graph, scc: List[str], manager: BuildManager) -> No
typing_mod = graph['typing'].tree
assert typing_mod, "The typing module was not parsed"
manager.semantic_analyzer.add_builtin_aliases(typing_mod)
for id in fresh:
graph[id].fix_cross_refs()
for id in stale:
graph[id].semantic_analysis()
for id in stale:
Expand Down
2 changes: 0 additions & 2 deletions mypy/dmypy_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,6 @@ def process_start_options(flags: List[str], allow_sources: bool) -> Options:
"pass it to check/recheck instead")
if not options.incremental:
sys.exit("dmypy: start/restart should not disable incremental mode")
if options.quick_and_dirty:
sys.exit("dmypy: start/restart should not specify quick_and_dirty mode")
# Our file change tracking can't yet handle changes to files that aren't
# specified in the sources list.
if options.follow_imports not in ('skip', 'error'):
Expand Down
13 changes: 0 additions & 13 deletions mypy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -670,10 +670,6 @@ def add_invertible_flag(flag: str,
parser.add_argument('--cache-map', nargs='+', dest='special-opts:cache_map',
help=argparse.SUPPRESS)

# deprecated options
parser.add_argument('--quick-and-dirty', action='store_true',
help=argparse.SUPPRESS)

# options specifying code to check
code_group = parser.add_argument_group(
title="Running code",
Expand Down Expand Up @@ -719,11 +715,6 @@ def add_invertible_flag(flag: str,
special_opts = argparse.Namespace()
parser.parse_args(args, SplitNamespace(options, special_opts, 'special-opts:'))

# Process deprecated options
if options.quick_and_dirty:
print("Warning: --quick-and-dirty is deprecated. It will disappear in the next release.",
file=sys.stderr)

# The python_version is either the default, which can be overridden via a config file,
# or stored in special_opts and is passed via the command line.
options.python_version = special_opts.python_version or options.python_version
Expand Down Expand Up @@ -781,10 +772,6 @@ def add_invertible_flag(flag: str,

process_cache_map(parser, special_opts, options)

# Let quick_and_dirty imply incremental.
if options.quick_and_dirty:
options.incremental = True

# Let logical_deps imply cache_fine_grained (otherwise the former is useless).
if options.logical_deps:
options.cache_fine_grained = True
Expand Down
3 changes: 1 addition & 2 deletions mypy/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class BuildType:
} # type: Final

OPTIONS_AFFECTING_CACHE = ((PER_MODULE_OPTIONS |
{"quick_and_dirty", "platform", "bazel", "plugins"})
{"platform", "bazel", "plugins"})
- {"debug_cache"}) # type: Final


Expand Down Expand Up @@ -169,7 +169,6 @@ def __init__(self) -> None:
self.cache_dir = defaults.CACHE_DIR
self.sqlite_cache = False
self.debug_cache = False
self.quick_and_dirty = False
self.skip_version_check = False
self.fine_grained_incremental = False
# Include fine-grained dependencies in written cache files
Expand Down
7 changes: 2 additions & 5 deletions mypy/test/testcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,8 @@ def verify_cache(self, module_data: List[Tuple[str, str, str]], a: List[str],
# for those that had an error in themselves or one of their
# dependencies.
error_paths = self.find_error_message_paths(a)
if manager.options.quick_and_dirty:
busted_paths = error_paths
else:
busted_paths = {m.path for id, m in manager.modules.items()
if graph[id].transitive_error}
busted_paths = {m.path for id, m in manager.modules.items()
if graph[id].transitive_error}
modules = self.find_module_files(manager)
modules.update({module_name: path for module_name, path, text in module_data})
missing_paths = self.find_missing_cache_files(modules, manager)
Expand Down
Loading

0 comments on commit b922266

Please sign in to comment.