Completed
Push — master ( cc0c85...fb223d )
by Gonzalo
62:48
created

conda/api.py (2 issues)

1 7
# -*- coding: utf-8 -*-
2
from __future__ import absolute_import, division, print_function, unicode_literals
3 7
4 7
from .common.constants import NULL
5 7
from .core.package_cache_data import PackageCacheData as _PackageCacheData
6 7
from .core.prefix_data import PrefixData as _PrefixData
7 7
from .core.solve import (DepsModifier as _DepsModifier, Solver as _Solver,
8 7
                         UpdateModifier as _UpdateModifier)
9
from .core.subdir_data import SubdirData as _SubdirData
10 7
from .models.channel import Channel
11
12
DepsModifier = _DepsModifier
13
"""Flags to enable alternate handling of dependencies."""
14
15
UpdateModifier = _UpdateModifier
16
"""Flags to enable alternate handling for updates of existing packages in the environment."""
17
18
19 7
class Solver(object):
20
    """
21 7
    **Beta** While in beta, expect both major and minor changes across minor releases.
22 7
23 7
    A high-level API to conda's solving logic. Three public methods are provided to access a
24 7
    solution in various forms.
25 7
26 7
      * :meth:`solve_final_state`
27 7
      * :meth:`solve_for_diff`
28 7
      * :meth:`solve_for_transaction`
29 7
30 7
    """
31 7
32 7
    def __init__(self, prefix, channels, subdirs=(), specs_to_add=(), specs_to_remove=()):
33 7
        """
34 7
        **Beta**
35
36 7
        Args:
37 7
            prefix (str):
38
                The conda prefix / environment location for which the :class:`Solver`
39
                is being instantiated.
40
            channels (Sequence[:class:`Channel`]):
41 7
                A prioritized list of channels to use for the solution.
42 7
            subdirs (Sequence[str]):
43 7
                A prioritized list of subdirs to use for the solution.
44 7
            specs_to_add (Set[:class:`MatchSpec`]):
45
                The set of package specs to add to the prefix.
46
            specs_to_remove (Set[:class:`MatchSpec`]):
47 7
                The set of package specs to remove from the prefix.
48
49
        """
50
        self._internal = _Solver(prefix, channels, subdirs, specs_to_add, specs_to_remove)
51
52
    def solve_final_state(self, update_modifier=NULL, deps_modifier=NULL, prune=NULL,
53
                          ignore_pinned=NULL, force_remove=NULL):
54
        """
55
        **Beta** While in beta, expect both major and minor changes across minor releases.
56
57
        Gives the final, solved state of the environment.
58
59
        Args:
60
            deps_modifier (DepsModifier):
61
                An optional flag indicating special solver handling for dependencies. The
62
                default solver behavior is to be as conservative as possible with dependency
63
                updates (in the case the dependency already exists in the environment), while
64
                still ensuring all dependencies are satisfied.  Options include
65
                    * NO_DEPS
66
                    * ONLY_DEPS
67
                    * UPDATE_DEPS
68
                    * UPDATE_DEPS_ONLY_DEPS
69
                    * FREEZE_INSTALLED
70
            prune (bool):
71
                If ``True``, the solution will not contain packages that were
72
                previously brought into the environment as dependencies but are no longer
73
                required as dependencies and are not user-requested.
74
            ignore_pinned (bool):
75
                If ``True``, the solution will ignore pinned package configuration
76
                for the prefix.
77
            force_remove (bool):
78
                Forces removal of a package without removing packages that depend on it.
79
80
        Returns:
81
            Tuple[PackageRef]:
82
                In sorted dependency order from roots to leaves, the package references for
83
                the solved state of the environment.
84
85
        """
86
        return self._internal.solve_final_state(update_modifier, deps_modifier, prune,
87
                                                ignore_pinned, force_remove)
88
89
    def solve_for_diff(self, update_modifier=NULL, deps_modifier=NULL, prune=NULL,
90
                       ignore_pinned=NULL, force_remove=NULL, force_reinstall=False):
