py-rattler 0.22.0__cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. py_rattler-0.22.0.dist-info/METADATA +208 -0
  2. py_rattler-0.22.0.dist-info/RECORD +68 -0
  3. py_rattler-0.22.0.dist-info/WHEEL +4 -0
  4. rattler/__init__.py +114 -0
  5. rattler/channel/__init__.py +5 -0
  6. rattler/channel/channel.py +94 -0
  7. rattler/channel/channel_config.py +43 -0
  8. rattler/channel/channel_priority.py +14 -0
  9. rattler/exceptions.py +120 -0
  10. rattler/explicit_environment/__init__.py +3 -0
  11. rattler/explicit_environment/environment.py +69 -0
  12. rattler/index/__init__.py +3 -0
  13. rattler/index/index.py +112 -0
  14. rattler/install/__init__.py +3 -0
  15. rattler/install/installer.py +96 -0
  16. rattler/lock/__init__.py +23 -0
  17. rattler/lock/channel.py +52 -0
  18. rattler/lock/environment.py +213 -0
  19. rattler/lock/hash.py +33 -0
  20. rattler/lock/lock_file.py +118 -0
  21. rattler/lock/package.py +302 -0
  22. rattler/match_spec/__init__.py +4 -0
  23. rattler/match_spec/match_spec.py +294 -0
  24. rattler/match_spec/nameless_match_spec.py +185 -0
  25. rattler/networking/__init__.py +21 -0
  26. rattler/networking/client.py +74 -0
  27. rattler/networking/fetch_repo_data.py +103 -0
  28. rattler/networking/middleware.py +234 -0
  29. rattler/package/__init__.py +26 -0
  30. rattler/package/about_json.py +329 -0
  31. rattler/package/index_json.py +437 -0
  32. rattler/package/no_arch_type.py +142 -0
  33. rattler/package/package_name.py +204 -0
  34. rattler/package/package_name_matcher.py +81 -0
  35. rattler/package/paths_json.py +696 -0
  36. rattler/package/run_exports_json.py +268 -0
  37. rattler/package_streaming/__init__.py +26 -0
  38. rattler/platform/__init__.py +4 -0
  39. rattler/platform/arch.py +59 -0
  40. rattler/platform/platform.py +217 -0
  41. rattler/prefix/__init__.py +4 -0
  42. rattler/prefix/prefix_paths.py +442 -0
  43. rattler/prefix/prefix_record.py +234 -0
  44. rattler/pty/__init__.py +25 -0
  45. rattler/pty/pty_process.py +391 -0
  46. rattler/pty/pty_session.py +241 -0
  47. rattler/py.typed +0 -0
  48. rattler/rattler.abi3.so +0 -0
  49. rattler/repo_data/__init__.py +19 -0
  50. rattler/repo_data/gateway.py +337 -0
  51. rattler/repo_data/package_record.py +938 -0
  52. rattler/repo_data/patch_instructions.py +22 -0
  53. rattler/repo_data/record.py +164 -0
  54. rattler/repo_data/repo_data.py +74 -0
  55. rattler/repo_data/source.py +85 -0
  56. rattler/repo_data/sparse.py +356 -0
  57. rattler/shell/__init__.py +3 -0
  58. rattler/shell/shell.py +134 -0
  59. rattler/solver/__init__.py +3 -0
  60. rattler/solver/solver.py +220 -0
  61. rattler/utils/rattler_version.py +19 -0
  62. rattler/version/__init__.py +5 -0
  63. rattler/version/version.py +591 -0
  64. rattler/version/version_spec.py +184 -0
  65. rattler/version/with_source.py +80 -0
  66. rattler/virtual_package/__init__.py +4 -0
  67. rattler/virtual_package/generic.py +136 -0
  68. rattler/virtual_package/virtual_package.py +201 -0
