ShellWrapperIntegrationTests.basic_posix()   F
last analyzed

Complexity

Conditions 18

Size

Total Lines 99

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 1
Metric Value
cc 18
dl 0
loc 99
rs 0.8727
c 3
b 1
f 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like ShellWrapperIntegrationTests.basic_posix() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
from __future__ import absolute_import, division, print_function, unicode_literals
3
4
from datetime import datetime
5
from logging import getLogger
6
import os
7
from os.path import dirname, isdir, join
8
import sys
9
from tempfile import gettempdir
10
from unittest import TestCase
11
from uuid import uuid4
12
13
from conda import CONDA_PACKAGE_ROOT
14
from conda._vendor.auxlib.ish import dals
15
from conda._vendor.toolz.itertoolz import concatv
16
from conda.activate import CmdExeActivator, CshActivator, FishActivator, PosixActivator, \
17
    PowershellActivator, XonshActivator, activator_map, main as activate_main, native_path_to_unix
18
from conda.base.constants import ROOT_ENV_NAME
19
from conda.base.context import context, reset_context
20
from conda.common.compat import ensure_text_type, iteritems, on_win, \
21
    string_types
22
from conda.common.io import captured, env_var, env_vars
23
from conda.exceptions import EnvironmentLocationNotFound, EnvironmentNameNotFound
24
from conda.gateways.disk.create import mkdir_p
25
from conda.gateways.disk.delete import rm_rf
26
from conda.gateways.disk.update import touch
27
import pytest
28
from tests.helpers import tempdir
29
30
try:
31
    from unittest.mock import patch
32
except ImportError:
33
    from mock import patch
34
35
log = getLogger(__name__)
36
37
38
if on_win:
39
    import ctypes
40
    PYTHONIOENCODING = ctypes.cdll.kernel32.GetACP()
41
else:
42
    PYTHONIOENCODING = None
43
44
POP_THESE = (
45
    'CONDA_SHLVL',
46
    'CONDA_DEFAULT_ENV',
47
    'CONDA_PREFIX',
48
    'CONDA_PREFIX_0',
49
    'CONDA_PREFIX_1',
50
    'CONDA_PREFIX_2',
51
    'PS1',
52
    'prompt',
53
)
54
55
56
class ActivatorUnitTests(TestCase):
57
58
    def setUp(self):
59
        self.hold_environ = os.environ.copy()
60
        for var in POP_THESE:
61
            os.environ.pop(var, None)
62
63
    def tearDown(self):
64
        os.environ.clear()
65
        os.environ.update(self.hold_environ)
66
67
    def test_activate_environment_not_found(self):
68
        activator = PosixActivator()
69
70
        with tempdir() as td:
71
            with pytest.raises(EnvironmentLocationNotFound):
72
                activator.build_activate(td)
73
74
        with pytest.raises(EnvironmentLocationNotFound):
75
            activator.build_activate('/not/an/environment')
76
77
        with pytest.raises(EnvironmentNameNotFound):
78
            activator.build_activate('wontfindmeIdontexist_abc123')
79
80
    def test_wrong_args(self):
81
        pass
82
83
    def test_activate_help(self):
84
        pass
85
86
    def test_PS1(self):
87
        with env_var("CONDA_CHANGEPS1", "yes", reset_context):
88
            activator = PosixActivator()
89
            assert activator._prompt_modifier('/dont/matter', ROOT_ENV_NAME) == '(%s) ' % ROOT_ENV_NAME
90
91
            instructions = activator.build_activate("base")
92
            assert instructions['export_vars']['CONDA_PROMPT_MODIFIER'] == '(%s) ' % ROOT_ENV_NAME
93
94
    def test_PS1_no_changeps1(self):
95
        with env_var("CONDA_CHANGEPS1", "no", reset_context):
96
            activator = PosixActivator()
97
            assert activator._prompt_modifier('/dont/matter', 'root') == ''
98
99
            instructions = activator.build_activate("base")
100
            assert instructions['export_vars']['CONDA_PROMPT_MODIFIER'] == ''
101
102
    def test_add_prefix_to_path(self):
103
        activator = PosixActivator()
104
105
        path_dirs = activator.path_conversion(['/path1/bin', '/path2/bin', '/usr/local/bin', '/usr/bin', '/bin'])
106
        assert len(path_dirs) == 5
107
        test_prefix = '/usr/mytest/prefix'
108
        added_paths = activator.path_conversion(activator._get_path_dirs(test_prefix))
109
        if isinstance(added_paths, string_types):
110
            added_paths = added_paths,
111
112
        new_path = activator._add_prefix_to_path(test_prefix, path_dirs)
113
        assert new_path == added_paths + path_dirs
114
115
    def test_remove_prefix_from_path_1(self):
116
        activator = PosixActivator()
117
        original_path = tuple(activator._get_starting_path_list())
118
        keep_path = activator.path_conversion('/keep/this/path')
119
        final_path = (keep_path,) + original_path
120
        final_path = activator.path_conversion(final_path)
121
122
        test_prefix = join(os.getcwd(), 'mytestpath')
123
        new_paths = tuple(activator._get_path_dirs(test_prefix))
124
        prefix_added_path = (keep_path,) + new_paths + original_path
125
        new_path = activator._remove_prefix_from_path(test_prefix, prefix_added_path)
126
        assert final_path == new_path
127
128
    def test_remove_prefix_from_path_2(self):
129
        # this time prefix doesn't actually exist in path
130
        activator = PosixActivator()
131
        original_path = tuple(activator._get_starting_path_list())
132
        keep_path = activator.path_conversion('/keep/this/path')
133
        final_path = (keep_path,) + original_path
134
        final_path = activator.path_conversion(final_path)
135
136
        test_prefix = join(os.getcwd(), 'mytestpath')
137
        prefix_added_path = (keep_path,) + original_path
138
        new_path = activator._remove_prefix_from_path(test_prefix, prefix_added_path)
139
140
        assert final_path == new_path
141
142
    def test_replace_prefix_in_path_1(self):
143
        activator = PosixActivator()
144
        original_path = tuple(activator._get_starting_path_list())
145
        new_prefix = join(os.getcwd(), 'mytestpath-new')
146
        new_paths = activator.path_conversion(activator._get_path_dirs(new_prefix))
147
        if isinstance(new_paths, string_types):
148
            new_paths = new_paths,
149
        keep_path = activator.path_conversion('/keep/this/path')
150
        final_path = (keep_path,) + new_paths + original_path
151
        final_path = activator.path_conversion(final_path)
152
153
        replace_prefix = join(os.getcwd(), 'mytestpath')
154
        replace_paths = tuple(activator._get_path_dirs(replace_prefix))
155
        prefix_added_path = (keep_path,) + replace_paths + original_path
156
        new_path = activator._replace_prefix_in_path(replace_prefix, new_prefix, prefix_added_path)
157
158
        assert final_path == new_path
159
160
    @pytest.mark.skipif(not on_win, reason="windows-specific test")
161
    def test_replace_prefix_in_path_2(self):
162
        path1 = join("c:\\", "temp", "6663 31e0")
163
        path2 = join("c:\\", "temp", "6663 31e0", "envs", "charizard")
164
        one_more = join("d:\\", "one", "more")
165
        #   old_prefix: c:\users\builder\appdata\local\temp\6663 31e0
166
        #   new_prefix: c:\users\builder\appdata\local\temp\6663 31e0\envs\charizard
167
        activator = CmdExeActivator()
168
        old_path = activator.pathsep_join(activator._add_prefix_to_path(path1))
169
        old_path = one_more + ";" + old_path
170
        with env_var('PATH', old_path):
171
            activator = PosixActivator()
172
            path_elements = activator._replace_prefix_in_path(path1, path2)
173
        old_path = native_path_to_unix(old_path.split(";"))
174
175
        assert path_elements[0] == native_path_to_unix(one_more)
176
        assert path_elements[1] == native_path_to_unix(next(activator._get_path_dirs(path2)))
177
        assert len(path_elements) == len(old_path)
178
179
    def test_default_env(self):
180
        activator = PosixActivator()
181
        assert ROOT_ENV_NAME == activator._default_env(context.root_prefix)
182
183
        with tempdir() as td:
184
            assert td == activator._default_env(td)
185
186
            p = mkdir_p(join(td, 'envs', 'named-env'))
187
            assert 'named-env' == activator._default_env(p)
188
189
    def test_build_activate_shlvl_0(self):
190
        with tempdir() as td:
191
            mkdir_p(join(td, 'conda-meta'))
192
            activate_d_dir = mkdir_p(join(td, 'etc', 'conda', 'activate.d'))
193
            activate_d_1 = join(activate_d_dir, 'see-me.sh')
194
            activate_d_2 = join(activate_d_dir, 'dont-see-me.bat')
195
            touch(join(activate_d_1))
196
            touch(join(activate_d_2))
197
198
            with env_var('CONDA_SHLVL', '0'):