91
        """
92
        **Beta** While in beta, expect both major and minor changes across minor releases.
93
94
        Gives the package references to remove from an environment, followed by
95
        the package references to add to an environment.
96
97
        Args:
98
            deps_modifier (DepsModifier):
99
                See :meth:`solve_final_state`.
100
            prune (bool):
101
                See :meth:`solve_final_state`.
102
            ignore_pinned (bool):
103
                See :meth:`solve_final_state`.
104
            force_remove (bool):
105
                See :meth:`solve_final_state`.
106
            force_reinstall (bool):
107
                For requested specs_to_add that are already satisfied in the environment,
108
                instructs the solver to remove the package and spec from the environment,
109
                and then add it back--possibly with the exact package instance modified,
110
                depending on the spec exactness.
111
112
        Returns:
113
            Tuple[PackageRef], Tuple[PackageRef]:
114
                A two-tuple of PackageRef sequences.  The first is the group of packages to
115
                remove from the environment, in sorted dependency order from leaves to roots.
116
                The second is the group of packages to add to the environment, in sorted
117
                dependency order from roots to leaves.
118
119
        """
120
        return self._internal.solve_for_diff(update_modifier, deps_modifier, prune, ignore_pinned,
121
                                             force_remove, force_reinstall)
122
123
    def solve_for_transaction(self, update_modifier=NULL, deps_modifier=NULL, prune=NULL,
124
                              ignore_pinned=NULL, force_remove=NULL, force_reinstall=False):
125
        """
126
        **Beta** While in beta, expect both major and minor changes across minor releases.
127
128
        Gives an UnlinkLinkTransaction instance that can be used to execute the solution
129
        on an environment.
130
131
        Args:
132
            deps_modifier (DepsModifier):
133
                See :meth:`solve_final_state`.
134
            prune (bool):
135
                See :meth:`solve_final_state`.
136
            ignore_pinned (bool):
137
                See :meth:`solve_final_state`.
138
            force_remove (bool):
139
                See :meth:`solve_final_state`.
140
            force_reinstall (bool):
141
                See :meth:`solve_for_diff`.
142
143
        Returns:
144
            UnlinkLinkTransaction:
145
146
        """
147
        return self._internal.solve_for_transaction(update_modifier, deps_modifier, prune,
148 View Code Duplication
                                                    ignore_pinned, force_remove, force_reinstall)
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
149
150
151
class SubdirData(object):
152
    """
153
    **Beta** While in beta, expect both major and minor changes across minor releases.
154
155
    High-level management and usage of repodata.json for subdirs.
156
    """
157
158
    def __init__(self, channel):
159
        """
160
        **Beta** While in beta, expect both major and minor changes across minor releases.
161
162
        Args:
163
            channel (str or Channel):
164
                The target subdir for the instance. Must either be a url that includes a subdir
165
                or a :obj:`Channel` that includes a subdir. e.g.:
166
                    * 'https://repo.anaconda.com/pkgs/main/linux-64'
167
                    * Channel('https://repo.anaconda.com/pkgs/main/linux-64')
168
                    * Channel('conda-forge/osx-64')
169
        """
170
        channel = Channel(channel)
171
        assert channel.subdir
172
        self._internal = _SubdirData(channel)
173
174
    def query(self, package_ref_or_match_spec):
175
        """
176
        **Beta** While in beta, expect both major and minor changes across minor releases.
177
178
        Run a query against this specific instance of repodata.
179
180
        Args:
181
            package_ref_or_match_spec (PackageRef or MatchSpec or str):
182
                Either an exact :obj:`PackageRef` to match against, or a :obj:`MatchSpec`
183
                query object.  A :obj:`str` will be turned into a :obj:`MatchSpec` automatically.
184
185
        Returns:
186
            Tuple[PackageRecord]
187
188
        """
189
        return tuple(self._internal.query(package_ref_or_match_spec))
190
191
    @staticmethod
192
    def query_all(package_ref_or_match_spec, channels=None, subdirs=None):
