Completed
Push — master ( 4489fe...5dabaa )
by Gonzalo
63:24
created

test_conda_env_create_no_existent_file()   A

Complexity

Conditions 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
c 1
b 0
f 1
dl 0
loc 9
rs 9.6666
1
import json
2
import os
3
from os.path import join
4
from shlex import split
5
import tempfile
6
import unittest
7
8
import pytest
9
10
from conda.base.constants import ROOT_ENV_NAME
11
from conda.base.context import context
12
from conda.cli.conda_argparse import do_call
13
from conda.cli.main import generate_parser
14
from conda.common.io import captured
15
from conda.core.envs_manager import list_all_known_prefixes
16
from conda.exceptions import EnvironmentLocationNotFound
17
from conda.install import rm_rf
18
from conda_env.cli.main import create_parser, do_call as do_call_conda_env
19
from conda_env.exceptions import EnvironmentFileNotFound
20
from conda_env.yaml import load as yaml_load
21
22
environment_1 = '''
23
name: env-1
24
dependencies:
25
  - python
26
channels:
27
  - malev
28
'''
29
30
environment_2 = '''
31
name: env-1
32
dependencies:
33
  - python
34
  - flask
35
channels:
36
  - malev
37
'''
38
39
test_env_name_1 = "env-1"
40
test_env_name_2 = "snowflakes"
41
test_env_name_3 = "env_foo"
42
43
44
def escape_for_winpath(p):
45
    if p:
46
        return p.replace('\\', '\\\\')
47
48
49
class Commands:
50
    ENV_CREATE = "create"
51
    ENV_REMOVE = "remove"
52
    ENV_EXPORT = "export"
53
    ENV_UPDATE = "update"
54
    LIST = "list"
55
    CREATE = "create"
56
    INFO = "info"
57
    INSTALL = "install"
58
59
60
def run_env_command(command, prefix, *arguments):
61
    """
62
        Run conda env commands
63
    Args:
64
        command: The command, create, remove, export
65
        prefix: The prefix, for remove and create
66
        *arguments: The extra arguments
67
    """
68
    p = create_parser()
69
    prefix = escape_for_winpath(prefix)
70
71
    if arguments:
72
        arguments = list(map(escape_for_winpath, arguments))
73
74
    if command is Commands.ENV_EXPORT:
75
        command_line = "{0} -n {1} {2}".format(command, prefix, " ".join(arguments))
76
    elif command is Commands.ENV_CREATE: # CREATE
77
        if prefix :
78
            command_line = "{0} -f {1}  {2}".format(command, prefix, " ".join(arguments))
79
        else:
80
            command_line = "{0} ".format(command)
81
    elif command is Commands.ENV_REMOVE:  # REMOVE
82
        command_line = "{0} --yes -n {1} {2}".format(command, prefix, " ".join(arguments))
83
    elif command is Commands.ENV_UPDATE:
84
        command_line = "{0} -n {1} {2}".format(command, prefix, " ".join(arguments))
85
    else:
86
        command_line = " --help "
87
88
    args = p.parse_args(split(command_line))
89
    context._set_argparse_args(args)
90
91
    with captured() as c:
92
        do_call_conda_env(args, p)
93
94
    return c.stdout, c.stderr
95
96
97
def run_conda_command(command, prefix, *arguments):
98
    """
99
        Run conda command,
100
    Args:
101
        command: conda create , list, info
102
        prefix: The prefix or the name of environment
103
        *arguments: Extra arguments
104
    """
105
    p = generate_parser()
106
107
    prefix = escape_for_winpath(prefix)
108
    if arguments:
109
        arguments = list(map(escape_for_winpath, arguments))
110
    if command is Commands.INFO:    # INFO
111
        command_line = "{0} {1}".format(command, " ".join(arguments))
112
    elif command is Commands.LIST:  # LIST
113
        command_line = "{0} -n {1} {2}".format(command, prefix, " ".join(arguments))
114
    else:  # CREATE
115
        command_line = "{0} -y -q -n {1} {2}".format(command, prefix, " ".join(arguments))
116
117
    args = p.parse_args(split(command_line))
118
    context._set_argparse_args(args)
119
    with captured() as c:
120
        do_call(args, p)
121
122
    return c.stdout, c.stderr
