Skip to content

Commit 965f04d

Browse files
ctruedenclaude
andcommitted
Unify endpoint handling around list[Dependency]
The resolver API, POM generation, environment builder, and CLI commands all previously operated on parallel lists of Components and Coordinates, with BOM management controlled via separate managed/boms parameters and a _current_boms side-channel on the builder. This made it impossible to preserve classifier, packaging, and scope through the pipeline, and split the "is this dependency raw?" concern across multiple call sites. Now Dependency is the primary downstream currency everywhere: - Add raw: bool to Dependency so BOMs can be computed from Dependencies alone (_compute_boms replaces _resolve_boms + filter_managed_components) - Resolver.resolve/get_dependency_list/get_dependency_tree accept list[Dependency] and compute BOMs internally; drop managed/boms params - generate_pom_xml accepts list[Dependency] and emits classifier, type, and scope elements when non-default - EnvironmentBuilder.from_endpoint uses _coordinates_to_dependencies directly instead of routing through from_components - _build_environment accepts list[Dependency]; remove _current_boms - Remove from_components, _parse_endpoint, _components_to_dependencies, filter_managed_components, _resolve_boms, _listify Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 66e1744 commit 965f04d

File tree

16 files changed

+345
-538
lines changed

16 files changed

+345
-538
lines changed

BUGS.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ Add py.typed file to package root for static type analyzers
1313
Use https://github.com/ross/requests-futures
1414
to do asynchronous parallel downloads of Maven artifacts?
1515

16-
Endpoints consist of Components right now -- this is wrong, it needs to be Artifacts/Dependencies -- because you should be able to mix in GACPVs with non-default classifier and/or packaging! (Well, packaging is arguable...)
17-
1816
Remove or repurpose obsolete files in docs/
1917

2018
Decide about remaining `~/.jgorc` references throughout the codebase

docs/migration-example.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@ from jgo.exec import JavaRunner
3030

3131
# Full control over each step
3232
maven = MavenContext()
33-
component = maven.project('org.python', 'jython-standalone').at_version('RELEASE')
34-
3533
builder = EnvironmentBuilder(context=maven)
36-
environment = builder.from_components([component])
34+
environment = builder.from_endpoint("org.python:jython-standalone:RELEASE")
3735

3836
runner = JavaRunner()
3937
result = runner.run(environment)
@@ -379,7 +377,9 @@ def build_analysis_environment():
379377
link_strategy=LinkStrategy.HARD
380378
)
381379

382-
environment = builder.from_components(components)
380+
environment = builder.from_endpoint(
381+
"+".join(f"{c.groupId}:{c.artifactId}:{c.version}" for c in components)
382+
)
383383

384384
return environment
385385

docs/migration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ component = maven.project("org.python", "jython-standalone").at_version("2.7.3")
229229

230230
# Layer 2: Environment materialization
231231
builder = EnvironmentBuilder(context=maven)
232-
env = builder.from_components([component])
232+
env = builder.from_endpoint("org.python:jython-standalone:2.7.3")
233233

234234
# Layer 3: Execution
235235
runner = JavaRunner()

docs/terminology.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ print(env.main_class) # org.python.util.jython
6969

7070
**Methods:**
7171
- `from_endpoint(endpoint: str)` - Build from endpoint string (e.g., "G:A:V")
72-
- `from_components(components: list[Component])` - Build from Component objects
72+
- `from_spec(spec: EnvironmentSpec)` - Build from a jgo.toml specification
7373

