Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,21 @@ Usage

Usage:
aq [--profile=<profile>] [--region=<region>] [--table-cache-ttl=<seconds>] [-v] [--debug]
aq [--profile=<profile>] [--region=<region>] [--table-cache-ttl=<seconds>] [-v] [--debug] <query>
aq [--profile=<profile>] [--region=<region>] [--table-cache-ttl=<seconds>] [-v] [--debug] [--format=<formatter>] <query>

Sample queries:
aq "select tags->'Name' from ec2_instances"
aq "select count(*) from us_west_1.ec2_instances"

Options:
--profile=<profile> Use a specific profile from your credential file
--region=<region> The region to use. Overrides config/env settings
--table-cache-ttl=<seconds> number of seconds to cache the tables
before we update them from AWS again [default: 300]
--format=<formatter> Choose a table, json, yaml, or csv formatter [default: table]

-v, --verbose enable verbose logging
--debug enable debug mode

Running ``aq`` without specifying any query will start a REPL to run your queries interactively.

Expand Down
18 changes: 14 additions & 4 deletions aq/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Usage:
aq [--profile=<profile>] [--region=<region>] [--table-cache-ttl=<seconds>] [-v] [--debug]
aq [--profile=<profile>] [--region=<region>] [--table-cache-ttl=<seconds>] [-v] [--debug] <query>
aq [--profile=<profile>] [--region=<region>] [--table-cache-ttl=<seconds>] [-v] [--debug] [--format=<formatter>] <query>

Sample queries:
aq "select tags->'Name' from ec2_instances"
Expand All @@ -13,6 +13,8 @@
--region=<region> The region to use. Overrides config/env settings
--table-cache-ttl=<seconds> number of seconds to cache the tables
before we update them from AWS again [default: 300]
--format=<formatter> Choose a table, json, yaml, or csv formatter [default: table]

-v, --verbose enable verbose logging
--debug enable debug mode
"""
Expand All @@ -25,12 +27,12 @@

from aq.engines import BotoSqliteEngine
from aq.errors import QueryError
from aq.formatters import TableFormatter
import aq.formatters
from aq.logger import initialize_logger
from aq.parsers import SelectParser
from aq.prompt import AqPrompt

__version__ = '0.1.1'
__version__ = '0.1.2'

QueryResult = namedtuple('QueryResult', ('parsed_query', 'query_metadata', 'columns', 'rows'))

Expand All @@ -44,7 +46,15 @@ def get_parser(options):


def get_formatter(options):
return TableFormatter(options)
format = options.get("--format")
if (format == "json"):
return formatters.JsonFormatter(options)
elif (format == "csv"):
return formatters.CsvFormatter(options)
elif (format == "yaml"):
return formatters.YamlFormatter(options)
else:
return formatters.TableFormatter(options)


def get_prompt(parser, engine, options):
Expand Down
60 changes: 59 additions & 1 deletion aq/formatters.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from tabulate import tabulate

import io
import json
import csv
import yaml

class TableFormatter(object):
def __init__(self, options=None):
Expand All @@ -8,3 +11,58 @@ def __init__(self, options=None):
@staticmethod
def format(columns, rows):
return tabulate(rows, headers=columns, tablefmt='psql', missingval='NULL')


# Returns an array of hashes with the columns as the keys
def mixinColumns(columns, rows):
rowsArr = []
cLen = len(columns)

for row in rows:
r = {}

for i in range(0, cLen):
r[columns[i]] = row[i]

rowsArr.append(r)

return rowsArr

class JsonFormatter(object):
def __init__(self, options=None):
self.options = options if options else {}

@staticmethod
def format(columns, rows):
rowsArr = mixinColumns(columns, rows)
return json.dumps(rowsArr)


class YamlFormatter(object):
def __init__(self, options=None):
self.options = options if options else {}

@staticmethod
def format(columns, rows):
rowsArr = mixinColumns(columns, rows)
return yaml.safe_dump(rowsArr, default_flow_style=False )


class CsvFormatter(object):
def __init__(self, options=None):
self.options = options if options else {}

@staticmethod
def format(columns, rows):
rowsData = io.BytesIO()
writer = csv.DictWriter(rowsData, fieldnames=columns)
writer.writeheader()

rowsArr = mixinColumns(columns, rows)
for row in rowsArr:
writer.writerow(row)

# Force string.
# Python2.7 getvalue() returns string
# Python 3.x returns bytes
return str(rowsData.getvalue())
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# Versions should comply with PEP440. For a discussion on single-sourcing
# the version across setup.py and the project code, see
# https://packaging.python.org/en/latest/single_source_version.html
version='0.1.1',
version='0.1.2',

description='Query AWS resources with SQL',
long_description=long_description,
Expand Down Expand Up @@ -75,6 +75,7 @@
'prompt_toolkit',
'pygments',
'six',
'pyyaml'
],

# List additional groups of dependencies here (e.g. development
Expand Down