4
4
import { cloneDeep } from 'lodash' ;
5
5
import * as path from 'path' ;
6
6
import {
7
- PythonEnvInfo , PythonEnvKind , PythonExecutableInfo , PythonVersion ,
7
+ FileInfo ,
8
+ PythonDistroInfo ,
9
+ PythonEnvInfo , PythonEnvKind , PythonVersion ,
8
10
} from '.' ;
11
+ import { Architecture } from '../../../common/utils/platform' ;
9
12
import { arePathsSame } from '../../common/externalDependencies' ;
10
- import { areEqualVersions } from './versionHelpers ' ;
13
+ import { areEqualVersions , areEquivalentVersions } from './pythonVersion ' ;
11
14
12
15
export function areSameEnvironment (
13
16
left : string | PythonEnvInfo ,
@@ -25,14 +28,9 @@ export function areSameEnvironment(
25
28
const leftVersion = typeof left === 'string' ? undefined : left . version ;
26
29
const rightVersion = typeof right === 'string' ? undefined : right . version ;
27
30
if ( leftVersion && rightVersion ) {
28
- if ( areEqualVersions ( leftVersion , rightVersion ) ) {
29
- return true ;
30
- }
31
-
32
31
if (
33
- allowPartialMatch
34
- && leftVersion . major === rightVersion . major
35
- && leftVersion . minor === rightVersion . minor
32
+ areEqualVersions ( leftVersion , rightVersion )
33
+ || ( allowPartialMatch && areEquivalentVersions ( leftVersion , rightVersion ) )
36
34
) {
37
35
return true ;
38
36
}
@@ -48,7 +46,7 @@ export function areSameEnvironment(
48
46
* weighted by most important to least important fields.
49
47
* Wn > Wn-1 + Wn-2 + ... W0
50
48
*/
51
- function getVersionInfoHeuristic ( version :PythonVersion ) : number {
49
+ function getPythonVersionInfoHeuristic ( version :PythonVersion ) : number {
52
50
let infoLevel = 0 ;
53
51
if ( version . major > 0 ) {
54
52
infoLevel += 20 ; // W4
@@ -75,32 +73,56 @@ function getVersionInfoHeuristic(version:PythonVersion): number {
75
73
76
74
/**
77
75
* Returns a heuristic value on how much information is available in the given executable object.
78
- * @param {PythonExecutableInfo } executable executable object to generate heuristic from.
76
+ * @param {FileInfo } executable executable object to generate heuristic from.
79
77
* @returns A heuristic value indicating the amount of info available in the object
80
78
* weighted by most important to least important fields.
81
79
* Wn > Wn-1 + Wn-2 + ... W0
82
80
*/
83
- function getExecutableInfoHeuristic ( executable : PythonExecutableInfo ) : number {
81
+ function getFileInfoHeuristic ( file : FileInfo ) : number {
84
82
let infoLevel = 0 ;
85
- if ( executable . filename . length > 0 ) {
86
- infoLevel += 10 ; // W3
87
- }
88
-
89
- if ( executable . sysPrefix . length > 0 ) {
83
+ if ( file . filename . length > 0 ) {
90
84
infoLevel += 5 ; // W2
91
85
}
92
86
93
- if ( executable . mtime ) {
87
+ if ( file . mtime ) {
94
88
infoLevel += 2 ; // W1
95
89
}
96
90
97
- if ( executable . ctime ) {
91
+ if ( file . ctime || file . mtime ) {
98
92
infoLevel += 1 ; // W0
99
93
}
100
94
101
95
return infoLevel ;
102
96
}
103
97
98
+ /**
99
+ * Returns a heuristic value on how much information is available in the given distro object.
100
+ * @param {PythonDistroInfo } distro distro object to generate heuristic from.
101
+ * @returns A heuristic value indicating the amount of info available in the object
102
+ * weighted by most important to least important fields.
103
+ * Wn > Wn-1 + Wn-2 + ... W0
104
+ */
105
+ function getDistroInfoHeuristic ( distro :PythonDistroInfo ) :number {
106
+ let infoLevel = 0 ;
107
+ if ( distro . org . length > 0 ) {
108
+ infoLevel += 20 ; // W3
109
+ }
110
+
111
+ if ( distro . defaultDisplayName ) {
112
+ infoLevel += 10 ; // W2
113
+ }
114
+
115
+ if ( distro . binDir ) {
116
+ infoLevel += 5 ; // W1
117
+ }
118
+
119
+ if ( distro . version ) {
120
+ infoLevel += 2 ;
121
+ }
122
+
123
+ return infoLevel ;
124
+ }
125
+
104
126
/**
105
127
* Gets a prioritized list of environment types for identification.
106
128
* @returns {PythonEnvKind[] } : List of environments ordered by identification priority
@@ -144,35 +166,58 @@ export function getPrioritizedEnvironmentKind(): PythonEnvKind[] {
144
166
}
145
167
146
168
/**
147
- * Selects an environment kind based on the environment selection priority. This should
169
+ * Selects an environment based on the environment selection priority. This should
148
170
* match the priority in the environment identifier.
149
- * @param left
150
- * @param right
151
171
*/
152
- function pickEnvironmentKind ( left : PythonEnvInfo , right : PythonEnvInfo ) : PythonEnvKind {
172
+ export function sortEnvInfoByPriority ( ... envs : PythonEnvInfo [ ] ) : PythonEnvInfo [ ] {
153
173
// tslint:disable-next-line: no-suspicious-comment
154
174
// TODO: When we consolidate the PythonEnvKind and EnvironmentType we should have
155
175
// one location where we define priority and
156
176
const envKindByPriority :PythonEnvKind [ ] = getPrioritizedEnvironmentKind ( ) ;
157
-
158
- return envKindByPriority . find ( ( env ) => left . kind === env || right . kind === env ) ?? PythonEnvKind . Unknown ;
177
+ return envs . sort (
178
+ ( a :PythonEnvInfo , b :PythonEnvInfo ) => envKindByPriority . indexOf ( a . kind ) - envKindByPriority . indexOf ( b . kind ) ,
179
+ ) ;
159
180
}
160
181
161
- export function mergeEnvironments ( left : PythonEnvInfo , right : PythonEnvInfo ) : PythonEnvInfo {
162
- const kind = pickEnvironmentKind ( left , right ) ;
163
- const version = ( getVersionInfoHeuristic ( left . version ) > getVersionInfoHeuristic ( right . version )
164
- ? left . version : right . version
182
+ /**
183
+ * Merges properties of the `target` environment and `other` environment and returns the merged environment.
184
+ * if the value in the `target` environment is not defined or has less information. This does not mutate
185
+ * the `target` instead it returns a new object that contains the merged results.
186
+ * @param {PythonEnvInfo } target : Properties of this object are favored.
187
+ * @param {PythonEnvInfo } other : Properties of this object are used to fill the gaps in the merged result.
188
+ */
189
+ export function mergeEnvironments ( target : PythonEnvInfo , other : PythonEnvInfo ) : PythonEnvInfo {
190
+ const merged = cloneDeep ( target ) ;
191
+
192
+ const version = cloneDeep (
193
+ getPythonVersionInfoHeuristic ( target . version ) > getPythonVersionInfoHeuristic ( other . version )
194
+ ? target . version : other . version ,
165
195
) ;
166
- const executable = ( getExecutableInfoHeuristic ( left . executable ) > getExecutableInfoHeuristic ( right . executable )
167
- ? left . executable : right . executable
196
+
197
+ const executable = cloneDeep (
198
+ getFileInfoHeuristic ( target . executable ) > getFileInfoHeuristic ( other . executable )
199
+ ? target . executable : other . executable ,
168
200
) ;
169
- const preferredEnv :PythonEnvInfo = left . kind === kind ? left : right ;
170
- const merged = cloneDeep ( preferredEnv ) ;
171
- merged . version = cloneDeep ( version ) ;
172
- merged . executable = cloneDeep ( executable ) ;
201
+ executable . sysPrefix = target . executable . sysPrefix ?? other . executable . sysPrefix ;
202
+
203
+ const distro = cloneDeep (
204
+ getDistroInfoHeuristic ( target . distro ) > getDistroInfoHeuristic ( other . distro )
205
+ ? target . distro : other . distro ,
206
+ ) ;
207
+
208
+ merged . arch = merged . arch === Architecture . Unknown ? other . arch : target . arch ;
209
+ merged . defaultDisplayName = merged . defaultDisplayName ?? other . defaultDisplayName ;
210
+ merged . distro = distro ;
211
+ merged . executable = executable ;
212
+
213
+ // No need to check this just use preferred kind. Since the first thing we do is figure out the
214
+ // preferred env based on kind.
215
+ merged . kind = target . kind ;
216
+
217
+ merged . location = merged . location ?? other . location ;
218
+ merged . name = merged . name ?? other . name ;
219
+ merged . searchLocation = merged . searchLocation ?? other . searchLocation ;
220
+ merged . version = version ;
173
221
174
- // tslint:disable-next-line: no-suspicious-comment
175
- // TODO: compute id for the merged environment
176
- merged . id = '' ;
177
222
return merged ;
178
223
}
0 commit comments