7474
**Usage:**
7575
```python

src/jgo/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
>>>
6161
>>> # Layer 2: Environment materialization
6262
>>> builder = EnvironmentBuilder(context=maven, link_strategy=LinkStrategy.HARD)
63-
>>> environment = builder.from_components([component])
63+
>>> environment = builder.from_endpoint("org.python:jython-standalone:2.7.3")
6464
>>>
6565
>>> # Layer 3: Execution
6666
>>> runner = JavaRunner(jvm_config=JVMConfig(max_heap="2G"))

src/jgo/cli/commands/info.py

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111

1212
from ...config import GlobalSettings
1313
from ...env import EnvironmentSpec
14-
from ...env.builder import filter_managed_components
1514
from ...env.jar import parse_manifest, read_raw_manifest
1615
from ...parse.coordinate import Coordinate
16+
from ...parse.endpoint import Endpoint
1717
from ...styles import COORD_HELP_FULL
1818
from ..args import build_parsed_args
1919
from ..console import console_print
@@ -431,28 +431,23 @@ def _print_deps(ctx, endpoint, list_mode: bool):
431431
context = create_maven_context(args, config.to_dict())
432432
builder = create_environment_builder(args, config.to_dict(), context)
433433

434-
# Parse coordinates into components
434+
# Parse coordinates into dependencies
435435
if args.is_spec_mode():
436436
spec_file = args.get_spec_file()
437437
if not spec_file.exists():
438438
_log.error(f"{spec_file} not found")
439439
ctx.exit(1)
440440
spec = EnvironmentSpec.load(spec_file)
441-
components = []
442-
for coord_str in spec.coordinates:
443-
coord = _parse_coord_or_die(ctx, coord_str)
444-
version = coord.version or "RELEASE"
445-
component = context.project(coord.groupId, coord.artifactId).at_version(
446-
version
447-
)
448-
components.append(component)
449-
boms = None # No BOM management for spec mode
441+
coordinates = [
442+
Coordinate.parse(coord_str) for coord_str in spec.coordinates
443+
]
444+
dependencies = builder._coordinates_to_dependencies(coordinates)
450445
else:
451446
if not endpoint:
452447
_log.error("No endpoint specified")
453448
ctx.exit(1)
454-
components, coordinates, _ = builder._parse_endpoint(endpoint)
455-
boms = filter_managed_components(components, coordinates)
449+
parsed = Endpoint.parse(endpoint)
450+
dependencies = builder._coordinates_to_dependencies(parsed.coordinates)
456451

457-
print_dependencies(components, context, boms=boms, list_mode=list_mode)
452+
print_dependencies(dependencies, context, list_mode=list_mode)
458453
ctx.exit(0)

src/jgo/cli/commands/list.py

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
from ...config import GlobalSettings
1111
from ...env import EnvironmentSpec
12-
from ...env.builder import filter_managed_components
1312
from ...parse.coordinate import Coordinate
13+
from ...parse.endpoint import Endpoint
1414
from ..args import build_parsed_args
1515
from ..context import create_environment_builder, create_maven_context
1616
from ..output import print_dependencies
@@ -58,33 +58,25 @@ def execute(args: ParsedArgs, config: dict) -> int:
5858
context = create_maven_context(args, config)
5959
builder = create_environment_builder(args, config, context)
6060

61-
# Parse coordinates into components
61+
# Parse coordinates into dependencies
6262
if args.is_spec_mode():
6363
spec_file = args.get_spec_file()
6464
if not spec_file.exists():
6565
_log.error(f"{spec_file} not found")
6666
return 1
6767
spec = EnvironmentSpec.load(spec_file)
68-
components = []
69-
for coord_str in spec.coordinates:
70-
coord = Coordinate.parse(coord_str)
71-
version = coord.version or "RELEASE"
72-
component = context.project(coord.groupId, coord.artifactId).at_version(
73-
version
74-
)
75-
components.append(component)
76-
boms = None
68+
coordinates = [Coordinate.parse(coord_str) for coord_str in spec.coordinates]
69+
dependencies = builder._coordinates_to_dependencies(coordinates)
7770
else:
7871
if not args.endpoint:
7972
_log.error("No endpoint specified")
8073
return 1
81-
components, coordinates, _ = builder._parse_endpoint(args.endpoint)
82-
boms = filter_managed_components(components, coordinates)
74+
parsed = Endpoint.parse(args.endpoint)
75+
dependencies = builder._coordinates_to_dependencies(parsed.coordinates)
8376

8477
print_dependencies(
85-
components,
78+
dependencies,
8679
context,
87-
boms=boms,
8880
list_mode=True,
8981
direct_only=args.direct_only,
9082
optional_depth=args.get_effective_optional_depth(),

src/jgo/cli/commands/tree.py

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
from ...config import GlobalSettings
1111
from ...env import EnvironmentSpec
12-
from ...env.builder import filter_managed_components
1312
from ...parse.coordinate import Coordinate
13+
from ...parse.endpoint import Endpoint
1414
from ..args import build_parsed_args
1515
from ..context import create_environment_builder, create_maven_context
1616
from ..output import print_dependencies
@@ -56,33 +56,25 @@ def execute(args: ParsedArgs, config: dict) -> int:
5656
context = create_maven_context(args, config)
5757
builder = create_environment_builder(args, config, context)
5858

59-
# Parse coordinates into components
59+
# Parse coordinates into dependencies
6060
if args.is_spec_mode():
6161
spec_file = args.get_spec_file()
6262
if not spec_file.exists():
6363
_log.error(f"{spec_file} not found")
6464
return 1
6565
spec = EnvironmentSpec.load(spec_file)
66-
components = []
67-
for coord_str in spec.coordinates:
68-
coord = Coordinate.parse(coord_str)
69-
version = coord.version or "RELEASE"
70-
component = context.project(coord.groupId, coord.artifactId).at_version(
71-
version
72-
)
73-
components.append(component)
74-
boms = None
66+
coordinates = [Coordinate.parse(coord_str) for coord_str in spec.coordinates]
67+
dependencies = builder._coordinates_to_dependencies(coordinates)
7568
else:
7669
if not args.endpoint:
7770
_log.error("No endpoint specified")
7871
return 1
79-
components, coordinates, _ = builder._parse_endpoint(args.endpoint)
80-
boms = filter_managed_components(components, coordinates)
72+
parsed = Endpoint.parse(args.endpoint)
73+
dependencies = builder._coordinates_to_dependencies(parsed.coordinates)
8174

8275
print_dependencies(
83-
components,
76+
dependencies,
8477
context,
85-
boms=boms,
8678
list_mode=False,
8779
optional_depth=args.get_effective_optional_depth(),
8880
)

src/jgo/cli/output.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
if TYPE_CHECKING:
2525
from ..env import Environment
2626
from ..maven import MavenContext
27-
from ..maven.core import Component
27+
from ..maven.core import Dependency
2828
from .args import ParsedArgs
2929

3030

@@ -175,20 +175,18 @@ def print_main_classes(environment: Environment) -> None:
175175

176176

177177
def print_dependencies(
178-
components: list[Component],
178+
dependencies: list[Dependency],
179179
context: MavenContext,
180-
boms: list[Component] | None = None,
181180
list_mode: bool = False,
182181
direct_only: bool = False,
183182
optional_depth: int = 0,
184183
) -> None:
185184
"""
186-
Print dependencies for the given components.
185+
Print dependencies for the given input dependencies.
187186
188187
Args:
189-
components: List of components to print dependencies for
188+
dependencies: List of input dependencies to print
190189
context: Maven context containing the resolver
191-
boms: List of components to use as managed BOMs (None = none managed)
192190
list_mode: If True, print flat list (like mvn dependency:list).
193191
If False, print tree (like mvn dependency:tree).
194192
direct_only: If True and list_mode is True, show only direct dependencies
@@ -203,9 +201,7 @@ def print_dependencies(
203201

204202
# Get the dependency list
205203
root, deps = context.resolver.get_dependency_list(
206-
components,
207-
managed=bool(boms),
208-
boms=boms,
204+
dependencies,
209205
transitive=not direct_only,
210206
optional_depth=optional_depth,
211207
)
@@ -220,9 +216,7 @@ def print_dependencies(
220216

221217
# Get the dependency tree
222218
tree = context.resolver.get_dependency_tree(
223-
components,
224-
managed=bool(boms),
225-
boms=boms,
219+
dependencies,
226220
optional_depth=optional_depth,
227221
)
228222

0 commit comments

Comments
 (0)