From f15a320ec2f5a09ef11313d6078ca2452a29c775 Mon Sep 17 00:00:00 2001 From: juancarlospaco Date: Fri, 6 Apr 2018 23:34:56 -0300 Subject: [PATCH 01/20] Add list_venvs helper function, add --list-venvs to CLI args, FIX #276 , FIX #306 , FIX ##216 --- fades/helpers.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/fades/helpers.py b/fades/helpers.py index 73c5e4b..785951d 100644 --- a/fades/helpers.py +++ b/fades/helpers.py @@ -22,6 +22,7 @@ import logging import subprocess +from datetime import datetime from urllib import request from urllib.error import HTTPError @@ -256,3 +257,22 @@ def check_pypi_exists(dependencies): logger.error("%s doesn't exists in PyPI.", dependency) return False return True + + +def list_venvs(index_path, logger=None): + if os.path.isfile(index_path): + log = logger.info if logger else print + tmplt = ("\nVENV_UUID:\t{uid}\nDATE_TIME:\t{dat}\nFULL_PATH:\t{pat}" + "\nPACKAGES:\t{pac}\nINTERPRETER:\t{pyv}\nOPTIONS:\t{opt}\n") + with open(index_path) as jotason: + for jotason_line in jotason: + v_dct_get = json.loads(jotason_line).get + venv_info = tmplt.format( + uid=v_dct_get("metadata")["env_path"].split("/fades/")[-1], + pat=v_dct_get("metadata")["env_path"], + pac=v_dct_get("installed"), + pyv=v_dct_get("interpreter"), + opt=v_dct_get("options"), + dat=datetime.fromtimestamp(v_dct_get("timestamp")).replace( + microsecond=0).astimezone().isoformat()) + log(venv_info) From fcff4df080f5cfbd5d13c90cefafc536e036b906 Mon Sep 17 00:00:00 2001 From: juancarlospaco Date: Fri, 6 Apr 2018 23:35:03 -0300 Subject: [PATCH 02/20] Add list_venvs helper function, add --list-venvs to CLI args, FIX #276 , FIX #306 , FIX ##216 --- fades/main.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fades/main.py b/fades/main.py index 588ec18..992ec28 100644 --- a/fades/main.py +++ b/fades/main.py @@ -125,13 +125,14 @@ def go(): help=("Extra options to be supplied to python. (this option can be " "used multiple times)")) parser.add_argument('--rm', dest='remove', metavar='UUID', - help=("Remove a virtualenv by UUID.")) + help=("Remove a virtualenv by UUID (see --list-venvs).")) parser.add_argument('--clean-unused-venvs', action='store', help=("This option remove venvs that haven't been used for more than " "CLEAN_UNUSED_VENVS days. Appart from that, will compact usage " "stats file.\n" "When this option is present, the cleaning takes place at the " "beginning of the execution.")) + parser.add_argument('--list-venvs', action='store_true', help=("List all venvs")) parser.add_argument('child_program', nargs='?', default=None) parser.add_argument('child_options', nargs=argparse.REMAINDER) @@ -161,6 +162,10 @@ def go(): logger.debug("Starting fades v. %s", fades.__version__) logger.debug("Arguments: %s", args) + if args.list_venvs: + helpers.list_venvs(os.path.join(helpers.get_basedir(), 'venvs.idx'), logger=logger) + sys.exit(0) + # verify that the module is NOT being used from a virtualenv if detect_inside_virtualenv(sys.prefix, getattr(sys, 'real_prefix', None), getattr(sys, 'base_prefix', None)): From 417d0c8c9c046cdc5f19a553d5ff41b3f024e139 Mon Sep 17 00:00:00 2001 From: juancarlospaco Date: Fri, 6 Apr 2018 23:56:08 -0300 Subject: [PATCH 03/20] Add DocString to list_venvs --- fades/helpers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fades/helpers.py b/fades/helpers.py index 785951d..25f11dc 100644 --- a/fades/helpers.py +++ b/fades/helpers.py @@ -260,6 +260,7 @@ def check_pypi_exists(dependencies): def list_venvs(index_path, logger=None): + """List all venvs from an index file path and print info to stdout.""" if os.path.isfile(index_path): log = logger.info if logger else print tmplt = ("\nVENV_UUID:\t{uid}\nDATE_TIME:\t{dat}\nFULL_PATH:\t{pat}" From 967f0d04858b1d85c66051a9fbce51bfb1dd44f4 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Fri, 13 Apr 2018 08:28:31 -0300 Subject: [PATCH 04/20] Remove logger, use print [SKIP CI] --- fades/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fades/main.py b/fades/main.py index 992ec28..6ce11cd 100644 --- a/fades/main.py +++ b/fades/main.py @@ -163,7 +163,7 @@ def go(): logger.debug("Arguments: %s", args) if args.list_venvs: - helpers.list_venvs(os.path.join(helpers.get_basedir(), 'venvs.idx'), logger=logger) + helpers.list_venvs(os.path.join(helpers.get_basedir(), 'venvs.idx')) sys.exit(0) # verify that the module is NOT being used from a virtualenv From bca5e57399021b57cf39eb3627430ee48f3827da Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Fri, 13 Apr 2018 08:30:48 -0300 Subject: [PATCH 05/20] Add new option to readme [SKIP CI] --- README.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.rst b/README.rst index bb9d48f..64b41b2 100644 --- a/README.rst +++ b/README.rst @@ -371,6 +371,10 @@ Uses the ``django-admin.py`` script to start a new project named ``foo``, withou Removes a virtualenv matching the given uuid from disk and cache index. +``fades --list-venvs`` + +List all virtualenvs, showing the information (UUID, timestamp, dependencies, interpreter, etc). + What if Python is updated in my system? --------------------------------------- From c84d74525252500c8591468cb43d2033499b468f Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Fri, 13 Apr 2018 08:37:29 -0300 Subject: [PATCH 06/20] Add changes from feedback to list_venvs function --- fades/helpers.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/fades/helpers.py b/fades/helpers.py index 25f11dc..c5c968d 100644 --- a/fades/helpers.py +++ b/fades/helpers.py @@ -259,21 +259,22 @@ def check_pypi_exists(dependencies): return True -def list_venvs(index_path, logger=None): +def list_venvs(index_path): """List all venvs from an index file path and print info to stdout.""" if os.path.isfile(index_path): - log = logger.info if logger else print - tmplt = ("\nVENV_UUID:\t{uid}\nDATE_TIME:\t{dat}\nFULL_PATH:\t{pat}" - "\nPACKAGES:\t{pac}\nINTERPRETER:\t{pyv}\nOPTIONS:\t{opt}\n") + tmplt = ("\nVirtualenv uuid:\t{uid}\n\ttimestamp:\t{dat}\n\tfull path:\t{pat}\n" + "\tdependencies:\t{pac}\n\tinterpreter:\t{pyv}\n\toptions:\t{opt}\n") + venv_info = "" with open(index_path) as jotason: for jotason_line in jotason: v_dct_get = json.loads(jotason_line).get - venv_info = tmplt.format( - uid=v_dct_get("metadata")["env_path"].split("/fades/")[-1], + venv_info += tmplt.format( + uid=v_dct_get("metadata")["env_path"][18:], pat=v_dct_get("metadata")["env_path"], pac=v_dct_get("installed"), pyv=v_dct_get("interpreter"), opt=v_dct_get("options"), dat=datetime.fromtimestamp(v_dct_get("timestamp")).replace( - microsecond=0).astimezone().isoformat()) - log(venv_info) + microsecond=0).astimezone().isoformat(" ")) + print(venv_info) + return venv_info From 1c43235b22304bb67a3a84e8a5d62f96497dfcf6 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Fri, 13 Apr 2018 09:51:35 -0300 Subject: [PATCH 07/20] Add list_venvs to man. --- man/fades.1 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/man/fades.1 b/man/fades.1 index 2d600ae..98e3b26 100644 --- a/man/fades.1 +++ b/man/fades.1 @@ -20,6 +20,7 @@ fades - A system that automatically handles the virtualenvs in the cases normall [\fB--pip-options\fR=\fIoptions\fR] [\fB--python-options\fR=\fIoptions\fR] [\fB--check-updates\fR] +[\fB--list-venvs\fR] [\fB--clean-unused-venvs\fR=\fImax_days_to_keep\fR] [child_program [child_options]] @@ -104,7 +105,7 @@ Extra options to be supplied to pip. (this option can beused multiple times) .BR --python-options=\fIPYTHON_OPTION\fR Extra options to be supplied to python. (this option can beused multiple times) -.TP +.TP .BR --check-updates Will check for updates in PyPI to verify if there are new versions for the requested dependencies. If a new version is available for a dependency, it will use it (if the dependency was requested without version) or just inform which new version is available (if the dependency was requested with a specific version). @@ -112,6 +113,10 @@ Will check for updates in PyPI to verify if there are new versions for the reque .BR --clean-unused-venvs=\fIMAX_DAYS_TO_KEEP\fR Will remove all virtualenvs that haven't been used for more than MAX_DAYS_TO_KEEP days. +.TP +.BR --list-venvs +List all virtualenvs, showing information (UUID, timestamp, path, dependencies, interpreter, etc). + .SH EXAMPLES .TP From 9bc6f972115a04de53d2e9d4bf90accbf8832610 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Fri, 13 Apr 2018 12:47:52 -0300 Subject: [PATCH 08/20] Add basic test list_venvs, WIP. --- tests/test_helpers.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index ef5ded1..fc6aef8 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -375,3 +375,19 @@ def test_redirect_response(self): exists = helpers.check_pypi_exists(deps) self.assertTrue(exists) self.assertLoggedWarning("Got a (unexpected) HTTP_STATUS") + + +class ListVenvsTestCase(unittest.TestCase): + """Utilities to list venvs.""" + + # def test_list_venvs(self): + # with patch('os.path.isfile') as mock_isfile: + # mock_isfile.return_value = True + # with patch('builtins.open') as mock_open: + # mock_open.return_value = io.StringIO() + + def test_index_path_empty(self): + self.assertEqual(helpers.list_venvs(""), None) + + def test_index_path_not_found(self): + self.assertEqual(helpers.list_venvs("directory_does_not_exist"), None) From e5d6517e9b35c0c324ed3b1cd5745a5749af9b14 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Fri, 13 Apr 2018 22:22:24 -0300 Subject: [PATCH 09/20] Improve basic test for list_venvs. --- tests/examples/venvs.idx | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/examples/venvs.idx diff --git a/tests/examples/venvs.idx b/tests/examples/venvs.idx new file mode 100644 index 0000000..f01bdb1 --- /dev/null +++ b/tests/examples/venvs.idx @@ -0,0 +1,8 @@ +{"timestamp": 1308193200, "installed": {}, "metadata": {"env_path": "/home/juan/.fades/d1cf2e61-4ac5-467d-9b65-1a3c0e913bf3", "env_bin_path": "/home/juan/.fades/d1cf2e61-4ac5-467d-9b65-1a3c0e913bf3/bin", "pip_installed": true}, "interpreter": "/usr/bin/python3", "options": {"pyvenv_options": [], "virtualenv_options": []}} +{"timestamp": 1234144800, "installed": {}, "metadata": {"env_path": "/home/juan/.fades/032e6e2c-bc7e-4a7f-ad1d-66ecb9106884", "env_bin_path": "/home/juan/.fades/032e6e2c-bc7e-4a7f-ad1d-66ecb9106884/bin", "pip_installed": true}, "interpreter": "/usr/bin/python3", "options": {"pyvenv_options": [], "virtualenv_options": []}} +{"timestamp": 992746800, "installed": {}, "metadata": {"env_path": "/home/juan/.fades/53c8f169-b105-4ed1-a7fc-25792b18fc4c", "env_bin_path": "/home/juan/.fades/53c8f169-b105-4ed1-a7fc-25792b18fc4c/bin", "pip_installed": true}, "interpreter": "/usr/bin/python3", "options": {"pyvenv_options": [], "virtualenv_options": []}} +{"timestamp": 1501902000, "installed": {}, "metadata": {"env_path": "/home/juan/.fades/8cc6666c-fb5e-474b-a8a7-217c9558d5e2", "env_bin_path": "/home/juan/.fades/8cc6666c-fb5e-474b-a8a7-217c9558d5e2/bin", "pip_installed": true}, "interpreter": "/usr/bin/python3", "options": {"pyvenv_options": [], "virtualenv_options": []}} +{"timestamp": 1441508400, "installed": {}, "metadata": {"env_path": "/home/juan/.fades/7a4a4eb8-b0d2-4d88-a890-4830278e0eb9", "env_bin_path": "/home/juan/.fades/7a4a4eb8-b0d2-4d88-a890-4830278e0eb9/bin", "pip_installed": true}, "interpreter": "/usr/bin/python3", "options": {"pyvenv_options": [], "virtualenv_options": []}} +{"timestamp": 1168830000, "installed": {}, "metadata": {"env_path": "/home/juan/.fades/7c10fa5f-037e-49b1-a9dd-3462c739e239", "env_bin_path": "/home/juan/.fades/7c10fa5f-037e-49b1-a9dd-3462c739e239/bin", "pip_installed": true}, "interpreter": "/usr/bin/python3", "options": {"pyvenv_options": [], "virtualenv_options": []}} +{"timestamp": 1026097200, "installed": {}, "metadata": {"env_path": "/home/juan/.fades/37de0f88-3db7-434a-a692-048aa35fbfe7", "env_bin_path": "/home/juan/.fades/37de0f88-3db7-434a-a692-048aa35fbfe7/bin", "pip_installed": true}, "interpreter": "/usr/bin/python3", "options": {"pyvenv_options": [], "virtualenv_options": []}} +{"timestamp": 1512529200, "installed": {}, "metadata": {"env_path": "/home/juan/.fades/000236c6-5ddb-4422-b210-93e09fab603f", "env_bin_path": "/home/juan/.fades/000236c6-5ddb-4422-b210-93e09fab603f/bin", "pip_installed": true}, "interpreter": "/usr/bin/python3", "options": {"pyvenv_options": [], "virtualenv_options": []}} From 4857e856c93aab7db3c15be12a8123661572807c Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Fri, 13 Apr 2018 22:22:56 -0300 Subject: [PATCH 10/20] Improve basic test for list_venvs. --- tests/examples/output.txt | 56 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 tests/examples/output.txt diff --git a/tests/examples/output.txt b/tests/examples/output.txt new file mode 100644 index 0000000..1ff44a2 --- /dev/null +++ b/tests/examples/output.txt @@ -0,0 +1,56 @@ + +Virtualenv uuid: d1cf2e61-4ac5-467d-9b65-1a3c0e913bf3 + timestamp: 2011-06-16 00:00:00-03:00 + full path: /home/juan/.fades/d1cf2e61-4ac5-467d-9b65-1a3c0e913bf3 + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv uuid: 032e6e2c-bc7e-4a7f-ad1d-66ecb9106884 + timestamp: 2009-02-09 00:00:00-02:00 + full path: /home/juan/.fades/032e6e2c-bc7e-4a7f-ad1d-66ecb9106884 + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv uuid: 53c8f169-b105-4ed1-a7fc-25792b18fc4c + timestamp: 2001-06-17 00:00:00-03:00 + full path: /home/juan/.fades/53c8f169-b105-4ed1-a7fc-25792b18fc4c + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv uuid: 8cc6666c-fb5e-474b-a8a7-217c9558d5e2 + timestamp: 2017-08-05 00:00:00-03:00 + full path: /home/juan/.fades/8cc6666c-fb5e-474b-a8a7-217c9558d5e2 + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv uuid: 7a4a4eb8-b0d2-4d88-a890-4830278e0eb9 + timestamp: 2015-09-06 00:00:00-03:00 + full path: /home/juan/.fades/7a4a4eb8-b0d2-4d88-a890-4830278e0eb9 + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv uuid: 7c10fa5f-037e-49b1-a9dd-3462c739e239 + timestamp: 2007-01-15 00:00:00-03:00 + full path: /home/juan/.fades/7c10fa5f-037e-49b1-a9dd-3462c739e239 + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv uuid: 37de0f88-3db7-434a-a692-048aa35fbfe7 + timestamp: 2002-07-08 00:00:00-03:00 + full path: /home/juan/.fades/37de0f88-3db7-434a-a692-048aa35fbfe7 + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv uuid: 000236c6-5ddb-4422-b210-93e09fab603f + timestamp: 2017-12-06 00:00:00-03:00 + full path: /home/juan/.fades/000236c6-5ddb-4422-b210-93e09fab603f + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} From f2f92af88191ce00648b3ca34bc00fc7199c5df4 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Fri, 13 Apr 2018 22:24:31 -0300 Subject: [PATCH 11/20] Improve basic test for list_venvs. --- .../autogenerate_random_venvsidx.py | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 tests/test_files/autogenerate_random_venvsidx.py diff --git a/tests/test_files/autogenerate_random_venvsidx.py b/tests/test_files/autogenerate_random_venvsidx.py new file mode 100644 index 0000000..b6dd0aa --- /dev/null +++ b/tests/test_files/autogenerate_random_venvsidx.py @@ -0,0 +1,42 @@ + + +"""Tiny tool to autogenerate random 'venvs.idx' content for testing purposes.""" + + +import os +from random import randint +from uuid import uuid4 +from shutil import which +import datetime +import json + + +def main(): + """Build a valid random-ish Fades venvs.idx content.""" + y3ar, h0me = datetime.date.today().year, os.path.join(os.path.expanduser("~"), ".fades") + venvs_idx = "" + for _ in range(randint(2, 9)): + random_envpath = os.path.join(h0me, str(uuid4())) + random_timestamp = int(datetime.datetime(year=randint(2000, y3ar), + month=randint(1, 12), + day=randint(1, 28)).timestamp()) + venvs_idx += json.dumps({ + "timestamp": random_timestamp, + "installed": {}, + "metadata": { + "env_path": random_envpath, + "env_bin_path": os.path.join(random_envpath, "bin"), + "pip_installed": True + }, + "interpreter": which("python3") or "/usr/bin/python3.6", + "options": { + "pyvenv_options": [], + "virtualenv_options": [] + } + }) + "\n" + print(venvs_idx.strip()) + return venvs_idx.strip() + + +if __name__ in "__main__": + main() From 0ebee499d6c120d8eda9436f54306ef5f1140641 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Fri, 13 Apr 2018 22:25:31 -0300 Subject: [PATCH 12/20] Improve basic test for list_venvs. --- tests/test_helpers.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index fc6aef8..6200036 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -378,13 +378,18 @@ def test_redirect_response(self): class ListVenvsTestCase(unittest.TestCase): + """Utilities to list venvs.""" - # def test_list_venvs(self): - # with patch('os.path.isfile') as mock_isfile: - # mock_isfile.return_value = True - # with patch('builtins.open') as mock_open: - # mock_open.return_value = io.StringIO() + maxDiff, __slots__ = None, () + + def test_list_venvs(self): + venvs_idx = os.path.join(PATH_TO_EXAMPLES, 'venvs.idx') + venvs_info = os.path.join(PATH_TO_EXAMPLES, 'output.txt') + str_list_venv = helpers.list_venvs(venvs_idx) + self.assertIsInstance(str_list_venv, str) + with open(venvs_info) as venvs_info_file: + self.assertEqual(str_list_venv, venvs_info_file.read()) def test_index_path_empty(self): self.assertEqual(helpers.list_venvs(""), None) From f2cab00b7afbd809e762eef7e81a873a3d2dc495 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Fri, 13 Apr 2018 23:02:51 -0300 Subject: [PATCH 13/20] Improve basic test for list_venvs. --- tests/test_helpers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 6200036..75f0290 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -383,6 +383,8 @@ class ListVenvsTestCase(unittest.TestCase): maxDiff, __slots__ = None, () + @unittest.skipIf('TRAVIS' in os.environ, + "Travis weird scaping https://travis-ci.org/PyAr/fades/jobs/366371756#L764") def test_list_venvs(self): venvs_idx = os.path.join(PATH_TO_EXAMPLES, 'venvs.idx') venvs_info = os.path.join(PATH_TO_EXAMPLES, 'output.txt') From 37e1f0e97354785ed97f63ff5b297214740e2353 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Fri, 13 Apr 2018 23:13:28 -0300 Subject: [PATCH 14/20] Improve basic test for list_venvs. --- tests/test_helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 75f0290..dcdf592 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -383,8 +383,8 @@ class ListVenvsTestCase(unittest.TestCase): maxDiff, __slots__ = None, () - @unittest.skipIf('TRAVIS' in os.environ, - "Travis weird scaping https://travis-ci.org/PyAr/fades/jobs/366371756#L764") + @unittest.skipIf('TRAVIS' in os.environ or 'APPVEYOR' in os.environ, + "Travis/AppVeyor weird scaping https://travis-ci.org/PyAr/fades/jobs/366371756#L764") def test_list_venvs(self): venvs_idx = os.path.join(PATH_TO_EXAMPLES, 'venvs.idx') venvs_info = os.path.join(PATH_TO_EXAMPLES, 'output.txt') From c0ad32d68dd8cd7631c5bdddc833bd841b00e299 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Fri, 13 Apr 2018 23:15:37 -0300 Subject: [PATCH 15/20] Improve basic test for list_venvs. --- tests/test_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index dcdf592..14c0547 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -384,7 +384,7 @@ class ListVenvsTestCase(unittest.TestCase): maxDiff, __slots__ = None, () @unittest.skipIf('TRAVIS' in os.environ or 'APPVEYOR' in os.environ, - "Travis/AppVeyor weird scaping https://travis-ci.org/PyAr/fades/jobs/366371756#L764") + "Travis/AppVeyor weird scaping travis-ci.org/PyAr/fades/jobs/366371756#L764") def test_list_venvs(self): venvs_idx = os.path.join(PATH_TO_EXAMPLES, 'venvs.idx') venvs_info = os.path.join(PATH_TO_EXAMPLES, 'output.txt') From f93dce9d707fa715a188fd031714dedf971a7a7c Mon Sep 17 00:00:00 2001 From: juancarlospaco Date: Tue, 24 Apr 2018 17:12:57 -0300 Subject: [PATCH 16/20] Add optional filter to list of venvs. --- tests/examples/output.txt | 110 +++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/tests/examples/output.txt b/tests/examples/output.txt index 1ff44a2..03328e9 100644 --- a/tests/examples/output.txt +++ b/tests/examples/output.txt @@ -1,56 +1,56 @@ -Virtualenv uuid: d1cf2e61-4ac5-467d-9b65-1a3c0e913bf3 - timestamp: 2011-06-16 00:00:00-03:00 - full path: /home/juan/.fades/d1cf2e61-4ac5-467d-9b65-1a3c0e913bf3 - dependencies: {} - interpreter: /usr/bin/python3 - options: {'pyvenv_options': [], 'virtualenv_options': []} - -Virtualenv uuid: 032e6e2c-bc7e-4a7f-ad1d-66ecb9106884 - timestamp: 2009-02-09 00:00:00-02:00 - full path: /home/juan/.fades/032e6e2c-bc7e-4a7f-ad1d-66ecb9106884 - dependencies: {} - interpreter: /usr/bin/python3 - options: {'pyvenv_options': [], 'virtualenv_options': []} - -Virtualenv uuid: 53c8f169-b105-4ed1-a7fc-25792b18fc4c - timestamp: 2001-06-17 00:00:00-03:00 - full path: /home/juan/.fades/53c8f169-b105-4ed1-a7fc-25792b18fc4c - dependencies: {} - interpreter: /usr/bin/python3 - options: {'pyvenv_options': [], 'virtualenv_options': []} - -Virtualenv uuid: 8cc6666c-fb5e-474b-a8a7-217c9558d5e2 - timestamp: 2017-08-05 00:00:00-03:00 - full path: /home/juan/.fades/8cc6666c-fb5e-474b-a8a7-217c9558d5e2 - dependencies: {} - interpreter: /usr/bin/python3 - options: {'pyvenv_options': [], 'virtualenv_options': []} - -Virtualenv uuid: 7a4a4eb8-b0d2-4d88-a890-4830278e0eb9 - timestamp: 2015-09-06 00:00:00-03:00 - full path: /home/juan/.fades/7a4a4eb8-b0d2-4d88-a890-4830278e0eb9 - dependencies: {} - interpreter: /usr/bin/python3 - options: {'pyvenv_options': [], 'virtualenv_options': []} - -Virtualenv uuid: 7c10fa5f-037e-49b1-a9dd-3462c739e239 - timestamp: 2007-01-15 00:00:00-03:00 - full path: /home/juan/.fades/7c10fa5f-037e-49b1-a9dd-3462c739e239 - dependencies: {} - interpreter: /usr/bin/python3 - options: {'pyvenv_options': [], 'virtualenv_options': []} - -Virtualenv uuid: 37de0f88-3db7-434a-a692-048aa35fbfe7 - timestamp: 2002-07-08 00:00:00-03:00 - full path: /home/juan/.fades/37de0f88-3db7-434a-a692-048aa35fbfe7 - dependencies: {} - interpreter: /usr/bin/python3 - options: {'pyvenv_options': [], 'virtualenv_options': []} - -Virtualenv uuid: 000236c6-5ddb-4422-b210-93e09fab603f - timestamp: 2017-12-06 00:00:00-03:00 - full path: /home/juan/.fades/000236c6-5ddb-4422-b210-93e09fab603f - dependencies: {} - interpreter: /usr/bin/python3 - options: {'pyvenv_options': [], 'virtualenv_options': []} +Virtualenv UUID: d1cf2e61-4ac5-467d-9b65-1a3c0e913bf3 + timestamp: 2011-06-16 00:00:00 + full path: /home/juan/.fades/d1cf2e61-4ac5-467d-9b65-1a3c0e913bf3 + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv UUID: 032e6e2c-bc7e-4a7f-ad1d-66ecb9106884 + timestamp: 2009-02-09 00:00:00 + full path: /home/juan/.fades/032e6e2c-bc7e-4a7f-ad1d-66ecb9106884 + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv UUID: 53c8f169-b105-4ed1-a7fc-25792b18fc4c + timestamp: 2001-06-17 00:00:00 + full path: /home/juan/.fades/53c8f169-b105-4ed1-a7fc-25792b18fc4c + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv UUID: 8cc6666c-fb5e-474b-a8a7-217c9558d5e2 + timestamp: 2017-08-05 00:00:00 + full path: /home/juan/.fades/8cc6666c-fb5e-474b-a8a7-217c9558d5e2 + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv UUID: 7a4a4eb8-b0d2-4d88-a890-4830278e0eb9 + timestamp: 2015-09-06 00:00:00 + full path: /home/juan/.fades/7a4a4eb8-b0d2-4d88-a890-4830278e0eb9 + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv UUID: 7c10fa5f-037e-49b1-a9dd-3462c739e239 + timestamp: 2007-01-15 00:00:00 + full path: /home/juan/.fades/7c10fa5f-037e-49b1-a9dd-3462c739e239 + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv UUID: 37de0f88-3db7-434a-a692-048aa35fbfe7 + timestamp: 2002-07-08 00:00:00 + full path: /home/juan/.fades/37de0f88-3db7-434a-a692-048aa35fbfe7 + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} + +Virtualenv UUID: 000236c6-5ddb-4422-b210-93e09fab603f + timestamp: 2017-12-06 00:00:00 + full path: /home/juan/.fades/000236c6-5ddb-4422-b210-93e09fab603f + dependencies: {} + interpreter: /usr/bin/python3 + options: {'pyvenv_options': [], 'virtualenv_options': []} From 0c4377cecaf3ac64cd9354d3165c97600c7411b9 Mon Sep 17 00:00:00 2001 From: juancarlospaco Date: Tue, 24 Apr 2018 17:13:04 -0300 Subject: [PATCH 17/20] Add optional filter to list of venvs. --- man/fades.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/fades.1 b/man/fades.1 index 98e3b26..b5dbcc8 100644 --- a/man/fades.1 +++ b/man/fades.1 @@ -114,8 +114,8 @@ Will check for updates in PyPI to verify if there are new versions for the reque Will remove all virtualenvs that haven't been used for more than MAX_DAYS_TO_KEEP days. .TP -.BR --list-venvs -List all virtualenvs, showing information (UUID, timestamp, path, dependencies, interpreter, etc). +.BR --list-venvs\fIFILTER\fR +List all virtualenvs, showing information (UUID, timestamp, path, dependencies, interpreter, etc). Optionally filter the list using FILTER, FILTER can be a word string or comma separated words. .SH EXAMPLES From b27c10c900ef8fe4d238e1968dc9fd57c77b72be Mon Sep 17 00:00:00 2001 From: juancarlospaco Date: Tue, 24 Apr 2018 17:13:09 -0300 Subject: [PATCH 18/20] Add optional filter to list of venvs. --- fades/main.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fades/main.py b/fades/main.py index 6ce11cd..e3c6676 100644 --- a/fades/main.py +++ b/fades/main.py @@ -132,7 +132,8 @@ def go(): "stats file.\n" "When this option is present, the cleaning takes place at the " "beginning of the execution.")) - parser.add_argument('--list-venvs', action='store_true', help=("List all venvs")) + parser.add_argument('-l', '--list-venvs', metavar='FILTER', nargs='?', const=' ', + help=("List all venvs. Optionally filter the list by FILTER.")) parser.add_argument('child_program', nargs='?', default=None) parser.add_argument('child_options', nargs=argparse.REMAINDER) @@ -163,7 +164,8 @@ def go(): logger.debug("Arguments: %s", args) if args.list_venvs: - helpers.list_venvs(os.path.join(helpers.get_basedir(), 'venvs.idx')) + print(f"args.list_venvs:{args.list_venvs}.") + helpers.list_venvs(os.path.join(helpers.get_basedir(), 'venvs.idx'), args.list_venvs) sys.exit(0) # verify that the module is NOT being used from a virtualenv From 8026cf59e4f3258ad9fec7f8df25f8bf161bd847 Mon Sep 17 00:00:00 2001 From: juancarlospaco Date: Tue, 24 Apr 2018 17:13:15 -0300 Subject: [PATCH 19/20] Add optional filter to list of venvs. --- fades/helpers.py | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/fades/helpers.py b/fades/helpers.py index c5c968d..5ad0a7c 100644 --- a/fades/helpers.py +++ b/fades/helpers.py @@ -16,11 +16,13 @@ """A collection of utilities for fades.""" -import os -import sys + import json import logging +import os +import re import subprocess +import sys from datetime import datetime from urllib import request @@ -40,6 +42,24 @@ print(json.dumps(d)) """ +LIST_VENVS_TEMPLATE = """ +Virtualenv UUID: {uid} + timestamp: {dat} + full path: {pat} + dependencies: {pac} + interpreter: {pyv} + options: {opt} +""" + +# UUID Regex, for v1 to v5. +UUID_REGEX = re.compile(( + '[a-f0-9]{8}-' + '[a-f0-9]{4}-' + '[1-5]' # Versions. + '[a-f0-9]{3}-' + '[89ab][a-f0-9]{3}-' + '[a-f0-9]{12}$' +), re.IGNORECASE) # the url to query PyPI for project versions BASE_PYPI_URL = 'https://pypi.python.org/pypi/{name}/json' @@ -259,22 +279,23 @@ def check_pypi_exists(dependencies): return True -def list_venvs(index_path): +def list_venvs(index_path, query=None, template=LIST_VENVS_TEMPLATE): """List all venvs from an index file path and print info to stdout.""" if os.path.isfile(index_path): - tmplt = ("\nVirtualenv uuid:\t{uid}\n\ttimestamp:\t{dat}\n\tfull path:\t{pat}\n" - "\tdependencies:\t{pac}\n\tinterpreter:\t{pyv}\n\toptions:\t{opt}\n") + if query: + query = tuple(set(query.lower().strip().split(","))) venv_info = "" with open(index_path) as jotason: for jotason_line in jotason: + if query and not any([qry in jotason_line.lower() for qry in query]): + continue v_dct_get = json.loads(jotason_line).get - venv_info += tmplt.format( - uid=v_dct_get("metadata")["env_path"][18:], + venv_info += template.format( + uid=UUID_REGEX.search(v_dct_get("metadata")["env_path"]).group(0), pat=v_dct_get("metadata")["env_path"], pac=v_dct_get("installed"), pyv=v_dct_get("interpreter"), opt=v_dct_get("options"), - dat=datetime.fromtimestamp(v_dct_get("timestamp")).replace( - microsecond=0).astimezone().isoformat(" ")) + dat=datetime.fromtimestamp(v_dct_get("timestamp"))) print(venv_info) return venv_info From 9a0a91c555768b4c5154a72dd1989fe9582eb12e Mon Sep 17 00:00:00 2001 From: juancarlospaco Date: Tue, 24 Apr 2018 17:13:26 -0300 Subject: [PATCH 20/20] Add optional filter to list of venvs. --- README.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.rst b/README.rst index 64b41b2..6115f74 100644 --- a/README.rst +++ b/README.rst @@ -375,6 +375,10 @@ Removes a virtualenv matching the given uuid from disk and cache index. List all virtualenvs, showing the information (UUID, timestamp, dependencies, interpreter, etc). +``fades --list-venvs ipython,prospector`` + +Optionally filter the list using FILTER, FILTER can be a word string or comma separated words. + What if Python is updated in my system? ---------------------------------------