199
                with env_var('CONDA_PREFIX', ''):
200
                    activator = PosixActivator()
201
                    builder = activator.build_activate(td)
202
                    new_path = activator.pathsep_join(activator._add_prefix_to_path(td))
203
                    conda_prompt_modifier = "(%s) " % td
204
                    ps1 = conda_prompt_modifier + os.environ.get('PS1', '')
205
206
                    assert builder['unset_vars'] == ()
207
208
                    set_vars = {
209
                        'PS1': ps1,
210
                    }
211
                    export_vars = {
212
                        'CONDA_PYTHON_EXE': activator.path_conversion(sys.executable),
213
                        'CONDA_EXE': activator.path_conversion(context.conda_exe),
214
                        'PATH': new_path,
215
                        'CONDA_PREFIX': td,
216
                        'CONDA_SHLVL': 1,
217
                        'CONDA_DEFAULT_ENV': td,
218
                        'CONDA_PROMPT_MODIFIER': conda_prompt_modifier,
219
                    }
220
                    assert builder['set_vars'] == set_vars
221
                    assert builder['export_vars'] == export_vars
222
                    assert builder['activate_scripts'] == (activator.path_conversion(activate_d_1),)
223
                    assert builder['deactivate_scripts'] == ()
224
225 View Code Duplication
    @pytest.mark.skipif(on_win, reason="cygpath isn't always on PATH")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
226
    def test_build_activate_shlvl_1(self):
227
        with tempdir() as td:
228
            mkdir_p(join(td, 'conda-meta'))
229
            activate_d_dir = mkdir_p(join(td, 'etc', 'conda', 'activate.d'))
230
            activate_d_1 = join(activate_d_dir, 'see-me.sh')
231
            activate_d_2 = join(activate_d_dir, 'dont-see-me.bat')
232
            touch(join(activate_d_1))
233
            touch(join(activate_d_2))
234
235
            old_prefix = '/old/prefix'
236
            activator = PosixActivator()
237
            old_path = activator.pathsep_join(activator._add_prefix_to_path(old_prefix))
238
239
            with env_vars({
240
                'CONDA_SHLVL': '1',
241
                'CONDA_PREFIX': old_prefix,
242
                'PATH': old_path,
243
                'CONDA_ENV_PROMPT': '({default_env})',
244
            }, reset_context):
245
                activator = PosixActivator()
246
                builder = activator.build_activate(td)
247
                new_path = activator.pathsep_join(activator._replace_prefix_in_path(old_prefix, td))
248
                conda_prompt_modifier = "(%s)" % td
249
                ps1 = conda_prompt_modifier + os.environ.get('PS1', '')
250
251
                assert td in new_path
252
                assert old_prefix not in new_path
253
254
                assert builder['unset_vars'] == ()
255
256
                set_vars = {
257
                    'PS1': ps1,
258
                }
259
                export_vars = {
260
                    'PATH': new_path,
261
                    'CONDA_PREFIX': td,
262
                    'CONDA_PREFIX_1': old_prefix,
263
                    'CONDA_SHLVL': 2,
264
                    'CONDA_DEFAULT_ENV': td,
265
                    'CONDA_PROMPT_MODIFIER': conda_prompt_modifier,
266
                }
267
                assert builder['set_vars'] == set_vars
268
                assert builder['export_vars'] == export_vars
269
                assert builder['activate_scripts'] == (activator.path_conversion(activate_d_1),)
270
                assert builder['deactivate_scripts'] == ()
271
272
                with env_vars({
273
                    'PATH': new_path,
274
                    'CONDA_PREFIX': td,
275
                    'CONDA_PREFIX_1': old_prefix,
276
                    'CONDA_SHLVL': 2,
277
                    'CONDA_DEFAULT_ENV': td,
278
                    'CONDA_PROMPT_MODIFIER': conda_prompt_modifier,
279
                }):
280
                    activator = PosixActivator()
281
                    builder = activator.build_deactivate()
282
283
                    assert builder['unset_vars'] == (
284
                        'CONDA_PREFIX_1',
285
                    )
286
                    assert builder['set_vars'] == {
287
                        'PS1': '(/old/prefix)',
288
                    }
289
                    assert builder['export_vars'] == {
290
                        'CONDA_DEFAULT_ENV': old_prefix,
291
                        'CONDA_PREFIX': old_prefix,
292
                        'CONDA_PROMPT_MODIFIER': '(%s)' % old_prefix,
293
                        'CONDA_SHLVL': 1,
294
                        'PATH': old_path,
295
                    }
296
                    assert builder['activate_scripts'] == ()
297
                    assert builder['deactivate_scripts'] == ()
298
299 View Code Duplication
    @pytest.mark.skipif(on_win, reason="cygpath isn't always on PATH")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
300
    def test_build_stack_shlvl_1(self):
301
        with tempdir() as td:
302
            mkdir_p(join(td, 'conda-meta'))
303
            activate_d_dir = mkdir_p(join(td, 'etc', 'conda', 'activate.d'))
304
            activate_d_1 = join(activate_d_dir, 'see-me.sh')
305
            activate_d_2 = join(activate_d_dir, 'dont-see-me.bat')
306
            touch(join(activate_d_1))
307
            touch(join(activate_d_2))
308
309
            old_prefix = '/old/prefix'
310
            activator = PosixActivator()
311
            old_path = activator.pathsep_join(activator._add_prefix_to_path(old_prefix))
312
313
            with env_vars({
314
                'CONDA_SHLVL': '1',
315
                'CONDA_PREFIX': old_prefix,
316
                'PATH': old_path,
317
                'CONDA_ENV_PROMPT': '({default_env})',
318
            }, reset_context):
319
                activator = PosixActivator()
320
                builder = activator.build_stack(td)
321
                new_path = activator.pathsep_join(activator._add_prefix_to_path(td))
322
                conda_prompt_modifier = "(%s)" % td
323
                ps1 = conda_prompt_modifier + os.environ.get('PS1', '')
324
325
                assert builder['unset_vars'] == ()
326
327
                assert td in new_path
328
                assert old_prefix in new_path
329
330
                set_vars = {
331
                    'PS1': ps1,
332
                }
333
                export_vars = {
334
                    'PATH': new_path,
335
                    'CONDA_PREFIX': td,
336
                    'CONDA_PREFIX_1': old_prefix,
337
                    'CONDA_SHLVL': 2,
338
                    'CONDA_DEFAULT_ENV': td,
339
                    'CONDA_PROMPT_MODIFIER': conda_prompt_modifier,
340
                    'CONDA_STACKED_2': 'true',
341
                }
342
                assert builder['set_vars'] == set_vars
343
                assert builder['export_vars'] == export_vars
344
                assert builder['activate_scripts'] == (activator.path_conversion(activate_d_1),)
345
                assert builder['deactivate_scripts'] == ()
346
347
                with env_vars({
348
                    'PATH': new_path,
349
                    'CONDA_PREFIX': td,
350
                    'CONDA_PREFIX_1': old_prefix,
351
                    'CONDA_SHLVL': 2,
352
                    'CONDA_DEFAULT_ENV': td,
353
                    'CONDA_PROMPT_MODIFIER': conda_prompt_modifier,
354
                    'CONDA_STACKED_2': 'true',
355
                }):
356
                    activator = PosixActivator()
357
                    builder = activator.build_deactivate()
358
359
                    assert builder['unset_vars'] == (
360
                        'CONDA_PREFIX_1',
361
                        'CONDA_STACKED_2',
362
                    )
363
                    assert builder['set_vars'] == {
364
                        'PS1': '(/old/prefix)',
365
                    }
366
                    assert builder['export_vars'] == {
367
                        'CONDA_DEFAULT_ENV': old_prefix,
368
                        'CONDA_PREFIX': old_prefix,
369
                        'CONDA_PROMPT_MODIFIER': '(%s)' % old_prefix,
370
                        'CONDA_SHLVL': 1,
371
                        'PATH': old_path,
372
                    }
373
                    assert builder['activate_scripts'] == ()
374
                    assert builder['deactivate_scripts'] == ()
375
376
    def test_activate_same_environment(self):
377
        with tempdir() as td:
378
            mkdir_p(join(td, 'conda-meta'))
379
            activate_d_dir = mkdir_p(join(td, 'etc', 'conda', 'activate.d'))
380
            activate_d_1 = join(activate_d_dir, 'see-me.sh')
381
            activate_d_2 = join(activate_d_dir, 'dont-see-me.bat')
382
            touch(join(activate_d_1))
383
            touch(join(activate_d_2))
384
385
            old_prefix = td
386
            deactivate_d_dir = mkdir_p(join(old_prefix, 'etc', 'conda', 'deactivate.d'))
387
            deactivate_d_1 = join(deactivate_d_dir, 'see-me.sh')
388
            deactivate_d_2 = join(deactivate_d_dir, 'dont-see-me.bat')
