Skip to content
Snippets Groups Projects
Commit 88942e84 authored by ramaland's avatar ramaland
Browse files

Merge branch 'main' into 'Add-item'

# Conflicts:
#   src/tjts5901/views.py
parents 488feaf8 a6957ae2
No related branches found
No related tags found
3 merge requests!9Add item,!8Add item,!7add items view
Pipeline #13698 failed
......@@ -164,4 +164,5 @@ cython_debug/
_docs/
.env
dotenv
.DS_Store
## Stage names in the pipeline.
stages:
- build
- test
- deploy
variables:
## Name for the generated image. Change this if you wish, but watch out
## for special characters and spaces!
DOCKER_IMAGE_NAME: ${DOCKER_REGISTRY}/tjts5901
DOCKER_TAG: latest
DOCKER_IMAGE_NAME: ${DOCKER_REGISTRY}/tjts5901teamfrozen
DOCKER_TAG: $CI_COMMIT_REF_SLUG
## (Optional) More verbose output from pipeline. Enabling it might reveal secrets.
#CI_DEBUG_TRACE: "true"
......@@ -43,3 +45,27 @@ build:
--local dockerfile=. \
--opt build-arg:CI_COMMIT_SHA=${CI_COMMIT_SHA} \
--output type=image,name=${DOCKER_IMAGE_NAME}:${DOCKER_TAG},push=true
## Run the tests. If any of the tests fails, pipeline is rejected.
test:
## Optional: include stage and environment name
stage: test
# environment: testing
image: ${DOCKER_IMAGE_NAME}:${DOCKER_TAG}
script:
- pip install --disable-pip-version-check -e .[test]
- pytest -v
- echo "Test were run succesfully!"
## Deploy latest image to the production
deploy:
stage: deploy
environment: production
image: docker:stable
only:
- main
script:
## Copy credentials to container
- mkdir -p ${HOME}/.docker && echo "${DOCKER_AUTH_CONFIG}" > "${HOME}/.docker/config.json"
## Add the `latest` tag to the image we have build.
- docker buildx imagetools create ${DOCKER_IMAGE_NAME}:${DOCKER_TAG} --tag ${DOCKER_IMAGE_NAME}:latest
......@@ -5,6 +5,13 @@
version: '3'
services:
# MongoDB container
mongodb:
image: mongo:4.2
restart: unless-stopped
ports:
- 27017:27017
tjts5901:
build:
context: .
......@@ -38,13 +45,6 @@ services:
depends_on:
- mongodb
# MongoDB container
mongodb:
image: mongo:4.2
restart: unless-stopped
ports:
- 27017:27017
volumes:
tjts5901-vscode-extensions:
......@@ -14,9 +14,4 @@
# developers or deployments, as you can simply share the .env file rather than hardcoding the
# values into the application itself.
FLASK_APP=tjts5901.app
FLASK_DEBUG=1
# Enable rich logging for more human readable log output. Requires installing
# `rich` and `flask-rich` packages.
#RICH_LOGGING=1
MONGO_URL = "mongodb://localhost:27017/
\ No newline at end of file
......@@ -28,6 +28,7 @@ dependencies = {file = ["requirements.txt"]}
[project.optional-dependencies]
test = [
"pytest",
"coverage",
]
docs = [
"mkdocs",
......
......@@ -2,9 +2,11 @@
importlib-metadata
# Framework and libraries
flask
flask==2.2.2
python-dotenv
flask-mongoengine==1.0
# Git hooks
pre-commit
......
......@@ -6,7 +6,14 @@ JYU TJTS5901 Course project
from importlib_metadata import (PackageNotFoundError,
version)
from .app import create_app
try:
__version__ = version(__name__)
except PackageNotFoundError:
__version__ = "unknown"
__all__ = [
"create_app",
"__version__",
]
\ No newline at end of file
......@@ -8,6 +8,7 @@ Flask tutorial: https://flask.palletsprojects.com/en/2.2.x/tutorial/
"""
from os import environ
import os
from typing import Dict, Optional
from dotenv import load_dotenv
......@@ -19,6 +20,7 @@ from flask import (
)
from .utils import get_version
from .db import init_db
def create_app(config: Optional[Dict] = None) -> Flask:
......@@ -29,16 +31,36 @@ def create_app(config: Optional[Dict] = None) -> Flask:
"""
flask_app = Flask(__name__, instance_relative_config=True)
if config:
flask_app.config.from_mapping(
SECRET_KEY='dev',
BRAND="Hill Valley DMC dealership",
)
# load the instance config, if it exists, when not testing
if config is None:
flask_app.config.from_pyfile('config.py', silent=True)
else:
flask_app.config.from_mapping(config)
# Set flask config variable for "rich" loggin from environment variable.
flask_app.config.from_envvar("RICH_LOGGING", silent=True)
# ensure the instance folder exists
try:
os.makedirs(flask_app.instance_path)
except OSError:
pass
# Initialize the database connection.
init_db(flask_app)
# Register blueprints
# Register blueprints
from . import views # pylint: disable=import-outside-toplevel
flask_app.register_blueprint(views.bp, url_prefix='')
# a simple page that says hello
@flask_app.route('/hello')
def hello():
return 'Hello, World!'
return flask_app
......@@ -49,13 +71,6 @@ load_dotenv()
# Create the Flask application.
app = create_app()
# Initialize "rich" output if enabled. It produces more human readable logs.
# You need to install `flask-rich` to use this.
if app.config.get("RICH_LOGGING"):
from flask_rich import RichApplication
RichApplication(app)
app.logger.info("Using [blue]rich[/blue] interface for logging")
@app.route("/server-info")
def server_info() -> Response:
......
from os import environ
from flask_mongoengine import MongoEngine
db = MongoEngine()
def init_db(app):
"""
Initialize the database connection.
Fetches the database connection string from the environment variable `MONGO_URL`
and, if present, sets the `MONGODB_SETTINGS` configuration variable to use it.
"""
# To keep secrets private, we use environment variables to store the database connection string.
# `MONGO_URL` is expected to be a valid MongoDB connection string, see: blah blah blah
mongodb_url = environ.get("MONGO_URL")
if mongodb_url is not None:
app.config["MONGODB_SETTINGS"] = {
"host": mongodb_url,
}
db.init_app(app)
\ No newline at end of file
from datetime import datetime
from .db import db
from mongoengine import (
StringField,
IntField,
ReferenceField,
DateTimeField,
EmailField,
)
class User(db.Document):
"""
Model representing a user of the auction site.
"""
email = EmailField(required=True, unique=True)
password = StringField(required=True)
created_at = DateTimeField(required=True, default=datetime.utcnow)
class Item(db.Document):
"""
A model for items that are listed on the auction site.
"""
title = StringField(max_length=100, required=True)
description = StringField(max_length=2000, required=True)
starting_bid = IntField(required=True, min_value=0)
seller = ReferenceField(User, required=True)
created_at = DateTimeField(required=True, default=datetime.utcnow)
closes_at = DateTimeField()
......@@ -23,6 +23,35 @@ def index() -> str:
html = render_template("index.html.j2", title="TJTS5901 Example. It was changed by Arno.")
return html
=======
@bp.route("/test")
def test_item_adding():
"""
Test item is added
"""
from .models import Item, User
# for test purpose create random number (unique mail address required)
import random
ran_int = str(random.randint(0,10000))
# Create a new user
user = User()
user.email = "test" + ran_int + "@gmail.com"
user.password = "placeholder"
user.save()
# Create a new item
item = Item()
item.title = "Test title"
item.description = "This is a test description"
item.starting_bid = 100
item.seller = user
item.save()
return "OK"
@bp.route("/addItem")
def addItem() -> str:
"""
......@@ -32,3 +61,4 @@ def addItem() -> str:
Item = render_template("addItem.html", title="Adding items")
return Item
>>>>>>> src/tjts5901/views.py
import pytest
from flask import Flask
from tjts5901.app import create_app
@pytest.fixture
def app():
"""
Application fixture.
Every test that requires `app` as parameter can use this fixture.
Example:
>>> def test_mytest(app: Flask):
>>> ...
"""
flask_app = create_app({
'TESTING': True,
'DEBUG': False,
# We need to set SERVER_NAME and PREFERRED_URL_SCHEME for testing.
'SERVER_NAME': 'localhost.localdomain',
'PREFERRED_URL_SCHEME': 'http',
})
# If you have done ties4080 course and have used Flask-WTF, you might
# have noticed that CSRF protection is enabled by default. This is
# problematic for testing, because we don't have a browser to generate
# CSRF tokens. We can disable CSRF protection for testing, but we need
# to make sure that we don't have CSRF protection enabled in production.
# flask_app.config['WTF_CSRF_ENABLED'] = False
# flask_app.config['WTF_CSRF_METHODS'] = []
# flask_app.config['WTF_CSRF_CHECK_DEFAULT'] = False
flask_app.testing = True
yield flask_app
# Do some cleanup here if needed.
...
@pytest.fixture
def client(app):
return app.test_client()
from tjts5901 import create_app
def test_config():
assert not create_app().testing
assert create_app({'TESTING': True}).testing
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment