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

challange-project-ateliware #101

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
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
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.DS_Store
__pycache__/
*.pyc
.env
.coverage
.pytest_cache
.idea
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/ChallangeProject.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM python:3.10

WORKDIR /app

COPY requirements.txt .

RUN pip install -r requirements.txt

COPY . .

CMD [ "python", "./app.py" ]
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: uwsgi uwsgi.ini
55 changes: 40 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,47 @@
# Desafio técnico para desenvolvedores
# Ateliware project challange

Construa uma nova aplicação, utilizando o framework de sua preferência (Ruby on Rails, Elixir Phoenix, Python Django ou Flask, NodeJS Sails, Java Spring, ASP.NET ou outro), a qual deverá conectar na API do GitHub e disponibilizar as seguintes funcionalidades:

- Botão para buscar e armazenar os repositórios destaques de 5 linguagens à sua escolha;
- Listar os repositórios encontrados;
- Visualizar os detalhes de cada repositório.
Botão para buscar e armazenar os repositórios destaques de 5 linguagens à sua escolha;
Listar os repositórios encontrados;
Visualizar os detalhes de cada repositório.

Alguns requisitos:

- Deve ser uma aplicação totalmente nova;
- A solução deve estar em um repositório público do GitHub;
- A aplicação deve armazenar as informações encontradas;
- Utilizar PostgreSQL, MySQL ou SQL Server;
- O deploy deve ser realizado, preferencialmente, no Heroku, AWS ou no Azure;
- A aplicação precisa ter testes automatizados;
- Preferenciamente dockerizar a aplicação;
- Por favor atualizar o readme da aplicação com passo a passo com instrução para subir o ambiente.
# About this project

Quando terminar, faça um Pull Request neste repo e avise-nos por email.
- Python 3.10
- Postgres 14
- Frontend Frameworks: Flask, Bootstrap
- Docker
- Heroku
- PyTest

**IMPORTANTE:** se você não conseguir finalizar o teste, por favor nos diga o motivo e descreva quais foram as suas dificuldades. Você pode também sugerir uma outra abordagem para avaliarmos seus skills técnicos, vender seu peixe, mostrar-nos do que é capaz.
# Deploy on Heroku
- https://ateliware-project-challange.herokuapp.com/

# Installation steps
- open project in terminal and run:
- $ docker-compose up --build

- open browser on: http://127.0.0.1:8001

# Requirements
- Docker

## Unit Tests
- Test new Repository (language, full_name=, html_url, stargazers_count, description)
- Test new History (email, fullname, language, url, description, date)
- Check register information found on database

## Functional Tests
- Search:
- Test page response
- Test make a new search
- Test GET and POST methods

- History:
- Test page response

- Run test:
- python -m pytest -v
- python -m pytest --setup-show --cov=project
12 changes: 12 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from project import create_app
from project.models.database import db


# Call the application factory function to construct a Flask application
# instance using the development configuration
app = create_app('flask.cfg')
app.app_context().push()
db.create_all()

if __name__ == '__main__':
app.run(port=8001)
22 changes: 22 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: "3.10"

services:
webserver:
build: .
command: uwsgi --ini uwsgi.ini
volumes:
- .:/app
ports:
- 8001:8001
depends_on:
- postgresdb
postgresdb:
image: postgres:14
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=QWERTY
volumes:
- postgres_data:/var/lib/postgresql/data/

volumes:
postgres_data:
36 changes: 36 additions & 0 deletions instance/flask.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
##########################################################
#
# This is a sample flask.cfg for developing a Flask application
#
##########################################################
import os


# Get the folder of the top-level directory of this project
BASEDIR = os.path.abspath(os.path.dirname(__file__))

# Update later by using a random number generator and moving
# the actual key outside of the source code under version control
SECRET_KEY = 'cd48e1c22de0961d5d1bfb14f8a66e006cfb1cfbf3f0c0f3'
WTF_CSRF_ENABLED = True
DEBUG = False

# DB CONNECTION
DATABASE = {
'engine': 'postgresql',
'user': 'postgres',
'pw': 'QWERTY',
'db': 'postgres',
'host': 'postgresdb', #postgresdb on docker
'port': '5432',
}

# Get database url from environment variables on Heroku else Docker
database_url = os.environ.get('DATABASE_URL', '%(engine)s://%(user)s:%(pw)s@%(host)s:%(port)s/%(db)s' % DATABASE)
if database_url and database_url.startswith("postgres://"):
database_url = database_url.replace("postgres://", "postgresql://", 1)
# rest of connection code using the connection string `database_url`