389
            touch(join(deactivate_d_1))
390
            touch(join(deactivate_d_2))
391
392
            with env_var('CONDA_SHLVL', '1'):
393
                with env_var('CONDA_PREFIX', old_prefix):
394
                    activator = PosixActivator()
395
396
                    builder = activator.build_activate(td)
397
398
                    new_path_parts = activator._replace_prefix_in_path(old_prefix, old_prefix)
399
                    conda_prompt_modifier = "(%s) " % old_prefix
400
                    ps1 = conda_prompt_modifier + os.environ.get('PS1', '')
401
402
                    set_vars = {
403
                        'PS1': ps1,
404
                    }
405
                    export_vars = {
406
                        'PATH': activator.pathsep_join(new_path_parts),
407
                        'CONDA_PROMPT_MODIFIER': "(%s) " % td,
408
                        'CONDA_SHLVL': 1,
409
                    }
410
                    assert builder['unset_vars'] == ()
411
                    assert builder['set_vars'] == set_vars
412
                    assert builder['export_vars'] == export_vars
413
                    assert builder['activate_scripts'] == (activator.path_conversion(activate_d_1),)
414
                    assert builder['deactivate_scripts'] == (activator.path_conversion(deactivate_d_1),)
415
416 View Code Duplication
    @pytest.mark.skipif(on_win, reason="cygpath isn't always on PATH")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
417
    def test_build_deactivate_shlvl_2_from_stack(self):
418
        with tempdir() as td:
419
            mkdir_p(join(td, 'conda-meta'))
420
            deactivate_d_dir = mkdir_p(join(td, 'etc', 'conda', 'deactivate.d'))
421
            deactivate_d_1 = join(deactivate_d_dir, 'see-me-deactivate.sh')
422
            deactivate_d_2 = join(deactivate_d_dir, 'dont-see-me.bat')
423
            touch(join(deactivate_d_1))
424
            touch(join(deactivate_d_2))
425
426
            old_prefix = join(td, 'old')
427
            activate_d_dir = mkdir_p(join(old_prefix, 'etc', 'conda', 'activate.d'))
428
            activate_d_1 = join(activate_d_dir, 'see-me-activate.sh')
429
            activate_d_2 = join(activate_d_dir, 'dont-see-me.bat')
430
            touch(join(activate_d_1))
431
            touch(join(activate_d_2))
432
433
            activator = PosixActivator()
434
            original_path = activator.pathsep_join(activator._add_prefix_to_path(old_prefix))
435
            with env_var('PATH', original_path):
436
                activator = PosixActivator()
437
                starting_path = activator.pathsep_join(activator._add_prefix_to_path(td))
438
439
                with env_vars({
440
                    'CONDA_SHLVL': '2',
441
                    'CONDA_PREFIX_1': old_prefix,
442
                    'CONDA_PREFIX': td,
443
                    'CONDA_STACKED_2': 'true',
444
                    'PATH': starting_path,
445
                }, reset_context):
446
                    activator = PosixActivator()
447
                    builder = activator.build_deactivate()
448
449
                    assert builder['unset_vars'] == (
450
                        'CONDA_PREFIX_1',
451
                        'CONDA_STACKED_2',
452
                    )
453
454
                    conda_prompt_modifier = "(%s) " % old_prefix
455
                    ps1 = conda_prompt_modifier + os.environ.get('PS1', '')
456
457
                    set_vars = {
458
                        'PS1': ps1,
459
                    }
460
                    export_vars = {
461
                        'PATH': original_path,
462
                        'CONDA_SHLVL': 1,
463
                        'CONDA_PREFIX': old_prefix,
464
                        'CONDA_DEFAULT_ENV': old_prefix,
465
                        'CONDA_PROMPT_MODIFIER': conda_prompt_modifier,
466
                    }
467
                    assert builder['set_vars'] == set_vars
468
                    assert builder['export_vars'] == export_vars
469
                    assert builder['activate_scripts'] == (activator.path_conversion(activate_d_1),)
470
                    assert builder['deactivate_scripts'] == (activator.path_conversion(deactivate_d_1),)
471
472 View Code Duplication
    @pytest.mark.skipif(on_win, reason="cygpath isn't always on PATH")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
473
    def test_build_deactivate_shlvl_2_from_activate(self):
474
        with tempdir() as td:
475
            mkdir_p(join(td, 'conda-meta'))
476
            deactivate_d_dir = mkdir_p(join(td, 'etc', 'conda', 'deactivate.d'))
477
            deactivate_d_1 = join(deactivate_d_dir, 'see-me-deactivate.sh')
478
            deactivate_d_2 = join(deactivate_d_dir, 'dont-see-me.bat')
479
            touch(join(deactivate_d_1))
480
            touch(join(deactivate_d_2))
481
482
            old_prefix = join(td, 'old')
483
            activate_d_dir = mkdir_p(join(old_prefix, 'etc', 'conda', 'activate.d'))
484
            activate_d_1 = join(activate_d_dir, 'see-me-activate.sh')
485
            activate_d_2 = join(activate_d_dir, 'dont-see-me.bat')
486
            touch(join(activate_d_1))
487
            touch(join(activate_d_2))
488
489
            activator = PosixActivator()
490
            original_path = activator.pathsep_join(activator._add_prefix_to_path(old_prefix))
491
            new_path = activator.pathsep_join(activator._add_prefix_to_path(td))
492
            with env_vars({
493
                'CONDA_SHLVL': '2',
494
                'CONDA_PREFIX_1': old_prefix,
495
                'CONDA_PREFIX': td,
496
                'PATH': new_path,
497
            }, reset_context):
498
                activator = PosixActivator()
499
                builder = activator.build_deactivate()
500
501
                assert builder['unset_vars'] == ('CONDA_PREFIX_1',)
502
503
                conda_prompt_modifier = "(%s) " % old_prefix
504
                ps1 = conda_prompt_modifier + os.environ.get('PS1', '')
505
506
                set_vars = {
507
                    'PS1': ps1,
508
                }
509
                export_vars = {
510
                    'PATH': original_path,
511
                    'CONDA_SHLVL': 1,
512
                    'CONDA_PREFIX': old_prefix,
513
                    'CONDA_DEFAULT_ENV': old_prefix,
514
                    'CONDA_PROMPT_MODIFIER': conda_prompt_modifier,
515
                }
516
                assert builder['set_vars'] == set_vars
517
                assert builder['export_vars'] == export_vars
518
                assert builder['activate_scripts'] == (activator.path_conversion(activate_d_1),)
519
                assert builder['deactivate_scripts'] == (activator.path_conversion(deactivate_d_1),)
520
521
    def test_build_deactivate_shlvl_1(self):
522
        with tempdir() as td:
523
            mkdir_p(join(td, 'conda-meta'))
524
            deactivate_d_dir = mkdir_p(join(td, 'etc', 'conda', 'deactivate.d'))
525
            deactivate_d_1 = join(deactivate_d_dir, 'see-me-deactivate.sh')
526
            deactivate_d_2 = join(deactivate_d_dir, 'dont-see-me.bat')
527
            touch(join(deactivate_d_1))
528
            touch(join(deactivate_d_2))
529
530
            with env_var('CONDA_SHLVL', '1'):
531
                with env_var('CONDA_PREFIX', td):
532
                    activator = PosixActivator()
533
                    original_path = tuple(activator._get_starting_path_list())
534
                    builder = activator.build_deactivate()
535
536
                    assert builder['unset_vars'] == (
537
                        'CONDA_PREFIX',
538
                        'CONDA_DEFAULT_ENV',
539
                        'CONDA_PYTHON_EXE',
540
                        'CONDA_PROMPT_MODIFIER',
541
                    )
542
543
                    new_path = activator.pathsep_join(activator.path_conversion(original_path))
544
                    assert builder['set_vars'] == {
545
                        'PS1': os.environ.get('PS1', ''),
546
                    }
547
                    assert builder['export_vars'] == {
548
                        'PATH': new_path,
549
                        'CONDA_SHLVL': 0,
550
                    }
551
                    assert builder['activate_scripts'] == ()
552
                    assert builder['deactivate_scripts'] == (activator.path_conversion(deactivate_d_1),)
553
554
555
class ShellWrapperUnitTests(TestCase):
556
557
    def setUp(self):
558
        tempdirdir = gettempdir()
559
560
        prefix_dirname = str(uuid4())[:4] + ' ' + str(uuid4())[:4]
561
        self.prefix = join(tempdirdir, prefix_dirname)
562
        mkdir_p(join(self.prefix, 'conda-meta'))
563
        assert isdir(self.prefix)
564
        touch(join(self.prefix, 'conda-meta', 'history'))
565
566
        self.hold_environ = os.environ.copy()
567
        for var in POP_THESE:
568
            os.environ.pop(var, None)
569
570
    def tearDown(self):
571
        rm_rf(self.prefix)
572
        os.environ.clear()
