initial creation
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import os
|
||||
|
||||
import click
|
||||
|
||||
cmd_folder = os.path.join(os.path.dirname(__file__), 'commands')
|
||||
cmd_prefix = 'cmd_'
|
||||
|
||||
|
||||
class CLI(click.MultiCommand):
|
||||
def list_commands(self, ctx):
|
||||
"""
|
||||
Obtain a list of all available commands.
|
||||
|
||||
:param ctx: Click context
|
||||
:return: List of sorted commands
|
||||
"""
|
||||
commands = []
|
||||
|
||||
for filename in os.listdir(cmd_folder):
|
||||
if filename.endswith('.py') and filename.startswith(cmd_prefix):
|
||||
commands.append(filename[4:-3])
|
||||
|
||||
commands.sort()
|
||||
|
||||
return commands
|
||||
|
||||
def get_command(self, ctx, name):
|
||||
"""
|
||||
Get a specific command by looking up the module.
|
||||
|
||||
:param ctx: Click context
|
||||
:param name: Command name
|
||||
:return: Module's cli function
|
||||
"""
|
||||
ns = {}
|
||||
|
||||
filename = os.path.join(cmd_folder, cmd_prefix + name + '.py')
|
||||
|
||||
with open(filename) as f:
|
||||
code = compile(f.read(), filename, 'exec')
|
||||
eval(code, ns, ns)
|
||||
|
||||
return ns['cli']
|
||||
|
||||
|
||||
@click.command(cls=CLI)
|
||||
def cli():
|
||||
""" Commands to help manage your project. """
|
||||
pass
|
||||
@@ -0,0 +1,276 @@
|
||||
import click
|
||||
import random
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from faker import Faker
|
||||
|
||||
from snakeeyes.app import create_app
|
||||
from snakeeyes.extensions import db
|
||||
from snakeeyes.blueprints.user.models import User
|
||||
from snakeeyes.blueprints.billing.models.invoice import Invoice
|
||||
from snakeeyes.blueprints.bet.models.bet import Bet
|
||||
from snakeeyes.blueprints.bet.models.dice import roll
|
||||
|
||||
# Create an app context for the database connection.
|
||||
app = create_app()
|
||||
db.app = app
|
||||
|
||||
fake = Faker()
|
||||
|
||||
|
||||
def _log_status(count, model_label):
|
||||
"""
|
||||
Log the output of how many records were created.
|
||||
|
||||
:param count: Amount created
|
||||
:type count: int
|
||||
:param model_label: Name of the model
|
||||
:type model_label: str
|
||||
:return: None
|
||||
"""
|
||||
click.echo('Created {0} {1}'.format(count, model_label))
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def _bulk_insert(model, data, label):
|
||||
"""
|
||||
Bulk insert data to a specific model and log it. This is much more
|
||||
efficient than adding 1 row at a time in a loop.
|
||||
|
||||
:param model: Model being affected
|
||||
:type model: SQLAlchemy
|
||||
:param data: Data to be saved
|
||||
:type data: list
|
||||
:param label: Label for the output
|
||||
:type label: str
|
||||
:param skip_delete: Optionally delete previous records
|
||||
:type skip_delete: bool
|
||||
:return: None
|
||||
"""
|
||||
with app.app_context():
|
||||
model.query.delete()
|
||||
|
||||
db.session.commit()
|
||||
db.engine.execute(model.__table__.insert(), data)
|
||||
|
||||
_log_status(model.query.count(), label)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
@click.group()
|
||||
def cli():
|
||||
""" Add items to the database. """
|
||||
pass
|
||||
|
||||
|
||||
@click.command()
|
||||
def users():
|
||||
"""
|
||||
Generate fake users.
|
||||
"""
|
||||
random_emails = []
|
||||
data = []
|
||||
|
||||
click.echo('Working...')
|
||||
|
||||
# Ensure we get about 100 unique random emails.
|
||||
for i in range(0, 99):
|
||||
random_emails.append(fake.email())
|
||||
|
||||
random_emails.append(app.config['SEED_ADMIN_EMAIL'])
|
||||
random_emails = list(set(random_emails))
|
||||
|
||||
while True:
|
||||
if len(random_emails) == 0:
|
||||
break
|
||||
|
||||
fake_datetime = fake.date_time_between(
|
||||
start_date='-1y', end_date='now').strftime('%s')
|
||||
|
||||
created_on = datetime.utcfromtimestamp(
|
||||
float(fake_datetime)).strftime('%Y-%m-%dT%H:%M:%S Z')
|
||||
|
||||
random_percent = random.random()
|
||||
|
||||
if random_percent >= 0.05:
|
||||
role = 'member'
|
||||
else:
|
||||
role = 'admin'
|
||||
|
||||
email = random_emails.pop()
|
||||
|
||||
random_percent = random.random()
|
||||
|
||||
if random_percent >= 0.5:
|
||||
random_trail = str(int(round((random.random() * 1000))))
|
||||
username = fake.first_name() + random_trail
|
||||
last_bet_on = created_on
|
||||
else:
|
||||
username = None
|
||||
last_bet_on = None
|
||||
|
||||
fake_datetime = fake.date_time_between(
|
||||
start_date='-1y', end_date='now').strftime('%s')
|
||||
|
||||
current_sign_in_on = datetime.utcfromtimestamp(
|
||||
float(fake_datetime)).strftime('%Y-%m-%dT%H:%M:%S Z')
|
||||
|
||||
params = {
|
||||
'created_on': created_on,
|
||||
'updated_on': created_on,
|
||||
'role': role,
|
||||
'email': email,
|
||||
'username': username,
|
||||
'password': User.encrypt_password('password'),
|
||||
'sign_in_count': random.random() * 100,
|
||||
'coins': 100,
|
||||
'last_bet_on': last_bet_on,
|
||||
'current_sign_in_on': current_sign_in_on,
|
||||
'current_sign_in_ip': fake.ipv4(),
|
||||
'last_sign_in_on': current_sign_in_on,
|
||||
'last_sign_in_ip': fake.ipv4()
|
||||
}
|
||||
|
||||
# Ensure the seeded admin is always an admin with the seeded password.
|
||||
if email == app.config['SEED_ADMIN_EMAIL']:
|
||||
password = User.encrypt_password(app.config['SEED_ADMIN_PASSWORD'])
|
||||
|
||||
params['role'] = 'admin'
|
||||
params['password'] = password
|
||||
|
||||
data.append(params)
|
||||
|
||||
return _bulk_insert(User, data, 'users')
|
||||
|
||||
|
||||
@click.command()
|
||||
def invoices():
|
||||
"""
|
||||
Generate random invoices.
|
||||
"""
|
||||
data = []
|
||||
|
||||
users = db.session.query(User).all()
|
||||
|
||||
for user in users:
|
||||
for i in range(0, random.randint(1, 12)):
|
||||
# Create a fake unix timestamp in the future.
|
||||
created_on = fake.date_time_between(
|
||||
start_date='-1y', end_date='now').strftime('%s')
|
||||
period_start_on = fake.date_time_between(
|
||||
start_date='now', end_date='+1y').strftime('%s')
|
||||
period_end_on = fake.date_time_between(
|
||||
start_date=period_start_on, end_date='+14d').strftime('%s')
|
||||
exp_date = fake.date_time_between(
|
||||
start_date='now', end_date='+2y').strftime('%s')
|
||||
|
||||
created_on = datetime.utcfromtimestamp(
|
||||
float(created_on)).strftime('%Y-%m-%dT%H:%M:%S Z')
|
||||
period_start_on = datetime.utcfromtimestamp(
|
||||
float(period_start_on)).strftime('%Y-%m-%d')
|
||||
period_end_on = datetime.utcfromtimestamp(
|
||||
float(period_end_on)).strftime('%Y-%m-%d')
|
||||
exp_date = datetime.utcfromtimestamp(
|
||||
float(exp_date)).strftime('%Y-%m-%d')
|
||||
|
||||
plans = ['BRONZE', 'GOLD', 'PLATINUM']
|
||||
cards = ['Visa', 'Mastercard', 'AMEX',
|
||||
'J.C.B', "Diner's Club"]
|
||||
|
||||
params = {
|
||||
'created_on': created_on,
|
||||
'updated_on': created_on,
|
||||
'user_id': user.id,
|
||||
'receipt_number': fake.md5(),
|
||||
'description': '{0} MONTHLY'.format(random.choice(plans)),
|
||||
'period_start_on': period_start_on,
|
||||
'period_end_on': period_end_on,
|
||||
'currency': 'usd',
|
||||
'tax': random.random() * 100,
|
||||
'tax_percent': random.random() * 10,
|
||||
'total': random.random() * 1000,
|
||||
'brand': random.choice(cards),
|
||||
'last4': random.randint(1000, 9000),
|
||||
'exp_date': exp_date
|
||||
}
|
||||
|
||||
data.append(params)
|
||||
|
||||
return _bulk_insert(Invoice, data, 'invoices')
|
||||
|
||||
|
||||
@click.command()
|
||||
def bets():
|
||||
"""
|
||||
Generate random bets.
|
||||
"""
|
||||
data = []
|
||||
|
||||
users = db.session.query(User).all()
|
||||
|
||||
for user in users:
|
||||
for i in range(0, random.randint(10, 20)):
|
||||
fake_datetime = fake.date_time_between(
|
||||
start_date='-1y', end_date='now').strftime('%s')
|
||||
|
||||
created_on = datetime.utcfromtimestamp(
|
||||
float(fake_datetime)).strftime('%Y-%m-%dT%H:%M:%S Z')
|
||||
|
||||
wagered = random.randint(1, 100)
|
||||
die_1 = roll()
|
||||
die_2 = roll()
|
||||
outcome = die_1 + die_2
|
||||
|
||||
random_percent = random.random()
|
||||
|
||||
if random_percent >= 0.75:
|
||||
guess = outcome
|
||||
else:
|
||||
guess = random.randint(2, 12)
|
||||
|
||||
payout = float(app.config['DICE_ROLL_PAYOUT'][str(guess)])
|
||||
is_winner = Bet.is_winner(guess, outcome)
|
||||
payout = Bet.determine_payout(payout, is_winner)
|
||||
net = Bet.calculate_net(wagered, payout, is_winner)
|
||||
|
||||
params = {
|
||||
'created_on': created_on,
|
||||
'updated_on': created_on,
|
||||
'user_id': user.id,
|
||||
'guess': guess,
|
||||
'die_1': die_1,
|
||||
'die_2': die_1,
|
||||
'roll': outcome,
|
||||
'wagered': wagered,
|
||||
'payout': payout,
|
||||
'net': net
|
||||
}
|
||||
|
||||
data.append(params)
|
||||
|
||||
return _bulk_insert(Bet, data, 'bets')
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.pass_context
|
||||
def all(ctx):
|
||||
"""
|
||||
Generate all data.
|
||||
|
||||
:param ctx:
|
||||
:return: None
|
||||
"""
|
||||
ctx.invoke(users)
|
||||
ctx.invoke(invoices)
|
||||
ctx.invoke(bets)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
cli.add_command(users)
|
||||
cli.add_command(invoices)
|
||||
cli.add_command(bets)
|
||||
cli.add_command(all)
|
||||
@@ -0,0 +1,16 @@
|
||||
import subprocess
|
||||
|
||||
import click
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument('path', default='snakeeyes')
|
||||
def cli(path):
|
||||
"""
|
||||
Run a test coverage report.
|
||||
|
||||
:param path: Test coverage path
|
||||
:return: Subprocess call result
|
||||
"""
|
||||
cmd = 'py.test --cov-report term-missing --cov {0}'.format(path)
|
||||
return subprocess.call(cmd, shell=True)
|
||||
@@ -0,0 +1,80 @@
|
||||
import click
|
||||
|
||||
from sqlalchemy_utils import database_exists, create_database
|
||||
|
||||
from snakeeyes.app import create_app
|
||||
from snakeeyes.extensions import db
|
||||
from snakeeyes.blueprints.user.models import User
|
||||
|
||||
# Create an app context for the database connection.
|
||||
app = create_app()
|
||||
db.app = app
|
||||
|
||||
|
||||
@click.group()
|
||||
def cli():
|
||||
""" Run PostgreSQL related tasks. """
|
||||
pass
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.option('--with-testdb/--no-with-testdb', default=False,
|
||||
help='Create a test db too?')
|
||||
def init(with_testdb):
|
||||
"""
|
||||
Initialize the database.
|
||||
|
||||
:param with_testdb: Create a test database
|
||||
:return: None
|
||||
"""
|
||||
db.drop_all()
|
||||
db.create_all()
|
||||
|
||||
if with_testdb:
|
||||
db_uri = '{0}_test'.format(app.config['SQLALCHEMY_DATABASE_URI'])
|
||||
|
||||
if not database_exists(db_uri):
|
||||
create_database(db_uri)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
@click.command()
|
||||
def seed():
|
||||
"""
|
||||
Seed the database with an initial user.
|
||||
|
||||
:return: User instance
|
||||
"""
|
||||
if User.find_by_identity(app.config['SEED_ADMIN_EMAIL']) is not None:
|
||||
return None
|
||||
|
||||
params = {
|
||||
'role': 'admin',
|
||||
'email': app.config['SEED_ADMIN_EMAIL'],
|
||||
'password': app.config['SEED_ADMIN_PASSWORD']
|
||||
}
|
||||
|
||||
return User(**params).save()
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.option('--with-testdb/--no-with-testdb', default=False,
|
||||
help='Create a test db too?')
|
||||
@click.pass_context
|
||||
def reset(ctx, with_testdb):
|
||||
"""
|
||||
Init and seed automatically.
|
||||
|
||||
:param with_testdb: Create a test database
|
||||
:return: None
|
||||
"""
|
||||
ctx.invoke(init, with_testdb=with_testdb)
|
||||
ctx.invoke(seed)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
cli.add_command(init)
|
||||
cli.add_command(seed)
|
||||
cli.add_command(reset)
|
||||
@@ -0,0 +1,24 @@
|
||||
import subprocess
|
||||
|
||||
import click
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.option('--skip-init/--no-skip-init', default=True,
|
||||
help='Skip __init__.py files?')
|
||||
@click.argument('path', default='snakeeyes')
|
||||
def cli(skip_init, path):
|
||||
"""
|
||||
Run flake8 to analyze your code base.
|
||||
|
||||
:param skip_init: Skip checking __init__.py files
|
||||
:param path: Test coverage path
|
||||
:return: Subprocess call result
|
||||
"""
|
||||
flake8_flag_exclude = ''
|
||||
|
||||
if skip_init:
|
||||
flake8_flag_exclude = ' --exclude __init__.py'
|
||||
|
||||
cmd = 'flake8 {0}{1}'.format(path, flake8_flag_exclude)
|
||||
return subprocess.call(cmd, shell=True)
|
||||
@@ -0,0 +1,44 @@
|
||||
from subprocess import check_output
|
||||
|
||||
import click
|
||||
|
||||
|
||||
def count_locs(file_type, comment_pattern):
|
||||
"""
|
||||
Detect if a program is on the system path.
|
||||
|
||||
:param file_type: Which file type will be searched?
|
||||
:param file_type: str
|
||||
:param comment_pattern: Escaped characters that are comments
|
||||
:param comment_pattern: str
|
||||
:return: str
|
||||
"""
|
||||
find = "find . -name '*.{0}' -print0".format(file_type)
|
||||
sed_pattern = "'/^\s*{0}/d;/^\s*$/d'".format(comment_pattern)
|
||||
|
||||
cmd = "{0} | xargs -0 sed {1} | wc -l".format(find, sed_pattern)
|
||||
|
||||
return check_output(cmd, shell=True).decode('utf-8').replace('\n', '')
|
||||
|
||||
|
||||
@click.command()
|
||||
def cli():
|
||||
"""
|
||||
Count lines of code in the project.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
file_types = (
|
||||
['Python', 'py', '#'],
|
||||
['HTML', 'html', '<!--'],
|
||||
['CSS', 'css', '\/\*'],
|
||||
['JS', 'js', '\/\/']
|
||||
)
|
||||
|
||||
click.echo('Lines of code\n-------------')
|
||||
|
||||
for file_type in file_types:
|
||||
click.echo("{0}: {1}".format(file_type[0], count_locs(file_type[1],
|
||||
file_type[2])))
|
||||
|
||||
return None
|
||||
@@ -0,0 +1,30 @@
|
||||
import click
|
||||
|
||||
from snakeeyes.app import create_app
|
||||
|
||||
app = create_app()
|
||||
|
||||
|
||||
@click.command()
|
||||
def cli():
|
||||
"""
|
||||
List all of the available routes.
|
||||
|
||||
:return: str
|
||||
"""
|
||||
output = {}
|
||||
|
||||
for rule in app.url_map.iter_rules():
|
||||
route = {
|
||||
'path': rule.rule,
|
||||
'methods': '({0})'.format(', '.join(rule.methods))
|
||||
}
|
||||
|
||||
output[rule.endpoint] = route
|
||||
|
||||
endpoint_padding = max(len(endpoint) for endpoint in output.keys()) + 2
|
||||
|
||||
for key in sorted(output):
|
||||
if 'debugtoolbar' not in key and 'debug_toolbar' not in key:
|
||||
click.echo('{0: >{1}}: {2}'.format(key, endpoint_padding,
|
||||
output[key]))
|
||||
@@ -0,0 +1,15 @@
|
||||
import binascii
|
||||
import os
|
||||
|
||||
import click
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument('bytes', default=128)
|
||||
def cli(bytes):
|
||||
"""
|
||||
Generate a random secret token.
|
||||
|
||||
:return: str
|
||||
"""
|
||||
return click.echo(binascii.b2a_hex(os.urandom(bytes)))
|
||||
@@ -0,0 +1,69 @@
|
||||
import click
|
||||
|
||||
from snakeeyes.app import create_app
|
||||
from snakeeyes.extensions import db
|
||||
from snakeeyes.blueprints.billing.gateways.stripecom import Plan as PaymentPlan
|
||||
|
||||
# Create an app context for the database connection.
|
||||
app = create_app()
|
||||
db.app = app
|
||||
|
||||
|
||||
@click.group()
|
||||
def cli():
|
||||
""" Perform various tasks with Stripe's API. """
|
||||
pass
|
||||
|
||||
|
||||
@click.command()
|
||||
def sync_plans():
|
||||
"""
|
||||
Sync (upsert) STRIPE_PLANS to Stripe.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
if app.config['STRIPE_PLANS'] is None:
|
||||
return None
|
||||
|
||||
for _, value in app.config['STRIPE_PLANS'].items():
|
||||
plan = PaymentPlan.retrieve(value.get('id'))
|
||||
|
||||
if plan:
|
||||
PaymentPlan.update(id=value.get('id'),
|
||||
name=value.get('name'),
|
||||
metadata=value.get('metadata'),
|
||||
statement_descriptor=value.get(
|
||||
'statement_descriptor'))
|
||||
else:
|
||||
PaymentPlan.create(**value)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument('plan_ids', nargs=-1)
|
||||
def delete_plans(plan_ids):
|
||||
"""
|
||||
Delete 1 or more plans from Stripe.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
for plan_id in plan_ids:
|
||||
PaymentPlan.delete(plan_id)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
@click.command()
|
||||
def list_plans():
|
||||
"""
|
||||
List all existing plans on Stripe.
|
||||
|
||||
:return: Stripe plans
|
||||
"""
|
||||
click.echo(PaymentPlan.list())
|
||||
|
||||
|
||||
cli.add_command(sync_plans)
|
||||
cli.add_command(delete_plans)
|
||||
cli.add_command(list_plans)
|
||||
@@ -0,0 +1,17 @@
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
import click
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument('path', default=os.path.join('snakeeyes', 'tests'))
|
||||
def cli(path):
|
||||
"""
|
||||
Run tests with Pytest.
|
||||
|
||||
:param path: Test path
|
||||
:return: Subprocess call result
|
||||
"""
|
||||
cmd = 'py.test {0}'.format(path)
|
||||
return subprocess.call(cmd, shell=True)
|
||||
Reference in New Issue
Block a user