Skip to content

Instantly share code, notes, and snippets.

@varun-seth
Created April 10, 2023 13:21
Show Gist options
  • Save varun-seth/402be6de8a55aeda4eb70abb9941a7ad to your computer and use it in GitHub Desktop.
Save varun-seth/402be6de8a55aeda4eb70abb9941a7ad to your computer and use it in GitHub Desktop.
Derive Poetry Lock from
import tomlkit
LOCK_FILE_PATH = "poetry.lock"
PYPROJECT_PATH = "pyproject.toml"
def main():
try:
with open(LOCK_FILE_PATH, "r") as lock_file:
lock_content = lock_file.read()
except FileNotFoundError:
raise AssertionError("Could not find the poetry.lock file.")
lock_data = tomlkit.parse(lock_content)
package_data = lock_data.get("package", [])
if not package_data:
raise AssertionError("No package data found in the poetry.lock file.")
doc = tomlkit.document()
tool_table = tomlkit.table()
doc.add("tool", tool_table)
poetry_table = tomlkit.table()
tool_table.add("poetry", poetry_table)
poetry_table.add("name", "app")
poetry_table.add("version", "0.0.0")
poetry_table.add("description", "")
poetry_table.add("authors", [])
dependencies_table = tomlkit.table()
poetry_table.add("dependencies", dependencies_table)
dependencies_table.add("python", "^3")
all_dependencies = set()
for package in package_data:
dependencies = package.get("dependencies", {})
all_dependencies.update(dependencies.keys())
top_level_packages = [
package for package in package_data if package["name"] not in all_dependencies]
for package in top_level_packages:
name = package["name"]
version = package["version"]
dependencies_table.add(name, f"^{version}")
with open(PYPROJECT_PATH, "w") as pyproject_file:
pyproject_file.write(tomlkit.dumps(doc))
if __name__ == "__main__":
main()
@m-roberts
Copy link

m-roberts commented May 2, 2023

This is great! Have you thought about creating a Poetry plugin?

  • create a temporary directory
  • copy poetry.lock into it
  • create a minimal pyproject.toml using this script
  • run poetry install --no-root in the directory

This would allow you to avoid bundling poetry_to_pyproject.py as part of your Dockerfile:

COPY poetry_to_pyproject.py poetry.lock ./
RUN python poetry_to_pyproject.py
RUN poetry install

would become:

RUN \
    --mount=type=bind,source=poetry.lock,target=/workspace/poetry.lock \
    poetry self add poetry-plugin-lock-install \
    && poetry lock-install

This might not be the exact way to do it, but hopefully you can see what I am saying?

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