573
        os.environ.update(self.hold_environ)
574
575
    def make_dot_d_files(self, extension):
576
        mkdir_p(join(self.prefix, 'etc', 'conda', 'activate.d'))
577
        mkdir_p(join(self.prefix, 'etc', 'conda', 'deactivate.d'))
578
579
        touch(join(self.prefix, 'etc', 'conda', 'activate.d', 'ignore.txt'))
580
        touch(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'ignore.txt'))
581
582
        touch(join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1' + extension))
583
        touch(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1' + extension))
584
585
    def test_native_path_to_unix(self):
586
        def assert_unix_path(path):
587
            assert '\\' not in path, path
588
            assert ':' not in path, path
589
            return True
590
591
        path1 = join(self.prefix, 'path', 'number', 'one')
592
        path2 = join(self.prefix, 'path', 'two')
593
        path3 = join(self.prefix, 'three')
594
        paths = (path1, path2, path3)
595
596
        if on_win:
597
            assert_unix_path(native_path_to_unix(path1))
598
        else:
599
            assert native_path_to_unix(path1) == path1
600
601
        if on_win:
602
            assert all(assert_unix_path(p) for p in native_path_to_unix(paths))
603
        else:
604
            assert native_path_to_unix(paths) == paths
605
606 View Code Duplication
    def test_posix_basic(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
607
        activator = PosixActivator()
608
        self.make_dot_d_files(activator.script_extension)
609
610
        with captured() as c:
611
            rc = activate_main(('', 'shell.posix', 'activate', self.prefix))
612
        assert not c.stderr
613
        assert rc == 0
614
        activate_data = c.stdout
615
616
        new_path_parts = activator._add_prefix_to_path(self.prefix)
617
        assert activate_data == dals("""
618
        PS1='%(ps1)s'
619
        \\export CONDA_DEFAULT_ENV='%(native_prefix)s'
620
        \\export CONDA_EXE='%(conda_exe)s'
621
        \\export CONDA_PREFIX='%(native_prefix)s'
622
        \\export CONDA_PROMPT_MODIFIER='(%(native_prefix)s) '
623
        \\export CONDA_PYTHON_EXE='%(sys_executable)s'
624
        \\export CONDA_SHLVL='1'
625
        \\export PATH='%(new_path)s'
626
        \\. "%(activate1)s"
627
        """) % {
628
            'converted_prefix': activator.path_conversion(self.prefix),
629
            'native_prefix': self.prefix,
630
            'new_path': activator.pathsep_join(new_path_parts),
631
            'sys_executable': activator.path_conversion(sys.executable),
632
            'activate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.sh')),
633
            'ps1': '(%s) ' % self.prefix + os.environ.get('PS1', ''),
634
            'conda_exe': activator.path_conversion(context.conda_exe),
635
        }
636
637
        with env_vars({
638
            'CONDA_PREFIX': self.prefix,
639
            'CONDA_SHLVL': '1',
640
            'PATH': os.pathsep.join(concatv(new_path_parts, (os.environ['PATH'],))),
641
        }):
642
            activator = PosixActivator()
643
            with captured() as c:
644
                rc = activate_main(('', 'shell.posix', 'reactivate'))
645
            assert not c.stderr
646
            assert rc == 0
647
            reactivate_data = c.stdout
648
649
            new_path_parts = activator._replace_prefix_in_path(self.prefix, self.prefix)
650
            assert reactivate_data == dals("""
651
            \\. "%(deactivate1)s"
652
            PS1='%(ps1)s'
653
            \\export CONDA_PROMPT_MODIFIER='(%(native_prefix)s) '
654
            \\export CONDA_SHLVL='1'
655
            \\export PATH='%(new_path)s'
656
            \\. "%(activate1)s"
657
            """) % {
658
                'activate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.sh')),
659
                'deactivate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.sh')),
660
                'native_prefix': self.prefix,
661
                'new_path': activator.pathsep_join(new_path_parts),
662
                'ps1': '(%s) ' % self.prefix + os.environ.get('PS1', ''),
663
            }
664
665
            with captured() as c:
666
                rc = activate_main(('', 'shell.posix', 'deactivate'))
667
            assert not c.stderr
668
            assert rc == 0
669
            deactivate_data = c.stdout
670
671
            new_path = activator.pathsep_join(activator._remove_prefix_from_path(self.prefix))
672
            assert deactivate_data == dals("""
673
            \\. "%(deactivate1)s"
674
            \\unset CONDA_DEFAULT_ENV
675
            \\unset CONDA_PREFIX
676
            \\unset CONDA_PROMPT_MODIFIER
677
            \\unset CONDA_PYTHON_EXE
678
            PS1='%(ps1)s'
679
            \\export CONDA_SHLVL='0'
680
            \\export PATH='%(new_path)s'
681
            """) % {
682
                'new_path': new_path,
683
                'deactivate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.sh')),
684
                'ps1': os.environ.get('PS1', ''),
685
            }
686
687 View Code Duplication
    @pytest.mark.skipif(not on_win, reason="cmd.exe only on Windows")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
688
    def test_cmd_exe_basic(self):
689
        activator = CmdExeActivator()
690
        self.make_dot_d_files(activator.script_extension)
691
692
        with captured() as c:
693
            rc = activate_main(('', 'shell.cmd.exe', 'activate', '', self.prefix))
694
        assert not c.stderr
695
        assert rc == 0
696
        activate_result = c.stdout
697
698
        with open(activate_result) as fh:
699
            activate_data = fh.read()
700
        rm_rf(activate_result)
701
702
        new_path_parts = activator._add_prefix_to_path(self.prefix)
703
        assert activate_data == dals("""
704
        @SET "CONDA_DEFAULT_ENV=%(native_prefix)s"
705
        @SET "CONDA_EXE=%(conda_exe)s"
706
        @SET "CONDA_PREFIX=%(converted_prefix)s"
707
        @SET "CONDA_PROMPT_MODIFIER=(%(native_prefix)s) "
708
        @SET "CONDA_PYTHON_EXE=%(sys_executable)s"
709
        @SET "CONDA_SHLVL=1"
710
        @SET "PATH=%(new_path)s"
711
        @SET "PYTHONIOENCODING=%(PYTHONIOENCODING)s"
712
        @CALL "%(activate1)s"
713
        """) % {
714
            'converted_prefix': activator.path_conversion(self.prefix),
715
            'native_prefix': self.prefix,
716
            'new_path': activator.pathsep_join(new_path_parts),
717
            'sys_executable': activator.path_conversion(sys.executable),
718
            'activate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.bat')),
719
            'PYTHONIOENCODING': PYTHONIOENCODING,
720
            'conda_exe': activator.path_conversion(context.conda_exe),
721
        }
722
723
        with env_vars({
724
            'CONDA_PREFIX': self.prefix,
725
            'CONDA_SHLVL': '1',
726
            'PATH': os.pathsep.join(concatv(new_path_parts, (os.environ['PATH'],))),
727
        }):
728
            activator = CmdExeActivator()
729
            with captured() as c:
730
                assert activate_main(('', 'shell.cmd.exe', 'reactivate')) == 0
731
            assert not c.stderr
732
            reactivate_result = c.stdout
733
734
            with open(reactivate_result) as fh:
735
                reactivate_data = fh.read()
736
            rm_rf(reactivate_result)
737
738
            new_path_parts = activator._replace_prefix_in_path(self.prefix, self.prefix)
739
            assert reactivate_data == dals("""
740
            @CALL "%(deactivate1)s"
741
            @SET "CONDA_PROMPT_MODIFIER=(%(native_prefix)s) "
742
            @SET "CONDA_SHLVL=1"
743
            @SET "PATH=%(new_path)s"
744
            @CALL "%(activate1)s"
745
            """) % {
746
                'activate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.bat')),
747
                'deactivate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.bat')),
748
                'native_prefix': self.prefix,
749
                'new_path': activator.pathsep_join(new_path_parts),
750
            }
751
752
            with captured() as c:
753
                assert activate_main(('', 'shell.cmd.exe', 'deactivate')) == 0
754
            assert not c.stderr
755
            deactivate_result = c.stdout
756
757
            with open(deactivate_result) as fh:
758
                deactivate_data = fh.read()
759
            rm_rf(deactivate_result)
760
761
            new_path = activator.pathsep_join(activator._remove_prefix_from_path(self.prefix))
762
            assert deactivate_data == dals("""
763
            @CALL "%(deactivate1)s"
764
            @SET CONDA_DEFAULT_ENV=
765
            @SET CONDA_PREFIX=
766
            @SET CONDA_PROMPT_MODIFIER=
767
            @SET CONDA_PYTHON_EXE=
768
            @SET "CONDA_SHLVL=0"
769
            @SET "PATH=%(new_path)s"
770
            """) % {
771
                'new_path': new_path,
772
                'deactivate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.bat')),
773
            }
