Skip to content

Instantly share code, notes, and snippets.

@diniremix
Last active October 18, 2021 18:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save diniremix/c1caffac72b7cea382a65a8a95f1bb6e to your computer and use it in GitHub Desktop.
Save diniremix/c1caffac72b7cea382a65a8a95f1bb6e to your computer and use it in GitHub Desktop.
gen-req reads a 'pyproject.toml' (Poetry) file and exports the list of dependencies to a 'requirements.txt' file, in a more easily understood, simple and traditional way.

gen-req reads a 'pyproject.toml' (Poetry) file and exports the list of dependencies to a 'requirements.txt' file, in a more easily understood, simple and traditional way.

Copyright (c) 2021 Jorge Brunal Perez diniremix@gmail.com

gen-req is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

gen-req is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with gen-req; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

this script does not pretend to cover all the configurations used by Poetry for depedencies. Dependencies in Poetry for a project can be specified in various forms, which depend on the type of the dependency and on the optional constraints that might be needed for it to be installed.

more info: https://python-poetry.org/docs/dependency-specification/

if you want to use the export of Poetry run:

poetry export -f requirements.txt --output requirements.txt --without-hashes

Poetry version: 1.1.11

does not require Poetry to be installed to work.

ToDO:

  • Wildcard requirements
  • Inequality requirements
  • path dependencies
  • url dependencies
  • Multiple constraints dependencies
  • git dependencies (branch)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
gen-req
reads a 'pyproject.toml' (Poetry) file and exports the list of dependencies
to a 'requirements.txt' file, in a more easily understood, simple and
traditional way.
Copyright (c) 2021 Jorge Brunal Perez <diniremix@gmail.com>
This file is part of cl4ptr4p.
gen-req is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
gen-req is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with gen-req; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
this script does not pretend to cover all the configurations used by Poetry for depedencies.
Dependencies in Poetry for a project can be specified in various forms,
which depend on the type of the dependency and on the optional constraints
that might be needed for it to be installed.
more info:
https://python-poetry.org/docs/dependency-specification/
if you want to use the export of Poetry run:
poetry export -f requirements.txt --output requirements.txt --without-hashes
Poetry version: 1.1.11
ToDO:
- Wildcard requirements
- Inequality requirements
- path dependencies
- url dependencies
- Multiple constraints dependencies
- git dependencies (branch)
"""
import sys
import os
import tomli
APP_NAME = "gen-req"
APP_VERSION = "V.1.0"
POETRY_VERSION = "Poetry 1.1.11"
THE_FILE = "pyproject.toml"
EXPORT_FILE = "requirements.txt"
NOT_ALLOWED_MODULES = ["python"]
def clear_screen():
if sys.platform.startswith("linux"):
os.system("clear")
elif sys.platform.startswith("win"):
os.system("cls")
def open_file():
print()
try:
print("open", THE_FILE, "...")
toml_dict = None
with open(THE_FILE, "r") as f:
toml_dict = tomli.load(f)
package_list = process_file(toml_dict)
export_data(package_list)
except tomli.TOMLDecodeError:
print("Error, definitely not valid.", THE_FILE)
except Exception as e:
print("Exception:", e)
def process_file(toml_dict=None):
print("checking", THE_FILE, "...")
if toml_dict is None:
print("Error: no valid scheme was found.")
sys.exit()
if "tool" not in toml_dict:
print("Error bad configuration: no 'tool' section")
sys.exit()
tools = toml_dict["tool"]
if "poetry" not in tools:
print("Error bad configuration: no 'poetry' section")
sys.exit()
poetry = tools["poetry"]
if "dependencies" not in poetry:
print("Error bad configuration: no 'dependencies' section")
sys.exit()
dependencies = poetry["dependencies"]
print("listing requirements...")
req_list = []
translation_table = dict.fromkeys(map(ord, "~^"), None)
for key, value in dependencies.items():
if key.lower() in NOT_ALLOWED_MODULES:
print("Warning: {0} [module not allowed] skipping...".format(key))
continue
if isinstance(value, (dict)):
if "git" in value:
if "rev" in value:
dep = "{0} @ git+{1}@{2}".format(key, value["git"], value["rev"])
print("- {0}".format(dep))
req_list.append(dep)
elif "tag" in value:
dep = "{0} @ git+{1}@{2}".format(key, value["git"], value["tag"])
print("- {0}".format(dep))
req_list.append(dep)
else:
dep = "{0} @ git+{1}@master".format(key, value["git"])
print("- {0}".format(dep))
req_list.append(dep)
elif "version" in value:
dep_version = value["version"]
print("- {0} {1}".format(key, dep_version))
new_value = dep_version.translate(translation_table)
req_list.append("{0}=={1}".format(key, new_value))
else:
print("Warning: {0} [unknown dependencies format] skipping...".format(key))
continue
elif isinstance(value, (tuple, list)):
print("Warning: {0} [Multiple constraints dependencies] skipping...".format(key))
continue
else:
print("- {0} {1}".format(key, value))
new_value = value.translate(translation_table)
req_list.append("{0}=={1}".format(key, new_value))
return req_list
def export_data(package_list):
print()
if len(package_list) <= 0:
print("Error: a list of dependencies was not found.")
sys.exit()
print("generating requirements...")
try:
with open(EXPORT_FILE, "w") as f:
intro = "#\n# This file is autogenerated by {0} {1}\n"
intro += "# from {2} ({3})\n"
intro += "#\n"
intro = intro.format(APP_NAME, APP_VERSION, THE_FILE, POETRY_VERSION)
f.write(intro)
for item in package_list:
line = "{0}\n".format(item)
f.write(line)
print("Yep, requirements.txt succesfully generated.")
print("now check the 'requirements.txt' file.")
except Exception as e:
print("Oops, definitely can not generate file...", e)
def help_cmd():
print(APP_NAME, APP_VERSION)
print("if you want to use the export of Poetry run:")
print("poetry export -f requirements.txt --output requirements.txt --without-hashes")
if __name__ == "__main__":
clear_screen()
help_cmd()
open_file()
#
# Python 3.9
#
toml==1.2.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment