Skip to content

Commit 1aefa4f

Browse files
committed
Ignore unresolved requirements
1 parent dcb59fd commit 1aefa4f

10 files changed

+32
-267
lines changed

Diff for: src/ssort/__init__.py

+1-9
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,13 @@
22
The python source code statement sorter.
33
"""
44

5-
from ssort._exceptions import (
6-
DecodingError,
7-
ParseError,
8-
ResolutionError,
9-
UnknownEncodingError,
10-
WildcardImportError,
11-
)
5+
from ssort._exceptions import DecodingError, ParseError, UnknownEncodingError
126
from ssort._ssort import ssort
137

148
# Let linting tools know that we do mean to re-export exception classes.
159
assert DecodingError is not None
1610
assert ParseError is not None
17-
assert ResolutionError is not None
1811
assert UnknownEncodingError is not None
19-
assert WildcardImportError is not None
2012

2113
try:
2214
from ssort._version import VERSION as __version__ # type: ignore

Diff for: src/ssort/_dependencies.py

+2-47
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from ssort._graphs import Graph
33

44

5-
def module_statements_graph(statements, *, on_unresolved, on_wildcard_import):
5+
def module_statements_graph(statements):
66
"""
77
Constructs a graph of the interdependencies in a list of module level
88
statements.
@@ -11,16 +11,6 @@ def module_statements_graph(statements, *, on_unresolved, on_wildcard_import):
1111
An ordered list of opaque `Statement` objects from which to construct
1212
the graph.
1313
14-
:param on_unresolved:
15-
An callback that should be invoked for each unresolved dependency. Can
16-
safely raise any arbitrary exception to abort constructing the graph.
17-
If no exception is raised, the graph returned by this function will not
18-
contain a link for the missing requirement.
19-
:param on_wildcard_import:
20-
A callback that should be invoked if ssort detects a `*` import. If no
21-
exception is raised, all dangling references will be pointed back to the
22-
last `*` import.
23-
2414
:returns:
2515
A `Graph` mapping from statements to the set of statements that they
2616
depend on.
@@ -35,7 +25,6 @@ def module_statements_graph(statements, *, on_unresolved, on_wildcard_import):
3525
for requirement in statement.requirements():
3626
all_requirements.append(requirement)
3727

38-
# TODO error if requirement is not deferred.
3928
if requirement.name in scope:
4029
resolved[requirement] = scope[requirement.name]
4130
continue
@@ -45,12 +34,6 @@ def module_statements_graph(statements, *, on_unresolved, on_wildcard_import):
4534
continue
4635

4736
for name in statement.bindings():
48-
if name == "*":
49-
on_wildcard_import(
50-
lineno=statement.node.lineno,
51-
col_offset=statement.node.col_offset,
52-
)
53-
5437
scope[name] = statement
5538

5639
# Patch up dependencies that couldn't be resolved immediately.
@@ -63,41 +46,13 @@ def module_statements_graph(statements, *, on_unresolved, on_wildcard_import):
6346

6447
resolved[requirement] = scope[requirement.name]
6548

66-
if "*" in scope:
67-
for requirement in all_requirements:
68-
if requirement in resolved:
69-
continue
70-
71-
resolved[requirement] = scope["*"]
72-
73-
else:
74-
unresolved = [
75-
requirement
76-
for requirement in all_requirements
77-
if requirement not in resolved
78-
]
79-
80-
for requirement in unresolved:
81-
on_unresolved(
82-
f"could not resolve {requirement.name!r}",
83-
name=requirement.name,
84-
lineno=requirement.lineno,
85-
col_offset=requirement.col_offset,
86-
)
87-
88-
if unresolved:
89-
# Not safe to attempt to re-order in the event of unresolved
90-
# dependencies. A typo could cause a statement to be moved ahead of
91-
# something that it should depend on.
92-
return None
93-
9449
graph = Graph()
9550
for statement in statements:
9651
graph.add_node(statement)
9752

9853
for statement in statements:
9954
for requirement in statement.requirements():
100-
if resolved[requirement] is not None:
55+
if resolved.get(requirement) is not None:
10156
graph.add_dependency(statement, resolved[requirement])
10257

10358
# Add links between statements that overwrite the same binding to make sure

Diff for: src/ssort/_exceptions.py

