14
14
from cs_tools .cli .types import Directory
15
15
from cs_tools .cli .ux import CSToolsCommand , CSToolsGroup , rich_console
16
16
from cs_tools .settings import _meta_config as meta
17
+ from cs_tools .sync import base
17
18
from cs_tools .updater import cs_tools_venv
18
19
from cs_tools .updater ._bootstrapper import get_latest_cs_tools_release
19
20
import rich
@@ -140,10 +141,11 @@ def analytics():
140
141
def download (
141
142
directory : pathlib .Path = typer .Option (help = "location to download the python binaries to" , click_type = Directory ()),
142
143
platform : str = typer .Option (help = "tag describing the OS and CPU architecture of the target environment" ),
143
- python_version : str = typer .Option (
144
+ python_version : AwesomeVersion = typer .Option (
144
145
metavar = "X.Y" , help = "major and minor version of your python install" , parser = AwesomeVersion
145
146
),
146
147
beta : bool = typer .Option (False , "--beta" , help = "if included, download the latest pre-release binary" ),
148
+ syncer_dialect : str = typer .Option (None , help = "the name of the dialect to fetch dependencies for" ),
147
149
):
148
150
"""
149
151
Generate an offline binary.
@@ -156,14 +158,35 @@ def download(
156
158
[b yellow]python -m sysconfig[/]
157
159
158
160
"""
161
+ # DEV NOTE: @boonhapus, 2024/05/21
162
+ #
163
+ # The idea behind the offline installer is to simulate `pip install` by downloading
164
+ # all the necessary packages to build our environment.
165
+ #
159
166
requirements = directory .joinpath ("requirements" )
167
+
168
+ log .info ("Fetching latest CS Tools release from GitHub" )
160
169
release_info = get_latest_cs_tools_release (allow_beta = beta )
161
170
release_tag = release_info ["tag_name" ]
162
171
163
- venv = cs_tools_venv
172
+ if syncer_dialect is not None :
173
+ syncer_dir = utils .get_package_directory ("cs_tools" ) / "sync" / syncer_dialect
174
+
175
+ if not syncer_dir .exists ():
176
+ log .error (f"Syncer dialect { syncer_dialect } not found" )
177
+ raise typer .Exit (1 )
178
+
179
+ log .info (f"Fetching { syncer_dialect } syncer dependencies.." )
180
+ manifest = base .SyncerManifest .model_validate_json (syncer_dir .joinpath ("MANIFEST.json" ).read_text ())
181
+ manifest .__ensure_pip_requirements__ ()
164
182
165
183
# freeze our own environment, which has all the dependencies needed to build
166
- frozen = {req for req in venv .pip ("freeze" , "--quiet" ).stdout .decode ().split ("\n " ) if "cs_tools" not in req }
184
+ log .info ("Freezing existing virtual environment.." )
185
+ frozen = {
186
+ r
187
+ for r in cs_tools_venv .pip ("freeze" , "--quiet" , visible_output = False ).stdout .decode ().split ("\n " )
188
+ if "cs_tools" not in r
189
+ }
167
190
168
191
# add in the latest release
169
192
frozen .add (f"cs_tools @ https://github.com/thoughtspot/cs_tools/archive/{ release_tag } .zip" )
@@ -183,7 +206,8 @@ def download(
183
206
if "win" in platform :
184
207
frozen .add ("pyreadline3 == 3.4.1" ) # from cs_tools
185
208
186
- venv .pip (
209
+ log .info ("Downloading dependent packages.." )
210
+ cs_tools_venv .pip (
187
211
"download" , * frozen ,
188
212
"--no-deps" , # we shouldn't need transitive dependencies, since we've build all the dependencies above
189
213
"--dest" , requirements .as_posix (),
@@ -199,6 +223,8 @@ def download(
199
223
from cs_tools .updater import _bootstrapper , _updater
200
224
201
225
zip_fp = directory .joinpath (f"cs-tools_{ __version__ } _{ platform } _{ python_version } " )
226
+
227
+ log .info (f"Preparing your download at { zip_fp } .." )
202
228
shutil .copy (_bootstrapper .__file__ , requirements .joinpath ("_bootstrapper.py" ))
203
229
shutil .copy (_updater .__file__ , requirements .joinpath ("_updater.py" ))
204
230
shutil .make_archive (zip_fp .as_posix (), "zip" , requirements )
0 commit comments