193
        """
194
        **Beta** While in beta, expect both major and minor changes across minor releases.
195
196
        Run a query against all repodata instances in channel/subdir matrix.
197
198
        Args:
199
            package_ref_or_match_spec (PackageRef or MatchSpec or str):
200
                Either an exact :obj:`PackageRef` to match against, or a :obj:`MatchSpec`
201
                query object.  A :obj:`str` will be turned into a :obj:`MatchSpec` automatically.
202
            channels (Iterable[Channel or str] or None):
203
                An iterable of urls for channels or :obj:`Channel` objects. If None, will fall
204
                back to context.channels.
205
            subdirs (Iterable[str] or None):
206
                If None, will fall back to context.subdirs.
207
208
        Returns:
209
            Tuple[PackageRecord]
210
211
        """
212
        return tuple(_SubdirData.query_all(package_ref_or_match_spec, channels, subdirs))
213
214
    def iter_records(self):
215
        """
216
        **Beta** While in beta, expect both major and minor changes across minor releases.
217
218
        Returns:
219
            Iterable[PackageRecord]: A generator over all records contained in the repodata.json
220
                instance.  Warning: this is a generator that is exhausted on first use.
221
222
        """
223
        return self._internal.iter_records()
224
225
    def reload(self):
226
        """
227
        **Beta** While in beta, expect both major and minor changes across minor releases.
228
229
        Update the instance with new information. Backing information (i.e. repodata.json)
230
        is lazily downloaded/loaded on first use by the other methods of this class. You
231
        should only use this method if you are *sure* you have outdated data.
232
233
        Returns:
234
            SubdirData
235
236
        """
237
        self._internal = self._internal.reload()
238
        return self
239
240
241
class PackageCacheData(object):
242
    """
243
    **Beta** While in beta, expect both major and minor changes across minor releases.
244
245
    High-level management and usage of package caches.
246
    """
247
248
    def __init__(self, pkgs_dir):
249
        """
250
        **Beta** While in beta, expect both major and minor changes across minor releases.
251
252
        Args:
253
            pkgs_dir (str):
254
        """
255
        self._internal = _PackageCacheData(pkgs_dir)
256
257
    def get(self, package_ref, default=NULL):
258
        """
259
        **Beta** While in beta, expect both major and minor changes across minor releases.
260
261
        Args:
262
            package_ref (PackageRef):
263
                A :obj:`PackageRef` instance representing the key for the
264
                :obj:`PackageCacheRecord` being sought.
265
            default: The default value to return if the record does not exist. If not
266
                specified and no record exists, :exc:`KeyError` is raised.
267
268
        Returns:
269
            PackageCacheRecord
270
271
        """
272
        return self._internal.get(package_ref, default)
273
274
    def query(self, package_ref_or_match_spec):
275
        """
276
        **Beta** While in beta, expect both major and minor changes across minor releases.
277
278
        Run a query against this specific package cache instance.
279
280
        Args:
281
            package_ref_or_match_spec (PackageRef or MatchSpec or str):
282
                Either an exact :obj:`PackageRef` to match against, or a :obj:`MatchSpec`
283
                query object.  A :obj:`str` will be turned into a :obj:`MatchSpec` automatically.
284
285
        Returns:
286
            Tuple[PackageCacheRecord]
287
288
        """
289
        return tuple(self._internal.query(package_ref_or_match_spec))
290
291
    @staticmethod
292
    def query_all(package_ref_or_match_spec, pkgs_dirs=None):
293
        """
294
        **Beta** While in beta, expect both major and minor changes across minor releases.
295
296
        Run a query against all package caches.
297
298
        Args:
299
            package_ref_or_match_spec (PackageRef or MatchSpec or str):
300
                Either an exact :obj:`PackageRef` to match against, or a :obj:`MatchSpec`
301
                query object.  A :obj:`str` will be turned into a :obj:`MatchSpec` automatically.
302
            pkgs_dirs (Iterable[str] or None):
303
                If None, will fall back to context.pkgs_dirs.
304
305
        Returns:
306
            Tuple[PackageCacheRecord]
307
308
        """
309
        return tuple(_PackageCacheData.query_all(package_ref_or_match_spec, pkgs_dirs))
310
311
    def iter_records(self):
312
        """
313
        **Beta** While in beta, expect both major and minor changes across minor releases.
314
315
        Returns:
316
            Iterable[PackageCacheRecord]: A generator over all records contained in the package
317
                cache instance.  Warning: this is a generator that is exhausted on first use.
318
319
        """
320
        return self._internal.iter_records()