774
775 View Code Duplication
    def test_csh_basic(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
776
        activator = CshActivator()
777
        self.make_dot_d_files(activator.script_extension)
778
779
        with captured() as c:
780
            rc = activate_main(('', 'shell.csh', 'activate', self.prefix))
781
        assert not c.stderr
782
        assert rc == 0
783
        activate_data = c.stdout
784
785
        new_path_parts = activator._add_prefix_to_path(self.prefix)
786
        assert activate_data == dals("""
787
        set prompt='%(prompt)s';
788
        setenv CONDA_DEFAULT_ENV "%(native_prefix)s";
789
        setenv CONDA_EXE "%(conda_exe)s";
790
        setenv CONDA_PREFIX "%(native_prefix)s";
791
        setenv CONDA_PROMPT_MODIFIER "(%(native_prefix)s) ";
792
        setenv CONDA_PYTHON_EXE "%(sys_executable)s";
793
        setenv CONDA_SHLVL "1";
794
        setenv PATH "%(new_path)s";
795
        source "%(activate1)s";
796
        """) % {
797
            'converted_prefix': activator.path_conversion(self.prefix),
798
            'native_prefix': self.prefix,
799
            'new_path': activator.pathsep_join(new_path_parts),
800
            'sys_executable': activator.path_conversion(sys.executable),
801
            'activate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.csh')),
802
            'prompt': '(%s) ' % self.prefix + os.environ.get('prompt', ''),
803
            'conda_exe': activator.path_conversion(context.conda_exe),
804
        }
805
806
        with env_vars({
807
            'CONDA_PREFIX': self.prefix,
808
            'CONDA_SHLVL': '1',
809
            'PATH': os.pathsep.join(concatv(new_path_parts, (os.environ['PATH'],))),
810
        }):
811
            activator = CshActivator()
812
            with captured() as c:
813
                rc = activate_main(('', 'shell.csh', 'reactivate'))
814
            assert not c.stderr
815
            assert rc == 0
816
            reactivate_data = c.stdout
817
818
            new_path_parts = activator._replace_prefix_in_path(self.prefix, self.prefix)
819
            assert reactivate_data == dals("""
820
            source "%(deactivate1)s";
821
            set prompt='%(prompt)s';
822
            setenv CONDA_PROMPT_MODIFIER "(%(native_prefix)s) ";
823
            setenv CONDA_SHLVL "1";
824
            setenv PATH "%(new_path)s";
825
            source "%(activate1)s";
826
            """) % {
827
                'prompt': '(%s) ' % self.prefix + os.environ.get('prompt', ''),
828
                'new_path': activator.pathsep_join(new_path_parts),
829
                'activate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.csh')),
830
                'deactivate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.csh')),
831
                'native_prefix': self.prefix,
832
            }
833
834
            with captured() as c:
835
                rc = activate_main(('', 'shell.csh', 'deactivate'))
836
            assert not c.stderr
837
            assert rc == 0
838
            deactivate_data = c.stdout
839
840
            new_path = activator.pathsep_join(activator._remove_prefix_from_path(self.prefix))
841
            assert deactivate_data == dals("""
842
            source "%(deactivate1)s";
843
            unsetenv CONDA_DEFAULT_ENV;
844
            unsetenv CONDA_PREFIX;
845
            unsetenv CONDA_PROMPT_MODIFIER;
846
            unsetenv CONDA_PYTHON_EXE;
847
            set prompt='%(prompt)s';
848
            setenv CONDA_SHLVL "0";
849
            setenv PATH "%(new_path)s";
850
            """) % {
851
                'new_path': new_path,
852
                'deactivate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.csh')),
853
                'prompt': os.environ.get('prompt', ''),
854
            }
855
856 View Code Duplication
    def test_xonsh_basic(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
857
        activator = XonshActivator()
858
        self.make_dot_d_files(activator.script_extension)
859
860
        with captured() as c:
861
            rc = activate_main(('', 'shell.xonsh', 'activate', self.prefix))
862
        assert not c.stderr
863
        assert rc == 0
864
        activate_result = c.stdout
865
866
        with open(activate_result) as fh:
867
            activate_data = fh.read()
868
        rm_rf(activate_result)
869
870
        new_path_parts = activator._add_prefix_to_path(self.prefix)
871
        assert activate_data == dals("""
872
        $CONDA_DEFAULT_ENV = '%(native_prefix)s'
873
        $CONDA_EXE = '%(conda_exe)s'
874
        $CONDA_PREFIX = '%(native_prefix)s'
875
        $CONDA_PROMPT_MODIFIER = '(%(native_prefix)s) '
876
        $CONDA_PYTHON_EXE = '%(sys_executable)s'
877
        $CONDA_SHLVL = '1'
878
        $PATH = '%(new_path)s'
879
        source "%(activate1)s"
880
        """) % {
881
            'converted_prefix': activator.path_conversion(self.prefix),
882
            'native_prefix': self.prefix,
883
            'new_path': activator.pathsep_join(new_path_parts),
884
            'sys_executable': activator.path_conversion(sys.executable),
885
            'activate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.xsh')),
886
            'conda_exe': activator.path_conversion(context.conda_exe),
887
        }
888
889
        with env_vars({
890
            'CONDA_PREFIX': self.prefix,
891
            'CONDA_SHLVL': '1',
892
            'PATH': os.pathsep.join(concatv(new_path_parts, (os.environ['PATH'],))),
893
        }):
894
            activator = XonshActivator()
895
            with captured() as c:
896
                assert activate_main(('', 'shell.xonsh', 'reactivate')) == 0
897
            assert not c.stderr
898
            reactivate_result = c.stdout
899
900
            with open(reactivate_result) as fh:
901
                reactivate_data = fh.read()
902
            rm_rf(reactivate_result)
903
904
            new_path_parts = activator._replace_prefix_in_path(self.prefix, self.prefix)
905
            assert reactivate_data == dals("""
906
            source "%(deactivate1)s"
907
            $CONDA_PROMPT_MODIFIER = '(%(native_prefix)s) '
908
            $CONDA_SHLVL = '1'
909
            $PATH = '%(new_path)s'
910
            source "%(activate1)s"
911
            """) % {
912
                'activate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.xsh')),
913
                'deactivate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.xsh')),
914
                'native_prefix': self.prefix,
915
                'new_path': activator.pathsep_join(new_path_parts),
916
            }
917
918
            with captured() as c:
919
                assert activate_main(('', 'shell.xonsh', 'deactivate')) == 0
920
            assert not c.stderr
921
            deactivate_result = c.stdout
922
923
            with open(deactivate_result) as fh:
924
                deactivate_data = fh.read()
925
            rm_rf(deactivate_result)
926
927
            new_path = activator.pathsep_join(activator._remove_prefix_from_path(self.prefix))
928
            assert deactivate_data == dals("""
929
            source "%(deactivate1)s"
930
            del $CONDA_DEFAULT_ENV
931
            del $CONDA_PREFIX
932
            del $CONDA_PROMPT_MODIFIER
933
            del $CONDA_PYTHON_EXE
934
            $CONDA_SHLVL = '0'
935
            $PATH = '%(new_path)s'
936
            """) % {
937
                'new_path': new_path,
938
                'deactivate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.xsh')),
939
            }
940
941 View Code Duplication
    def test_fish_basic(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
942
        activator = FishActivator()
943
        self.make_dot_d_files(activator.script_extension)
944
945
        with captured() as c:
946
            rc = activate_main(('', 'shell.fish', 'activate', self.prefix))
947
        assert not c.stderr
948
        assert rc == 0
949
        activate_data = c.stdout
950
951
        new_path_parts = activator._add_prefix_to_path(self.prefix)
952
        assert activate_data == dals("""
953
        set -gx CONDA_DEFAULT_ENV "%(native_prefix)s";
954
        set -gx CONDA_EXE "%(conda_exe)s";
955
        set -gx CONDA_PREFIX "%(native_prefix)s";
956
        set -gx CONDA_PROMPT_MODIFIER "(%(native_prefix)s) ";
957
        set -gx CONDA_PYTHON_EXE "%(sys_executable)s";
958
        set -gx CONDA_SHLVL "1";
959
        set -gx PATH "%(new_path)s";
960
        source "%(activate1)s";
961
        """) % {
962
            'converted_prefix': activator.path_conversion(self.prefix),
963
            'native_prefix': self.prefix,
964
            'new_path': activator.pathsep_join(new_path_parts),
965
            'sys_executable': activator.path_conversion(sys.executable),
966
            'activate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.fish')),
967
            'conda_exe': activator.path_conversion(context.conda_exe),
968
        }
969
970
        with env_vars({
971
            'CONDA_PREFIX': self.prefix,
972
            'CONDA_SHLVL': '1',
973
            'PATH': os.pathsep.join(concatv(new_path_parts, (os.environ['PATH'],))),
974
        }):
975
            activator = FishActivator()
976
            with captured() as c:
977
                rc = activate_main(('', 'shell.fish', 'reactivate'))
978
            assert not c.stderr
979
            assert rc == 0
980
            reactivate_data = c.stdout
981
982
            new_path_parts = activator._replace_prefix_in_path(self.prefix, self.prefix)
983
            assert reactivate_data == dals("""
984
            source "%(deactivate1)s";
985
            set -gx CONDA_PROMPT_MODIFIER "(%(native_prefix)s) ";
986
            set -gx CONDA_SHLVL "1";
987
            set -gx PATH "%(new_path)s";
988
            source "%(activate1)s";
989
            """) % {
990
                'new_path': activator.pathsep_join(new_path_parts),
991
                'activate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.fish')),
992
                'deactivate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.fish')),
993
                'native_prefix': self.prefix,
994
            }
995
996
            with captured() as c:
997
                rc = activate_main(('', 'shell.fish', 'deactivate'))
998
            assert not c.stderr
999
            assert rc == 0
1000
            deactivate_data = c.stdout
1001
1002
            new_path = activator.pathsep_join(activator._remove_prefix_from_path(self.prefix))
1003
            assert deactivate_data == dals("""
1004
            source "%(deactivate1)s";
1005
            set -e CONDA_DEFAULT_ENV;
1006
            set -e CONDA_PREFIX;
1007
            set -e CONDA_PROMPT_MODIFIER;
1008
            set -e CONDA_PYTHON_EXE;
1009
            set -gx CONDA_SHLVL "0";
1010
            set -gx PATH "%(new_path)s";
1011
            """) % {
1012
                'new_path': new_path,
1013
                'deactivate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.fish')),
1014
1015
            }