-15
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,3 @@ def __init__(self, msg, *, lineno, col_offset):
1313
super().__init__(msg)
1414
self.lineno = lineno
1515
self.col_offset = col_offset
16-
17-
18-
class ResolutionError(Exception):
19-
def __init__(self, msg, *, name, lineno, col_offset):
20-
super().__init__(msg)
21-
self.name = name
22-
self.lineno = lineno
23-
self.col_offset = col_offset
24-
25-
26-
class WildcardImportError(Exception):
27-
def __init__(self, msg, *, lineno, col_offset):
28-
super().__init__(msg)
29-
self.lineno = lineno
30-
self.col_offset = col_offset

Diff for: src/ssort/_main.py

-17
Original file line numberDiff line numberDiff line change
@@ -104,28 +104,11 @@ def _on_parse_error(message, *, lineno, col_offset, **kwargs):
104104
+ f"line {lineno}, column {col_offset}\n"
105105
)
106106

107-
def _on_unresolved(message, *, name, lineno, col_offset, **kwargs):
108-
nonlocal errors
109-
errors = True
110-
111-
sys.stderr.write(
112-
f"ERROR: unresolved dependency {name!r} "
113-
+ f"in {escape_path(path)}: "
114-
+ f"line {lineno}, column {col_offset}\n"
115-
)
116-
117-
def _on_wildcard_import(**kwargs):
118-
sys.stderr.write(
119-
"WARNING: can't determine dependencies on * import\n"
120-
)
121-
122107
try:
123108
updated = ssort(
124109
original,
125110
filename=escape_path(path),
126111
on_parse_error=_on_parse_error,
127-
on_unresolved=_on_unresolved,
128-
on_wildcard_import=_on_wildcard_import,
129112
)
130113

131114
if errors:

Diff for: src/ssort/_ssort.py