321
322
    @property
323
    def is_writable(self):
324
        """
325
        **Beta** While in beta, expect both major and minor changes across minor releases.
326
327
        Indicates if the package cache location is writable or read-only.
328
329
        Returns:
330
            bool
331
332
        """
333
        return self._internal.is_writable
334
335
    @staticmethod
336
    def first_writable(pkgs_dirs=None):
337
        """
338
        **Beta** While in beta, expect both major and minor changes across minor releases.
339
340
        Get an instance object for the first writable package cache.
341
342
        Args:
343
            pkgs_dirs (Iterable[str]):
344
                If None, will fall back to context.pkgs_dirs.
345
346
        Returns:
347
            PackageCacheData:
348
                An instance for the first writable package cache.
349
350
        """
351
        return PackageCacheData(_PackageCacheData.first_writable(pkgs_dirs).pkgs_dir)
352
353
    def reload(self):
354
        """
355
        **Beta** While in beta, expect both major and minor changes across minor releases.
356
357
        Update the instance with new information. Backing information (i.e. contents of
358
        the pkgs_dir) is lazily loaded on first use by the other methods of this class. You
359
        should only use this method if you are *sure* you have outdated data.
360
361
        Returns:
362
            PackageCacheData
363
364
        """
365
        self._internal = self._internal.reload()
366 View Code Duplication
        return self
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
367
368
369
class PrefixData(object):
370
    """
371
    **Beta** While in beta, expect both major and minor changes across minor releases.
372
373
    High-level management and usage of conda environment prefixes.
374
    """
375
376
    def __init__(self, prefix_path):
377
        """
378
        **Beta** While in beta, expect both major and minor changes across minor releases.
379
380
        Args:
381
            prefix_path (str):
382
        """
383
        self._internal = _PrefixData(prefix_path)
384
385
    def get(self, package_ref, default=NULL):
386
        """
387
        **Beta** While in beta, expect both major and minor changes across minor releases.
388
389
        Args:
390
            package_ref (PackageRef):
391
                A :obj:`PackageRef` instance representing the key for the
392
                :obj:`PrefixRecord` being sought.
393
            default: The default value to return if the record does not exist. If not
394
                specified and no record exists, :exc:`KeyError` is raised.
395
396
        Returns:
397
            PrefixRecord
398
399
        """
400
        return self._internal.get(package_ref.name, default)
401
402
    def query(self, package_ref_or_match_spec):
403
        """
404
        **Beta** While in beta, expect both major and minor changes across minor releases.
405
406
        Run a query against this specific prefix instance.
407
408
        Args:
409
            package_ref_or_match_spec (PackageRef or MatchSpec or str):
410
                Either an exact :obj:`PackageRef` to match against, or a :obj:`MatchSpec`
411
                query object.  A :obj:`str` will be turned into a :obj:`MatchSpec` automatically.
412
413
        Returns:
414
            Tuple[PrefixRecord]
415
416
        """
417
        return tuple(self._internal.query(package_ref_or_match_spec))
418
419
    def iter_records(self):
420
        """
421
        **Beta** While in beta, expect both major and minor changes across minor releases.
422
423
        Returns:
424
            Iterable[PrefixRecord]: A generator over all records contained in the prefix.
425
                Warning: this is a generator that is exhausted on first use.
426
427
        """
428
        return self._internal.iter_records()
429
430
    @property
431
    def is_writable(self):
432
        """
433
        **Beta** While in beta, expect both major and minor changes across minor releases.
434
435
        Indicates if the prefix is writable or read-only.
436
437
        Returns:
438
            bool or None:
439
                True if the prefix is writable.  False if read-only.  None if the prefix
440
                does not exist as a conda environment.
441
442
        """
443
        return self._internal.is_writable
444
445
    def reload(self):
446
        """
447
        **Beta** While in beta, expect both major and minor changes across minor releases.
448
449
        Update the instance with new information. Backing information (i.e. contents of
450
        the conda-meta directory) is lazily loaded on first use by the other methods of this
451
        class. You should only use this method if you are *sure* you have outdated data.
452
453
        Returns:
454
            PrefixData
455
456
        """
457
        self._internal = self._internal.reload()
458
        return self
459