1016
1017 View Code Duplication
    def test_powershell_basic(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1018
        activator = PowershellActivator()
1019
        self.make_dot_d_files(activator.script_extension)
1020
1021
        with captured() as c:
1022
            rc = activate_main(('', 'shell.powershell', 'activate', self.prefix))
1023
        assert not c.stderr
1024
        assert rc == 0
1025
        activate_data = c.stdout
1026
1027
        new_path_parts = activator._add_prefix_to_path(self.prefix)
1028
        assert activate_data == dals("""
1029
        $env:CONDA_DEFAULT_ENV = "%(prefix)s"
1030
        $env:CONDA_EXE = "%(conda_exe)s"
1031
        $env:CONDA_PREFIX = "%(prefix)s"
1032
        $env:CONDA_PROMPT_MODIFIER = "(%(prefix)s) "
1033
        $env:CONDA_PYTHON_EXE = "%(sys_executable)s"
1034
        $env:CONDA_SHLVL = "1"
1035
        $env:PATH = "%(new_path)s"
1036
        . "%(activate1)s"
1037
        """) % {
1038
            'prefix': self.prefix,
1039
            'new_path': activator.pathsep_join(new_path_parts),
1040
            'sys_executable': sys.executable,
1041
            'activate1': join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.ps1'),
1042
            'conda_exe': context.conda_exe,
1043
        }
1044
1045
        with env_vars({
1046
            'CONDA_PREFIX': self.prefix,
1047
            'CONDA_SHLVL': '1',
1048
            'PATH': os.pathsep.join(concatv(new_path_parts, (os.environ['PATH'],))),
1049
        }):
1050
            activator = PowershellActivator()
1051
            with captured() as c:
1052
                rc = activate_main(('', 'shell.powershell', 'reactivate'))
1053
            assert not c.stderr
1054
            assert rc == 0
1055
            reactivate_data = c.stdout
1056
1057
            new_path_parts = activator._replace_prefix_in_path(self.prefix, self.prefix)
1058
            assert reactivate_data == dals("""
1059
            . "%(deactivate1)s"
1060
            $env:CONDA_PROMPT_MODIFIER = "(%(prefix)s) "
1061
            $env:CONDA_SHLVL = "1"
1062
            $env:PATH = "%(new_path)s"
1063
            . "%(activate1)s"
1064
            """) % {
1065
                'activate1': join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.ps1'),
1066
                'deactivate1': join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.ps1'),
1067
                'prefix': self.prefix,
1068
                'new_path': activator.pathsep_join(new_path_parts),
1069
            }
1070
1071
            with captured() as c:
1072
                rc = activate_main(('', 'shell.powershell', 'deactivate'))
1073
            assert not c.stderr
1074
            assert rc == 0
1075
            deactivate_data = c.stdout
1076
1077
            new_path = activator.pathsep_join(activator._remove_prefix_from_path(self.prefix))
1078
            assert deactivate_data == dals("""
1079
            . "%(deactivate1)s"
1080
            Remove-Variable CONDA_DEFAULT_ENV
1081
            Remove-Variable CONDA_PREFIX
1082
            Remove-Variable CONDA_PROMPT_MODIFIER
1083
            Remove-Variable CONDA_PYTHON_EXE
1084
            $env:CONDA_SHLVL = "0"
1085
            $env:PATH = "%(new_path)s"
1086
            """) % {
1087
                'new_path': new_path,
1088
                'deactivate1': join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.ps1'),
1089
1090
            }
1091
1092
    def test_unicode(self):
1093
        shell = 'shell.posix'
1094
        prompt = 'PS1'
1095
        prompt_value = u'%{\xc2\xbb'.encode(sys.getfilesystemencoding())
1096
        with env_vars({prompt: prompt_value}):
1097
            # use a file as output stream to simulate PY2 default stdout
1098
            with tempdir() as td:
1099
                with open(join(td, "stdout"), "wt") as stdout:
1100
                    with captured(stdout=stdout) as c:
1101
                        rc = activate_main(('', shell, 'activate', self.prefix))
1102
1103
1104
class InteractiveShell(object):
1105
    activator = None
1106
    init_command = None
1107
    print_env_var = None
1108
    shells = {
1109
        'posix': {
1110
            'activator': 'posix',
1111
            'init_command': 'env | sort && eval "$(python -m conda shell.posix hook)"',
1112
            'print_env_var': 'echo "$%s"',
1113
        },
1114
        'bash': {
1115
            'base_shell': 'posix',  # inheritance implemented in __init__
1116
        },
1117
        'dash': {
1118
            'base_shell': 'posix',  # inheritance implemented in __init__
1119
        },
1120
        'zsh': {
1121
            'base_shell': 'posix',  # inheritance implemented in __init__
1122
            'init_command': 'env | sort && eval "$(python -m conda shell.zsh hook)"',
1123
        },
1124
        'cmd.exe': {
1125
            'activator': 'cmd.exe',
1126
            'init_command': 'set "CONDA_SHLVL=" '
1127
                            '&& @CALL conda\\shell\\condacmd\\conda_hook.bat '
1128
                            '&& set "CONDA_EXE=python -m conda"',
1129
            'print_env_var': '@echo %%%s%%',
1130
        },
1131
        'csh': {
1132
            'activator': 'csh',
1133
            'init_command': 'source conda/shell/etc/profile.d/conda.csh',
1134
            'print_env_var': 'echo "$%s"',
1135
        },
1136
        'tcsh': {
1137
            'base_shell': 'csh',
1138
        },
1139
        'fish': {
1140
            'activator': 'fish',
1141
            'init_command': 'eval (python -m conda shell.fish hook)',
1142
            'print_env_var': 'echo $%s',
1143
        },
1144
    }
1145
1146
    def __init__(self, shell_name):
1147
        self.shell_name = shell_name
1148
        base_shell = self.shells[shell_name].get('base_shell')
1149
        shell_vals = self.shells.get(base_shell, {})
1150
        shell_vals.update(self.shells[shell_name])
1151
        for key, value in iteritems(shell_vals):
1152
            setattr(self, key, value)
1153
        self.activator = activator_map[shell_vals['activator']]()
1154
1155
    def __enter__(self):
1156
        from pexpect.popen_spawn import PopenSpawn
1157
1158
        # remove all CONDA_ env vars
1159
        env = {str(k): str(v) for k, v in iteritems(os.environ)}
1160
        remove_these = {var_name for var_name in env if var_name.startswith('CONDA_')}
1161
        for var_name in remove_these:
1162
            del env[var_name]
1163
1164
        p = PopenSpawn(self.shell_name, timeout=12, maxread=2000, searchwindowsize=None,
1165
                       logfile=sys.stdout, cwd=os.getcwd(), env=env, encoding=None,
1166
                       codec_errors='strict')
1167
1168
        # set state for context
1169
        joiner = os.pathsep.join if self.shell_name == 'fish' else self.activator.pathsep_join
1170
        PATH = joiner(self.activator.path_conversion(concatv(
1171
            (dirname(sys.executable),),
1172
            self.activator._get_starting_path_list(),
1173
            (dirname(which(self.shell_name)),),
1174
        )))
1175
        self.original_path = PATH
1176
        env = {
1177
            'CONDA_AUTO_ACTIVATE_BASE': 'false',
1178
            'PYTHONPATH': CONDA_PACKAGE_ROOT,
1179
            'PATH': PATH,
1180
        }
1181
        for name, val in iteritems(env):
1182
            p.sendline(self.activator.export_var_tmpl % (name, val))
1183
1184
        if self.init_command:
1185
            p.sendline(self.init_command)
1186
        self.p = p
1187
        return self
1188
1189
    def __exit__(self, exc_type, exc_val, exc_tb):
1190
        if self.p:
1191
            import signal
1192
            self.p.kill(signal.SIGINT)
1193
1194
    def sendline(self, s):
1195
        return self.p.sendline(s)
1196
1197
    def expect(self, pattern, timeout=-1, searchwindowsize=-1, async=False):
1198
        return self.p.expect(pattern, timeout, searchwindowsize, async)
1199
1200
    def assert_env_var(self, env_var, value, use_exact=False):
1201
        # value is actually a regex
1202
        self.sendline(self.print_env_var % env_var)
1203
        try:
1204
            if use_exact:
1205
                self.p.expect_exact(value)
1206
                self.expect('.*\n')
1207
            else:
1208
                self.expect('%s\n' % value)
1209
        except:
1210
            print(self.p.before)
1211
            print(self.p.after)
1212
            raise
1213
1214
    def get_env_var(self, env_var):
1215
        if self.shell_name == 'cmd.exe':
1216
            self.sendline("@echo %%%s%%" % env_var)
1217
            self.expect("@echo %%%s%%\r\n([^\r]*)\r" % env_var)
1218
            value = self.p.match.groups()[0]
1219
            return ensure_text_type(value).strip()
1220
        else:
1221
            self.sendline('echo get_var_start')
1222
            self.sendline(self.print_env_var % env_var)
1223
            self.sendline('echo get_var_end')
1224
            self.expect('get_var_start(.*)get_var_end')
1225
            value = self.p.match.groups()[0]
1226
            return ensure_text_type(value).strip()
1227
1228
1229
def which(executable):
1230
    from distutils.spawn import find_executable
1231
    return find_executable(executable)
1232
1233
1234
@pytest.mark.integration
1235
class ShellWrapperIntegrationTests(TestCase):
1236
1237
    @classmethod
1238
    def setUpClass(cls):
1239
        try:
1240
            mkdir_p(join(sys.prefix, 'conda-meta'))
1241
            touch(join(sys.prefix, 'conda-meta', 'history'))
1242
        except Exception:
1243
            pass
1244
1245
    def setUp(self):
1246
        tempdirdir = gettempdir()
1247
1248
        prefix_dirname = str(uuid4())[:4] + ' ' + str(uuid4())[:4]
1249
        self.prefix = join(tempdirdir, prefix_dirname)
1250
        mkdir_p(join(self.prefix, 'conda-meta'))
1251
        assert isdir(self.prefix)
1252
        touch(join(self.prefix, 'conda-meta', 'history'))
1253
1254
        self.prefix2 = join(self.prefix, 'envs', 'charizard')
1255
        mkdir_p(join(self.prefix2, 'conda-meta'))
1256
        touch(join(self.prefix2, 'conda-meta', 'history'))
1257
1258
        self.prefix3 = join(self.prefix, 'envs', 'venusaur')
1259
        mkdir_p(join(self.prefix3, 'conda-meta'))
1260
        touch(join(self.prefix3, 'conda-meta', 'history'))
1261
1262
    def tearDown(self):
1263
        rm_rf(self.prefix)
1264
1265
    def basic_posix(self, shell):
1266
        num_paths_added = len(tuple(PosixActivator()._get_path_dirs(self.prefix)))
1267
        shell.assert_env_var('CONDA_SHLVL', '0')
1268
        PATH0 = shell.get_env_var('PATH').strip(':')
1269
1270
        shell.sendline('conda activate base')
1271
        # shell.sendline('env | sort')
1272
        shell.assert_env_var('PS1', '(base).*')
1273
        shell.assert_env_var('CONDA_SHLVL', '1')
1274
        PATH1 = shell.get_env_var('PATH').strip(':')
1275
        assert len(PATH0.split(':')) + num_paths_added == len(PATH1.split(':'))
1276
1277
        shell.sendline('conda activate "%s"' % self.prefix)
1278
        # shell.sendline('env | sort')
1279
        shell.assert_env_var('CONDA_SHLVL', '2')
1280
        shell.assert_env_var('CONDA_PREFIX', self.prefix, True)
1281
        PATH2 = shell.get_env_var('PATH').strip(':')
1282
        assert len(PATH0.split(':')) + num_paths_added == len(PATH2.split(':'))
1283
1284
        shell.sendline('env | sort | grep CONDA')
1285
        shell.expect('CONDA_')
1286
        shell.sendline("echo \"PATH=$PATH\"")
1287
        shell.expect('PATH=')
1288
        shell.sendline('conda activate "%s"' % self.prefix2)
1289
        shell.sendline('env | sort | grep CONDA')
1290
        shell.expect('CONDA_')
1291
        shell.sendline("echo \"PATH=$PATH\"")
1292
        shell.expect('PATH=')
1293
        shell.assert_env_var('PS1', '(charizard).*')
1294
        shell.assert_env_var('CONDA_SHLVL', '3')
1295
        PATH3 = shell.get_env_var('PATH').strip(':')
1296
        assert len(PATH0.split(':')) + num_paths_added == len(PATH3.split(':'))
1297
1298
        shell.sendline('conda install -yq sqlite=3.21 openssl')  # TODO: this should be a relatively light package, but also one that has activate.d or deactivate.d scripts
1299
        shell.expect('Executing transaction: ...working... done.*\n', timeout=35)
1300
        shell.assert_env_var('?', '0', True)
1301
        # TODO: assert that reactivate worked correctly
1302
1303
        shell.sendline('sqlite3 -version')
1304
        shell.expect('3\.21\..*\n')
1305
1306
        # conda run integration test
1307
        shell.sendline('conda run sqlite3 -version')
1308
        shell.expect('3\.21\..*\n')
1309
1310
        # regression test for #6840
1311
        shell.sendline('conda install --blah')
1312
        shell.assert_env_var('?', '2', use_exact=True)
1313
        shell.sendline('conda list --blah')
1314
        shell.assert_env_var('?', '2', use_exact=True)
1315
1316
        shell.sendline('conda deactivate')
1317
        shell.assert_env_var('CONDA_SHLVL', '2')
1318
        PATH = shell.get_env_var('PATH').strip(':')
1319
        assert len(PATH0.split(':')) + num_paths_added == len(PATH.split(':'))
1320
1321
        shell.sendline('conda deactivate')
1322
        shell.assert_env_var('CONDA_SHLVL', '1')
1323
        PATH = shell.get_env_var('PATH').strip(':')
1324
        assert len(PATH0.split(':')) + num_paths_added == len(PATH.split(':'))
1325
1326
        shell.sendline('conda deactivate')
1327
        shell.assert_env_var('CONDA_SHLVL', '0')
1328
        PATH = shell.get_env_var('PATH').strip(':')
1329
        assert len(PATH0.split(':')) == len(PATH.split(':'))
1330
1331
        shell.sendline(shell.print_env_var % 'PS1')
1332
        shell.expect('.*\n')
1333
        assert 'CONDA_PROMPT_MODIFIER' not in str(shell.p.after)
1334
1335
        shell.sendline('conda deactivate')
1336
        shell.assert_env_var('CONDA_SHLVL', '0')
1337
        PATH0 = shell.get_env_var('PATH').strip(':')
1338
1339
        shell.sendline('conda activate "%s"' % self.prefix2)
1340
        shell.assert_env_var('CONDA_SHLVL', '1')
1341
        PATH1 = shell.get_env_var('PATH').strip(':')
1342
        assert len(PATH0.split(':')) + num_paths_added == len(PATH1.split(':'))
1343
1344
        shell.sendline('conda activate "%s" --stack' % self.prefix3)
1345
        shell.assert_env_var('CONDA_SHLVL', '2')
1346
        PATH2 = shell.get_env_var('PATH').strip(':')
1347
        assert 'charizard' in PATH2
1348
        assert 'venusaur' in PATH2
1349
        assert len(PATH0.split(':')) + num_paths_added * 2 == len(PATH2.split(':'))
1350
1351
        shell.sendline('conda activate "%s"' % self.prefix)
1352
        shell.assert_env_var('CONDA_SHLVL', '3')
1353
        PATH3 = shell.get_env_var('PATH')
1354
        assert 'charizard' in PATH3
1355
        assert 'venusaur' not in PATH3
1356
        assert len(PATH0.split(':')) + num_paths_added * 2 == len(PATH3.split(':'))
1357
1358
        shell.sendline('conda deactivate')
1359
        shell.assert_env_var('CONDA_SHLVL', '2')
1360
        PATH4 = shell.get_env_var('PATH').strip(':')
1361
        assert 'charizard' in PATH4
1362
        assert 'venusaur' in PATH4
1363
        assert PATH4 == PATH2
1364
1365
    @pytest.mark.skipif(not which('bash'), reason='bash not installed')
1366
    def test_bash_basic_integration(self):
1367
        with InteractiveShell('bash') as shell:
1368
            self.basic_posix(shell)
1369
1370
    @pytest.mark.skipif(not which('dash') or on_win, reason='dash not installed')
1371
    def test_dash_basic_integration(self):
1372
        with InteractiveShell('dash') as shell:
1373
            self.basic_posix(shell)
1374
1375
    @pytest.mark.skipif(not which('zsh'), reason='zsh not installed')
1376
    def test_zsh_basic_integration(self):
1377
        with InteractiveShell('zsh') as shell:
1378
            self.basic_posix(shell)
1379
1380
    def basic_csh(self, shell):
1381
        shell.assert_env_var('CONDA_SHLVL', '0')
1382
        shell.sendline('conda activate base')
1383
        shell.assert_env_var('prompt', '(base).*')
1384
        shell.assert_env_var('CONDA_SHLVL', '1')
1385
        shell.sendline('conda activate "%s"' % self.prefix)
1386
        shell.assert_env_var('CONDA_SHLVL', '2')
1387
        shell.assert_env_var('CONDA_PREFIX', self.prefix, True)
1388
        shell.sendline('conda deactivate')
1389
        shell.assert_env_var('CONDA_SHLVL', '1')
1390
        shell.sendline('conda deactivate')
1391
        shell.assert_env_var('CONDA_SHLVL', '0')
1392
1393
        assert 'CONDA_PROMPT_MODIFIER' not in str(shell.p.after)
1394
1395
        shell.sendline('conda deactivate')
1396
        shell.assert_env_var('CONDA_SHLVL', '0')
1397
1398
    @pytest.mark.skipif(not which('csh'), reason='csh not installed')
1399
    @pytest.mark.xfail(reason="pure csh doesn't support argument passing to sourced scripts")
1400
    def test_csh_basic_integration(self):
1401
        with InteractiveShell('csh') as shell:
1402
            self.basic_csh(shell)
1403
1404
    @pytest.mark.skipif(not which('tcsh'), reason='tcsh not installed')
1405
    def test_tcsh_basic_integration(self):
1406
        with InteractiveShell('tcsh') as shell:
1407
            self.basic_csh(shell)
1408
1409
    @pytest.mark.skipif(not which('fish'), reason='fish not installed')
1410
    @pytest.mark.xfail(reason="fish and pexpect don't seem to work together?")
1411
    def test_fish_basic_integration(self):
1412
        with InteractiveShell('fish') as shell:
1413
            shell.sendline('env | sort')
1414
            # We should be seeing environment variable output to terminal with this line, but
1415
            # we aren't.  Haven't experienced this problem yet with any other shell...
1416
1417
            shell.assert_env_var('CONDA_SHLVL', '0')
1418
            shell.sendline('conda activate base')
1419
            shell.assert_env_var('CONDA_SHLVL', '1')
1420
            shell.sendline('conda activate "%s"' % self.prefix)
1421
            shell.assert_env_var('CONDA_SHLVL', '2')
1422
            shell.assert_env_var('CONDA_PREFIX', self.prefix, True)
1423
            shell.sendline('conda deactivate')
1424
            shell.assert_env_var('CONDA_SHLVL', '1')
1425
            shell.sendline('conda deactivate')
1426
            shell.assert_env_var('CONDA_SHLVL', '0')
1427
1428
            shell.sendline(shell.print_env_var % 'PS1')
1429
            shell.expect('.*\n')
1430
            assert 'CONDA_PROMPT_MODIFIER' not in str(shell.p.after)
1431
1432
            shell.sendline('conda deactivate')
1433
            shell.assert_env_var('CONDA_SHLVL', '0')
1434
1435
    @pytest.mark.skipif(not which('cmd.exe'), reason='cmd.exe not installed')
1436
    def test_cmd_exe_basic_integration(self):
1437
        charizard = join(self.prefix, 'envs', 'charizard')
1438
        with InteractiveShell('cmd.exe') as shell:
1439
            shell.sendline('where conda')
1440
            shell.p.expect_exact('conda.bat')
1441
            shell.expect('.*\n')
1442
            shell.sendline('conda activate "%s"' % charizard)
1443
            shell.assert_env_var('CONDA_SHLVL', '1\r')
1444
            shell.sendline('conda activate "%s"' % self.prefix)
1445
            shell.assert_env_var('CONDA_SHLVL', '2\r')
1446
            shell.assert_env_var('CONDA_PREFIX', self.prefix, True)
1447
1448
            shell.sendline('conda install -yq sqlite=3.21 openssl')  # TODO: this should be a relatively light package, but also one that has activate.d or deactivate.d scripts
1449
            shell.expect('Executing transaction: ...working... done.*\n', timeout=35)
1450
            shell.assert_env_var('errorlevel', '0', True)
1451
            # TODO: assert that reactivate worked correctly
1452
1453
            shell.sendline('sqlite3 -version')
1454
            shell.expect('3\.21\..*\n')
1455
1456
            # conda run integration test
1457
            shell.sendline('conda run sqlite3 -version')
1458
            shell.expect('3\.21\..*\n')
1459
1460
            shell.sendline('conda deactivate')
1461
            shell.assert_env_var('CONDA_SHLVL', '1\r')
1462
            shell.sendline('conda deactivate')
1463
            shell.assert_env_var('CONDA_SHLVL', '0\r')
1464
            shell.sendline('conda deactivate')
1465
            shell.assert_env_var('CONDA_SHLVL', '0\r')
1466
1467
    @pytest.mark.skipif(not which('bash'), reason='bash not installed')
1468
    def test_bash_activate_error(self):
1469
        with InteractiveShell('bash') as shell:
1470
            shell.sendline("conda activate environment-not-found-doesnt-exist")
1471
            shell.expect('Could not find conda environment: environment-not-found-doesnt-exist')
1472
            shell.assert_env_var('CONDA_SHLVL', '0')
1473
1474
            shell.sendline("conda activate -h blah blah")
1475
            shell.expect('usage: conda activate')
1476
1477
    @pytest.mark.skipif(not which('cmd.exe'), reason='cmd.exe not installed')
1478
    def test_cmd_exe_activate_error(self):
1479
        with InteractiveShell('cmd.exe') as shell:
1480
            shell.sendline("conda activate environment-not-found-doesnt-exist")
1481
            shell.expect('Could not find conda environment: environment-not-found-doesnt-exist')
1482
            shell.assert_env_var('errorlevel', '1\r')
1483
1484
            shell.sendline("conda activate -h blah blah")
1485
            shell.expect('usage: conda activate')
1486
1487 View Code Duplication
    @pytest.mark.skipif(not which('bash'), reason='bash not installed')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1488
    def test_legacy_activate_deactivate_bash(self):
1489
        with InteractiveShell('bash') as shell:
1490
            shell.sendline("export _CONDA_ROOT='%s/shell'" % CONDA_PACKAGE_ROOT)
1491
            shell.sendline("source activate \"%s\"" % self.prefix2)
1492
            PATH = shell.get_env_var("PATH")
1493
            assert 'charizard' in PATH
1494
1495
            shell.sendline("source activate \"%s\"" % self.prefix3)
1496
            PATH = shell.get_env_var("PATH")
1497
            assert 'venusaur' in PATH
1498
1499
            shell.sendline("source deactivate")
1500
            PATH = shell.get_env_var("PATH")
1501
            assert 'charizard' in PATH
1502
1503
            shell.sendline("source deactivate")
1504
            shell.assert_env_var('CONDA_SHLVL', '0')
1505
1506 View Code Duplication
    @pytest.mark.skipif(not which('cmd.exe'), reason='cmd.exe not installed')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1507
    def test_legacy_activate_deactivate_cmd_exe(self):
1508
        with InteractiveShell('cmd.exe') as shell:
1509
            shell.sendline("echo off")
1510
1511
            shell.sendline("SET \"PATH=%s\\shell\\Scripts;%%PATH%%\"" % CONDA_PACKAGE_ROOT)
1512
            shell.sendline("activate \"%s\"" % self.prefix2)
1513
            PATH = shell.get_env_var("PATH")
1514
            assert 'charizard' in PATH
1515
1516
            shell.sendline("activate \"%s\"" % self.prefix3)
1517
            PATH = shell.get_env_var("PATH")
1518
            assert 'venusaur' in PATH
1519
1520
            shell.sendline("deactivate")
1521
            PATH = shell.get_env_var("PATH")
1522
            assert 'charizard' in PATH
1523
1524
            shell.sendline("deactivate")
1525
            conda_shlvl = shell.get_env_var('CONDA_SHLVL')
1526
            assert int(conda_shlvl) == 0, conda_shlvl
1527