Skip to content

Split the analyzer backends into install extras: cldk[java], cldk[typescript], cldk[python] #340

Open

Description

@rahlk

Is your feature request related to a problem? Please describe.

Every pip install cldk installs every analyzer, so a consumer who only reads a Neo4j graph, or only analyzes Python, still pays for the others. With #339 that becomes concrete: the Java analyzer carries a 35 MB bundled JVM (jdk4py), and jdk4py's PyPI metadata declares bare GPLv2 with no license file, so enterprise policy gates flag it for consumers who never analyze Java. (The runtime itself is ordinary OpenJDK, GPLv2 with the Classpath Exception; the friction is metadata, not licensing.)

[project.optional-dependencies] neo4j already declares only the driver, so pip install "cldk[neo4j]" looks like it should be analyzer-free. It is not, because the analyzers are hard dependencies.

Measured on release/2.0:

dependency loaded by import cldk?
codeanalyzer-java no (works uninstalled)
codeanalyzer-typescript declared, not imported at import time
codeanalyzer-python yes, eagerly, 14 modules

Describe the solution you'd like

  • pip install "cldk[neo4j]" installs no analyzer and no JVM; CLDK.python(...)/typescript/java with a Neo4j config still work
  • pip install "cldk[java]" is the only way to get the JVM (delivered by Java backend: depend on the codeanalyzer-java wheel (bundled JVM) instead of a bundled jar plus _jdk.py #339)
  • import cldk works with any subset of the analyzers absent; calling a facade whose analyzer is missing raises naming the distribution and pip install "cldk[<extra>]"
  • The shared artifact/config/span/body models no longer live under cldk/models/python/, and cldk/analysis/commons/ imports nothing from a language package
  • The release workflow and the test groups install the extras the suites need

Describe alternatives you've considered

Not stated in the original issue.

Additional context

The blocker for cldk[python]

The core sources its cross-language vocabulary from the Python analyzer's schema:

  • cldk/models/python/__init__.py:24 re-exports codeanalyzer.schema.py_schema.
  • cldk/analysis/commons/backend.py:60 imports PyArtifact, PyConfigKey, PyConfigRead, PyConfigUseEdge, PyDependency from it — the return types the generic AnalysisBackend promises for every language.
  • cldk/analysis/commons/results.py:55 imports Span and BodyNode from it.

So codeanalyzer-python is a dependency of the core, not of the Python backend. The artifact/config/span/body types are shared by design (leg 1 D2 chose per-language models but a shared artifact layer); they are simply living in the wrong package, and their Py prefix now misnames them.

Scope boundary

In scope: java and typescript extras with lazy imports and an error that names the missing distribution and its install extra; relocating the shared artifact/span/body models out of cldk/models/python/ into a language-neutral home so codeanalyzer-python can become the python extra; keeping cldk[neo4j] analyzer-free; an all extra.

Out of scope: renaming the shared types on the public surface (PyArtifact and friends are returned by existing accessors, so a rename is a separate, sanctioned break). Whether the bare cldk install keeps any analyzer at all is the decision this issue exists to make.

Caveats and known risks

  • Breaking for anyone relying on pip install cldk then CLDK.python(...). 2.0 is the release that can carry it; it needs a CHANGELOG entry with the one-line migration per language.
  • Relocating the shared models moves types that appear in public return values. Keep the class identities and re-export from the old paths, or it stops being a packaging change and becomes an API break.
  • codeanalyzer-python is also the source of AnalysisLevel-adjacent schema helpers used by the Python Neo4j backend; check every import before declaring the core clean.

Definition of done

  • A fresh venv per extra combination (cldk, cldk[neo4j], cldk[java], cldk[python], cldk[all]) imports cleanly, and pip list shows no analyzer the combination did not ask for
  • grep -rn "codeanalyzer" cldk/analysis/commons cldk/models/commons is empty
  • Each facade's missing-analyzer error is asserted by a test, with the extra named in the message
  • Full suite green with the extras installed; the release workflow installs them

Activity

  1. rahlk commented on Sep 6, 2026

    @rahlk
    CollaboratorAuthor

    Decision, 2026-09-06: thin base plus additive extras, with cldk[all] as the everything install.

    This settles the open question in the scope boundary above. The reasoning is that extras are purely additive under PEP 508, so pip install "cldk[neo4j]" can never subtract what the base requires. A fat base and a JVM-free Neo4j install are mutually exclusive; only a thin base delivers the second.

    Target contract:

    command installs
    pip install cldk facade and models only
    pip install "cldk[neo4j]" plus the Neo4j driver, no analyzer and no JVM
    pip install "cldk[python]" plus codeanalyzer-python
    pip install "cldk[typescript]" plus codeanalyzer-typescript
    pip install "cldk[java]" plus codeanalyzer-java, which carries the jar and jdk4py
    pip install "cldk[all]" everything

    Landing in two steps. #339 adds the java and all extras now (all = ["cldk[java]", "cldk[neo4j]"], a self-referential spelling so this issue only has to append to it), with a lazy import and an error that names the distribution and the install extra. This issue then moves codeanalyzer-typescript and codeanalyzer-python into extras, which for Python requires relocating the shared artifact, config, span and body-node models out of cldk/models/python/ first, as described above.

    Breaking for anyone who does pip install cldk and then calls a facade. The migration is one line per language, and cldk[all] reproduces today's behaviour exactly, so the CHANGELOG should lead with that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions