Skip to content

Commit 8dd9467

Browse files
authored
add update() function (#60)
* feat: add update() function to update Julia dependencies * revert not removing manifest.toml * update registries when force=True * more reverts --------- Co-authored-by: Christopher Doris <github.com/cjdoris>
1 parent 7dad053 commit 8dd9467

File tree

5 files changed

+85
-29
lines changed

5 files changed

+85
-29
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
## Unreleased
44
* Support editable dependencies from setuptools (experimental).
5-
* Better input validation.
5+
* Add `update()` function.
6+
* Improved input validation.
67

78
## v0.1.17 (2025-05-13)
89
* Respect `JULIAUP_DEPOT_PATH` when searching for Julia using juliaup.

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ Julia v1.*.* and the Example package v0.5.*:
5959

6060
- `juliapkg.executable()` returns a compatible Julia executable.
6161
- `juliapkg.project()` returns the project into which the packages have been installed.
62-
- `juliapkg.resolve(force=False)` ensures all the dependencies are installed. You don't
62+
- `juliapkg.resolve(force=False, dry_run=False)` ensures all the dependencies are installed. You don't
6363
normally need to do this because the other functions resolve automatically.
64+
- `juliapkg.update(dry_run=False)` updates the dependencies.
6465

6566
## Details
6667

src/juliapkg/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
resolve,
99
rm,
1010
status,
11+
update,
1112
)
1213

1314
__all__ = [
@@ -20,4 +21,5 @@
2021
"add",
2122
"rm",
2223
"offline",
24+
"update",
2325
]

src/juliapkg/deps.py

Lines changed: 72 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from .compat import Compat, Version
1212
from .find_julia import find_julia, julia_version
13-
from .install_julia import log
13+
from .install_julia import log, log_script
1414
from .state import STATE
1515

1616
logger = logging.getLogger("juliapkg")
@@ -363,10 +363,25 @@ def merge_any(dep, kfvs, k):
363363
return compat, deps
364364

365365

366-
def resolve(force=False, dry_run=False):
366+
def resolve(force=False, dry_run=False, update=False):
367+
"""
368+
Resolve the dependencies.
369+
370+
Args:
371+
force (bool): Force resolution.
372+
dry_run (bool): Dry run.
373+
update (bool): Update the dependencies.
374+
375+
Returns:
376+
bool: Whether the dependencies are resolved (always True unless dry_run is
377+
True).
378+
"""
379+
# update implies force
380+
if update:
381+
force = True
367382
# fast check to see if we have already resolved
368383
if (not force) and STATE["resolved"]:
369-
return False
384+
return True
370385
STATE["resolved"] = False
371386
# use a lock to prevent concurrent resolution
372387
project = STATE["project"]
@@ -413,9 +428,7 @@ def resolve(force=False, dry_run=False):
413428
projtoml.extend(
414429
f'{pkg.name} = "{pkg.version}"' for pkg in pkgs if pkg.version
415430
)
416-
log("Writing Project.toml:")
417-
for line in projtoml:
418-
log(" ", line, cont=True)
431+
log_script(projtoml, "Writing Project.toml:")
419432
with open(os.path.join(project, "Project.toml"), "wt") as fp:
420433
for line in projtoml:
421434
print(line, file=fp)
@@ -437,28 +450,13 @@ def resolve(force=False, dry_run=False):
437450
for pkg in add_pkgs:
438451
script.append(f" {pkg.jlstr()},")
439452
script.append("])")
440-
script.append("Pkg.resolve()")
453+
if update:
454+
script.append("Pkg.update()")
455+
else:
456+
script.append("Pkg.resolve()")
441457
script.append("Pkg.precompile()")
442-
log("Installing packages:")
443-
for line in script:
444-
log(" ", line, cont=True)
445-
env = os.environ.copy()
446-
if sys.executable:
447-
# prefer PythonCall to use the current Python executable
448-
# TODO: this is a hack, it would be better for PythonCall to detect that
449-
# Julia is being called from Python
450-
env.setdefault("JULIA_PYTHONCALL_EXE", sys.executable)
451-
run(
452-
[
453-
exe,
454-
"--project=" + project,
455-
"--startup-file=no",
456-
"-e",
457-
"\n".join(script),
458-
],
459-
check=True,
460-
env=env,
461-
)
458+
log_script(script, "Installing packages:")
459+
run_julia(script, executable=exe, project=project)
462460
# record that we resolved
463461
save_meta(
464462
{
@@ -486,6 +484,39 @@ def resolve(force=False, dry_run=False):
486484
lock.release()
487485

488486

487+
def run_julia(script, executable=None, project=None):
488+
"""
489+
Run a Julia script with the specified executable and project.
490+
491+
Args:
492+
executable (str): Path to the Julia executable.
493+
project (str): Path to the Julia project.
494+
script (list): List of strings representing the Julia script to run.
495+
"""
496+
if executable is None:
497+
executable = STATE["executable"]
498+
if project is None:
499+
project = STATE["project"]
500+
501+
env = os.environ.copy()
502+
if sys.executable:
503+
# prefer PythonCall to use the current Python executable
504+
# TODO: this is a hack, it would be better for PythonCall to detect that
505+
# Julia is being called from Python
506+
env.setdefault("JULIA_PYTHONCALL_EXE", sys.executable)
507+
run(
508+
[
509+
executable,
510+
"--project=" + project,
511+
"--startup-file=no",
512+
"-e",
513+
"\n".join(script),
514+
],
515+
check=True,
516+
env=env,
517+
)
518+
519+
489520
def executable():
490521
resolve()
491522
return STATE["executable"]
@@ -496,6 +527,20 @@ def project():
496527
return STATE["project"]
497528

498529

530+
def update(dry_run=False):
531+
"""
532+
Resolve and update the dependencies.
533+
534+
Args:
535+
dry_run (bool): Dry run.
536+
537+
Returns:
538+
bool: Whether the dependencies were updated (always True unless dry_run is
539+
True).
540+
"""
541+
return resolve(dry_run=dry_run, update=True)
542+
543+
499544
def cur_deps_file(target=None):
500545
if target is None:
501546
return STATE["deps"]

src/juliapkg/install_julia.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ def log(*args, cont=False):
2424
print(prefix, *args)
2525

2626

27+
def log_script(script, title=None):
28+
if title is not None:
29+
log(title)
30+
for line in script:
31+
log("|", line, cont=True)
32+
33+
2734
def all_julia_versions():
2835
global _all_julia_versions
2936
if _all_julia_versions is None:

0 commit comments

Comments
 (0)