123
124
125
def create_env(content, filename='environment.yml'):
126
    with open(filename, 'w') as fenv:
127
        fenv.write(content)
128
129
130
def remove_env_file(filename='environment.yml'):
131
    os.remove(filename)
132
133
134
@pytest.mark.integration
135
class IntegrationTests(unittest.TestCase):
136
137
    def setUp(self):
138
        rm_rf("environment.yml")
139
        if env_is_created(test_env_name_1):
140
            run_env_command(Commands.ENV_REMOVE, test_env_name_1)
141
142
    def tearDown(self):
143
        rm_rf("environment.yml")
144
        if env_is_created(test_env_name_1):
145
            run_env_command(Commands.ENV_REMOVE, test_env_name_1)
146
147
    def test_conda_env_create_no_file(self):
148
        '''
149
        Test `conda env create` without an environment.yml file
150
        Should fail
151
        '''
152
        try:
153
            run_env_command(Commands.ENV_CREATE, None)
154
        except Exception as e:
155
            self.assertIsInstance(e, EnvironmentFileNotFound)
156
157
    def test_conda_env_create_no_existent_file(self):
158
        '''
159
        Test `conda env create --file=not_a_file.txt` with a file that does not
160
        exist.
161
        '''
162
        try:
163
            run_env_command(Commands.ENV_CREATE, None, '--file not_a_file.txt')
164
        except Exception as e:
165
            self.assertIsInstance(e, EnvironmentFileNotFound)
166
167
    def test_create_valid_env(self):
168
        '''
169
        Creates an environment.yml file and
170
        creates and environment with it
171
        '''
172
173
        create_env(environment_1)
174
        run_env_command(Commands.ENV_CREATE, None)
175
        self.assertTrue(env_is_created(test_env_name_1))
176
177
        o, e = run_conda_command(Commands.INFO, None, "--json")
178
        parsed = json.loads(o)
179
        self.assertNotEqual(
180
            len([env for env in parsed['envs'] if env.endswith(test_env_name_1)]), 0
181
        )
182
183
    def test_update(self):
184
        create_env(environment_1)
185
        run_env_command(Commands.ENV_CREATE, None)
186
        create_env(environment_2)
187
188
        run_env_command(Commands.ENV_UPDATE, test_env_name_1)
189
190
        o, e = run_conda_command(Commands.LIST, test_env_name_1, "flask", "--json")
191
        parsed = json.loads(o)
192
        self.assertNotEqual(len(parsed), 0)
193
194
    def test_name(self):
195
        # smoke test for gh-254
196
        create_env(environment_1)
197
        try:
198
            run_env_command(Commands.ENV_CREATE, test_env_name_1, "create")
199
        except Exception as e:
200
            self.assertIsInstance(e, EnvironmentFileNotFound, str(e))
201
202
203
def env_is_created(env_name):
204
    """
205
        Assert an environment is created
206
    Args:
207
        env_name: the environment name
208
    Returns: True if created
209
             False otherwise
210
    """
211
    from os.path import basename
212
213
    for prefix in list_all_known_prefixes():
214
        name = (ROOT_ENV_NAME if prefix == context.root_dir else
215
                basename(prefix))
216
        if name == env_name:
217
            return True
218
219
    return False
220
221
222
@pytest.mark.integration
223
class NewIntegrationTests(unittest.TestCase):
224
    """
225
        This is integration test for conda env
226
        make sure all instruction on online documentation works
227
        Please refer to link below
228
        http://conda.pydata.org/docs/using/envs.html#export-the-environment-file
229
    """
230
231
    def setUp(self):
232
        if env_is_created(test_env_name_2):
233
            run_env_command(Commands.ENV_REMOVE, test_env_name_2)
234
        if env_is_created(test_env_name_3):
235
            run_env_command(Commands.ENV_REMOVE, test_env_name_3)
236
237
    def tearDown(self):
238
        if env_is_created(test_env_name_2):
239
            run_env_command(Commands.ENV_REMOVE, test_env_name_2)
240
        if env_is_created(test_env_name_3):
241
            run_env_command(Commands.ENV_REMOVE, test_env_name_3)
242
243
    def test_create_remove_env(self):
244
        """
245
            Test conda create and remove env
246
        """
247
248
        run_conda_command(Commands.CREATE, test_env_name_3)
249
        self.assertTrue(env_is_created(test_env_name_3))
250
251
        run_env_command(Commands.ENV_REMOVE, test_env_name_3)
252
        self.assertFalse(env_is_created(test_env_name_3))
253
254
        with pytest.raises(EnvironmentLocationNotFound) as execinfo:
255
            run_env_command(Commands.ENV_REMOVE, 'does-not-exist')
256
257
    def test_env_export(self):
258
        """
259
            Test conda env export
260
        """
261
262
        run_conda_command(Commands.CREATE, test_env_name_2, "flask")
263
        self.assertTrue(env_is_created(test_env_name_2))
264
265
        snowflake, e,  = run_env_command(Commands.ENV_EXPORT, test_env_name_2)
266
267
        with tempfile.NamedTemporaryFile(mode="w", suffix="yml", delete=False) as env_yaml:
268
            env_yaml.write(snowflake)
269
            env_yaml.flush()
270
            env_yaml.close()
271
272
            run_env_command(Commands.ENV_REMOVE, test_env_name_2)
273
            self.assertFalse(env_is_created(test_env_name_2))
274
            run_env_command(Commands.ENV_CREATE, env_yaml.name)
275
            self.assertTrue(env_is_created(test_env_name_2))
276
277
            # regression test for #6220
278
            snowflake, e, = run_env_command(Commands.ENV_EXPORT, test_env_name_2, '--no-builds')
279
            assert not e.strip()
280
            env_description = yaml_load(snowflake)
281
            assert len(env_description['dependencies'])
282
            for spec_str in env_description['dependencies']:
283
                assert spec_str.count('=') == 1
284
285
    def test_list(self):
286
        """
287
            Test conda list -e and conda create from txt
288
        """
289
290
        run_conda_command(Commands.CREATE, test_env_name_2)
291
        self.assertTrue(env_is_created(test_env_name_2))
292
293
        snowflake, e = run_conda_command(Commands.LIST, test_env_name_2, "-e")
294
295
        with tempfile.NamedTemporaryFile(mode="w", suffix="txt", delete=False) as env_txt:
296
            env_txt.write(snowflake)
297
            env_txt.flush()
298
            env_txt.close()
299
            run_env_command(Commands.ENV_REMOVE, test_env_name_2)
300
            self.assertFalse(env_is_created(test_env_name_2))
301
            run_conda_command(Commands.CREATE, test_env_name_2, "--file " + env_txt.name)
302
            self.assertTrue(env_is_created(test_env_name_2))
303
304
        snowflake2, e = run_conda_command(Commands.LIST, test_env_name_2, "-e")
305
        self.assertEqual(snowflake, snowflake2)
306
307
    def test_export_muti_channel(self):
308
        """
309
            Test conda env export
310
        """
311
        from conda.core.prefix_data import PrefixData
312
        PrefixData._cache_.clear()
313
        run_conda_command(Commands.CREATE, test_env_name_2, "python=3.5")
314
        self.assertTrue(env_is_created(test_env_name_2))
315
316
        # install something from other channel not in config file
317
        run_conda_command(Commands.INSTALL, test_env_name_2, "-c", "numba", "llvmlite")
318
        snowflake, e, = run_env_command(Commands.ENV_EXPORT, test_env_name_2)
319
        assert 'numba' in snowflake
320
321
        check1, e = run_conda_command(Commands.LIST, test_env_name_2, "--explicit")
322
323
        with tempfile.NamedTemporaryFile(mode="w", suffix="yml", delete=False) as env_yaml:
324
            env_yaml.write(snowflake)
325
            env_yaml.flush()
326
            env_yaml.close()
327
            run_env_command(Commands.ENV_REMOVE, test_env_name_2)
328
            self.assertFalse(env_is_created(test_env_name_2))
329
            run_env_command(Commands.ENV_CREATE, env_yaml.name)
330
            self.assertTrue(env_is_created(test_env_name_2))
331
332
        # check explicit that we have same file
333
        check2, e = run_conda_command(Commands.LIST, test_env_name_2, "--explicit")
334
        self.assertEqual(check1, check2)
335
336
337
if __name__ == '__main__':
338
    unittest.main()
339