grimp 3.2__tar.gz → 3.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {grimp-3.2 → grimp-3.3}/PKG-INFO +2 -2
- {grimp-3.2 → grimp-3.3}/pyproject.toml +2 -2
- {grimp-3.2 → grimp-3.3}/rust/Cargo.lock +85 -18
- {grimp-3.2 → grimp-3.3}/rust/Cargo.toml +3 -2
- {grimp-3.2 → grimp-3.3}/rust/src/containers.rs +1 -2
- {grimp-3.2 → grimp-3.3}/rust/src/layers.rs +61 -47
- {grimp-3.2 → grimp-3.3}/rust/src/lib.rs +85 -49
- {grimp-3.2 → grimp-3.3}/rust/tests/large.rs +6 -6
- {grimp-3.2 → grimp-3.3}/src/grimp/__init__.py +1 -1
- {grimp-3.2 → grimp-3.3}/src/grimp/adaptors/filesystem.py +1 -1
- {grimp-3.2 → grimp-3.3}/README.rst +0 -0
- {grimp-3.2 → grimp-3.3}/rust/.cargo/config +0 -0
- {grimp-3.2 → grimp-3.3}/rust/src/dependencies.rs +0 -0
- {grimp-3.2 → grimp-3.3}/rust/src/importgraph.rs +0 -0
- {grimp-3.2 → grimp-3.3}/rust/tests/large_graph.json +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/adaptors/__init__.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/adaptors/_layers.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/adaptors/caching.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/adaptors/graph.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/adaptors/importscanner.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/adaptors/modulefinder.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/adaptors/packagefinder.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/adaptors/timing.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/algorithms/__init__.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/algorithms/shortest_path.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/application/__init__.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/application/config.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/application/ports/__init__.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/application/ports/caching.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/application/ports/filesystem.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/application/ports/graph.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/application/ports/importscanner.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/application/ports/modulefinder.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/application/ports/packagefinder.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/application/ports/timing.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/application/usecases.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/domain/__init__.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/domain/analysis.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/domain/valueobjects.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/exceptions.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/helpers.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/main.py +0 -0
- {grimp-3.2 → grimp-3.3}/src/grimp/py.typed +0 -0
{grimp-3.2 → grimp-3.3}/PKG-INFO
RENAMED
|
@@ -8,7 +8,7 @@ module-name = "grimp._rustgrimp"
|
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "grimp"
|
|
11
|
-
version = "3.
|
|
11
|
+
version = "3.3"
|
|
12
12
|
license = {text = "BSD 2-Clause License"}
|
|
13
13
|
description = "Builds a queryable graph of the imports within one or more Python packages."
|
|
14
14
|
authors = [
|
|
@@ -54,4 +54,4 @@ namespaces = false
|
|
|
54
54
|
|
|
55
55
|
[tool.black]
|
|
56
56
|
line-length = 99
|
|
57
|
-
exclude = 'tests/assets/syntaxerrorpackage'
|
|
57
|
+
exclude = 'tests/assets/syntaxerrorpackage'
|
|
@@ -9,6 +9,7 @@ dependencies = [
|
|
|
9
9
|
"log",
|
|
10
10
|
"pyo3",
|
|
11
11
|
"pyo3-log",
|
|
12
|
+
"rayon",
|
|
12
13
|
"serde_json",
|
|
13
14
|
]
|
|
14
15
|
|
|
@@ -36,11 +37,48 @@ version = "1.0.0"
|
|
|
36
37
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
37
38
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
38
39
|
|
|
40
|
+
[[package]]
|
|
41
|
+
name = "crossbeam-deque"
|
|
42
|
+
version = "0.8.5"
|
|
43
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
44
|
+
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
|
45
|
+
dependencies = [
|
|
46
|
+
"crossbeam-epoch",
|
|
47
|
+
"crossbeam-utils",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[[package]]
|
|
51
|
+
name = "crossbeam-epoch"
|
|
52
|
+
version = "0.9.18"
|
|
53
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
54
|
+
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
|
55
|
+
dependencies = [
|
|
56
|
+
"crossbeam-utils",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[[package]]
|
|
60
|
+
name = "crossbeam-utils"
|
|
61
|
+
version = "0.8.20"
|
|
62
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
63
|
+
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
|
64
|
+
|
|
65
|
+
[[package]]
|
|
66
|
+
name = "either"
|
|
67
|
+
version = "1.12.0"
|
|
68
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
69
|
+
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
|
|
70
|
+
|
|
71
|
+
[[package]]
|
|
72
|
+
name = "heck"
|
|
73
|
+
version = "0.4.1"
|
|
74
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
75
|
+
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
|
76
|
+
|
|
39
77
|
[[package]]
|
|
40
78
|
name = "indoc"
|
|
41
|
-
version = "
|
|
79
|
+
version = "2.0.5"
|
|
42
80
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
43
|
-
checksum = "
|
|
81
|
+
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
|
44
82
|
|
|
45
83
|
[[package]]
|
|
46
84
|
name = "itoa"
|
|
@@ -108,6 +146,12 @@ dependencies = [
|
|
|
108
146
|
"windows-targets",
|
|
109
147
|
]
|
|
110
148
|
|
|
149
|
+
[[package]]
|
|
150
|
+
name = "portable-atomic"
|
|
151
|
+
version = "1.6.0"
|
|
152
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
153
|
+
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
|
154
|
+
|
|
111
155
|
[[package]]
|
|
112
156
|
name = "proc-macro2"
|
|
113
157
|
version = "1.0.64"
|
|
@@ -119,15 +163,16 @@ dependencies = [
|
|
|
119
163
|
|
|
120
164
|
[[package]]
|
|
121
165
|
name = "pyo3"
|
|
122
|
-
version = "0.
|
|
166
|
+
version = "0.21.2"
|
|
123
167
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
124
|
-
checksum = "
|
|
168
|
+
checksum = "a5e00b96a521718e08e03b1a622f01c8a8deb50719335de3f60b3b3950f069d8"
|
|
125
169
|
dependencies = [
|
|
126
170
|
"cfg-if",
|
|
127
171
|
"indoc",
|
|
128
172
|
"libc",
|
|
129
173
|
"memoffset",
|
|
130
174
|
"parking_lot",
|
|
175
|
+
"portable-atomic",
|
|
131
176
|
"pyo3-build-config",
|
|
132
177
|
"pyo3-ffi",
|
|
133
178
|
"pyo3-macros",
|
|
@@ -136,9 +181,9 @@ dependencies = [
|
|
|
136
181
|
|
|
137
182
|
[[package]]
|
|
138
183
|
name = "pyo3-build-config"
|
|
139
|
-
version = "0.
|
|
184
|
+
version = "0.21.2"
|
|
140
185
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
141
|
-
checksum = "
|
|
186
|
+
checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50"
|
|
142
187
|
dependencies = [
|
|
143
188
|
"once_cell",
|
|
144
189
|
"target-lexicon",
|
|
@@ -146,9 +191,9 @@ dependencies = [
|
|
|
146
191
|
|
|
147
192
|
[[package]]
|
|
148
193
|
name = "pyo3-ffi"
|
|
149
|
-
version = "0.
|
|
194
|
+
version = "0.21.2"
|
|
150
195
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
151
|
-
checksum = "
|
|
196
|
+
checksum = "01be5843dc60b916ab4dad1dca6d20b9b4e6ddc8e15f50c47fe6d85f1fb97403"
|
|
152
197
|
dependencies = [
|
|
153
198
|
"libc",
|
|
154
199
|
"pyo3-build-config",
|
|
@@ -156,9 +201,9 @@ dependencies = [
|
|
|
156
201
|
|
|
157
202
|
[[package]]
|
|
158
203
|
name = "pyo3-log"
|
|
159
|
-
version = "0.
|
|
204
|
+
version = "0.10.0"
|
|
160
205
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
161
|
-
checksum = "
|
|
206
|
+
checksum = "2af49834b8d2ecd555177e63b273b708dea75150abc6f5341d0a6e1a9623976c"
|
|
162
207
|
dependencies = [
|
|
163
208
|
"arc-swap",
|
|
164
209
|
"log",
|
|
@@ -167,9 +212,9 @@ dependencies = [
|
|
|
167
212
|
|
|
168
213
|
[[package]]
|
|
169
214
|
name = "pyo3-macros"
|
|
170
|
-
version = "0.
|
|
215
|
+
version = "0.21.2"
|
|
171
216
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
172
|
-
checksum = "
|
|
217
|
+
checksum = "77b34069fc0682e11b31dbd10321cbf94808394c56fd996796ce45217dfac53c"
|
|
173
218
|
dependencies = [
|
|
174
219
|
"proc-macro2",
|
|
175
220
|
"pyo3-macros-backend",
|
|
@@ -179,11 +224,13 @@ dependencies = [
|
|
|
179
224
|
|
|
180
225
|
[[package]]
|
|
181
226
|
name = "pyo3-macros-backend"
|
|
182
|
-
version = "0.
|
|
227
|
+
version = "0.21.2"
|
|
183
228
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
184
|
-
checksum = "
|
|
229
|
+
checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c"
|
|
185
230
|
dependencies = [
|
|
231
|
+
"heck",
|
|
186
232
|
"proc-macro2",
|
|
233
|
+
"pyo3-build-config",
|
|
187
234
|
"quote",
|
|
188
235
|
"syn",
|
|
189
236
|
]
|
|
@@ -197,6 +244,26 @@ dependencies = [
|
|
|
197
244
|
"proc-macro2",
|
|
198
245
|
]
|
|
199
246
|
|
|
247
|
+
[[package]]
|
|
248
|
+
name = "rayon"
|
|
249
|
+
version = "1.10.0"
|
|
250
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
251
|
+
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
|
252
|
+
dependencies = [
|
|
253
|
+
"either",
|
|
254
|
+
"rayon-core",
|
|
255
|
+
]
|
|
256
|
+
|
|
257
|
+
[[package]]
|
|
258
|
+
name = "rayon-core"
|
|
259
|
+
version = "1.12.1"
|
|
260
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
261
|
+
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
|
262
|
+
dependencies = [
|
|
263
|
+
"crossbeam-deque",
|
|
264
|
+
"crossbeam-utils",
|
|
265
|
+
]
|
|
266
|
+
|
|
200
267
|
[[package]]
|
|
201
268
|
name = "redox_syscall"
|
|
202
269
|
version = "0.3.5"
|
|
@@ -243,9 +310,9 @@ checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
|
|
|
243
310
|
|
|
244
311
|
[[package]]
|
|
245
312
|
name = "syn"
|
|
246
|
-
version = "
|
|
313
|
+
version = "2.0.32"
|
|
247
314
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
248
|
-
checksum = "
|
|
315
|
+
checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2"
|
|
249
316
|
dependencies = [
|
|
250
317
|
"proc-macro2",
|
|
251
318
|
"quote",
|
|
@@ -266,9 +333,9 @@ checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73"
|
|
|
266
333
|
|
|
267
334
|
[[package]]
|
|
268
335
|
name = "unindent"
|
|
269
|
-
version = "0.
|
|
336
|
+
version = "0.2.3"
|
|
270
337
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
271
|
-
checksum = "
|
|
338
|
+
checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"
|
|
272
339
|
|
|
273
340
|
[[package]]
|
|
274
341
|
name = "windows-targets"
|
|
@@ -9,11 +9,12 @@ crate-type = ["cdylib", "rlib"]
|
|
|
9
9
|
|
|
10
10
|
[dependencies]
|
|
11
11
|
log = "0.4.19"
|
|
12
|
-
pyo3-log = "0.
|
|
12
|
+
pyo3-log = "0.10.0"
|
|
13
13
|
serde_json = "1.0.103"
|
|
14
|
+
rayon = "1.10"
|
|
14
15
|
|
|
15
16
|
[dependencies.pyo3]
|
|
16
|
-
version = "0.
|
|
17
|
+
version = "0.21.2"
|
|
17
18
|
|
|
18
19
|
[features]
|
|
19
20
|
extension-module = ["pyo3/extension-module"]
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
use crate::importgraph::ImportGraph;
|
|
2
2
|
use std::collections::HashSet;
|
|
3
3
|
|
|
4
|
-
|
|
5
4
|
pub fn check_containers_exist<'a>(
|
|
6
5
|
graph: &'a ImportGraph,
|
|
7
|
-
containers: &'a HashSet
|
|
6
|
+
containers: &'a HashSet<String>,
|
|
8
7
|
) -> Result<(), String> {
|
|
9
8
|
for container in containers {
|
|
10
9
|
if !graph.contains_module(container) {
|
|
@@ -2,47 +2,45 @@ use crate::dependencies::{PackageDependency, Route};
|
|
|
2
2
|
use crate::importgraph::ImportGraph;
|
|
3
3
|
|
|
4
4
|
use log::info;
|
|
5
|
+
use rayon::prelude::*;
|
|
5
6
|
use std::collections::HashSet;
|
|
6
7
|
use std::time::Instant;
|
|
7
8
|
|
|
8
9
|
/// A group of layers at the same level in the layering.
|
|
9
10
|
#[derive(PartialEq, Eq, Hash, Debug)]
|
|
10
|
-
pub struct Level
|
|
11
|
-
pub layers: Vec
|
|
11
|
+
pub struct Level {
|
|
12
|
+
pub layers: Vec<String>,
|
|
12
13
|
pub independent: bool,
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
pub fn find_illegal_dependencies<'a>(
|
|
16
17
|
graph: &'a ImportGraph,
|
|
17
18
|
levels: &'a Vec<Level>,
|
|
18
|
-
containers: &'a HashSet
|
|
19
|
+
containers: &'a HashSet<String>,
|
|
19
20
|
) -> Vec<PackageDependency> {
|
|
20
|
-
let mut dependencies: Vec<PackageDependency> = vec![];
|
|
21
21
|
let layers = _layers_from_levels(levels);
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
dependencies
|
|
23
|
+
_generate_module_permutations(graph, levels, containers)
|
|
24
|
+
.into_par_iter()
|
|
25
|
+
.filter_map(|(higher_layer_package, lower_layer_package, container)| {
|
|
26
|
+
// TODO: it's inefficient to do this for sibling layers, as we don't need
|
|
27
|
+
// to clone and trim the graph for identical pairs.
|
|
28
|
+
info!(
|
|
29
|
+
"Searching for import chains from {} to {}...",
|
|
30
|
+
lower_layer_package, higher_layer_package
|
|
31
|
+
);
|
|
32
|
+
let now = Instant::now();
|
|
33
|
+
let dependency_or_none = _search_for_package_dependency(
|
|
34
|
+
&higher_layer_package,
|
|
35
|
+
&lower_layer_package,
|
|
36
|
+
&layers,
|
|
37
|
+
&container,
|
|
38
|
+
graph,
|
|
39
|
+
);
|
|
40
|
+
_log_illegal_route_count(&dependency_or_none, now.elapsed().as_secs());
|
|
41
|
+
dependency_or_none
|
|
42
|
+
})
|
|
43
|
+
.collect()
|
|
46
44
|
}
|
|
47
45
|
|
|
48
46
|
/// Return every permutation of modules that exist in the graph
|
|
@@ -50,7 +48,7 @@ pub fn find_illegal_dependencies<'a>(
|
|
|
50
48
|
fn _generate_module_permutations<'a>(
|
|
51
49
|
graph: &'a ImportGraph,
|
|
52
50
|
levels: &'a [Level],
|
|
53
|
-
containers: &'a HashSet
|
|
51
|
+
containers: &'a HashSet<String>,
|
|
54
52
|
) -> Vec<(String, String, Option<String>)> {
|
|
55
53
|
let mut permutations: Vec<(String, String, Option<String>)> = vec![];
|
|
56
54
|
|
|
@@ -71,7 +69,7 @@ fn _generate_module_permutations<'a>(
|
|
|
71
69
|
continue;
|
|
72
70
|
}
|
|
73
71
|
|
|
74
|
-
// Build the layers that mustn't import this higher layer.
|
|
72
|
+
// Build the layers that mustn't import this higher layer.
|
|
75
73
|
// That includes:
|
|
76
74
|
// * lower layers.
|
|
77
75
|
// * sibling layers, if the layer is independent.
|
|
@@ -164,7 +162,7 @@ fn _search_for_package_dependency<'a>(
|
|
|
164
162
|
fn _layers_from_levels<'a>(levels: &'a Vec<Level>) -> Vec<&'a str> {
|
|
165
163
|
let mut layers: Vec<&str> = vec![];
|
|
166
164
|
for level in levels {
|
|
167
|
-
layers.extend(level.layers.iter());
|
|
165
|
+
layers.extend(level.layers.iter().map(|s| s.as_str()));
|
|
168
166
|
}
|
|
169
167
|
layers
|
|
170
168
|
}
|
|
@@ -341,15 +339,19 @@ mod tests {
|
|
|
341
339
|
let levels = vec![
|
|
342
340
|
Level {
|
|
343
341
|
independent: true,
|
|
344
|
-
layers: vec!["high"],
|
|
342
|
+
layers: vec!["high".to_string()],
|
|
345
343
|
},
|
|
346
344
|
Level {
|
|
347
345
|
independent: true,
|
|
348
|
-
layers: vec![
|
|
346
|
+
layers: vec![
|
|
347
|
+
"mid_a".to_string(),
|
|
348
|
+
"mid_b".to_string(),
|
|
349
|
+
"mid_c".to_string(),
|
|
350
|
+
],
|
|
349
351
|
},
|
|
350
352
|
Level {
|
|
351
353
|
independent: true,
|
|
352
|
-
layers: vec!["low"],
|
|
354
|
+
layers: vec!["low".to_string()],
|
|
353
355
|
},
|
|
354
356
|
];
|
|
355
357
|
let containers = HashSet::new();
|
|
@@ -416,14 +418,14 @@ mod tests {
|
|
|
416
418
|
let levels = vec![
|
|
417
419
|
Level {
|
|
418
420
|
independent: true,
|
|
419
|
-
layers: vec!["high"],
|
|
421
|
+
layers: vec!["high".to_string()],
|
|
420
422
|
},
|
|
421
423
|
Level {
|
|
422
424
|
independent: true,
|
|
423
|
-
layers: vec!["low"],
|
|
425
|
+
layers: vec!["low".to_string()],
|
|
424
426
|
},
|
|
425
427
|
];
|
|
426
|
-
let containers = HashSet::from(["mypackage"]);
|
|
428
|
+
let containers = HashSet::from(["mypackage".to_string()]);
|
|
427
429
|
|
|
428
430
|
let dependencies = find_illegal_dependencies(&graph, &levels, &containers);
|
|
429
431
|
|
|
@@ -473,18 +475,22 @@ mod tests {
|
|
|
473
475
|
let levels = vec![
|
|
474
476
|
Level {
|
|
475
477
|
independent: true,
|
|
476
|
-
layers: vec!["high"],
|
|
478
|
+
layers: vec!["high".to_string()],
|
|
477
479
|
},
|
|
478
480
|
Level {
|
|
479
481
|
independent: true,
|
|
480
|
-
layers: vec![
|
|
482
|
+
layers: vec![
|
|
483
|
+
"mid_a".to_string(),
|
|
484
|
+
"mid_b".to_string(),
|
|
485
|
+
"mid_c".to_string(),
|
|
486
|
+
],
|
|
481
487
|
},
|
|
482
488
|
Level {
|
|
483
489
|
independent: true,
|
|
484
|
-
layers: vec!["low"],
|
|
490
|
+
layers: vec!["low".to_string()],
|
|
485
491
|
},
|
|
486
492
|
];
|
|
487
|
-
let containers = HashSet::from(["mypackage"]);
|
|
493
|
+
let containers = HashSet::from(["mypackage".to_string()]);
|
|
488
494
|
|
|
489
495
|
let perms = _generate_module_permutations(&graph, &levels, &containers);
|
|
490
496
|
|
|
@@ -593,18 +599,22 @@ mod tests {
|
|
|
593
599
|
let levels = vec![
|
|
594
600
|
Level {
|
|
595
601
|
independent: true,
|
|
596
|
-
layers: vec!["high"],
|
|
602
|
+
layers: vec!["high".to_string()],
|
|
597
603
|
},
|
|
598
604
|
Level {
|
|
599
605
|
independent: false,
|
|
600
|
-
layers: vec![
|
|
606
|
+
layers: vec![
|
|
607
|
+
"mid_a".to_string(),
|
|
608
|
+
"mid_b".to_string(),
|
|
609
|
+
"mid_c".to_string(),
|
|
610
|
+
],
|
|
601
611
|
},
|
|
602
612
|
Level {
|
|
603
613
|
independent: true,
|
|
604
|
-
layers: vec!["low"],
|
|
614
|
+
layers: vec!["low".to_string()],
|
|
605
615
|
},
|
|
606
616
|
];
|
|
607
|
-
let containers = HashSet::from(["mypackage"]);
|
|
617
|
+
let containers = HashSet::from(["mypackage".to_string()]);
|
|
608
618
|
|
|
609
619
|
let perms = _generate_module_permutations(&graph, &levels, &containers);
|
|
610
620
|
|
|
@@ -663,15 +673,19 @@ mod tests {
|
|
|
663
673
|
let levels = vec![
|
|
664
674
|
Level {
|
|
665
675
|
independent: true,
|
|
666
|
-
layers: vec!["high"],
|
|
676
|
+
layers: vec!["high".to_string()],
|
|
667
677
|
},
|
|
668
678
|
Level {
|
|
669
679
|
independent: true,
|
|
670
|
-
layers: vec![
|
|
680
|
+
layers: vec![
|
|
681
|
+
"medium_a".to_string(),
|
|
682
|
+
"medium_b".to_string(),
|
|
683
|
+
"medium_c".to_string(),
|
|
684
|
+
],
|
|
671
685
|
},
|
|
672
686
|
Level {
|
|
673
687
|
independent: true,
|
|
674
|
-
layers: vec!["low"],
|
|
688
|
+
layers: vec!["low".to_string()],
|
|
675
689
|
},
|
|
676
690
|
];
|
|
677
691
|
|
|
@@ -12,47 +12,79 @@ use log::info;
|
|
|
12
12
|
use pyo3::create_exception;
|
|
13
13
|
use pyo3::prelude::*;
|
|
14
14
|
use pyo3::types::{PyDict, PyFrozenSet, PySet, PyString, PyTuple};
|
|
15
|
-
use std::collections::HashSet;
|
|
15
|
+
use std::collections::{HashMap, HashSet};
|
|
16
16
|
|
|
17
17
|
#[pymodule]
|
|
18
|
-
fn _rustgrimp(
|
|
18
|
+
fn _rustgrimp(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
19
19
|
pyo3_log::init();
|
|
20
20
|
|
|
21
21
|
m.add_function(wrap_pyfunction!(find_illegal_dependencies, m)?)?;
|
|
22
|
-
m.add("NoSuchContainer",
|
|
22
|
+
m.add("NoSuchContainer", py.get_type_bound::<NoSuchContainer>())?;
|
|
23
23
|
Ok(())
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
create_exception!(_rustgrimp, NoSuchContainer, pyo3::exceptions::PyException);
|
|
27
27
|
|
|
28
28
|
#[pyfunction]
|
|
29
|
-
pub fn find_illegal_dependencies<'
|
|
30
|
-
py: Python<'
|
|
31
|
-
levels: &'
|
|
32
|
-
containers: &'
|
|
33
|
-
importeds_by_importer: &'
|
|
34
|
-
) -> PyResult
|
|
29
|
+
pub fn find_illegal_dependencies<'py>(
|
|
30
|
+
py: Python<'py>,
|
|
31
|
+
levels: &Bound<'py, PyTuple>,
|
|
32
|
+
containers: &Bound<'py, PySet>,
|
|
33
|
+
importeds_by_importer: &Bound<'py, PyDict>,
|
|
34
|
+
) -> PyResult<Bound<'py, PyTuple>> {
|
|
35
35
|
info!("Using Rust to find illegal dependencies.");
|
|
36
|
-
let graph = ImportGraph::new(importeds_by_importer.extract()?);
|
|
37
36
|
|
|
37
|
+
let importeds_by_importer_strings: HashMap<String, HashSet<String>> =
|
|
38
|
+
importeds_by_importer.extract()?;
|
|
39
|
+
let importeds_by_importer_strs = strings_to_strs_hashmap(&importeds_by_importer_strings);
|
|
40
|
+
|
|
41
|
+
let graph = ImportGraph::new(importeds_by_importer_strs);
|
|
38
42
|
let levels_rust = rustify_levels(levels);
|
|
39
|
-
let containers_rust: HashSet
|
|
43
|
+
let containers_rust: HashSet<String> = containers.extract()?;
|
|
40
44
|
|
|
41
45
|
if let Err(err) = check_containers_exist(&graph, &containers_rust) {
|
|
42
46
|
return Err(NoSuchContainer::new_err(err));
|
|
43
47
|
}
|
|
44
48
|
|
|
45
|
-
let dependencies =
|
|
49
|
+
let dependencies = py.allow_threads(|| {
|
|
50
|
+
layers::find_illegal_dependencies(&graph, &levels_rust, &containers_rust)
|
|
51
|
+
});
|
|
46
52
|
|
|
47
53
|
convert_dependencies_to_python(py, dependencies, &graph)
|
|
48
54
|
}
|
|
49
55
|
|
|
50
|
-
fn
|
|
56
|
+
fn strings_to_strs_hashmap<'a>(
|
|
57
|
+
string_map: &'a HashMap<String, HashSet<String>>,
|
|
58
|
+
) -> HashMap<&'a str, HashSet<&'a str>> {
|
|
59
|
+
let mut str_map: HashMap<&str, HashSet<&str>> = HashMap::new();
|
|
60
|
+
|
|
61
|
+
for (key, set) in string_map {
|
|
62
|
+
let mut str_set: HashSet<&str> = HashSet::new();
|
|
63
|
+
for item in set.iter() {
|
|
64
|
+
str_set.insert(item);
|
|
65
|
+
}
|
|
66
|
+
str_map.insert(key.as_str(), str_set);
|
|
67
|
+
}
|
|
68
|
+
str_map
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
fn rustify_levels<'a>(levels_python: &Bound<'a, PyTuple>) -> Vec<Level> {
|
|
51
72
|
let mut rust_levels: Vec<Level> = vec![];
|
|
52
73
|
for level_python in levels_python.into_iter() {
|
|
53
74
|
let level_dict = level_python.downcast::<PyDict>().unwrap();
|
|
54
|
-
let layers: HashSet
|
|
55
|
-
|
|
75
|
+
let layers: HashSet<String> = level_dict
|
|
76
|
+
.get_item("layers")
|
|
77
|
+
.unwrap()
|
|
78
|
+
.unwrap()
|
|
79
|
+
.extract()
|
|
80
|
+
.unwrap();
|
|
81
|
+
|
|
82
|
+
let independent: bool = level_dict
|
|
83
|
+
.get_item("independent")
|
|
84
|
+
.unwrap()
|
|
85
|
+
.unwrap()
|
|
86
|
+
.extract()
|
|
87
|
+
.unwrap();
|
|
56
88
|
rust_levels.push(Level {
|
|
57
89
|
independent,
|
|
58
90
|
layers: layers.into_iter().collect(),
|
|
@@ -61,47 +93,47 @@ fn rustify_levels(levels_python: &PyTuple) -> Vec<Level> {
|
|
|
61
93
|
rust_levels
|
|
62
94
|
}
|
|
63
95
|
|
|
64
|
-
fn convert_dependencies_to_python<'
|
|
65
|
-
py: Python<'
|
|
96
|
+
fn convert_dependencies_to_python<'py>(
|
|
97
|
+
py: Python<'py>,
|
|
66
98
|
dependencies: Vec<PackageDependency>,
|
|
67
99
|
graph: &ImportGraph,
|
|
68
|
-
) -> PyResult
|
|
69
|
-
let mut python_dependencies: Vec
|
|
100
|
+
) -> PyResult<Bound<'py, PyTuple>> {
|
|
101
|
+
let mut python_dependencies: Vec<Bound<'py, PyDict>> = vec![];
|
|
70
102
|
|
|
71
103
|
for rust_dependency in dependencies {
|
|
72
|
-
let python_dependency = PyDict::
|
|
104
|
+
let python_dependency = PyDict::new_bound(py);
|
|
73
105
|
python_dependency.set_item("imported", graph.names_by_id[&rust_dependency.imported])?;
|
|
74
106
|
python_dependency.set_item("importer", graph.names_by_id[&rust_dependency.importer])?;
|
|
75
|
-
let mut python_routes: Vec
|
|
107
|
+
let mut python_routes: Vec<Bound<'py, PyDict>> = vec![];
|
|
76
108
|
for rust_route in rust_dependency.routes {
|
|
77
|
-
let route = PyDict::
|
|
78
|
-
let heads: Vec
|
|
109
|
+
let route = PyDict::new_bound(py);
|
|
110
|
+
let heads: Vec<Bound<'py, PyString>> = rust_route
|
|
79
111
|
.heads
|
|
80
112
|
.iter()
|
|
81
|
-
.map(|i| PyString::
|
|
113
|
+
.map(|i| PyString::new_bound(py, graph.names_by_id[&i]))
|
|
82
114
|
.collect();
|
|
83
|
-
route.set_item("heads", PyFrozenSet::
|
|
84
|
-
let middle: Vec
|
|
115
|
+
route.set_item("heads", PyFrozenSet::new_bound(py, &heads)?)?;
|
|
116
|
+
let middle: Vec<Bound<'py, PyString>> = rust_route
|
|
85
117
|
.middle
|
|
86
118
|
.iter()
|
|
87
|
-
.map(|i| PyString::
|
|
119
|
+
.map(|i| PyString::new_bound(py, graph.names_by_id[&i]))
|
|
88
120
|
.collect();
|
|
89
|
-
route.set_item("middle", PyTuple::
|
|
90
|
-
let tails: Vec
|
|
121
|
+
route.set_item("middle", PyTuple::new_bound(py, &middle))?;
|
|
122
|
+
let tails: Vec<Bound<'py, PyString>> = rust_route
|
|
91
123
|
.tails
|
|
92
124
|
.iter()
|
|
93
|
-
.map(|i| PyString::
|
|
125
|
+
.map(|i| PyString::new_bound(py, graph.names_by_id[&i]))
|
|
94
126
|
.collect();
|
|
95
|
-
route.set_item("tails", PyFrozenSet::
|
|
127
|
+
route.set_item("tails", PyFrozenSet::new_bound(py, &tails)?)?;
|
|
96
128
|
|
|
97
129
|
python_routes.push(route);
|
|
98
130
|
}
|
|
99
131
|
|
|
100
|
-
python_dependency.set_item("routes", PyTuple::
|
|
132
|
+
python_dependency.set_item("routes", PyTuple::new_bound(py, python_routes))?;
|
|
101
133
|
python_dependencies.push(python_dependency)
|
|
102
134
|
}
|
|
103
135
|
|
|
104
|
-
Ok(PyTuple::
|
|
136
|
+
Ok(PyTuple::new_bound(py, python_dependencies))
|
|
105
137
|
}
|
|
106
138
|
|
|
107
139
|
#[cfg(test)]
|
|
@@ -113,7 +145,7 @@ mod tests {
|
|
|
113
145
|
macro_rules! pydict {
|
|
114
146
|
($py: ident, {$($k: expr => $v: expr),*, $(,)?}) => {
|
|
115
147
|
{
|
|
116
|
-
let dict = PyDict::
|
|
148
|
+
let dict = PyDict::new_bound($py);
|
|
117
149
|
$(
|
|
118
150
|
dict.set_item($k, $v)?;
|
|
119
151
|
)*
|
|
@@ -126,7 +158,7 @@ mod tests {
|
|
|
126
158
|
fn test_rustify_levels_no_sibling_layers() {
|
|
127
159
|
pyo3::prepare_freethreaded_python();
|
|
128
160
|
Python::with_gil(|py| -> PyResult<()> {
|
|
129
|
-
let elements
|
|
161
|
+
let elements = vec![
|
|
130
162
|
pydict! (py, {
|
|
131
163
|
"independent" => true,
|
|
132
164
|
"layers" => HashSet::from(["high"]),
|
|
@@ -138,26 +170,26 @@ mod tests {
|
|
|
138
170
|
pydict! (py, {
|
|
139
171
|
"independent" => true,
|
|
140
172
|
"layers" => HashSet::from(["low"]),
|
|
141
|
-
})
|
|
173
|
+
}),
|
|
142
174
|
];
|
|
143
|
-
let python_levels
|
|
175
|
+
let python_levels = PyTuple::new_bound(py, elements);
|
|
144
176
|
|
|
145
|
-
let result = rustify_levels(python_levels);
|
|
177
|
+
let result = rustify_levels(&python_levels);
|
|
146
178
|
|
|
147
179
|
assert_eq!(
|
|
148
180
|
result,
|
|
149
181
|
vec![
|
|
150
182
|
Level {
|
|
151
183
|
independent: true,
|
|
152
|
-
layers: vec!["high"]
|
|
184
|
+
layers: vec!["high".to_string()]
|
|
153
185
|
},
|
|
154
186
|
Level {
|
|
155
187
|
independent: true,
|
|
156
|
-
layers: vec!["medium"]
|
|
188
|
+
layers: vec!["medium".to_string()]
|
|
157
189
|
},
|
|
158
190
|
Level {
|
|
159
191
|
independent: true,
|
|
160
|
-
layers: vec!["low"]
|
|
192
|
+
layers: vec!["low".to_string()]
|
|
161
193
|
}
|
|
162
194
|
]
|
|
163
195
|
);
|
|
@@ -171,7 +203,7 @@ mod tests {
|
|
|
171
203
|
fn test_rustify_levels_sibling_layers() {
|
|
172
204
|
pyo3::prepare_freethreaded_python();
|
|
173
205
|
Python::with_gil(|py| -> PyResult<()> {
|
|
174
|
-
let elements
|
|
206
|
+
let elements = vec![
|
|
175
207
|
pydict! (py, {
|
|
176
208
|
"independent" => true,
|
|
177
209
|
"layers" => HashSet::from(["high"]),
|
|
@@ -187,11 +219,11 @@ mod tests {
|
|
|
187
219
|
pydict! (py, {
|
|
188
220
|
"independent" => true,
|
|
189
221
|
"layers" => HashSet::from(["low"]),
|
|
190
|
-
})
|
|
222
|
+
}),
|
|
191
223
|
];
|
|
192
|
-
let python_levels
|
|
224
|
+
let python_levels = PyTuple::new_bound(py, elements);
|
|
193
225
|
|
|
194
|
-
let mut result = rustify_levels(python_levels);
|
|
226
|
+
let mut result = rustify_levels(&python_levels);
|
|
195
227
|
|
|
196
228
|
for level in &mut result {
|
|
197
229
|
level.layers.sort();
|
|
@@ -201,19 +233,23 @@ mod tests {
|
|
|
201
233
|
vec![
|
|
202
234
|
Level {
|
|
203
235
|
independent: true,
|
|
204
|
-
layers: vec!["high"]
|
|
236
|
+
layers: vec!["high".to_string()]
|
|
205
237
|
},
|
|
206
238
|
Level {
|
|
207
239
|
independent: true,
|
|
208
|
-
layers: vec![
|
|
240
|
+
layers: vec![
|
|
241
|
+
"blue".to_string(),
|
|
242
|
+
"green".to_string(),
|
|
243
|
+
"orange".to_string()
|
|
244
|
+
]
|
|
209
245
|
},
|
|
210
246
|
Level {
|
|
211
247
|
independent: false,
|
|
212
|
-
layers: vec!["red", "yellow"]
|
|
248
|
+
layers: vec!["red".to_string(), "yellow".to_string()]
|
|
213
249
|
},
|
|
214
250
|
Level {
|
|
215
251
|
independent: true,
|
|
216
|
-
layers: vec!["low"]
|
|
252
|
+
layers: vec!["low".to_string()]
|
|
217
253
|
}
|
|
218
254
|
]
|
|
219
255
|
);
|
|
@@ -22,26 +22,26 @@ fn test_large_graph() {
|
|
|
22
22
|
let levels = vec![
|
|
23
23
|
Level {
|
|
24
24
|
independent: true,
|
|
25
|
-
layers: vec!["plugins"],
|
|
25
|
+
layers: vec!["plugins".to_string()],
|
|
26
26
|
},
|
|
27
27
|
Level {
|
|
28
28
|
independent: true,
|
|
29
|
-
layers: vec!["interfaces"],
|
|
29
|
+
layers: vec!["interfaces".to_string()],
|
|
30
30
|
},
|
|
31
31
|
Level {
|
|
32
32
|
independent: true,
|
|
33
|
-
layers: vec!["application"],
|
|
33
|
+
layers: vec!["application".to_string()],
|
|
34
34
|
},
|
|
35
35
|
Level {
|
|
36
36
|
independent: true,
|
|
37
|
-
layers: vec!["domain"],
|
|
37
|
+
layers: vec!["domain".to_string()],
|
|
38
38
|
},
|
|
39
39
|
Level {
|
|
40
40
|
independent: true,
|
|
41
|
-
layers: vec!["data"],
|
|
41
|
+
layers: vec!["data".to_string()],
|
|
42
42
|
},
|
|
43
43
|
];
|
|
44
|
-
let containers = HashSet::from(["mypackage"]);
|
|
44
|
+
let containers = HashSet::from(["mypackage".to_string()]);
|
|
45
45
|
|
|
46
46
|
find_illegal_dependencies(&graph, &levels, &containers);
|
|
47
47
|
}
|
|
@@ -18,7 +18,7 @@ class FileSystem(AbstractFileSystem):
|
|
|
18
18
|
return os.path.dirname(filename)
|
|
19
19
|
|
|
20
20
|
def walk(self, directory_name: str) -> Iterator[Tuple[str, List[str], List[str]]]:
|
|
21
|
-
yield from os.walk(directory_name)
|
|
21
|
+
yield from os.walk(directory_name, followlinks=True)
|
|
22
22
|
|
|
23
23
|
def join(self, *components: str) -> str:
|
|
24
24
|
return os.path.join(*components)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|