Skip to content
This repository has been archived by the owner on Sep 13, 2024. It is now read-only.

Commit

Permalink
CLI para llenar BD
Browse files Browse the repository at this point in the history
  • Loading branch information
tyoc213 committed Apr 7, 2021
0 parents commit a6e28f6
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__pycache__/
.vscode/
37 changes: 37 additions & 0 deletions ghdb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///clidata.sqlite3'
app.config['SECRET_KEY'] = "aa20ff7c-8ad5-44a7-b0c3-8060b126e186"
db = SQLAlchemy(app)


class GithubUser(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=False)
user = db.Column(db.String(80), unique=True, nullable=False)
image_url = db.Column(db.String(1200), unique=False, nullable=False)
profile = db.Column(db.String(1200), unique=False, nullable=False)
typ3 = db.Column(db.String(10), unique=False, nullable=False)

def __repr__(self):
return '<User %r>' % self.user

def update_or_insert(user_dict):
# get all incoming ids and ids on database
all_incoming_ids = set(user_dict.keys())
all_ids = set(dict(db.session.query(GithubUser.id, GithubUser)))
# which ones are already on db?
updatable_ids = all_ids & all_incoming_ids
# and which are new?
insertable_ids = all_incoming_ids - updatable_ids
# create the list of items to insert and to update in bulk
upd = [user_dict[e] for e in updatable_ids]
ins = [user_dict[e] for e in insertable_ids]
db.session.bulk_insert_mappings(GithubUser, ins)
db.session.bulk_update_mappings(GithubUser, upd)
db.session.commit()

return True

def create_all():
SQLAlchemy.create_all(db)
18 changes: 18 additions & 0 deletions githubusers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# From https://docs.github.com/en/rest/reference/users#list-users
# example: https://api.github.com/users?per_page=10&since=0

import requests

def get_github_users(per_page, since):
'''Return a dict of id:user with specific keys from github users'''
r = requests.get('https://api.github.com/users?per_page=%d&since=%d'%(per_page, since))
if r.status_code == 200:
return {r['id']:{
'user': r['login'],
'id': r['id'],
"image_url": r['avatar_url'],
"profile": r['html_url'],
"typ3": r['type']
} for r in r.json()}
else:
return {}
15 changes: 15 additions & 0 deletions seed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import click
from githubusers import get_github_users
from ghdb import create_all, update_or_insert

@click.command()
@click.option('--total', default=150, show_default=True) # TODO: type=click.IntRange(1, 100)
@click.option('--page', default=0, show_default=True)
def seed(total, page):
'''Save the users from github user list'''
create_all()
user_list = get_github_users(total, page)
update_or_insert(user_list)
click.echo(f'%d users'%(total))


30 changes: 30 additions & 0 deletions task.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Using the [API of GitHub](https://docs.github.com/en/free-pro-team@latest/rest/reference) do the following tasks:

- Create a script called [seed.py](http://seed.py) that populates a SQLite database. By default it should search for the first 150 users from GitHub but the script should accept a param called total to customize the number of users.
- The fields required for this users are:
- username
- id
- image url
- type
- link to his GitHub profile

Once you have created the script and has a complete db create a Flask application that has:

- A view to show the info of all the users of the database in a table. Profile avatar should be visible and clicking the username should send me to the GitHub profile. Pagination is needed and by default it should be of size 25. Make sure that the page is responsive even with a large amount of data (use any optimization) *Optional but desired*: arguments to change pagination size and ordering

Create an script to run your server and a README.md file where you explain your decisions and architecture.

Unit tests for all the code is needed.

After completion of the tasks create a public repository and put all the code there. Be sure to not include compiled files and the db.

### Optional

- Add an endpoint where you return a JSON with the information stored in the database. The user will be able to use query params to filter the results. At least there should be for username and id but for type, pagination size, order by and GitHub profile is a plus. Example:

<your_endpoint>/profiles?username=test1&pagination=20&order_by=id

- Deploy your app to a Heroku server or any other free option and include the link in the email
- Include as many optimizations as you can (e.g cache)

*Note: Things like code style, documentation, architecture are really important. Develop this app assuming production quality code*
13 changes: 13 additions & 0 deletions test_ghdb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from click.testing import CliRunner
from githubusers import get_github_users
from ghdb import db, GithubUser, update_or_insert


def test_can_update_or_insert():
first_user = get_github_users(1,0)
upd_word = 'No profile!!!!'
first_user[1]['profile'] = upd_word
assert update_or_insert(first_user)
# retrieve again from db
first_user = dict(db.session.query(GithubUser.id, GithubUser))
assert first_user[1].profile == upd_word
18 changes: 18 additions & 0 deletions test_githubusers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from click.testing import CliRunner
from githubusers import get_github_users

def test_first_user():
first_user = get_github_users(1,0)
assert first_user == {1:
{
"user": "mojombo",
"id": 1,
"image_url": "https://avatars.githubusercontent.com/u/1?v=4",
"profile": "https://github.com/mojombo",
"typ3": "User"
}
}

def test_no_users():
no_result= get_github_users(10_000, 89_999_999)
assert no_result == {}
15 changes: 15 additions & 0 deletions test_seed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from click.testing import CliRunner
from seed import seed


def test_no_params():
runner = CliRunner()
result = runner.invoke(seed)
assert result.exit_code == 0
assert result.output == '150 users\n'

def test_total():
runner = CliRunner()
result = runner.invoke(seed, ['--total',800])
assert result.exit_code == 0
assert result.output == '800 users\n'

0 comments on commit a6e28f6

Please sign in to comment.