@@ -0,0 +1,3 @@
1
+ from rattler.explicit_environment.environment import ExplicitEnvironmentSpec, ExplicitEnvironmentEntry
2
+
3
+ __all__ = ["ExplicitEnvironmentSpec", "ExplicitEnvironmentEntry"]
@@ -0,0 +1,69 @@
1
+ from pathlib import Path
2
+ from typing import List, Optional
3
+
4
+ from rattler.rattler import PyExplicitEnvironmentSpec as _PyExplicitEnvironmentSpec
5
+ from rattler.rattler import PyExplicitEnvironmentEntry as _PyExplicitEnvironmentEntry
6
+ from rattler.platform import Platform
7
+
8
+
9
+ class ExplicitEnvironmentEntry:
10
+ """A wrapper around an explicit environment entry which represents a URL to a package"""
11
+
12
+ def __init__(self, inner: _PyExplicitEnvironmentEntry) -> None:
13
+ self._inner = inner
14
+
15
+ @property
16
+ def url(self) -> str:
17
+ """Returns the URL of the package"""
18
+ return self._inner.url()
19
+
20
+
21
+ class ExplicitEnvironmentSpec:
22
+ """The explicit environment (e.g. env.txt) file that contains a list of all URLs in a environment"""
23
+
24
+ def __init__(self, inner: _PyExplicitEnvironmentSpec) -> None:
25
+ self._inner = inner
26
+
27
+ @classmethod
28
+ def from_path(cls, path: Path) -> "ExplicitEnvironmentSpec":
29
+ """Parses the object from a file specified by a `path`, using a format appropriate for the file type.
30
+
31
+ For example, if the file is in text format, this function reads the data from the file at
32
+ the specified path, parses the text and returns the resulting object. If the file is
33
+ not in a parsable format or if the file could not be read, this function raises an error.
34
+ """
35
+ return cls(_PyExplicitEnvironmentSpec.from_path(path))
36
+
37
+ @classmethod
38
+ def from_str(cls, content: str) -> "ExplicitEnvironmentSpec":
39
+ """
40
+ Parses the object from a string containing the explicit environment specification
41
+
42
+ Examples:
43
+
44
+ ```python
45
+ >>> spec = ExplicitEnvironmentSpec.from_str('''@EXPLICIT
46
+ ... # platform: linux-64
47
+ ... http://repo.anaconda.com/pkgs/main/linux-64/python-3.9.0-h3.tar.bz2
48
+ ... ''')
49
+ >>> spec.platform
50
+ Platform(linux-64)
51
+ >>> spec.packages[0].url
52
+ 'http://repo.anaconda.com/pkgs/main/linux-64/python-3.9.0-h3.tar.bz2'
53
+ >>>
54
+ ```
55
+ """
56
+ return cls(_PyExplicitEnvironmentSpec.from_str(content))
57
+
58
+ @property
59
+ def platform(self) -> Optional[Platform]:
60
+ """Returns the platform specified in the explicit environment specification"""
61
+ platform = self._inner.platform()
62
+ if platform is not None:
63
+ return Platform._from_py_platform(platform)
64
+ return None
65
+
66
+ @property
67
+ def packages(self) -> List[ExplicitEnvironmentEntry]:
68
+ """Returns the environment entries (URLs) specified in the explicit environment specification"""
69
+ return [ExplicitEnvironmentEntry(p) for p in self._inner.packages()]
@@ -0,0 +1,3 @@
1
+ from rattler.index.index import index_fs, index_s3, S3Credentials
2
+
3
+ __all__ = ["index_s3", "index_fs", "S3Credentials"]
rattler/index/index.py ADDED
@@ -0,0 +1,112 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ import os
5
+ from typing import Optional, Literal
6
+
7
+ from rattler.platform import Platform
8
+ from rattler.rattler import py_index_fs, py_index_s3
9
+
10
+
11
+ @dataclass
12
+ class S3Credentials:
13
+ """Credentials for accessing an S3 backend."""
14
+
15
+ # The endpoint URL of the S3 backend
16
+ endpoint_url: str
17
+
18
+ # The region of the S3 backend
19
+ region: str
20
+
21
+ # The access key ID for the S3 bucket.
22
+ access_key_id: Optional[str] = None
23
+
24
+ # The secret access key for the S3 bucket.
25
+ secret_access_key: Optional[str] = None
26
+
27
+ # The session token for the S3 bucket.
28
+ session_token: Optional[str] = None
29
+
30
+ # Defines how to address the bucket, either using virtual-hosted-style or path-style.
31
+ addressing_style: Literal["path", "virtual-host"] = "virtual-host"
32
+
33
+
34
+ async def index_fs(
35
+ channel_directory: os.PathLike[str],
36
+ target_platform: Optional[Platform] = None,
37
+ repodata_patch: Optional[str] = None,
38
+ write_zst: bool = True,
39
+ write_shards: bool = True,
40
+ force: bool = False,
41
+ max_parallel: int | None = None,
42
+ ) -> None:
43
+ """
44
+ Indexes dependencies in the `channel_directory` for one or more subdirectories within said directory.
45
+ Will generate repodata.json files in each subdirectory containing metadata about each present package,
46
+ or if `target_platform` is specified will only consider the subdirectory corresponding to this platform.
47
+ Will always index the "noarch" subdirectory, and thus this subdirectory should always be present, because
48
+ conda channels at a minimum must include this subdirectory.
49
+
50
+ Arguments:
51
+ channel_directory: A `os.PathLike[str]` that is the directory containing subdirectories
52
+ of dependencies to index.
53
+ target_platform: A `Platform` to index dependencies for.
54
+ repodata_patch: The name of the conda package (expected to be in the `noarch` subdir) that should be used for repodata patching.
55
+ write_zst: Whether to write repodata.json.zst.
56
+ write_shards: Whether to write sharded repodata.
57
+ force: Whether to forcefully re-index all subdirs.
58
+ max_parallel: The maximum number of packages to process in-memory simultaneously.
59
+ """
60
+ await py_index_fs(
61
+ channel_directory,
62
+ target_platform._inner if target_platform else target_platform,
63
+ repodata_patch,
64
+ write_zst,
65
+ write_shards,
66
+ force,
67
+ max_parallel,
68
+ )
69
+
70
+
71
+ async def index_s3(
72
+ channel_url: str,
73
+ credentials: Optional[S3Credentials] = None,
74
+ target_platform: Optional[Platform] = None,
75
+ repodata_patch: Optional[str] = None,
76
+ write_zst: bool = True,
77
+ write_shards: bool = True,
78
+ force: bool = False,
79
+ max_parallel: int | None = None,
80
+ precondition_checks: bool = True,
81
+ ) -> None:
82
+ """
83
+ Indexes dependencies in the `channel_url` for one or more subdirectories in the S3 directory.
84
+ Will generate repodata.json files in each subdirectory containing metadata about each present package,
85
+ or if `target_platform` is specified will only consider the subdirectory corresponding to this platform.
86
+ Will always index the "noarch" subdirectory, and thus this subdirectory should always be present, because
87
+ conda channels at a minimum must include this subdirectory.
88
+
89
+ Arguments:
90
+ channel_url: An S3 URL (e.g., s3://my-bucket/my-channel that containins the subdirectories
91
+ of dependencies to index.
92
+ credentials: The credentials to use for accessing the S3 bucket. If not provided, will use the default
93
+ credentials from the environment.
94
+ target_platform: A `Platform` to index dependencies for.
95
+ repodata_patch: The name of the conda package (expected to be in the `noarch` subdir) that should be used for repodata patching.
96
+ write_zst: Whether to write repodata.json.zst.
97
+ write_shards: Whether to write sharded repodata.
98
+ force: Whether to forcefully re-index all subdirs.
99
+ max_parallel: The maximum number of packages to process in-memory simultaneously.
100
+ precondition_checks: Whether to perform precondition checks before indexing on S3 buckets which helps to prevent data corruption when indexing with multiple processes at the same time. Defaults to True.
101
+ """
102
+ await py_index_s3(
103
+ channel_url,
104
+ credentials,
105
+ target_platform._inner if target_platform else target_platform,
106
+ repodata_patch,
107
+ write_zst,
108
+ write_shards,
109
+ force,
110
+ max_parallel,
111
+ precondition_checks,
112
+ )
@@ -0,0 +1,3 @@
1
+ from rattler.install.installer import install
2
+
3
+ __all__ = ["install"]
@@ -0,0 +1,96 @@
1
+ from __future__ import annotations
2
+ import os
3
+ from typing import List, Optional
4
+
5
+ from rattler.match_spec import MatchSpec
6
+ from rattler.networking.client import Client
7
+ from rattler.platform.platform import Platform
8
+ from rattler.prefix.prefix_record import PrefixRecord
9
+ from rattler.repo_data.record import RepoDataRecord
10
+
11
+ from rattler.rattler import py_install
12
+
13
+
14
+ async def install(
15
+ records: List[RepoDataRecord],
16
+ target_prefix: str | os.PathLike[str],
17
+ cache_dir: Optional[os.PathLike[str]] = None,
18
+ installed_packages: Optional[List[PrefixRecord]] = None,
19
+ reinstall_packages: Optional[set[str]] = None,
20
+ ignored_packages: Optional[set[str]] = None,
21
+ platform: Optional[Platform] = None,
22
+ execute_link_scripts: bool = False,
23
+ show_progress: bool = True,
24
+ client: Optional[Client] = None,
25
+ requested_specs: Optional[List[MatchSpec]] = None,
26
+ ) -> None:
27
+ """
28
+ Create an environment by downloading and linking the `dependencies` in
29
+ the `target_prefix` directory.
30
+
31
+ !!! warning
32
+
33
+ When `execute_link_scripts` is set to `True` the post-link and pre-unlink scripts of
34
+ packages will be executed. These scripts are not sandboxed and can be used to execute
35
+ arbitrary code. It is therefor discouraged to enable executing link scripts.
36
+
37
+ Example
38
+ -------
39
+ ```python
40
+ >>> import asyncio
41
+ >>> from rattler import solve, install
42
+ >>> from tempfile import TemporaryDirectory
43
+ >>> temp_dir = TemporaryDirectory()
44
+ >>>
45
+ >>> async def main():
46
+ ... # Solve an environment with python 3.9 for the current platform
47
+ ... records = await solve(sources=["conda-forge"], specs=["python 3.9.*"])
48
+ ...
49
+ ... # Link the environment in a temporary directory (you can pass any kind of path here).
50
+ ... await install(records, target_prefix=temp_dir.name)
51
+ ...
52
+ ... # That's it! The environment is now created.
53
+ ... # You will find Python under `f"{temp_dir.name}/bin/python"` or `f"{temp_dir.name}/python.exe"` on Windows.
54
+ >>> asyncio.run(main())
55
+
56
+ ```
57
+
58
+ Arguments:
59
+ records: A list of solved `RepoDataRecord`s.
60
+ target_prefix: Path to the directory where the environment should
61
+ be created.
62
+ cache_dir: Path to directory where the dependencies will be
63
+ downloaded and cached.
64
+ installed_packages: A list of `PrefixRecord`s which are
65
+ already installed in the `target_prefix`. This can be obtained by loading
66
+ `PrefixRecord`s from `{target_prefix}/conda-meta/`.
67
+ If `None` is specified then the `target_prefix` will be scanned for installed
68
+ packages.
69
+ reinstall_packages: A list of package names that should be reinstalled.
70
+ ignored_packages: A list of package names that should be ignored (left untouched).
71
+ These packages will not be removed, installed, or updated.
72
+ platform: Target platform to create and link the
73
+ environment. Defaults to current platform.
74
+ execute_link_scripts: whether to execute the post-link and pre-unlink scripts
75
+ that may be part of a package. Defaults to False.
76
+ show_progress: If set to `True` a progress bar will be shown on the CLI.
77
+ client: An authenticated client to use for downloading packages. If not specified a default
78
+ client will be used.
79
+ requested_specs: A list of `MatchSpec`s that were originally requested. These will be used
80
+ to populate the `requested_specs` field in the generated `conda-meta/*.json` files.
81
+ If `None`, the `requested_specs` field will remain empty.
82
+ """
83
+
84
+ await py_install(
85
+ records=records,
86
+ target_prefix=str(target_prefix),
87
+ cache_dir=cache_dir,
88
+ installed_packages=installed_packages,
89
+ reinstall_packages=reinstall_packages,
90
+ ignored_packages=ignored_packages,
91
+ platform=platform._inner if platform is not None else None,
92
+ client=client._client if client is not None else None,
93
+ execute_link_scripts=execute_link_scripts,
94
+ show_progress=show_progress,
95
+ requested_specs=requested_specs,
96
+ )
@@ -0,0 +1,23 @@
1
+ from rattler.lock.lock_file import LockFile
2
+ from rattler.lock.environment import Environment
3
+ from rattler.lock.channel import LockChannel
4
+ from rattler.lock.hash import PackageHashes
5
+ from rattler.lock.package import (
6
+ LockedPackage,
7
+ PypiLockedPackage,
8
+ CondaLockedPackage,
9
+ CondaLockedBinaryPackage,
10
+ CondaLockedSourcePackage,
11
+ )
12
+
13
+ __all__ = [
14
+ "LockFile",
15
+ "Environment",
16
+ "LockChannel",
17
+ "PackageHashes",
18
+ "LockedPackage",
19
+ "PypiLockedPackage",
20
+ "CondaLockedPackage",
21
+ "CondaLockedBinaryPackage",
22
+ "CondaLockedSourcePackage",
23
+ ]
@@ -0,0 +1,52 @@
1
+ from __future__ import annotations
2
+
3
+ from rattler.rattler import PyLockChannel
4
+
5
+
6
+ class LockChannel:
7
+ _channel: PyLockChannel
8
+
9
+ def __init__(self, url: str) -> None:
10
+ """
11
+ Create a new channel.
12
+ """
13
+ self._channel = PyLockChannel(url)
14
+
15
+ @classmethod
16
+ def _from_py_lock_channel(cls, channel: PyLockChannel) -> LockChannel:
17
+ """
18
+ Construct Rattler LockChannel from FFI PyLockChannel object.
19
+ """
20
+ chan = cls.__new__(cls)
21
+ chan._channel = channel
22
+ return chan
23
+
24
+ def __str__(self) -> str:
25
+ """
26
+ Returns a string representation of the LockChannel.
27
+
28
+ Examples
29
+ --------
30
+ ```python
31
+ >>> channel = LockChannel("https://conda.anaconda.org/conda-forge/")
32
+ >>> str(channel)
33
+ 'https://conda.anaconda.org/conda-forge/'
34
+ >>>
35
+ ```
36
+ """
37
+ return self._channel.as_str()
38
+
39
+ def __repr__(self) -> str:
40
+ """
41
+ Returns a representation of the LockChannel.
42
+
43
+ Examples
44
+ --------
45
+ ```python
46
+ >>> channel = LockChannel("https://conda.anaconda.org/conda-forge/")
47
+ >>> channel
48
+ LockChannel(url="https://conda.anaconda.org/conda-forge/")
49
+ >>>
50
+ ```
51
+ """
52
+ return f'LockChannel(url="{self._channel.as_str()}")'
@@ -0,0 +1,213 @@
1
+ from __future__ import annotations
2
+ from typing import Dict, List, Optional
3
+
4
+ from rattler.lock.channel import LockChannel
5
+ from rattler.lock.package import LockedPackage, PypiLockedPackage
6
+ from rattler.platform.platform import Platform
7
+
8
+ from rattler.rattler import PyEnvironment
9
+ from rattler.repo_data.record import RepoDataRecord
10
+
11
+
12
+ class Environment:
13
+ """
14
+ Information about a specific environment in the lock-file.
15
+ """
16
+
17
+ _env: PyEnvironment
18
+
19
+ def __init__(
20
+ self, name: str, requirements: Dict[Platform, List[RepoDataRecord]], channels: List[LockChannel]
21
+ ) -> None:
22
+ """
23
+ Create a new environment.
24
+ """
25
+ self._env = PyEnvironment(
26
+ name=name,
27
+ # TODO: move this logic to rust
28
+ records={
29
+ platform._inner: [record._record for record in records] for (platform, records) in requirements.items()
30
+ },
31
+ channels=[channel._channel for channel in channels],
32
+ )
33
+
34
+ def platforms(self) -> List[Platform]:
35
+ """
36
+ Returns all the platforms for which we have a locked-down environment.
37
+
38
+ Examples
39
+ --------
40
+ ```python
41
+ >>> from rattler import LockFile
42
+ >>> lock_file = LockFile.from_path("../test-data/test.lock")
43
+ >>> env = lock_file.default_environment()
44
+ >>> env.platforms()
45
+ [...]
46
+ >>>
47
+ ```
48
+ """
49
+ return [Platform._from_py_platform(p) for p in self._env.platforms()]
50
+
51
+ def channels(self) -> List[LockChannel]:
52
+ """
53
+ Returns the channels that are used by this environment.
54
+ Note that the order of the channels is significant.
55
+ The first channel is the highest priority channel.
56
+
57
+ Examples
58
+ --------
59
+ ```python
60
+ >>> from rattler import LockFile
61
+ >>> lock_file = LockFile.from_path("../test-data/test.lock")
62
+ >>> env = lock_file.default_environment()
63
+ >>> env.channels()
64
+ [LockChannel(url="https://conda.anaconda.org/conda-forge/")]
65
+ >>>
66
+ ```
67
+ """
68
+ return [LockChannel._from_py_lock_channel(c) for c in self._env.channels()]
69
+
70
+ def packages(self, platform: Platform) -> Optional[List[LockedPackage]]:
71
+ """
72
+ Returns all the packages for a specific platform in this environment.
73
+
74
+ Examples
75
+ --------
76
+ ```python
77
+ >>> from rattler import Platform, LockFile
78
+ >>> lock_file = LockFile.from_path("../test-data/test.lock")
79
+ >>> env = lock_file.default_environment()
80
+ >>> env.packages(Platform("osx-arm64"))[0]
81
+ CondaLockedBinaryPackage(name='tzdata',location='https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda')
82
+ >>>
83
+ ```
84
+ """
85
+ if packages := self._env.packages(platform._inner):
86
+ return [LockedPackage._from_py_locked_package(p) for p in packages]
87
+ return None
88
+
89
+ def packages_by_platform(self) -> Dict[Platform, List[LockedPackage]]:
90
+ """
91
+ Returns a list of all packages and platforms defined for this environment.
92
+
93
+ Examples
94
+ --------
95
+ ```python
96
+ >>> from rattler import LockFile
97
+ >>> lock_file = LockFile.from_path("../test-data/test.lock")
98
+ >>> env = lock_file.default_environment()
99
+ >>> pkgs = env.packages_by_platform()
100
+ >>> list(pkgs.keys())
101
+ [Platform(...)]
102
+ >>>
103
+ ```
104
+ """
105
+ return {
106
+ Platform._from_py_platform(platform): [LockedPackage._from_py_locked_package(p) for p in packages]
107
+ for (platform, packages) in self._env.packages_by_platform()
108
+ }
109
+
110
+ def pypi_packages(
111
+ self,
112
+ ) -> Dict[Platform, List[PypiLockedPackage]]:
113
+ """
114
+ Returns all pypi packages for all platforms.
115
+
116
+ Examples
117
+ --------
118
+ ```python
119
+ >>> from rattler import LockFile, Platform
120
+ >>> lock_file = LockFile.from_path("../test-data/test.lock")
121
+ >>> env = lock_file.default_environment()
122
+ >>> pypi_packages = env.pypi_packages()
123
+ >>> pypi_packages[Platform("osx-arm64")][0]
124
+ PypiLockedPackage(name='charset-normalizer',location='https://files.pythonhosted.org/packages/3a/52/9f9d17c3b54dc238de384c4cb5a2ef0e27985b42a0e5cc8e8a31d918d48d/charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl#sha256=55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6')
125
+ >>>
126
+ ```
127
+ """
128
+ return {
129
+ Platform._from_py_platform(platform): [PypiLockedPackage._from_py_locked_package(pypi) for pypi in pypi_tup]
130
+ for (platform, pypi_tup) in self._env.pypi_packages().items()
131
+ }
132
+
133
+ def conda_repodata_records(self) -> Dict[Platform, List[RepoDataRecord]]:
134
+ """
135
+ Returns all conda packages for all platforms.
136
+
137
+ Examples
138
+ --------
139
+ ```python
140
+ >>> from rattler import LockFile
141
+ >>> lock_file = LockFile.from_path("../test-data/test.lock")
142
+ >>> env = lock_file.default_environment()
143
+ >>> env.conda_repodata_records()
144
+ {'osx-arm64': [RepoDataRecord(...), ...]}
145
+ >>>
146
+ ```
147
+ """
148
+ return {
149
+ platform.name: [RepoDataRecord._from_py_record(r) for r in records]
150
+ for (platform, records) in self._env.conda_repodata_records().items()
151
+ }
152
+
153
+ def conda_repodata_records_for_platform(self, platform: Platform) -> Optional[List[RepoDataRecord]]:
154
+ """
155
+ Takes all the conda packages, converts them to [`RepoDataRecord`] and returns them or
156
+ returns an error if the conversion failed. Returns `None` if the specified platform is not
157
+ defined for this environment.
158
+
159
+ Examples
160
+ --------
161
+ ```python
162
+ >>> from rattler import LockFile, Platform
163
+ >>> lock_file = LockFile.from_path("../test-data/test.lock")
164
+ >>> env = lock_file.default_environment()
165
+ >>> rdr = env.conda_repodata_records_for_platform(Platform("osx-arm64"))
166
+ >>> rdr
167
+ [...]
168
+ >>> rdr[0]
169
+ RepoDataRecord(...)
170
+ >>>
171
+ ```
172
+ """
173
+ if records := self._env.conda_repodata_records_for_platform(platform._inner):
174
+ return [RepoDataRecord._from_py_record(r) for r in records]
175
+ return None
176
+
177
+ def pypi_packages_for_platform(self, platform: Platform) -> Optional[List[PypiLockedPackage]]:
178
+ """
179
+ Returns all the pypi packages and their associated environment data for the specified
180
+ platform. Returns `None` if the platform is not defined for this environment.
181
+
182
+ Examples
183
+ --------
184
+ ```python
185
+ >>> from rattler import LockFile, Platform
186
+ >>> lock_file = LockFile.from_path("../test-data/test.lock")
187
+ >>> env = lock_file.default_environment()
188
+ >>> osx_pypi_pkgs = env.pypi_packages_for_platform(Platform("osx-arm64"))
189
+ >>> osx_pypi_pkgs
190
+ [...]
191
+ >>> osx_pypi_pkgs[0]
192
+ PypiLockedPackage(name='charset-normalizer',location='https://files.pythonhosted.org/packages/3a/52/9f9d17c3b54dc238de384c4cb5a2ef0e27985b42a0e5cc8e8a31d918d48d/charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl#sha256=55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6')
193
+ >>>
194
+ ```
195
+ """
196
+ if data := self._env.pypi_packages_for_platform(platform._inner):
197
+ return [PypiLockedPackage._from_py_locked_package(pkg) for pkg in data]
198
+ return None
199
+
200
+ @classmethod
201
+ def _from_py_environment(cls, py_environment: PyEnvironment) -> Environment:
202
+ """
203
+ Construct Rattler Environment from FFI PyEnvironment object.
204
+ """
205
+ env = cls.__new__(cls)
206
+ env._env = py_environment
207
+ return env
208
+
209
+ def __repr__(self) -> str:
210
+ """
211
+ Returns a representation of the Environment.
212
+ """
213
+ return "Environment()"
rattler/lock/hash.py ADDED
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+ from typing import Optional
3
+ from rattler.rattler import PyPackageHashes
4
+
5
+
6
+ class PackageHashes:
7
+ _hashes: PyPackageHashes
8
+
9
+ @property
10
+ def md5(self) -> Optional[bytes]:
11
+ """
12
+ Returns the Sha256 hash.
13
+ """
14
+ return self._hashes.md5
15
+
16
+ @property
17
+ def sha256(self) -> Optional[bytes]:
18
+ """
19
+ Returns the Sha256 hash.
20
+ """
21
+ return self._hashes.sha256
22
+
23
+ @classmethod
24
+ def _from_py_package_hashes(cls, pkg_hashes: PyPackageHashes) -> PackageHashes:
25
+ """
26
+ Construct Rattler PackageHashes from FFI PyPackageHashes object.
27
+ """
28
+ hashes = cls.__new__(cls)
29
+ hashes._hashes = pkg_hashes
30
+ return hashes
31
+
32
+ def __repr__(self) -> str:
33
+ return "PackageHashes()"