# SQLAlchemy
SQLALCHEMY_DATABASE_URI = database_url
SQLALCHEMY_TRACK_MODIFICATIONS = False
42 changes: 42 additions & 0 deletions instance/flask_test.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
##########################################################
#
# flask_test.cfg is intended to be used for testing a Flask application
#
##########################################################
import os


# Get the folder of the top-level directory of this project
BASEDIR = os.path.abspath(os.path.dirname(__file__))

# Update later by using a random number generator and moving
# the actual key outside of the source code under version control
SECRET_KEY = 'cd48e1c22de0961d5d1bfb14f8a66e006cfb1cfbf3f0c0f3'
DEBUG = True

# DB CONNECTION
DATABASE = {
'engine': 'postgresql',
'user': 'postgres',
'pw': 'QWERTY',
'db': 'postgres',
'host': 'localhost', #postgresdb on docker
'port': '5432',
}

# Get database url from environment variables on Heroku else Docker
database_url = os.environ.get('DATABASE_URL', '%(engine)s://%(user)s:%(pw)s@%(host)s:%(port)s/%(db)s' % DATABASE)
if database_url and database_url.startswith("postgres://"):
database_url = database_url.replace("postgres://", "postgresql://", 1)
# rest of connection code using the connection string `database_url`

# SQLAlchemy
SQLALCHEMY_DATABASE_URI = database_url
SQLALCHEMY_TRACK_MODIFICATIONS = False

# Enable the TESTING flag to disable the error catching during request handling
# so that you get better error reports when performing test requests against the application.
TESTING = True

# Disable CSRF tokens in the Forms (only valid for testing purposes!)
WTF_CSRF_ENABLED = False
44 changes: 44 additions & 0 deletions project/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from flask import Flask
from flask_migrate import Migrate
from flask_bootstrap import Bootstrap5
from project.models.database import db


#######################
#### Configuration ####
#######################


######################################
#### Application Factory Function ####
######################################

def create_app(config_filename=None):
app = Flask(__name__, instance_relative_config=True)
app.config.from_pyfile(config_filename)
initialize_extensions(app)
register_blueprints(app)
bootstrap = Bootstrap5(app)
return app


##########################
#### Helper Functions ####
##########################

def initialize_extensions(app):
# Since the application instance is now created, pass it to each Flask
# extension instance to bind it to the Flask application instance (app)
db.init_app(app)
migrate = Migrate()
migrate.init_app(app, db)


def register_blueprints(app):
# Since the application instance is now created, register each Blueprint
# with the Flask application instance (app)
from project.views.history import history_blueprints
from project.views.search import search_blueprints

app.register_blueprint(history_blueprints, url_prefix="/history")
app.register_blueprint(search_blueprints, url_prefix="/")
62 changes: 62 additions & 0 deletions project/controllers/Core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from datetime import datetime
from project.models.database import db, History
import json
from types import SimpleNamespace
from urllib.parse import urlencode
import requests
from project.models.repository import Repo


# DATABASE
def handled_history(email, data):
# store the repositories found in the search
new_history = History(email=email, fullname=data.full_name, language=data.language, url=data.html_url,
description=data.description, date=datetime.now().strftime("%d/%m/%Y %H:%M:%S"))

db.session.add(new_history)
db.session.commit()


# GITHUB
def search_github(email, keywords):
# API URL EXAMPLE https://api.github.com/search/repositories?q=Python+language:Python&sort=stars&order=desc
# This request search for repositories with the word "Python" in the name, the description, or the README.
# Limiting the results to only find repositories where the primary language is Python. Sorting by stars
# in descending order, so that the most popular repositories appear first in the search results.

results = []
qty = 0
keywords = [keyword.strip() for keyword in keywords.split(',')]
for keyword in keywords:
api_url = "https://api.github.com/search/repositories?"
sort, order = 'star', 'desc'
params = {'q': (keyword + 'language:' + keyword), 'sort': sort, 'order': order}
query_url = api_url + urlencode(params)
r = requests.get(query_url)
if r.status_code == 200:
data = json.loads(r.text, object_hook=lambda d: SimpleNamespace(**d))
qty += len(data.items)
for i in data.items[:2]:
results.append(Repo(i))

for repo in results:
handled_history(email, repo)

return results, qty


def get_languages():
# Retrieve a list of languages from GitHub API https://api.github.com/languages
languages_list = []
api_url = "https://api.github.com/languages"
r = requests.get(api_url)
if r.status_code == 200:
data = json.loads(r.text)
for lang in data:
languages_list.append(lang['name'])
return languages_list

else:
# In case response 403 GitHub API Rate limit exceeded return an error
return {'error loading data'}

Empty file added project/controllers/__init__.py
Empty file.
1 change: 1 addition & 0 deletions project/migrations/README
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Single-database configuration for Flask.
Empty file added project/migrations/__init__.py
Empty file.
Loading