commit azure-cli-feedback for openSUSE:Factory
Hello community, here is the log from the commit of package azure-cli-feedback for openSUSE:Factory checked in at 2019-05-22 11:00:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/azure-cli-feedback (Old) and /work/SRC/openSUSE:Factory/.azure-cli-feedback.new.5148 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "azure-cli-feedback" Wed May 22 11:00:09 2019 rev:5 rq:696836 version:2.2.0 Changes: -------- --- /work/SRC/openSUSE:Factory/azure-cli-feedback/azure-cli-feedback.changes 2018-10-15 10:44:37.435314408 +0200 +++ /work/SRC/openSUSE:Factory/.azure-cli-feedback.new.5148/azure-cli-feedback.changes 2019-05-22 11:00:12.882752093 +0200 @@ -1,0 +2,15 @@ +Wed Apr 17 07:19:57 UTC 2019 - John Paul Adrian Glaubitz <adrian.glaubitz@suse.com> + +- New upstream release + + Version 2.2.0 + + For detailed information about changes see the + HISTORY.txt file provided with this package +- Bump minimum version for Python Azure SDK namespace + packages to 3.0.0 in BuildRequires and Requires +- Remove python3-devel package from BuildRequires +- Remove unzip package from BuildRequires +- Run fdupes to hardlink duplicate files + + Add fdupes to BuildRequires + + Add %fdupes invocation to %install + +------------------------------------------------------------------- Old: ---- azure-cli-feedback-2.1.4.tar.gz New: ---- azure-cli-feedback-2.2.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ azure-cli-feedback.spec ++++++ --- /var/tmp/diff_new_pack.JEchYy/_old 2019-05-22 11:00:13.618751139 +0200 +++ /var/tmp/diff_new_pack.JEchYy/_new 2019-05-22 11:00:13.622751134 +0200 @@ -1,7 +1,7 @@ # # spec file for package azure-cli-feedback # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: azure-cli-feedback -Version: 2.1.4 +Version: 2.2.0 Release: 0 Summary: Microsoft Azure CLI 'feedback' Command Module License: MIT @@ -27,15 +27,14 @@ Source1: LICENSE.txt BuildRequires: azure-cli-command-modules-nspkg BuildRequires: azure-cli-nspkg -BuildRequires: python3-azure-nspkg -BuildRequires: python3-devel +BuildRequires: fdupes +BuildRequires: python3-azure-nspkg >= 3.0.0 BuildRequires: python3-setuptools -BuildRequires: unzip Requires: azure-cli-command-modules-nspkg Requires: azure-cli-core Requires: azure-cli-nspkg Requires: python3-applicationinsights -Requires: python3-azure-nspkg +Requires: python3-azure-nspkg >= 3.0.0 Conflicts: azure-cli < 2.0.0 BuildArch: noarch @@ -55,6 +54,7 @@ %install python3 setup.py install --root=%{buildroot} --prefix=%{_prefix} --install-lib=%{python3_sitelib} +%python_expand %fdupes %{buildroot}%{$python_sitelib} rm -rf %{buildroot}%{python3_sitelib}/azure/cli/command_modules/__init__.* rm -rf %{buildroot}%{python3_sitelib}/azure/cli/command_modules/__pycache__ rm -rf %{buildroot}%{python3_sitelib}/azure/cli/__init__.* ++++++ azure-cli-feedback-2.1.4.tar.gz -> azure-cli-feedback-2.2.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-feedback-2.1.4/HISTORY.rst new/azure-cli-feedback-2.2.0/HISTORY.rst --- old/azure-cli-feedback-2.1.4/HISTORY.rst 2018-07-14 01:41:34.000000000 +0200 +++ new/azure-cli-feedback-2.2.0/HISTORY.rst 2019-04-05 00:46:52.000000000 +0200 @@ -3,6 +3,12 @@ Release History =============== +2.2.0 ++++++ +* `az feedback` now shows metadata on recently run commands +* `az feedback` prompts user to assist in issue creation process. Opens browser to issue url and copies auto-generated issue + text containing command and system related information to clipboard. Prints out issue body when run with '--verbose' + 2.1.4 +++++ * Minor fixes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-feedback-2.1.4/PKG-INFO new/azure-cli-feedback-2.2.0/PKG-INFO --- old/azure-cli-feedback-2.1.4/PKG-INFO 2018-07-14 01:41:55.000000000 +0200 +++ new/azure-cli-feedback-2.2.0/PKG-INFO 2019-04-05 00:47:37.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: azure-cli-feedback -Version: 2.1.4 +Version: 2.2.0 Summary: Microsoft Azure Command-Line Tools Feedback Command Module Home-page: https://github.com/Azure/azure-cli Author: Microsoft Corporation @@ -20,6 +20,12 @@ Release History =============== + 2.2.0 + +++++ + * `az feedback` now shows metadata on recently run commands + * `az feedback` prompts user to assist in issue creation process. Opens browser to issue url and copies auto-generated issue + text containing command and system related information to clipboard. Prints out issue body when run with '--verbose' + 2.1.4 +++++ * Minor fixes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-feedback-2.1.4/azure/cli/command_modules/feedback/custom.py new/azure-cli-feedback-2.2.0/azure/cli/command_modules/feedback/custom.py --- old/azure-cli-feedback-2.1.4/azure/cli/command_modules/feedback/custom.py 2018-07-14 01:41:34.000000000 +0200 +++ new/azure-cli-feedback-2.2.0/azure/cli/command_modules/feedback/custom.py 2019-04-05 00:46:52.000000000 +0200 @@ -4,61 +4,552 @@ # -------------------------------------------------------------------------------------------- from __future__ import print_function -import sys +import os +import math +import platform +import datetime + +try: + from urllib.parse import urlencode # python 3 +except ImportError: + from urllib import urlencode # python 2 + +from collections import namedtuple from knack.log import get_logger from knack.prompting import prompt, NoTTYException from knack.util import CLIError -from azure.cli.core.util import COMPONENT_PREFIX, get_installed_cli_distributions -from azure.cli.core.telemetry import set_feedback +from azure.cli.core.util import get_az_version_string +from azure.cli.core.azlogging import _UNKNOWN_COMMAND, _CMD_LOG_LINE_PREFIX +from azure.cli.core.util import open_page_in_browser +import pyperclip + +_ONE_MIN_IN_SECS = 60 + +_ONE_HR_IN_SECS = 3600 + logger = get_logger(__name__) -MSG_RATE = '\nHow likely is it you would recommend our Azure CLI to a friend or colleague? [0 to 10]: ' -MSG_INTR = 'We appreciate your feedback! This survey is only two questions and should take less than a minute.' -MSG_BAD = '\nWhat changes would we have to make for you to give us a higher rating? ' -MSG_GOOD = '\nWhat do we do really well? ' -MSG_EMIL = '\nIf you would like to join our insiders program and receive tips, tricks, and early access to new ' \ - 'features, let us know by leaving your email address (leave blank to skip): ' -MSG_THNK = '\nThanks for your feedback!' +_MSG_THNK = 'Thanks for your feedback!' + +_GET_STARTED_URL = "aka.ms/azcli/get-started" +_QUESTIONS_URL = "aka.ms/azcli/questions" +_CLI_ISSUES_URL = "aka.ms/azcli/issues" +_EXTENSIONS_ISSUES_URL = "aka.ms/azcli/ext/issues" + +_MSG_INTR = \ + '\nWe appreciate your feedback!\n\n' \ + 'For more information on getting started, visit: {}\n' \ + 'If you have questions, visit our Stack Overflow page: {}\n'\ + .format(_GET_STARTED_URL, _QUESTIONS_URL) + +_MSG_CMD_ISSUE = "\nEnter the number of the command you would like to create an issue for. Enter q to quit: " + +_MSG_ISSUE = "Would you like to create an issue? Enter Y or N: " + +_ISSUES_TEMPLATE_PREFIX = """ + +BEGIN TEMPLATE +=============== +**A browser has been opened to {} to create an issue.** +**The issue template has been copied to your clipboard. You can also run `az feedback --verbose` to emit the output to stdout.** +""" + +_ISSUES_TEMPLATE = """ + +### **This is an autogenerated template. Please review and update as needed.** + +## Describe the bug + +**Command Name** +`{command_name}` + +**Errors:** +{errors_string} + +## To Reproduce: +Steps to reproduce the behavior. Note: Command arguments have been redacted. + +- `Fill in additional info here` +- `Run: {executed_command}` + +## Expected Behavior + +A clear and concise description of what you expected to happen. + +## Environment Summary +``` +{platform} +{python_info} +{shell} + +{cli_version} +``` +## Additional Context +Add any other context about the problem here. + +<!-- Please do not remove these markdown comments --> +{auto_gen_comment} + +""" + +_AUTO_GEN_COMMENT = "<!--auto-generated-->" + +_LogMetadataType = namedtuple('LogMetadata', ['cmd', 'seconds_ago', 'file_path', 'p_id']) + + +class CommandLogFile(object): + _LogRecordType = namedtuple("LogRecord", ["p_id", "date_time", "level", "logger", "log_msg"]) + UNKNOWN_CMD = "Unknown" + + def __init__(self, log_file_path, time_now=None): + + if (time_now is not None) and (not isinstance(time_now, datetime.datetime)): + raise TypeError("Expected type {} for time_now, instead received {}.".format(datetime.datetime, type(time_now))) # pylint: disable=line-too-long + + if not os.path.isfile(log_file_path): + raise ValueError("File {} is not an existing file.".format(log_file_path)) + + self._command_name = None + self._log_file_path = log_file_path + + if time_now is None: + self._time_now = datetime.datetime.now() + else: + self._time_now = time_now + + self._metadata = self._get_command_metadata_from_file() + self._data = None + + @property + def metadata_tup(self): + return self._metadata + + @property + def command_data_dict(self): + if not self._data: + self._data = self._get_command_data_from_metadata() + return self._data + def get_command_name_str(self): + if self._command_name is not None: + return self._command_name # attempt to return cached command name + + if not self.metadata_tup: + return "" + + args = self.command_data_dict.get("command_args", "") + + if self.metadata_tup.cmd != self.UNKNOWN_CMD: + self._command_name = self.metadata_tup.cmd + + if "-h" in args or "--help" in args: + self._command_name += " --help" + else: + self._command_name = self.UNKNOWN_CMD + if args: + command_args = args if len(args) < 16 else args[:11] + " ..." + command_args = command_args.replace("=", "").replace("{", "").replace("}", "") + self._command_name = "{} ({}) ".format(self._command_name, command_args) + + return self._command_name + + def get_command_status(self): + if not self.command_data_dict: + return "" + + was_successful = self.command_data_dict.get("success", None) + if was_successful is None: + success_msg = "RUNNING" + else: + success_msg = "SUCCESS" if was_successful else "FAILURE" + return success_msg + + def get_command_time_str(self): + if not self.metadata_tup: + return "" + + total_seconds = self.metadata_tup.seconds_ago + + time_delta = datetime.timedelta(seconds=total_seconds) + logger.debug("%s time_delta", time_delta) + + if time_delta.days > 0: + time_str = "Ran: {} days ago".format(time_delta.days) + elif total_seconds > _ONE_HR_IN_SECS: + hrs, secs = divmod(total_seconds, _ONE_HR_IN_SECS) + logger.debug("%s hrs, %s secs", hrs, secs) + hrs = int(hrs) + mins = math.floor(secs / _ONE_MIN_IN_SECS) + time_str = "Ran: {} hrs {:02} mins ago".format(hrs, mins) + elif total_seconds > _ONE_MIN_IN_SECS: + time_str = "Ran: {} mins ago".format(math.floor(total_seconds / _ONE_MIN_IN_SECS)) + else: + time_str = "Ran: {} secs ago".format(math.floor(total_seconds)) + + return time_str + + def _get_command_metadata_from_file(self): + if not self._log_file_path: + return None + + time_now = datetime.datetime.now() if not self._time_now else self._time_now -def _prompt_net_promoter_score(): - score = -1 - help_string = 'Please rate between 0 and 10' - while score < 0 or score > 10: try: - score = int(prompt(MSG_RATE, help_string=help_string)) - except ValueError: - logger.warning(help_string) + _, file_name = os.path.split(self._log_file_path) + poss_date, poss_time, poss_command, poss_pid, _ = file_name.split(".") + date_time_stamp = datetime.datetime.strptime("{}-{}".format(poss_date, poss_time), "%Y-%m-%d-%H-%M-%S") + command = "az " + poss_command.replace("_", " ") if poss_command != _UNKNOWN_COMMAND else self.UNKNOWN_CMD # pylint: disable=line-too-long + except ValueError as e: + logger.debug("Could not load metadata from file name %s.", self._log_file_path) + logger.debug(e) + return None + + difference = time_now - date_time_stamp + + total_seconds = difference.total_seconds() + + return _LogMetadataType(cmd=command, seconds_ago=total_seconds, file_path=self._log_file_path, p_id=int(poss_pid)) # pylint: disable=line-too-long + + def _get_command_data_from_metadata(self): # pylint: disable=too-many-statements + def _get_log_record_list(log_fp, p_id): + """ + Get list of records / messages in the log file + :param log_fp: log file object + :param p_id: process id of command + :return: + """ + prev_record = None + log_record_list = [] + for line in log_fp: + # attempt to extract log data + log_record = CommandLogFile._get_info_from_log_line(line, p_id) + + if log_record: # if new record parsed, add old record to the list + if prev_record: + log_record_list.append(prev_record) + prev_record = log_record + elif prev_record: # otherwise this is a continuation of a log record, add to prev record + new_log_msg = prev_record.log_msg + line + prev_record = CommandLogFile._LogRecordType(p_id=prev_record.p_id, date_time=prev_record.date_time, + # pylint: disable=line-too-long + level=prev_record.level, logger=prev_record.logger, + log_msg=new_log_msg) + if prev_record: + log_record_list.append(prev_record) + return log_record_list + + if not self.metadata_tup: + return {} - return score + _EXT_NAME_PREFIX = "extension name:" + _EXT_VERS_PREFIX = "extension version:" + file_name = self.metadata_tup.file_path + p_id = self.metadata_tup.p_id + + try: + with open(file_name, 'r') as log_fp: + log_record_list = _get_log_record_list(log_fp, p_id) + except IOError: + logger.debug("Failed to open command log file %s", file_name) + return {} + + if not log_record_list: + logger.debug("No command log messages found in file %s", file_name) + return {} + + log_data = {} + # 1. Figure out whether the command was successful or not. Last log record should be the exit code + try: + status_msg = log_record_list[-1].log_msg.strip() + if status_msg.startswith("exit code"): + idx = status_msg.index(":") # raises ValueError + exit_code = int(log_record_list[-1].log_msg[idx + 1:].strip()) + log_data["success"] = True if not exit_code else False + except (IndexError, ValueError): + logger.debug("Couldn't extract exit code from command log %s.", file_name) + + # 2. If there are any errors, this is a failed command. Log the errors + # 3. Also get extension information. + for record in log_record_list: + errors = log_data.setdefault("errors", []) # log_data["errors"] + if record.level.lower() == "error": + log_data["success"] = False + errors.append(record.log_msg) + + poss_ext_msg = record.log_msg.strip() + if record.level.lower() == "info": + if poss_ext_msg.startswith(_EXT_NAME_PREFIX): + log_data["extension_name"] = poss_ext_msg[len(_EXT_NAME_PREFIX):].strip() + elif poss_ext_msg.startswith(_EXT_VERS_PREFIX): + log_data["extension_version"] = poss_ext_msg[len(_EXT_VERS_PREFIX):].strip() + + # 4. Get command args string. from first record + try: + command_args_msg = log_record_list[0].log_msg.strip() + if command_args_msg.lower().startswith("command args:"): + idx = command_args_msg.index(":") + log_data["command_args"] = command_args_msg[idx + 1:].strip() + else: + raise ValueError + except (IndexError, ValueError): + logger.debug("Couldn't get command args from command log %s.", file_name) + + return log_data + + @staticmethod + def _get_info_from_log_line(line, p_id): + """ + + Extract log line information based on the following command log format in azlogging.py + + lfmt = logging.Formatter('%(process)d | %(created)s | %(levelname)s | %(name)s | %(message)s') + + :param line: the line from the log file. + :return: returned parsed line information or None + """ + + if not line.startswith(_CMD_LOG_LINE_PREFIX): + return None + + line = line[len(_CMD_LOG_LINE_PREFIX):] + parts = line.split("|", 4) + + if len(parts) != 5: # there must be 5 items + return None + + for i, part in enumerate(parts): + parts[i] = part.strip() + if i == 0: + parts[0] = int(parts[0]) + if parts[0] != p_id: # ensure that this is indeed a valid log. + return None + + return CommandLogFile._LogRecordType(*parts) + + +def _build_issue_info_tup(command_log_file=None): + def _get_parent_proc_name(): + import psutil + parent = psutil.Process(os.getpid()).parent() + if parent: + # powershell.exe launches cmd.exe to launch the cli. + grandparent = parent.parent() + if grandparent and grandparent.name().lower().startswith("powershell"): + return grandparent.name() + # if powershell is not the grandparent, simply return the parent's name. + return parent.name() + return None + + format_dict = {"command_name": "", "errors_string": "", + "executed_command": ""} + + is_ext = False + # Get command information, if applicable + if command_log_file: + command_name = command_log_file.metadata_tup.cmd + format_dict["command_name"] = command_name + + if command_log_file.command_data_dict: + errors = "\n".join(command_log_file.command_data_dict.get("errors", [])) + executed_command = command_log_file.command_data_dict.get("command_args", "") + extension_name = command_log_file.command_data_dict.get("extension_name", "") + extension_version = command_log_file.command_data_dict.get("extension_version", "") + + extension_info = "" + if extension_name: + extension_info = "\nExtension Name: {}. Version: {}.".format(extension_name, extension_version) + is_ext = True + + if errors: + num_lines = errors.count("\n") + reaction = ":confused:" + if num_lines >= 100: + reaction = ":expressionless:" + elif num_lines >= 15: + reaction = ":open_mouth:" + errors = "\n{}\n\n```{}```".format(reaction, errors) + + format_dict["errors_string"] = errors + format_dict["executed_command"] = "az " + executed_command if executed_command else executed_command + format_dict["command_name"] += extension_info + + # Get other system information + format_dict["cli_version"] = _get_az_version_summary() + format_dict["python_info"] = "Python {}".format(platform.python_version()) + format_dict["platform"] = "{}".format(platform.platform()) + format_dict["shell"] = "Shell: {}".format(_get_parent_proc_name()) + format_dict["auto_gen_comment"] = _AUTO_GEN_COMMENT + + issues_url = _EXTENSIONS_ISSUES_URL if is_ext else _CLI_ISSUES_URL + + # prefix formatted url with 'https://' if necessary and supply empty body to remove any existing issue template + formatted_issues_url = issues_url + if not formatted_issues_url.startswith("http"): + formatted_issues_url = "https://" + formatted_issues_url + new_placeholder = urlencode({'body': "The issue has been copied to your clipboard. Paste it here!" + "\nTo print out the issue body locally, run `az feedback --verbose`"}) + formatted_issues_url = "{}?{}".format(formatted_issues_url, new_placeholder) + + return _ISSUES_TEMPLATE_PREFIX.format(issues_url), _ISSUES_TEMPLATE.format(**format_dict), formatted_issues_url + + +def _get_az_version_summary(): + """ + This depends on get_az_version_string not being changed, add some tests to make this and other methods more robust. + :return: az version info + """ + az_vers_string = get_az_version_string()[0] + + lines = az_vers_string.splitlines() + + new_lines = [] + ext_line = -1 + legal_line = -1 + for i, line in enumerate(lines): + if line.startswith("azure-cli"): + new_lines.append(line) + if line.lower().startswith("extensions:"): + ext_line = i + continue + l_lower = line.lower() + if all(["legal" in l_lower, "docs" in l_lower, "info" in l_lower]): + legal_line = i + break + + new_lines.append("") + + if 0 < ext_line < legal_line: + for i in range(ext_line, legal_line): + new_lines.append(lines[i]) + + return "\n".join(new_lines) + + +def _get_command_log_files(cli_ctx, time_now=None): + command_logs_dir = cli_ctx.logging.get_command_log_dir() + files = os.listdir(command_logs_dir) + files = (file_name for file_name in files if file_name.endswith(".log")) + files = sorted(files) + command_log_files = [] + for file_name in files: + file_path = os.path.join(command_logs_dir, file_name) + cmd_log_file = CommandLogFile(file_path, time_now) + + if cmd_log_file.metadata_tup: + command_log_files.append(cmd_log_file) + else: + logger.debug("%s is an invalid command log file.", file_path) + return command_log_files + + +def _display_recent_commands(cmd): + def _pad_string(my_str, pad_len): + while len(my_str) < pad_len: + my_str += " " + return my_str + + time_now = datetime.datetime.now() + + command_log_files = _get_command_log_files(cmd.cli_ctx, time_now) + + # if no command log files, return + if not command_log_files: + return [] + + command_log_files = command_log_files[-9:] + + max_len_dict = dict(name_len=0, success_len=0, time_len=0) + + for log_file in command_log_files: + max_len_dict["name_len"] = max(len(log_file.get_command_name_str()), max_len_dict["name_len"]) + max_len_dict["success_len"] = max(len(log_file.get_command_status()), max_len_dict["success_len"]) + max_len_dict["time_len"] = max(len(log_file.get_command_time_str()), max_len_dict["time_len"]) + + print("Recent commands:\n") + command_log_files = [None] + command_log_files + for i, log_info in enumerate(command_log_files): + if log_info is None: + print(" [{}] {}".format(i, "create a generic issue.")) + else: + cmd_name = _pad_string(log_info.get_command_name_str(), max_len_dict["name_len"]) + success_msg = _pad_string(log_info.get_command_status() + ".", max_len_dict["success_len"] + 1) + time_msg = _pad_string(log_info.get_command_time_str() + ".", max_len_dict["time_len"] + 1) + print(" [{}] {}: {} {}".format(i, cmd_name, success_msg, time_msg)) + + return command_log_files + + +def _prompt_issue(recent_command_list): + if recent_command_list: + max_idx = len(recent_command_list) - 1 + ans = -1 + help_string = 'Please choose between 0 and {}, or enter q to quit: '.format(max_idx) + + while ans < 0 or ans > max_idx: + try: + ans = prompt(_MSG_CMD_ISSUE.format(max_idx), help_string=help_string) + if ans.lower() in ["q", "quit"]: + ans = ans.lower() + break + ans = int(ans) + except ValueError: + logger.warning(help_string) + ans = -1 + + else: + ans = None + help_string = 'Please choose between Y and N: ' + + while not ans: + ans = prompt(_MSG_ISSUE, help_string=help_string) + if ans.lower() not in ["y", "n", "yes", "no", "q"]: + ans = None + continue + + # strip to short form + ans = ans[0].lower() if ans else None + + if ans in ["y", "n"]: + if ans == "y": + prefix, body, url = _build_issue_info_tup() + else: + return False + else: + if ans in ["q", "quit"]: + return False + if ans == 0: + prefix, body, url = _build_issue_info_tup() + else: + prefix, body, url = _build_issue_info_tup(recent_command_list[ans]) + + print(prefix) + + # open issues page in browser and copy issue body to clipboard + try: + pyperclip.copy(body) + except pyperclip.PyperclipException as ex: + logger.debug(ex) -def _get_version_info(): - installed_dists = get_installed_cli_distributions() + logger.info(body) + open_page_in_browser(url) - component_version_info = sorted([{'name': dist.key.replace(COMPONENT_PREFIX, ''), - 'version': dist.version} - for dist in installed_dists - if dist.key.startswith(COMPONENT_PREFIX)], - key=lambda x: x['name']) - return str(component_version_info), sys.version + return True -def handle_feedback(): +def handle_feedback(cmd): try: - print(MSG_INTR) - score = _prompt_net_promoter_score() - if score == 10: - suggestion = prompt(MSG_GOOD) - else: - suggestion = prompt(MSG_BAD) - email_address = prompt(MSG_EMIL) - set_feedback('[{}]{}[{}]'.format(score, suggestion, email_address)) - print(MSG_THNK) + print(_MSG_INTR) + recent_commands = _display_recent_commands(cmd) + res = _prompt_issue(recent_commands) + + if res: + print(_MSG_THNK) + return except NoTTYException: - raise CLIError('This command is interactive and no tty available.') + raise CLIError('This command is interactive, however no tty is available.') except (EOFError, KeyboardInterrupt): print() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-feedback-2.1.4/azure_cli_feedback.egg-info/PKG-INFO new/azure-cli-feedback-2.2.0/azure_cli_feedback.egg-info/PKG-INFO --- old/azure-cli-feedback-2.1.4/azure_cli_feedback.egg-info/PKG-INFO 2018-07-14 01:41:55.000000000 +0200 +++ new/azure-cli-feedback-2.2.0/azure_cli_feedback.egg-info/PKG-INFO 2019-04-05 00:47:37.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: azure-cli-feedback -Version: 2.1.4 +Version: 2.2.0 Summary: Microsoft Azure Command-Line Tools Feedback Command Module Home-page: https://github.com/Azure/azure-cli Author: Microsoft Corporation @@ -20,6 +20,12 @@ Release History =============== + 2.2.0 + +++++ + * `az feedback` now shows metadata on recently run commands + * `az feedback` prompts user to assist in issue creation process. Opens browser to issue url and copies auto-generated issue + text containing command and system related information to clipboard. Prints out issue body when run with '--verbose' + 2.1.4 +++++ * Minor fixes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-feedback-2.1.4/azure_cli_feedback.egg-info/requires.txt new/azure-cli-feedback-2.2.0/azure_cli_feedback.egg-info/requires.txt --- old/azure-cli-feedback-2.1.4/azure_cli_feedback.egg-info/requires.txt 2018-07-14 01:41:55.000000000 +0200 +++ new/azure-cli-feedback-2.2.0/azure_cli_feedback.egg-info/requires.txt 2019-04-05 00:47:37.000000000 +0200 @@ -1,2 +1 @@ -applicationinsights azure-cli-core diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-feedback-2.1.4/setup.py new/azure-cli-feedback-2.2.0/setup.py --- old/azure-cli-feedback-2.1.4/setup.py 2018-07-14 01:41:34.000000000 +0200 +++ new/azure-cli-feedback-2.2.0/setup.py 2019-04-05 00:46:52.000000000 +0200 @@ -15,7 +15,7 @@ cmdclass = {} -VERSION = "2.1.4" +VERSION = "2.2.0" CLASSIFIERS = [ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', @@ -31,7 +31,6 @@ ] DEPENDENCIES = [ - 'applicationinsights', 'azure-cli-core', ]
participants (1)
-
root