-
-
Notifications
You must be signed in to change notification settings - Fork 564
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automate the creation of requirement.txt and fetch deps #2118
Automate the creation of requirement.txt and fetch deps #2118
Conversation
By running this script, we will able to create and update the requirements.txt by providing the input directory like thirdparty . Also adding deps setuptools which is deps of zc.lockfile-2.0 Signed-off-by: Abhishek Kumar <[email protected]>
Identify Python version to extract abi of wheels which helps us in filtering the required deps. Signed-off-by: Abhishek Kumar <[email protected]>
This script will fetch dependencies with all corresponding files(.whl,.tar.gz,.LICENCE,.NOTICE,.ABOUT) from the given target . This feature will ask ScanCode's developer to provide dependencies as package_name,version and target directory where the built wheels and tarballs would be fetched. Signed-off-by: Abhishek Kumar <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks... see my comments!
) | ||
] | ||
if not (os.path.isdir("required_deps")): | ||
os.mkdir("required_deps") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you create that directory?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To filter the dependencies of specific python version we want because we have both py2 and py3 wheels in thirdparty. Don't worry it will deleted later by scripts itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, so please add a comment explaining that... and also this may not be created where you want. Make sure you use a well known location or better use some temp directory instead since this is temporary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you mean to say bin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use a temp dir instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
etc/scripts/scancode.py
Outdated
@@ -0,0 +1,128 @@ | |||
# -*- coding: utf-8 -*- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please do not name this scancode ;) that's confusing!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest the better name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deps_info.py
etc/scripts/scancode.py
Outdated
about = [files for files in dependency if files.endswith(".ABOUT")] | ||
notice = [files for files in dependency if files.endswith(".NOTICE")] | ||
license = [files for files in dependency if files.endswith(".LICENSE")] | ||
print(*whl, sep="\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you print all that ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because scancode's developer want to fetch the deps in target directory. Script will know developer by printing the info of deps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's too verbose by default. Hide the prints behind an option
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it shows ONLY .ABOUT/.NOTICE/.LICENCE/.whl/.tar.gz . Not too verbose i have seen
@@ -0,0 +1,15 @@ | |||
about_resource: setuptools-41.2.0-py2.py3-none-any.whl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should already have setuptools..... good catch. But please do not commit it there, craft another PR instead just for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't worry, i already mentioned in PR description. FYI there is no deps named setuptools
. That's why i added wheels setuptools also here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get that, but please provide a different PR for adding that back (and FYI zopefoundation/zc.lockfile#22 )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed and PR #2123
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks... please see my comments inline
"--output-file", | ||
output_file, | ||
"--verbose", | ||
"--upgrade-package", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you do this? we never want to do some unwanted upgrade-package
IMHO and what is "package_name",
below about?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this feature alow you to upgrade specfic package. See help by running this arg.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I known that but what is "package_name"
I know of no package whose name is "package_name"
If this is some kind of magic, explain it in comments, do not make me chase down the help of that command
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In any case why would I want to upgrade a package there? Please elaborate and explain in comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Package name may be intbitset, banal, urlpy . Anything deps that exist in thirdparty
|
||
parser.add_argument( | ||
"--upgrade", | ||
help="Upgrade all dependencies to new version. ", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: you have trailing whitespaces here and elsewhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
""" | ||
Generate a requirement.txt file of all dependencies present in thirdparty. | ||
""" | ||
thirdparty = list(resource_iter(input_dir, with_dirs=False)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The list() wrapper is not needed here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
def generate_req_text(input_dir, output_file=False, package_name=False): | ||
""" | ||
Generate a requirement.txt file of all dependencies present in thirdparty. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and what are the args?
this should IMHO be something such as:
Generate a requirement file at `output_file` of all dependencies wheels and sdists present in the `input_dir` directory.
If a `package_name` is provided it will be updated to its latest version.
though I am not sure this is true for package_name
Also output_file=False, package_name=False
is weird. These should be None... and output_file should always be required
Also what is the base used there? the setup.py or some requirements.in file? I think we will need a requirements.in file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Base used here : setup.py and no need of requirements.in file. And by default output_file is requirements.txt
and it is default arguments.
etc/scripts/scancode.py
Outdated
about = [files for files in dependency if files.endswith(".ABOUT")] | ||
notice = [files for files in dependency if files.endswith(".NOTICE")] | ||
license = [files for files in dependency if files.endswith(".LICENSE")] | ||
print(*whl, sep="\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's too verbose by default. Hide the prints behind an option
@@ -0,0 +1,15 @@ | |||
about_resource: setuptools-41.2.0-py2.py3-none-any.whl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get that, but please provide a different PR for adding that back (and FYI zopefoundation/zc.lockfile#22 )
Signed-off-by: Abhishek Kumar <[email protected]>
Signed-off-by: Abhishek Kumar <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks... see my comments
etc/scripts/deps_info.py
Outdated
|
||
def main_with_args(args: str) -> None: | ||
parser = argparse.ArgumentParser( | ||
description="""Fetch a specific package with version in given target like thirdparty by default. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thsi command seems if fetches nothing at all, does it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it description of function , you know this thing by running --help
option. I help developer when he put --help
option
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be instead:
Search PACKAGE_NAME (with an optional VERSION_OF_PACKAGE) in the TARGET_DIR directory.
Print results on screen.
|
||
def generate_req_text(input_dir, output_file=None, package_name=None): | ||
""" | ||
Generate a requirement file at `output_file`(by default requirements.txt) of all dependencies wheels and sdists present in the `input_dir` directory. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please wrap this. Also if you want a default of (by default requirements.txt)
... then set the default in the function definition and not as None
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Already set as defaults.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By wrap, wrap the very long lines.
) | ||
] | ||
if not (os.path.isdir("required_deps")): | ||
os.mkdir("required_deps") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use a temp dir instead
"--output-file", | ||
output_file, | ||
"--verbose", | ||
"--upgrade-package", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I known that but what is "package_name"
I know of no package whose name is "package_name"
If this is some kind of magic, explain it in comments, do not make me chase down the help of that command
"--output-file", | ||
output_file, | ||
"--verbose", | ||
"--upgrade-package", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In any case why would I want to upgrade a package there? Please elaborate and explain in comments
"--no-index", | ||
] | ||
) | ||
shutil.rmtree("required_deps") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather you use a temp file with a "with" context manager to avoid leaving dangling files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not a file , it is directory
|
||
parser.add_argument( | ||
"--output", | ||
help="Output file name. Required if more than one input file is given. Will be derived from input file otherwise.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid implicit, derived name. It is preferred to always require an input instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pip-tools uses --output-file
for same purpose why should i not not use --output
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My point is to avoid using a derived name. Instead make this always required and not implied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok , your call i changing the option --output
to --requirement
. And making always required.
tpdir = args.deps_directory | ||
output_file = args.output | ||
package_name = args.upgrade_package | ||
upgrade = args.upgrade or None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This argument is not used at all... so what is it for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
upgrade is for upgrading all packages whereas upgrade_package is for specific package,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But where do you use it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is not an argument used anywhere in your functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great catch .It is an option just like ON/OFF . It is used here only , i have tested it it works, if you want i will paste output here.
Signed-off-by: Abhishek Kumar <[email protected]>
c351eed
to
0a9db9f
Compare
Signed-off-by: Abhishek Kumar <[email protected]>
"--verbose", | ||
"--allow-unsafe", | ||
"--upgrade-package", | ||
"package_name", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"package_name"
is NOT a variable here ... but a plain string. This cannot work as it is... you need to test your code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, yeah it is function parameter through arguments . I have treated like temp dir
as That is also also in double quotes but it is dir not variable . Same issue with upgrade parameter also.
Signed-off-by: Abhishek Kumar <[email protected]>
Signed-off-by: Abhishek Kumar <[email protected]>
etc/scripts/deps_info.py
Outdated
parser = argparse.ArgumentParser( | ||
description="""Fetch a specific package with version in given target like thirdparty by default. | ||
EXAMPLE: | ||
scancode.py \\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deps
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my nitpickings inline for your review!
Thanks you for your persistence!
etc/scripts/deps_info.py
Outdated
import sys | ||
|
||
|
||
def search_package(package_name, target, version): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please version=None
since this is optional
etc/scripts/deps_info.py
Outdated
import argparse | ||
import fnmatch | ||
from commoncode.fileutils import resource_iter | ||
import sys |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sort imports
etc/scripts/deps_info.py
Outdated
|
||
def search_package(package_name, target, version): | ||
""" | ||
Search specific package in given directory with all corresponding files. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use instead:
Search `package_name` (with an optional `version`) in the `target` directory. Print results on screen.
etc/scripts/deps_info.py
Outdated
|
||
def main_with_args(args: str) -> None: | ||
parser = argparse.ArgumentParser( | ||
description="""Fetch a specific package with version in given target like thirdparty by default. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be instead:
Search PACKAGE_NAME (with an optional VERSION_OF_PACKAGE) in the TARGET_DIR directory.
Print results on screen.
etc/scripts/deps_info.py
Outdated
|
||
parser.add_argument( | ||
"--target", | ||
help=" a target directory where the built wheels and tarballs would be fetched.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use this:
"Directory to search for package wheels and tarballs. [default: thirdparty]"
|
||
def generate_req_text(input_dir, output_file=None, package_name=None): | ||
""" | ||
Generate a requirement file at `output_file`(by default requirements.txt) of all dependencies wheels and sdists present in the `input_dir` directory. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By wrap, wrap the very long lines.
'pip-compile', | ||
'--generate-hashes', | ||
'--find-links', | ||
'temp dir', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean to use this https://docs.python.org/3/library/tempfile.html?highlight=tempfile#module-tempfile
No a dir name temp dir
if package_name: | ||
pip_args.extend(['--upgrade-package', package_name]) | ||
run(pip_args) | ||
rmtree('temp dir') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With a proper https://docs.python.org/3/library/tempfile.html?highlight=tempfile#module-tempfile you will NOT need to rm anything, with will be handled for you if you use a context manager.
such as this example from the Python doc:
# create a temporary directory using the context manager
>>> with tempfile.TemporaryDirectory() as tmpdirname:
... print('created temporary directory', tmpdirname)
.... do your things here
--deps_directory DEPS_DIRECTORY \\ | ||
--output OUTPUT \\ | ||
--upgrade_package PACKAGE_NAME \\ | ||
""", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this example.
package_name = args.upgrade_package | ||
upgrade = args.upgrade or False | ||
generate_req_text(tpdir, requirement_file, package_name, upgrade) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prefer named keyword arguments for example:
(tpdir=tpdir, requirement_file=requirement_file, package_name=package_name, upgrade=upgrade) But do not use these names... use the same variable names on both sides: e.g. if you use
args.deps_directory then use
deps_directoryand not
tpdir`
…requirements.txt
Signed-off-by: Abhishek Kumar <[email protected]>
from fnmatch import fnmatchcase | ||
import os | ||
from subprocess import run | ||
from shutil import copy, rmtree |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking: your imports are not sorted. Try to use https://pypi.org/project/isort/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh , i missed that .Also i have to remove unused import
def generate_req_text(find_links, req_file, package_name=None, upgrade=False): | ||
""" | ||
Generate a requirement file at `req_file` of all dependencies wheels and | ||
sdists present in the `input_dir` directory.If a `package_name` is provided |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no input_dir?
...sdists present in the
input_dir directory...
Do you mind doing an extra review pass on this PR and #2117 to make sure the docstrings are well synced with the actual function arguments and what the function does>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, this PR has reviewed many times. I would like work on diff PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Signed-off-by: Abhishek Kumar <[email protected]>
Signed-off-by: Philippe Ombredanne <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking fine. Thank you! merging
By running this script, we will able to create and update the requirements.txt by providing the input directory like thirdparty .
This script will fetch dependencies with all corresponding files(.whl,.tar.gz,.LICENCE,.NOTICE,.ABOUT) from the given target . This feature will ask ScanCode's developer to provide dependencies as package_name,version and target directory where the built wheels and tarballs would be fetched.
Signed-off-by: Abhishek Kumar [email protected]
Fixes aboutcode-org/skeleton#50 #2087