PK+^mJ%[azureshell/cache.py# -*- coding: utf-8 -*- class AzureShellCache: __inst = None __cache = {} @staticmethod def Instance(): if AzureShellCache.__inst == None: AzureShellCache() return AzureShellCache.__inst def __init__(self): if AzureShellCache.__inst != None: raise Exception("This must not be called!!") AzureShellCache.__inst = self def set(self, k, v): self.__cache[k] = v def get(self, k): return self.__cache.get(k) PKܾqJ**azureshell/__init__.py# -*- coding: utf-8 -*- from __future__ import print_function, unicode_literals import os import sys import argparse from .azureshell import AzureShell from .completer import AzureShellCompleter from .index import AzureShellIndex, AzureShellIndexException from .config import AzureShellConfig from .cache import AzureShellCache from .utils import get_cli_version, find_executable_path, _ERR from .logger import init_logger __version__ = '0.1.0' _DEFAULT_AZURE_SHELL_BASE_DIR = '{}/.azureshell'.format(os.environ['HOME']) _MINIMUM_AZURE_CLI_VERSION = '2.0.0' def main(): parser = argparse.ArgumentParser(description='An interactive Azure CLI command line interface') parser.add_argument( '--version', action='version', version=__version__) parser.add_argument( '--basedir', help='Azure Shell base dir path ($HOME/.azureshell by default)') parser.add_argument( '--config', help='Azure Shell config file path ($HOME/.azureshell/azureshell.conf by default)') parser.add_argument( '--index', help='Azure Shell index file to load ($HOME/.azureshel/cli-index-.json)') args = parser.parse_args() ## az executable command path check if not find_executable_path('az'): _ERR("[ERROR] NO azure cli (az) executable command found!") _ERR("Please install Azure CLI 2.0 and set its executable dir to PATH") _ERR("See https://github.com/Azure/azure-cli") sys.exit(1) azure_cli_version = utils.get_cli_version() ## Check minimum azure-cli version if azure_cli_version < _MINIMUM_AZURE_CLI_VERSION: _ERR("[ERROR] Azure CLI 2.0 minimum version failure!") _ERR("Minimum azure-cli version required: {} (Your version: {})".format(_MINIMUM_AZURE_CLI_VERSION,azure_cli_version)) _ERR("Please install the latest azure-cli and set its executable dir to PATH") _ERR("See https://github.com/Azure/azure-cli") sys.exit(1) print("azure-shell version:{}".format(__version__)) #print("AzureCLI version:{}".format(azure_cli_version)) base_dir = args.basedir if args.basedir else _DEFAULT_AZURE_SHELL_BASE_DIR config_file = args.config if args.config else '{}/azureshell.conf'.format(base_dir) config = None ## Check if config file exists if not os.path.exists(config_file): _ERR("[WARNING] No config file found:{}".format(config_file)) _ERR("Creating an default config file :{}".format(config_file)) AzureShellConfig.makedefaultconfig(config_file) config = AzureShellConfig(config_file) init_logger('azureshell', config.log_file, config.log_level) index = AzureShellIndex(base_dir) index_file = '' index_version = '' if args.index: index_file = args.index # Check if specified index file exists and exit if the file does not exist if not os.path.exists(index_file): _ERR("[ERROR] index file doesn't exist: {}".format(index_file)) sys.exit(1) else: # Check if default index file exists and download the file if not exist on local index_version = index.get_local_version() index_file = index.get_index_file(index_version) if not index_version or \ not os.path.exists(index_file) or index_version < azure_cli_version: index = AzureShellIndex(base_dir) index_version = index.download_index_from_repository(azure_cli_version) index_file = index.get_index_file(index_version) AzureShellCache.Instance().set('base_dir', base_dir) AzureShellCache.Instance().set('index_file', index_file) AzureShellCache.Instance().set('config_file',config_file) index_data = {} try: index_data = AzureShellIndex.load_index(index_file) except AzureShellIndexException as e: _ERR("[ERROR] index file loading failure: {}".format(index_file)) _ERR(str(e)) sys.exit(1) completer = AzureShellCompleter(index_data) azureshell = AzureShell(config,completer) azureshell.run() if __name__ == '__main__': main() PKrJ/azureshell/completer.py# -*- coding: utf-8 -*- from __future__ import unicode_literals import os import logging from prompt_toolkit.completion import Completer, Completion logger = logging.getLogger('azureshell.completer') class AzureShellCompleter(Completer): def __init__(self, index_data): self._index = index_data self._root_name = 'az' self._current_name = '' self._current = self._index[self._root_name] self._last_position = 0 self._current_line = '' self._last_option = '' self.cmd_path = [self._current_name] @property def last_option(self): return self._last_option @property def current_command(self): return u' '.join(self.cmd_path) def get_completions(self, document, complete_event): cursor = document.text_before_cursor stripped_cursor = cursor.strip() logger.debug("get_completions cursor:{}".format(cursor)) # Skip _autocomplete if user typed in NON 'az' command if stripped_cursor and not stripped_cursor.startswith('az'): # Skip except the case that stripped_cursor is 'a' if not stripped_cursor =='a': return completions = self._autocomplete(cursor) prompt_completions = [] word_before_cursor = '' if stripped_cursor: word_before_cursor = stripped_cursor.split()[-1] for completion in completions: arg_tree = self._current.get('argument_tree', {}) if completion.startswith('--') and completion in arg_tree: meta = arg_tree[completion] if meta['required']: display_text = '%s (required)' % completion else: display_text = completion display_meta = arg_tree[completion].get('help','') elif completion == 'az': display_text = completion display_meta = '' else: cmd_tree = self._current.get('command_tree',{}) display_text = completion display_meta = cmd_tree[completion].get('summary','') if cursor and cursor[-1] == ' ': location = 0 else: location = -len(word_before_cursor) # Converting multiple options like '--help -h' into single # like '--help' for usability normalized_completion = completion.split()[0] prompt_completions.append ( Completion(normalized_completion, location, display=display_text, display_meta=display_meta) ) for c in prompt_completions: yield c def _autocomplete(self, line): current_length = len(line) self._current_line = line logger.debug("_autocomplete cur_line:{} (cur_len:{}, last_pos:{})".format(self._current_line, current_length, self._last_position)) if current_length == 1 and self._last_position > 1: self._reset() elif current_length < self._last_position: # Hit backspace, and handling backspace return self._handle_backspace() elif not line: return [] #elif current_length != self._last_position + 1: # return self._complete_from_full_parse() # Only update the _last_position after the cases above were verified self._last_position = len(line) # Autocomplete with 'az' if line is a single space or 'a' # (assuming that user hits a space on a new line or typed in 'a') stripped_line = line.strip() if line and ( not stripped_line or stripped_line == 'a' ): return ['az'] # Skip if it's only space ' ' words = line.split() if (len(words) < 1): return [] # Now you have at least single word in the line like # azure> az # azure> az vm # azure> az vm list .. last_word = words[-1] logger.debug("_autocomplete last_word: {}".format(last_word)) if last_word in self._current.get('argument_tree', {}): # The last thing we completed was an argument, record this as self.last_arg self._last_option = last_word if line[-1] == ' ': # this is the case like: # (1)'az vm ' or (2)'az vm --debug ' # and # (1) current command is 'az vm', then proceed next command # completions if the command has childres # (2) line is 'az vm --debug ', and current command is 'az vm', # then process the current command completion if not last_word.startswith('-'): next_command = self._current['command_tree'].get(last_word) if next_command is not None: self._current = next_command self._current_name = last_word self.cmd_path.append(self._current_name) return self._current['commands'][:] elif last_word.startswith('-'): all_args = self._current['arguments'] # Select args with Forward matching return [arg for arg in sorted(all_args) if arg.startswith(last_word)] logger.debug("_autocomplete dump: {}".format([cmd for cmd in sorted(self._current['commands']) if cmd.startswith(last_word)])) # Select commands with Forward matching return [cmd for cmd in sorted(self._current['commands']) if cmd.startswith(last_word)] def _reset(self): self._current_name = self._root_name self._current = self._index[self._root_name] self._last_position = 0 self._last_option = '' self.cmd_path = [self._current_name] def _handle_backspace(self): # reseting and starting from the beginning self._reset() line = self._current_line for i in range(1, len(self._current_line)): self._autocomplete(line[:i]) return self._autocomplete(line) PKN6pJWazureshell/index.py# -*- coding: utf-8 -*- import os import json import logging import urllib2 from . import utils logger = logging.getLogger('azureshell.index') _AZURE_SHELL_REMOTE_URL_BASE = "https://azureshellrepo.blob.core.windows.net/index" _AZURE_SHELL_AVAILABLE_INDEX_FILE = "index.available" _AZURE_SHELL_LOCAL_INDEX_VERSION_FILE = "index.local" class AzureShellIndexException(Exception): pass class AzureShellIndex(object): def __init__(self, index_base_dir): self._index_base_dir = index_base_dir self._version_file = "{}/{}".format(index_base_dir, _AZURE_SHELL_LOCAL_INDEX_VERSION_FILE) def get_index_file(self, index_version): return "{}/cli-index.{}.json".format(self._index_base_dir, index_version) def get_local_version(self): if not os.path.exists(self._version_file): return None f = open(self._version_file) v = f.readline().strip() f.close return v def set_local_version(self,index_version): f = open(self._version_file,"w") f.writelines(str(index_version)) f.close def download_index_from_repository(self, index_version ): # Check available list and get the best version version_to_download = AzureShellIndex.get_best_index_version_in_repository(index_version) local_index_version = self.get_local_version() # Download index if needed if not local_index_version or version_to_download > local_index_version: if not os.path.isdir(self._index_base_dir): os.makedirs(self._index_base_dir) remote_url = "{}/cli-index.{}.json".format( _AZURE_SHELL_REMOTE_URL_BASE,version_to_download) logger.debug("Downloading...:{}".format(remote_url)) f = urllib2.urlopen(remote_url) data = f.read() local_index_file = "{}/cli-index.{}.json".format(self._index_base_dir, version_to_download) with open(local_index_file, "wb") as code: code.write(data) ## Update local index version self.set_local_version(version_to_download) return version_to_download def load(self, index_version): index_file = "{}/cli-index.{}.json".format(self._index_base_dir, index_version) return AzureShellIndex.load_index(index_file) ### TODO: error handling @staticmethod def get_best_index_version_in_repository( index_version ): # Check available list and get the best version remote_url = "{}/{}".format( _AZURE_SHELL_REMOTE_URL_BASE, _AZURE_SHELL_AVAILABLE_INDEX_FILE) logger.debug("Reading...:{}".format(remote_url)) f = urllib2.urlopen(remote_url) data = f.read() versions=data.splitlines() versions.sort(reverse=True) ## check if versions contains myversion my_nearest_version = index_version if not index_version in versions: ## get my nearest available version if not versions contains index_version for i in versions: if index_version > i: my_nearest_version = i break return my_nearest_version @staticmethod def load_index(index_file): if not os.path.exists(index_file): estr="index file does not exist:{}".format(index_file) logger.error(estr) raise AzureShellIndexException(estr) data = {} try: with open(index_file, 'r') as f: data = json.load(f) except Exception as e: logger.error(str(e)) raise AzureShellIndexException(str(e)) return data def _parse_command(name, command_obj,completions): if not command_obj: return if command_obj.has_key('arguments'): args = command_obj['arguments'] for arg in args: options = arg.split() completions['args'].update(options) if command_obj.has_key('commands') and command_obj.has_key('command_tree'): subcommand_names = command_obj['commands'] completions['commands'].extend(subcommand_names) cmd_tree = command_obj['command_tree'] for subcommand_name in cmd_tree.keys(): subcommand_obj = cmd_tree[subcommand_name] _parse_command(subcommand_name, subcommand_obj,completions) def get_completions_commands_and_arguments( index_data = {} ): completions = { 'commands': [], 'args': set() } index_root = index_data['az'] completions['commands'] = index_root['commands'] for command_name in completions['commands']: command_obj = index_root['command_tree'].get(command_name) _parse_command(command_name, command_obj, completions) return completions PKnJt_kkazureshell/lexer.py# -*- coding: utf-8 -*- from pygments.lexer import words from pygments.lexer import RegexLexer from pygments.token import Text, Keyword, Literal, Name, Operator from .index import AzureShellIndex, get_completions_commands_and_arguments from .cache import AzureShellCache class AzureShellLexer(RegexLexer): index_data = {} index_data = AzureShellIndex.load_index( AzureShellCache.Instance().get('index_file')) completions = get_completions_commands_and_arguments(index_data) tokens = { 'root': [ (words( tuple(['az']), prefix=r'\b', suffix=r'\b'), Literal.String), (words( tuple(completions['commands']), prefix=r'\b', suffix=r'\b'), Name.Class), (words( tuple(list(completions['args'])), prefix=r'', suffix=r'\b'), Keyword.Declaration), # Everything else (r'.*\n', Text), ] } PKoJS iazureshell/compat.py# -*- coding: utf-8 -*- import sys if sys.version_info[0] == 3: ## Python3 text_type = str else: ## Python2 text_type = unicode PKoJ/NU!azureshell/utils.py# -*- coding: utf-8 -*- import os import sys import re import subprocess from .cache import AzureShellCache def _ERR(s): sys.stderr.write("{}\n".format(s)) def find_executable_path(executable): path = os.environ['PATH'] pathlist = path.split(os.pathsep) if os.path.isfile(executable): return executable else: for path in pathlist: f = os.path.join(path, executable) if os.path.isfile(f): return f return '' def get_cli_version(): v = AzureShellCache.Instance().get('azure_cli_version') if v: return v cmd_string = 'az --version' proc = subprocess.Popen(cmd_string,shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while True: line = proc.stdout.readline() l = line.strip() if l.startswith('azure-cli'): r = re.compile("([a-z-]*) \((.*)\)") o = r.findall(l) if len(o) == 1 and len(o[0]) ==2: v = o[0][1] AzureShellCache.Instance().set('azure_cli_version',v) break if not line and proc.poll() is not None: break return v PKoJpazureshell/azureshell.conf[azureshell] # Pygments: highlighter style # run ./scripts/get-styles.py # 'manni', 'igor', 'lovelace', 'xcode', 'vim', 'autumn', 'abap', 'vs', # 'rrt', 'native', 'perldoc', 'borland', 'arduino', 'tango', 'emacs', 'friendly' # To disable themes, set highlighter_style = none highlighter_style = vim # log_file location. log_file = ~/.azureshell/azureshell.log # # # Default log level. Possible values: "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG". log_level = INFO PKLnJ)  azureshell/logger.pyimport os import logging _DEFAULT_AZURE_SHELL_LOG_LEVEL = 'INFO' _DEFAULT_AZURE_SHELL_LOG_FORMAT = '%(asctime)s %(levelname)s %(message)s' def init_logger(name, log_file, log_level = _DEFAULT_AZURE_SHELL_LOG_LEVEL, log_format = _DEFAULT_AZURE_SHELL_LOG_FORMAT): logger = logging.getLogger(name) handler = logging.FileHandler(os.path.expanduser(log_file)) formatter = logging.Formatter(log_format) handler.setFormatter(formatter) logger.addHandler(handler) switcher = { 'CRITICAL': logging.CRITICAL, 'ERROR': logging.ERROR, 'WARNING': logging.WARNING, 'INFO': logging.INFO, 'DEBUG': logging.DEBUG } logger.setLevel(switcher.get(log_level.upper(),logging.INFO)) PK.qJ'(azureshell/config.py# -*- coding: utf-8 -*- import os from ConfigParser import SafeConfigParser, NoOptionError _DEFAULT_AZURE_SHELL_CONFIG_HIGHLIGHTER_STYLE = 'vim' _DEFAULT_AZURE_SHELL_CONFIG_LOG_FILE = '~/azureshell.log' _DEFAULT_AZURE_SHELL_CONFIG_LOG_LEVEL = 'INFO' class AzureShellConfig(object): def __init__(self, config_file=None): self._config_file = config_file self._config_parser = SafeConfigParser() if self._config_file: self._config_parser.read(config_file) @staticmethod def makedefaultconfig(config_file): dir_name = os.path.dirname(config_file) if not os.path.isdir(dir_name): os.makedirs(dir_name) with open(config_file, "w") as f: f.write("[azureshell]\n# Pygments: highlighter style\n# run ./scripts/get-styles.py\n# 'manni', 'igor', 'lovelace', 'xcode', 'vim', 'autumn', 'abap', 'vs', 'rrt', 'native', 'perldoc', 'borland', 'arduino', 'tango', 'emacs', 'friendly', 'monokai', 'paraiso-dark'\n# To disable themes, set highlighter_style = none\nhighlighter_style = vim\n\n# log_file location\nlog_file = ~/.azureshell/azureshell.log\n\n# Default log level. Possible values: 'CRITICAL', 'ERROR', 'WARNING', 'INFO' and 'DEBUG'\nlog_level = DEBUG") def _get_string(self, section, key, default_val): v ='' if not self._config_file: return default_val try: v = self._config_parser.get(section, key) except NoOptionError as e: v = default_val return v @property def highlighter_style(self): return self._get_string('azureshell','highlighter_style',_DEFAULT_AZURE_SHELL_CONFIG_HIGHLIGHTER_STYLE) @property def log_file(self): return self._get_string('azureshell','log_file',_DEFAULT_AZURE_SHELL_CONFIG_LOG_FILE) @property def log_level(self): return self._get_string('azureshell','log_level',_DEFAULT_AZURE_SHELL_CONFIG_LOG_LEVEL) PKqJ,azureshell/azureshell.py# -*- coding: utf-8 -*- from __future__ import unicode_literals import os import sys import subprocess import logging from prompt_toolkit.document import Document from prompt_toolkit.shortcuts import create_eventloop,create_default_layout from prompt_toolkit.layout.processors import HighlightMatchingBracketProcessor, ConditionalProcessor from prompt_toolkit.filters import Always, HasFocus, IsDone from prompt_toolkit.enums import DEFAULT_BUFFER from prompt_toolkit.buffer import Buffer from prompt_toolkit.interface import CommandLineInterface, Application, AbortAction, AcceptAction from prompt_toolkit.auto_suggest import AutoSuggestFromHistory from prompt_toolkit.history import InMemoryHistory, FileHistory from prompt_toolkit.key_binding.manager import KeyBindingManager from pygments.token import Token from pygments.util import ClassNotFound from pygments.styles import get_style_by_name from prompt_toolkit.styles import default_style_extensions, style_from_dict from .cache import AzureShellCache logger = logging.getLogger('azureshell.azureshell') class InputInterrupt(Exception): pass class AzureShell(object): def __init__(self, config, completer): self._cli = None self._env = os.environ.copy() self.history = InMemoryHistory() self.file_history = FileHistory( "{}/history".format(AzureShellCache.Instance().get('base_dir'))) self._config = config self.completer = completer def run(self): while True: try: document = self.get_cli().run(reset_current_buffer=True) text = document.text except InputInterrupt: pass except (KeyboardInterrupt, EOFError): logger.debug("breaking loop due to KeyboardInterrupt or EOFError") break else: if text.startswith('exit') or text.startswith('quit'): sys.exit(0) if text.startswith('az'): full_cmd = text self.history.append(full_cmd) else: full_cmd = text[0:] logger.debug("Execute subprocess command:{}".format(full_cmd)) self.get_cli().request_redraw() p = subprocess.Popen(full_cmd, shell=True, env=self._env) p.communicate() def on_input_timeout(self, cli): document = cli.current_buffer.document text = document.text logger.debug("on_input_timeout document:{}".format(document)) # Add 'az' to current buffer if no text typed in #if not document.text: # cli.current_buffer.document = Document(u'az', 2) cli.request_redraw() def get_cli(self): if self._cli is None: self._cli = self.create_cli() return self._cli def create_cli(self): ## KeyBindings configuration key_binding = KeyBindingManager( enable_search=True, enable_abort_and_exit_bindings=True, enable_system_bindings=True, enable_auto_suggest_bindings=True, enable_open_in_editor=False) ## Buffer configuration default_buffer= Buffer( history=self.file_history, auto_suggest=AutoSuggestFromHistory(), enable_history_search=True, completer=self.completer, complete_while_typing=Always(), accept_action=AcceptAction.RETURN_DOCUMENT) ## Style configuration try: style = get_style_by_name(self._config.highlighter_style) except ClassNotFound: style = get_style_by_name('native') styles = {} styles.update(style.styles) styles.update(default_style_extensions) styles.update({ Token.Menu.Completions.Completion: 'bg:#003fff #ffffff', Token.Menu.Completions.Completion.Current: 'bg:#5ab300 #000000', Token.Menu.Completions.Meta.Current: 'bg:#5ab300 #ffffff', Token.Menu.Completions.Meta: 'bg:#ffffff #000000', Token.Scrollbar: 'bg:#003fff', Token.Scrollbar.Button: 'bg:#003333', }) prompt_style = style_from_dict(styles) ## Application application = Application( layout=self.create_cli_layout(), mouse_support=False, style=prompt_style, buffer=default_buffer, on_abort=AbortAction.RETRY, on_exit=AbortAction.RAISE_EXCEPTION, on_input_timeout=self.on_input_timeout, key_bindings_registry=key_binding.registry, ) cli = CommandLineInterface(application=application, eventloop=create_eventloop()) return cli def create_cli_layout(self): from .lexer import AzureShellLexer lexer = AzureShellLexer return create_default_layout ( message =u'azure> ', reserve_space_for_menu=8, lexer=lexer, extra_input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor(chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()) ] ) PKhrJj+azure_shell-0.1.0.dist-info/DESCRIPTION.rst# azure-shell An interactive Azure CLI 2.0 command line interface ![](https://github.com/yokawasa/azure-shell/raw/master/img/azure-shell-console.gif) ## Supported Environments * Python versions: 2.7, 3.3, 3.4, 3.5, 3.5 and maybe more * OS: Mac, Ubuntu, CentOS, Bash-on-Windows, or any platform where azure-cli can be installed ## prerequisites You need Azure CLI 2.0 installed as prerequisites for azure-shell. Please refer to [Install Azure CLI 2.0](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and install it if not yet installed ## Installation The azure-shell requires python and pip to install. You can install the azure-shell using pip: ``` pip install azure-shell ``` If you've already have azure-shell installed and want to upgrade to the latest version, you can upgrade like this: ``` pip install --upgrade azure-shell ``` Once you've installed the azure-shell, you can run azure-shell now: ``` azure-shell ``` ## Configuration You can basically run without making any configurations by default but you can give options to azure-shell to configure: ``` azure-shell --help Usage: azure-shell [-h] [--version] [--basedir BASEDIR] [--config CONFIG] [--index INDEX] An interactive Azure CLI command line interface optional arguments: -h, --help show this help message and exit --version show program's version number and exit --basedir BASEDIR Azure Shell base dir path ($HOME/.azureshell by default) --config CONFIG Azure Shell config file path ($HOME/.azureshell/azureshell.conf by default) --index INDEX Azure Shell index file to load ($HOME/.azureshel/cli- index-.json) ``` ## Contributing Bug reports and pull requests are welcome on GitHub at https://github.com/yokawasa/azure-shell ## More Information * [Get started with Azure CLI 2.0](https://docs.microsoft.com/en-us/cli/azure/get-started-with-azure-cli) * [Install Azure CLI 2.0](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) PKgrJe11,azure_shell-0.1.0.dist-info/entry_points.txt[console_scripts] azure-shell = azureshell:main PKhrJ/)azure_shell-0.1.0.dist-info/metadata.json{"classifiers": ["Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "Natural Language :: English", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6"], "extensions": {"python.commands": {"wrap_console": {"azure-shell": "azureshell:main"}}, "python.details": {"contacts": [{"name": "Yoichi Kawasaki", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/yokawasa/azure-shell"}}, "python.exports": {"console_scripts": {"azure-shell": "azureshell:main"}}}, "extras": [], "generator": "bdist_wheel (0.26.0)", "keywords": ["azure", "azure-shell", "shell", "azure-cli"], "license": "Apache License 2.0", "metadata_version": "2.0", "name": "azure-shell", "platform": "any", "run_requires": [{"requires": ["Pygments (<3.0.0,>=2.1.3)", "configparser (>=3.5.0)", "prompt-toolkit (<1.1.0,>=1.0.0)"]}], "summary": "An interactive Azure CLI 2.0 command line interface", "version": "0.1.0"}PKgrJS%% )azure_shell-0.1.0.dist-info/top_level.txtazureshell PKhrJndnn!azure_shell-0.1.0.dist-info/WHEELWheel-Version: 1.0 Generator: bdist_wheel (0.26.0) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any PKhrJ4   $azure_shell-0.1.0.dist-info/METADATAMetadata-Version: 2.0 Name: azure-shell Version: 0.1.0 Summary: An interactive Azure CLI 2.0 command line interface Home-page: https://github.com/yokawasa/azure-shell Author: Yoichi Kawasaki Author-email: UNKNOWN License: Apache License 2.0 Keywords: azure azure-shell,shell,azure-cli Platform: any Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Intended Audience :: System Administrators Classifier: Natural Language :: English Classifier: License :: OSI Approved :: Apache Software License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Requires-Dist: Pygments (<3.0.0,>=2.1.3) Requires-Dist: configparser (>=3.5.0) Requires-Dist: prompt-toolkit (<1.1.0,>=1.0.0) # azure-shell An interactive Azure CLI 2.0 command line interface ![](https://github.com/yokawasa/azure-shell/raw/master/img/azure-shell-console.gif) ## Supported Environments * Python versions: 2.7, 3.3, 3.4, 3.5, 3.5 and maybe more * OS: Mac, Ubuntu, CentOS, Bash-on-Windows, or any platform where azure-cli can be installed ## prerequisites You need Azure CLI 2.0 installed as prerequisites for azure-shell. Please refer to [Install Azure CLI 2.0](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and install it if not yet installed ## Installation The azure-shell requires python and pip to install. You can install the azure-shell using pip: ``` pip install azure-shell ``` If you've already have azure-shell installed and want to upgrade to the latest version, you can upgrade like this: ``` pip install --upgrade azure-shell ``` Once you've installed the azure-shell, you can run azure-shell now: ``` azure-shell ``` ## Configuration You can basically run without making any configurations by default but you can give options to azure-shell to configure: ``` azure-shell --help Usage: azure-shell [-h] [--version] [--basedir BASEDIR] [--config CONFIG] [--index INDEX] An interactive Azure CLI command line interface optional arguments: -h, --help show this help message and exit --version show program's version number and exit --basedir BASEDIR Azure Shell base dir path ($HOME/.azureshell by default) --config CONFIG Azure Shell config file path ($HOME/.azureshell/azureshell.conf by default) --index INDEX Azure Shell index file to load ($HOME/.azureshel/cli- index-.json) ``` ## Contributing Bug reports and pull requests are welcome on GitHub at https://github.com/yokawasa/azure-shell ## More Information * [Get started with Azure CLI 2.0](https://docs.microsoft.com/en-us/cli/azure/get-started-with-azure-cli) * [Install Azure CLI 2.0](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) PKhrJ< "azure_shell-0.1.0.dist-info/RECORDazure_shell-0.1.0.dist-info/DESCRIPTION.rst,sha256=vhal-oP7X1YopFA93s2Nfqkh2etcVYVrAs5X08lwku8,2069 azure_shell-0.1.0.dist-info/METADATA,sha256=d9YJ4p3cC8lvoIfg6W-iwA-ZvFMxRDF6lqN_z3kN2Mc,3073 azure_shell-0.1.0.dist-info/RECORD,, azure_shell-0.1.0.dist-info/WHEEL,sha256=GrqQvamwgBV4nLoJe0vhYRSWzWsx7xjlt74FT0SWYfE,110 azure_shell-0.1.0.dist-info/entry_points.txt,sha256=yulG-rNe7D9bW1DEeNfsD_VVHK1IgcaQ3joXdqj--cs,49 azure_shell-0.1.0.dist-info/metadata.json,sha256=PaI1y9QKdrPHRB8ZJsqswyjYV9uCKmsIAUKgynOVAz0,1278 azure_shell-0.1.0.dist-info/top_level.txt,sha256=an8Gmn97jB7oKhXZMXHY9mjwxDYfk1iPQ_cehSGR3us,11 azureshell/__init__.py,sha256=l4nC7l4fUrinmUJ5qs12KiAQi7dbXaN9DwpmnvUj_vg,4138 azureshell/azureshell.conf,sha256=pd6vOlH5EFv45x6qoE_MCYHtG8gOQvo2ZPXdeW0Ukts,474 azureshell/azureshell.py,sha256=EqgKik4sq8uQZF072h7iZEdP6WiXupJtJ_sgGbX4heA,5391 azureshell/cache.py,sha256=mThpIA_a8e7TrN8flMUhe1_1uEqaQvLzwKvyZkrMf_w,509 azureshell/compat.py,sha256=XTszSVcaPFSfJDdo3nJwZk7uXyslYpl_kxBuwWbVeAQ,148 azureshell/completer.py,sha256=HJWeM_WQvkUMMdJFI_mFoH5PE2UUIKARzWjaLo_ykDg,6118 azureshell/config.py,sha256=XjAOjtMXlIHmG5vZf6jrLfJ9FT3wavk6U0x5PSftTvE,1970 azureshell/index.py,sha256=AvLKpGpuDPXreJ399cjGJpVd7xpLTMlBt0WCl8_Dias,4834 azureshell/lexer.py,sha256=t9pOmHU5ufefuzYMKanU_NO7Oln677Gmic1rFAEJQUc,875 azureshell/logger.py,sha256=LBGY63n_zFVRNhr9JMciS9tRa6RX07vnbw-_zJ-sf0M,778 azureshell/utils.py,sha256=LpbwsZLgDUPLIyHqsQLHtixeJKdUycePbbmxBLNfcpI,1181 PK+^mJ%[azureshell/cache.pyPKܾqJ**.azureshell/__init__.pyPKrJ/azureshell/completer.pyPKN6pJW*azureshell/index.pyPKnJt_kk=azureshell/lexer.pyPKoJS iVAazureshell/compat.pyPKoJ/NU!Bazureshell/utils.pyPKoJpFazureshell/azureshell.confPKLnJ)  Hazureshell/logger.pyPK.qJ'(8Lazureshell/config.pyPKqJ,Tazureshell/azureshell.pyPKhrJj+aiazure_shell-0.1.0.dist-info/DESCRIPTION.rstPKgrJe11,qazure_shell-0.1.0.dist-info/entry_points.txtPKhrJ/):razure_shell-0.1.0.dist-info/metadata.jsonPKgrJS%% )wazure_shell-0.1.0.dist-info/top_level.txtPKhrJndnn!wazure_shell-0.1.0.dist-info/WHEELPKhrJ4   $~xazure_shell-0.1.0.dist-info/METADATAPKhrJ< "azure_shell-0.1.0.dist-info/RECORDPK3̊