+2-65
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,7 @@
77
class_statements_runtime_graph,
88
module_statements_graph,
99
)
10-
from ssort._exceptions import (
11-
DecodingError,
12-
ParseError,
13-
ResolutionError,
14-
UnknownEncodingError,
15-
WildcardImportError,
16-
)
10+
from ssort._exceptions import DecodingError, ParseError, UnknownEncodingError
1711
from ssort._graphs import (
1812
is_topologically_sorted,
1913
replace_cycles,
@@ -393,70 +387,19 @@ def _interpret_on_parse_error_action(on_parse_error):
393387
return on_parse_error
394388

395389

396-
def _on_unresolved_ignore(message, *, name, lineno, col_offset, **kwargs):
397-
pass
398-
399-
400-
def _on_unresolved_raise(message, *, name, lineno, col_offset, **kwargs):
401-
raise ResolutionError(
402-
message,
403-
name=name,
404-
lineno=lineno,
405-
col_offset=col_offset,
406-
)
407-
408-
409-
def _interpret_on_unresolved_action(on_unresolved):
410-
if on_unresolved == "ignore":
411-
return _on_unresolved_ignore
412-
413-
if on_unresolved == "raise":
414-
return _on_unresolved_raise
415-
416-
return on_unresolved
417-
418-
419-
def _on_wildcard_import_ignore(**kwargs):
420-
pass
421-
422-
423-
def _on_wildcard_import_raise(*, lineno, col_offset, **kwargs):
424-
raise WildcardImportError(
425-
"can't reliably determine dependencies on * import",
426-
lineno=lineno,
427-
col_offset=col_offset,
428-
)
429-
430-
431-
def _interpret_on_wildcard_import_action(on_wildcard_import):
432-
if on_wildcard_import == "ignore":
433-
return _on_wildcard_import_ignore
434-
435-
if on_wildcard_import == "raise":
436-
return _on_wildcard_import_raise
437-
438-
return on_wildcard_import
439-
440-
441390
def ssort(
442391
text,
443392
*,
444393
filename="<unknown>",
445394
on_unknown_encoding_error="raise",
446395
on_decoding_error="raise",
447396
on_parse_error="raise",
448-
on_unresolved="raise",
449-
on_wildcard_import="raise",
450397
):
451398
on_unknown_encoding_error = _interpret_on_unknown_encoding_action(
452399
on_unknown_encoding_error
453400
)
454401
on_decoding_error = _interpret_on_decoding_error_action(on_decoding_error)
455402
on_parse_error = _interpret_on_parse_error_action(on_parse_error)
456-
on_unresolved = _interpret_on_unresolved_action(on_unresolved)
457-
on_wildcard_import = _interpret_on_wildcard_import_action(
458-
on_wildcard_import
459-
)
460403

461404
try:
462405
encoding = None
@@ -483,13 +426,7 @@ def ssort(
483426
if not statements:
484427
return text
485428

486-
graph = module_statements_graph(
487-
statements,
488-
on_unresolved=on_unresolved,
489-
on_wildcard_import=on_wildcard_import,
490-
)
491-
if graph is None:
492-
return text
429+
graph = module_statements_graph(statements)
493430

494431
replace_cycles(graph, key=sort_key_from_iter(statements))
495432

Diff for: tests/test_dependencies.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ def _clean(source):
88
return textwrap.dedent(source).strip() + "\n"
99

1010

11-
def _unreachable(*args, **kwargs):
12-
raise AssertionError("unreachable")
13-
14-
1511
def test_dependencies_ordered_by_first_use():
1612
source = _clean(
1713
"""
@@ -28,8 +24,6 @@ def b():
2824
"""
2925
)
3026
c, a, b = statements = list(parse(source, filename="<unknown>"))
31-
graph = module_statements_graph(
32-
statements, on_unresolved=_unreachable, on_wildcard_import=_unreachable
33-
)
27+
graph = module_statements_graph(statements)
3428

3529
assert list(graph.dependencies[a]) == [b, c]

Diff for: tests/test_error_hooks.py

+1-85
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
import pytest
22

3-
from ssort import (
4-
DecodingError,
5-
ParseError,
6-
ResolutionError,
7-
UnknownEncodingError,
8-
WildcardImportError,
9-
ssort,
10-
)
3+
from ssort import DecodingError, ParseError, UnknownEncodingError, ssort
114

125

136
class _DummyException(Exception):
@@ -104,80 +97,3 @@ def on_parse_error(message, *, lineno, col_offset):
10497
with pytest.raises(_DummyException) as exc_info:
10598
ssort(original, on_parse_error=on_parse_error)
10699
assert exc_info.value.args == ("invalid syntax", 1, 4)
107-
108-
109-
# === Unresolved ===============================================================
110-
111-
112-
def test_on_unresolved_raise():
113-
original = "def fun():\n unresolved()"
114-
115-
with pytest.raises(ResolutionError) as exc_info:
116-
ssort(original, on_unresolved="raise")
117-
118-
assert str(exc_info.value) == "could not resolve 'unresolved'"
119-
assert exc_info.value.name == "unresolved"
120-
assert exc_info.value.lineno == 2
121-
assert exc_info.value.col_offset == 4
122-
123-
124-
def test_on_unresolved_ignore():
125-
original = "def fun():\n unresolved()"
126-
127-
actual = ssort(original, on_unresolved="ignore")
128-
129-
assert actual == original
130-
131-
132-
def test_on_unresolved_callback():
133-
original = "def fun():\n unresolved()"
134-
135-
def on_unresolved(message, *, name, lineno, col_offset):
136-
raise _DummyException(message, name, lineno, col_offset)
137-
138-
with pytest.raises(_DummyException) as exc_info:
139-
ssort(original, on_unresolved=on_unresolved)
140-
141-
assert exc_info.value.args == (
142-
"could not resolve 'unresolved'",
143-
"unresolved",
144-
2,
145-
4,
146-
)
147-
148-
149-
# === Wildcard Import ==========================================================
150-
151-
152-
def test_on_wildcard_import_raise():
153-
original = "from module import *"
154-
155-
with pytest.raises(WildcardImportError) as exc_info:
156-
ssort(original, on_wildcard_import="raise")
157-
158-
assert (
159-
str(exc_info.value)
160-
== "can't reliably determine dependencies on * import"
161-
)
162-
assert exc_info.value.lineno == 1
163-
assert exc_info.value.col_offset == 0
164-
165-
166-
def test_on_wildcard_import_ignore():
167-
original = "from module import *\n"
168-
169-
actual = ssort(original, on_wildcard_import="ignore")
170-
171-
assert actual == original
172-
173-
174-
def test_on_wildcard_import_callback():
175-
original = "from module import *"
176-
177-
def on_wildcard_import(*, lineno, col_offset):
178-
raise _DummyException(lineno, col_offset)
179-
180-
with pytest.raises(_DummyException) as exc_info:
181-
ssort(original, on_wildcard_import=on_wildcard_import)
182-
183-
assert exc_info.value.args == (1, 0)

0 commit comments

Comments
 (0)