fargopy 0.4.0__py3-none-any.whl → 1.0.1__py3-none-any.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.
- fargopy/__init__.py +8 -346
- fargopy/base.py +377 -0
- fargopy/bin/ifargopy +91 -0
- fargopy/bin/vfargopy +2111 -0
- fargopy/data/fargopy_logo.png +0 -0
- fargopy/fields.py +1400 -415
- fargopy/flux.py +809 -723
- fargopy/plot.py +553 -8
- fargopy/simulation.py +1548 -577
- fargopy/sys.py +116 -65
- fargopy/tests/test_base.py +8 -0
- fargopy/tests/test_flux.py +76 -0
- fargopy/tests/test_interp.py +132 -0
- fargopy-1.0.1.data/scripts/ifargopy +91 -0
- fargopy-1.0.1.data/scripts/vfargopy +2111 -0
- fargopy-1.0.1.dist-info/METADATA +450 -0
- fargopy-1.0.1.dist-info/RECORD +21 -0
- {fargopy-0.4.0.dist-info → fargopy-1.0.1.dist-info}/WHEEL +1 -1
- fargopy-1.0.1.dist-info/licenses/LICENSE +661 -0
- fargopy/fsimulation.py +0 -429
- fargopy/tests/test___init__.py +0 -0
- fargopy/util.py +0 -21
- fargopy/version.py +0 -1
- fargopy-0.4.0.data/scripts/ifargopy +0 -15
- fargopy-0.4.0.dist-info/METADATA +0 -492
- fargopy-0.4.0.dist-info/RECORD +0 -17
- fargopy-0.4.0.dist-info/licenses/LICENSE +0 -21
- {fargopy-0.4.0.dist-info → fargopy-1.0.1.dist-info}/entry_points.txt +0 -0
- {fargopy-0.4.0.dist-info → fargopy-1.0.1.dist-info}/top_level.txt +0 -0
fargopy/base.py
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
###############################################################
|
|
2
|
+
# Package documentation
|
|
3
|
+
###############################################################
|
|
4
|
+
"""
|
|
5
|
+
FARGOpy Base Module
|
|
6
|
+
===================
|
|
7
|
+
|
|
8
|
+
This module contains the base classes, configuration, and initialization logic for FARGOpy.
|
|
9
|
+
It is separated from __init__.py to avoid circular import issues with other modules like sys.py.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import warnings
|
|
13
|
+
import os
|
|
14
|
+
import json
|
|
15
|
+
import sys
|
|
16
|
+
import numpy as np
|
|
17
|
+
|
|
18
|
+
# Version
|
|
19
|
+
__version__ = '1.0.1'
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"__version__",
|
|
23
|
+
"Debug",
|
|
24
|
+
"Dictobj",
|
|
25
|
+
"Fargobj",
|
|
26
|
+
"Conf",
|
|
27
|
+
"initialize",
|
|
28
|
+
"DEG",
|
|
29
|
+
"RAD",
|
|
30
|
+
"IN_COLAB",
|
|
31
|
+
"_welcome",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
###############################################################
|
|
35
|
+
# Constants
|
|
36
|
+
###############################################################
|
|
37
|
+
DEG = np.pi / 180
|
|
38
|
+
RAD = 1 / DEG
|
|
39
|
+
|
|
40
|
+
# Check if we are in colab
|
|
41
|
+
IN_COLAB = "google.colab" in sys.modules
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
###############################################################
|
|
45
|
+
# Base classes
|
|
46
|
+
###############################################################
|
|
47
|
+
class Debug(object):
|
|
48
|
+
"""The Debug class controls the debugging messages of the package.
|
|
49
|
+
|
|
50
|
+
Attributes
|
|
51
|
+
----------
|
|
52
|
+
VERBOSE : bool
|
|
53
|
+
If True all the trace messages are shown. Default is False.
|
|
54
|
+
|
|
55
|
+
Methods
|
|
56
|
+
-------
|
|
57
|
+
trace(msg)
|
|
58
|
+
Show a debugging message if VERBOSE=True.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
VERBOSE = False
|
|
62
|
+
|
|
63
|
+
@staticmethod
|
|
64
|
+
def trace(msg):
|
|
65
|
+
if Debug.VERBOSE:
|
|
66
|
+
print("::" + msg)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class Dictobj(object):
|
|
70
|
+
"""Convert a dictionary to an object
|
|
71
|
+
|
|
72
|
+
Initialization attributes:
|
|
73
|
+
dict: dictionary:
|
|
74
|
+
Dictionary containing the attributes.
|
|
75
|
+
|
|
76
|
+
Attributes:
|
|
77
|
+
All the keys in the initialization dictionary.
|
|
78
|
+
|
|
79
|
+
Methods:
|
|
80
|
+
keys():
|
|
81
|
+
It works like the keys() method of a dictionary.
|
|
82
|
+
item(key):
|
|
83
|
+
Recover the value of an attribute as it was a dictionary.
|
|
84
|
+
print_keys():
|
|
85
|
+
Print a list of keys
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
def __init__(self, **kwargs):
|
|
89
|
+
if "dict" in kwargs.keys():
|
|
90
|
+
kwargs.update(kwargs["dict"])
|
|
91
|
+
for key, value in kwargs.items():
|
|
92
|
+
if key == "dict":
|
|
93
|
+
continue
|
|
94
|
+
setattr(self, key, value)
|
|
95
|
+
|
|
96
|
+
def __getitem__(self, key):
|
|
97
|
+
return self.item(str(key))
|
|
98
|
+
|
|
99
|
+
def keys(self):
|
|
100
|
+
"""Show the list of attributes of Dictobj"""
|
|
101
|
+
props = []
|
|
102
|
+
for i, prop in enumerate(self.__dict__.keys()):
|
|
103
|
+
if "__" in prop:
|
|
104
|
+
continue
|
|
105
|
+
props += [prop]
|
|
106
|
+
return props
|
|
107
|
+
|
|
108
|
+
def item(self, key):
|
|
109
|
+
"""Get the value of an item of a Dictobj."""
|
|
110
|
+
if key not in self.keys():
|
|
111
|
+
raise ValueError(f"Key 'key' not in Dictobj")
|
|
112
|
+
return self.__dict__[key]
|
|
113
|
+
|
|
114
|
+
def __getitem__(self, key):
|
|
115
|
+
return self.item(str(key))
|
|
116
|
+
|
|
117
|
+
def print_keys(self):
|
|
118
|
+
"""Print all the keys of a Dictobj."""
|
|
119
|
+
prop_list = ""
|
|
120
|
+
for i, prop in enumerate(self.keys()):
|
|
121
|
+
prop_list += f"{prop}, "
|
|
122
|
+
if ((i + 1) % 10) == 0:
|
|
123
|
+
prop_list += "\n"
|
|
124
|
+
print(prop_list.strip(", "))
|
|
125
|
+
|
|
126
|
+
def __str__(self):
|
|
127
|
+
return str(self.__dict__)
|
|
128
|
+
|
|
129
|
+
def __repr__(self):
|
|
130
|
+
return self.__str__()
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class Fargobj(object):
|
|
134
|
+
def __init__(self, **kwargs):
|
|
135
|
+
self.fobject = True
|
|
136
|
+
self.kwargs = kwargs
|
|
137
|
+
|
|
138
|
+
def save_object(self, filename=None, verbose=False):
|
|
139
|
+
"""Save Fargobj into a filename in JSON format"""
|
|
140
|
+
if filename is None:
|
|
141
|
+
object_hash = str(abs(hash(str(self.__dict__))))
|
|
142
|
+
filename = f"/tmp/fargobj_{object_hash}.json"
|
|
143
|
+
if verbose:
|
|
144
|
+
print(f"Saving object to {filename}...")
|
|
145
|
+
with open(filename, "w") as file_object:
|
|
146
|
+
file_object.write(
|
|
147
|
+
json.dumps(self.__dict__, default=lambda obj: "<not serializable>")
|
|
148
|
+
)
|
|
149
|
+
file_object.close()
|
|
150
|
+
|
|
151
|
+
def set_property(self, property, default, method=lambda prop: prop):
|
|
152
|
+
"""Set a property of object using a given method"""
|
|
153
|
+
if property in self.kwargs.keys():
|
|
154
|
+
method(self.kwargs[property])
|
|
155
|
+
self.__dict__[property] = self.kwargs[property]
|
|
156
|
+
return True
|
|
157
|
+
else:
|
|
158
|
+
method(default)
|
|
159
|
+
self.__dict__[property] = default
|
|
160
|
+
return False
|
|
161
|
+
|
|
162
|
+
def has(self, key):
|
|
163
|
+
"""Check if a key is an attribute of Fargobj object"""
|
|
164
|
+
if key in self.__dict__.keys():
|
|
165
|
+
return True
|
|
166
|
+
else:
|
|
167
|
+
return False
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
###############################################################
|
|
171
|
+
# Package configuration
|
|
172
|
+
###############################################################
|
|
173
|
+
# Basic (unmodifiable) variables
|
|
174
|
+
Conf = Dictobj()
|
|
175
|
+
|
|
176
|
+
# Cross-platform home directory detection
|
|
177
|
+
if os.name == "nt": # Windows
|
|
178
|
+
Conf.FP_HOME = os.environ.get("USERPROFILE", os.path.expanduser("~"))
|
|
179
|
+
else: # Unix-like systems (Linux, macOS)
|
|
180
|
+
Conf.FP_HOME = os.environ.get("HOME", os.path.expanduser("~"))
|
|
181
|
+
|
|
182
|
+
Conf.FP_DOTDIR = os.path.join(Conf.FP_HOME, ".fargopy")
|
|
183
|
+
Conf.FP_RCFILE = os.path.join(Conf.FP_DOTDIR, "fargopyrc")
|
|
184
|
+
|
|
185
|
+
# Default configuration file content
|
|
186
|
+
Conf.FP_CONFIGURATION = f"""# This is the configuration variables for FARGOpy
|
|
187
|
+
# Package
|
|
188
|
+
FP_VERSION = '{__version__}'
|
|
189
|
+
# System
|
|
190
|
+
FP_HOME = '{Conf.FP_HOME}/'
|
|
191
|
+
# Directories
|
|
192
|
+
FP_DOTDIR = '{Conf.FP_DOTDIR}'
|
|
193
|
+
FP_RCFILE = '{Conf.FP_RCFILE}'
|
|
194
|
+
# Behavior
|
|
195
|
+
FP_VERBOSE = False
|
|
196
|
+
# FARGO3D variables
|
|
197
|
+
FP_FARGO3D_CLONECMD = 'GIT_TERMINAL_PROMPT=0 git clone https://bitbucket.org/fargo3d/public.git'
|
|
198
|
+
FP_FARGO3D_BASEDIR = '{Conf.FP_HOME}'
|
|
199
|
+
FP_FARGO3D_PACKDIR = 'fargo3d/'
|
|
200
|
+
FP_FARGO3D_BINARY = 'fargo3d'
|
|
201
|
+
FP_FARGO3D_HEADER = 'src/fargo3d.h'
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
# Default initialization script
|
|
205
|
+
Conf.FP_INITIAL_SCRIPT = """
|
|
206
|
+
import sys
|
|
207
|
+
import fargopy as fp
|
|
208
|
+
get_ipython().run_line_magic('load_ext','autoreload')
|
|
209
|
+
get_ipython().run_line_magic('autoreload','2')
|
|
210
|
+
fp.initialize(' '.join(sys.argv))
|
|
211
|
+
"""
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def initialize(options="", force=False, **kwargs):
|
|
215
|
+
"""Initialization routine
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
options: string, default = '':
|
|
219
|
+
Action(s) to be performed. Valid actions include:
|
|
220
|
+
'configure': configure the package.
|
|
221
|
+
'download': download FARGO3D directory.
|
|
222
|
+
'check': attempt to compile FARGO3D in the machine.
|
|
223
|
+
'all': all actions.
|
|
224
|
+
|
|
225
|
+
force: bool, default = False:
|
|
226
|
+
If True, force any action that depends on a previous condition.
|
|
227
|
+
For instance if options = 'configure' and force = True it will
|
|
228
|
+
override FARGOpy directory.
|
|
229
|
+
"""
|
|
230
|
+
|
|
231
|
+
# Import fargopy inside the function to avoid circular imports
|
|
232
|
+
# when accessing fargopy.Sys or other components that might rely on base.py
|
|
233
|
+
import fargopy
|
|
234
|
+
|
|
235
|
+
if ("configure" in options) or ("all" in options):
|
|
236
|
+
# Create configuration directory
|
|
237
|
+
if not os.path.isdir(Conf.FP_DOTDIR) or force:
|
|
238
|
+
Debug.trace(f"Configuring FARGOpy at {Conf.FP_DOTDIR}...")
|
|
239
|
+
# Create directory
|
|
240
|
+
os.system(f"mkdir -p {Conf.FP_DOTDIR}")
|
|
241
|
+
# Create configuration variables
|
|
242
|
+
f = open(f"{Conf.FP_DOTDIR}/fargopyrc", "w")
|
|
243
|
+
f.write(Conf.FP_CONFIGURATION)
|
|
244
|
+
f.close()
|
|
245
|
+
# Create initialization script
|
|
246
|
+
f = open(f"{Conf.FP_DOTDIR}/ifargopy.py", "w")
|
|
247
|
+
f.write(Conf.FP_INITIAL_SCRIPT)
|
|
248
|
+
f.close()
|
|
249
|
+
else:
|
|
250
|
+
Debug.trace(f"Configuration already in place.")
|
|
251
|
+
|
|
252
|
+
if ("download" in options) or ("all" in options):
|
|
253
|
+
fargo_dir = f"{Conf.FP_FARGO3D_BASEDIR}/{Conf.FP_FARGO3D_PACKDIR}".replace(
|
|
254
|
+
"//", "/"
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
print("Downloading FARGOpy...")
|
|
258
|
+
if not os.path.isdir(fargo_dir) or force:
|
|
259
|
+
if os.path.isdir(fargo_dir):
|
|
260
|
+
print(f"Directory '{fargo_dir}' already exists. Removing it...")
|
|
261
|
+
os.system(f"rm -rf {fargo_dir}")
|
|
262
|
+
# Ensure GIT_TERMINAL_PROMPT=0 is set to avoid stalling if authentication is requested
|
|
263
|
+
clone_cmd = Conf.FP_FARGO3D_CLONECMD
|
|
264
|
+
if "GIT_TERMINAL_PROMPT" not in clone_cmd:
|
|
265
|
+
clone_cmd = "GIT_TERMINAL_PROMPT=0 " + clone_cmd
|
|
266
|
+
|
|
267
|
+
fargopy.Sys.simple(
|
|
268
|
+
f"cd {Conf.FP_FARGO3D_BASEDIR} && {clone_cmd} {Conf.FP_FARGO3D_PACKDIR}"
|
|
269
|
+
)
|
|
270
|
+
print(f"\tFARGO3D downloaded to {fargo_dir}")
|
|
271
|
+
else:
|
|
272
|
+
print(f"\tFARGO3D directory already present in '{fargo_dir}'")
|
|
273
|
+
|
|
274
|
+
fargo_header = f"{fargo_dir}/{Conf.FP_FARGO3D_HEADER}"
|
|
275
|
+
if not os.path.isfile(fargo_header):
|
|
276
|
+
print(f"No header file for fargo found in '{fargo_header}'")
|
|
277
|
+
else:
|
|
278
|
+
print(f"Header file for FARGO3D found in the fargo directory {fargo_dir}")
|
|
279
|
+
|
|
280
|
+
if ("check" in options) or ("all" in options):
|
|
281
|
+
fargo_dir = f"{Conf.FP_FARGO3D_BASEDIR}/{Conf.FP_FARGO3D_PACKDIR}".replace(
|
|
282
|
+
"//", "/"
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
print("Test compilation of FARGO3D")
|
|
286
|
+
if not os.path.isdir(fargo_dir):
|
|
287
|
+
print(
|
|
288
|
+
f"Directory '{fargo_dir}' does not exist. Please download it with fargopy.initialize('download')"
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
cmd_fun = lambda options, mode: (
|
|
292
|
+
f"make -C {fargo_dir} clean mrproper all {options} 2>&1 |tee /tmp/fargo_{mode}.log"
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
for option, mode in zip(
|
|
296
|
+
["PARALLEL=0 GPU=0", "PARALLEL=0 GPU=1", "PARALLEL=1 GPU=0"],
|
|
297
|
+
["regular", "gpu", "parallel"],
|
|
298
|
+
):
|
|
299
|
+
# Verify if you want to check this mode
|
|
300
|
+
if (mode in kwargs.keys()) and (kwargs[mode] == 0):
|
|
301
|
+
print(f"\tSkipping {mode} compilation")
|
|
302
|
+
exec(f"Conf.FP_FARGO3D_{mode.upper()} = 0")
|
|
303
|
+
continue
|
|
304
|
+
|
|
305
|
+
cmd = cmd_fun(option, mode)
|
|
306
|
+
print(f"\tChecking normal compilation.\n\tRunning '{cmd}':")
|
|
307
|
+
# fargopy.Sys is used here
|
|
308
|
+
error, output = fargopy.Sys.run(cmd)
|
|
309
|
+
if not os.path.isfile(f"{fargo_dir}/{Conf.FP_FARGO3D_BINARY}"):
|
|
310
|
+
print(
|
|
311
|
+
f"\t\tCompilation failed for '{mode}'. Check log file '/tmp/fargo_{mode}.log'"
|
|
312
|
+
)
|
|
313
|
+
exec(f"Conf.FP_FARGO3D_{mode.upper()} = 0")
|
|
314
|
+
else:
|
|
315
|
+
print(f"\t\tCompilation in mode {mode} successful.")
|
|
316
|
+
exec(f"Conf.FP_FARGO3D_{mode.upper()} = 1")
|
|
317
|
+
|
|
318
|
+
print(f"Summary of compilation modes:")
|
|
319
|
+
print(f"\tRegular: {Conf.FP_FARGO3D_REGULAR}")
|
|
320
|
+
print(f"\tGPU: {Conf.FP_FARGO3D_GPU}")
|
|
321
|
+
print(f"\tParallel: {Conf.FP_FARGO3D_PARALLEL}")
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
# Showing version
|
|
325
|
+
def _welcome():
|
|
326
|
+
"""Welcome message"""
|
|
327
|
+
print(f"Running FARGOpy version {__version__}")
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
###############################################################
|
|
331
|
+
# Initialization logic (moved from __init__.py)
|
|
332
|
+
###############################################################
|
|
333
|
+
# Avoid warnings
|
|
334
|
+
warnings.filterwarnings("ignore")
|
|
335
|
+
|
|
336
|
+
# Read FARGOpy configuration variables
|
|
337
|
+
if not os.path.isdir(Conf.FP_DOTDIR):
|
|
338
|
+
print(f"Configuring FARGOpy for the first time")
|
|
339
|
+
initialize("configure")
|
|
340
|
+
Debug.trace(f"::Reading configuration variables")
|
|
341
|
+
|
|
342
|
+
# Load configuration variables into Conf
|
|
343
|
+
conf_dict = dict()
|
|
344
|
+
if os.path.isfile(Conf.FP_RCFILE):
|
|
345
|
+
exec(open(f"{Conf.FP_RCFILE}").read(), dict(), conf_dict)
|
|
346
|
+
Conf.__dict__.update(conf_dict)
|
|
347
|
+
|
|
348
|
+
# Derivative configuration variables
|
|
349
|
+
Debug.VERBOSE = Conf.FP_VERBOSE
|
|
350
|
+
Conf.FP_FARGO3D_DIR = (Conf.FP_FARGO3D_BASEDIR + "/" + Conf.FP_FARGO3D_PACKDIR).replace(
|
|
351
|
+
"//", "/"
|
|
352
|
+
)
|
|
353
|
+
Conf.FP_FARGO3D_LOCKFILE = f"{Conf.FP_DOTDIR}/fargopy.lock"
|
|
354
|
+
|
|
355
|
+
# Check if version in RCFILE is different from installed FARGOpy version
|
|
356
|
+
if Conf.FP_VERSION != __version__:
|
|
357
|
+
print(
|
|
358
|
+
f"Your configuration file version '{Conf.FP_VERSION}' it is different than the installed version of FARGOpy '{__version__}'"
|
|
359
|
+
)
|
|
360
|
+
# Interactive check only if stream is a TTY? Or just skip if not?
|
|
361
|
+
# Original code asks for input. This might be blocking in some envs.
|
|
362
|
+
# We'll keep it as is, but rely on it not triggering often in CI/tests if version matches.
|
|
363
|
+
# However, since I'm creating a new file, I'll assume users might encounter this.
|
|
364
|
+
try:
|
|
365
|
+
# Check if sys.stdin has interactive capabilities
|
|
366
|
+
if sys.stdin.isatty():
|
|
367
|
+
ans = input(
|
|
368
|
+
f"Do you want to update configuration file '{Conf.FP_RCFILE}'? [Y/n]: "
|
|
369
|
+
)
|
|
370
|
+
if ans and ("Y" not in ans.upper()):
|
|
371
|
+
if "N" in ans.upper():
|
|
372
|
+
print("We will keeping asking you this until you update it, sorry!")
|
|
373
|
+
else:
|
|
374
|
+
os.system(f"cp -rf {Conf.FP_RCFILE} {Conf.FP_RCFILE}.save")
|
|
375
|
+
initialize("configure", force=True)
|
|
376
|
+
except Exception:
|
|
377
|
+
pass
|
fargopy/bin/ifargopy
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import sys
|
|
3
|
+
import os
|
|
4
|
+
import subprocess
|
|
5
|
+
import argparse
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_version():
|
|
9
|
+
try:
|
|
10
|
+
try:
|
|
11
|
+
from importlib.metadata import version
|
|
12
|
+
return version("fargopy")
|
|
13
|
+
except ImportError:
|
|
14
|
+
# Fallback for Python < 3.8
|
|
15
|
+
import pkg_resources
|
|
16
|
+
return pkg_resources.get_distribution("fargopy").version
|
|
17
|
+
except Exception:
|
|
18
|
+
# Fallback if package not installed or in development
|
|
19
|
+
try:
|
|
20
|
+
import fargopy.version
|
|
21
|
+
return fargopy.version.version
|
|
22
|
+
except ImportError:
|
|
23
|
+
return "unknown"
|
|
24
|
+
|
|
25
|
+
def run_verify():
|
|
26
|
+
try:
|
|
27
|
+
import fargopy
|
|
28
|
+
v = get_version()
|
|
29
|
+
print(f"fargopy {v} is successfully installed.")
|
|
30
|
+
print(f"Location: {os.path.dirname(fargopy.__file__)}")
|
|
31
|
+
except ImportError:
|
|
32
|
+
print("Error: fargopy is not installed or cannot be imported.")
|
|
33
|
+
sys.exit(1)
|
|
34
|
+
|
|
35
|
+
def run_tests():
|
|
36
|
+
try:
|
|
37
|
+
import fargopy
|
|
38
|
+
package_dir = os.path.dirname(fargopy.__file__)
|
|
39
|
+
test_dir = os.path.join(package_dir, 'tests')
|
|
40
|
+
if not os.path.exists(test_dir):
|
|
41
|
+
print(f"Error: tests directory not found at {test_dir}")
|
|
42
|
+
sys.exit(1)
|
|
43
|
+
|
|
44
|
+
print(f"Running tests in {test_dir}...")
|
|
45
|
+
subprocess.check_call([sys.executable, "-m", "pytest", test_dir])
|
|
46
|
+
except ImportError:
|
|
47
|
+
print("Error: fargopy is not installed.")
|
|
48
|
+
sys.exit(1)
|
|
49
|
+
except subprocess.CalledProcessError as e:
|
|
50
|
+
sys.exit(e.returncode)
|
|
51
|
+
|
|
52
|
+
def main():
|
|
53
|
+
parser = argparse.ArgumentParser(description="fargopy interactive shell and utilities")
|
|
54
|
+
parser.add_argument("--verify", action="store_true", help="Verify installation and show version")
|
|
55
|
+
parser.add_argument("--test", action="store_true", help="Run the distributed tests")
|
|
56
|
+
|
|
57
|
+
# If no arguments are provided, or just unknown args (which arguably should be passed to ipython?
|
|
58
|
+
# but for now let's stick to the requested logic: optional args for cmd, else launch ipython)
|
|
59
|
+
# The issue is that argparse will parse all args. If the user wants to pass args to ipython, this might conflict.
|
|
60
|
+
# However, standard pattern is usually wrapper handles its flags, pass others.
|
|
61
|
+
# But ifargopy historically just wraps ipython.
|
|
62
|
+
|
|
63
|
+
# Let's check if we have specific flags.
|
|
64
|
+
if "--verify" in sys.argv:
|
|
65
|
+
run_verify()
|
|
66
|
+
return
|
|
67
|
+
if "--test" in sys.argv:
|
|
68
|
+
run_tests()
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
# Original behavior: launch IPython
|
|
72
|
+
user_home = os.path.expanduser("~")
|
|
73
|
+
fp_dotdir = os.path.join(user_home, ".fargopy")
|
|
74
|
+
|
|
75
|
+
if not os.path.isdir(fp_dotdir):
|
|
76
|
+
# First time initialization logic
|
|
77
|
+
init_script = "/tmp/ifargopy_initialize.py"
|
|
78
|
+
with open(init_script, "w") as f:
|
|
79
|
+
f.write("import fargopy as fp\n")
|
|
80
|
+
f.write("fp.initialize('configure')\n")
|
|
81
|
+
f.write("print('We have configured fargopy for the first time. Run it again.')\n")
|
|
82
|
+
|
|
83
|
+
subprocess.call(["ipython", "-i", init_script])
|
|
84
|
+
else:
|
|
85
|
+
startup_script = os.path.join(fp_dotdir, "ifargopy.py")
|
|
86
|
+
# Pass all arguments to ipython except the script name itself
|
|
87
|
+
cmd = ["ipython", "-i", startup_script] + sys.argv[1:]
|
|
88
|
+
subprocess.call(cmd)
|
|
89
|
+
|
|
90
|
+
if __name__ == "__main__":
|
|
91
|
+
main()
|