tweag / FawltyDeps

Python dependency checker
Other
201 stars 14 forks source link

Determine and document the _minimum_ Python language version supported by FawltyDeps #460

Open jherland opened 1 month ago

jherland commented 1 month ago

Even though FawltyDeps now needs Python >=v3.8 to run (after https://github.com/tweag/FawltyDeps/pull/459 is merged), we pride ourselves on FawltyDeps being able to analyze projects that are stuck on older Python versions.

However, I don't think we've ever clearly stated what is the minimum Python version that we support analyzing. AFAICS these are the aspects of a project that is likely to determine what minimum version we support:

  1. Python syntax: The syntax of the Python language changes from one version to the next, and in order to be able to extract imports (and dependencies from setup.py files), we need to be able to parse the Python syntax used in the project being analyzed.
  2. Old dependency declaration formats: If older projects use different ways of declaring dependencies, we need to support these formats in order to support projects using these formats.
  3. Obsolete Python environments: If older projects use different ways of setting up Python environments and installing dependencies, we would have to understand these, unless we want to rely on custom mappings (or the identity mapping).

Here are the bounds that I'm aware of:

That leaves, I believe, Python syntax as the main determining factor for what minimum version we support. Since we use the ast module to parse Python code, this question essentially becomes: For a given version of the ast parser that FawltyDeps is running on, what is the oldest version of Python syntax that is supported by this parser?

Here is what different versions of ast.parse() has to say about supported Python versions:

AFAICS, when the feature_version flag is not set, it defaults to the current version, i.e. the one FawltyDeps is running on. We're currently not setting this flag, which means that any older project that we attempt to analyize will fail if it uses syntax that is not forward-compatible to the version FawltyDeps is running on.

FWIW, the feature_version flag to ast.parse() was added in Python v3.8, so I don't believe dropping support for running FD on Python v3.7 (see #459) has changed what older Python projects we might support.


Taking a step back, I suspect this is not a huge problem in practice, as Python tries very hard not to break old code when new syntax is introduced. The biggest problem - I assume - is the introduction of new keywords (e.g. async, await, match) that might have been used as e.g. variable names in older code.

Still, if we want to tackle this, we need a suite of tests with "old" Python source code samples that is incompatible with various "new" Python versions. We also need some way for projects to configure FawltyDeps as to which feature_version they need to use.

In summary, I see three main ways we can approach this:

  1. Document the current behavior: The Python syntax supported by FawltyDeps must be compatible with the Python version that FawltyDeps is running on. Meaning that if you're analyzing an old project, you should be running FawltyDeps on Python v3.8, in order to minimize the chance of encountering incompatible syntax.
  2. Add a settings flag to specify the Python version used by the project. This will be passed as feature_version to ast.parse(), and requires that FawltyDeps is running on a version that supports the given version number. That is, if your project is using Python version v3.4-v3.6, you must run FawltyDeps on Python <v3.13; if your project is using Python version <v3.4, you're out of luck.
  3. Use a 3rd-party Python parser like e.g. parso that supports parsing a wider range of Python version (even Python v2!).