Skip to content

Commit

Permalink
Feat 31 add rom support (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
ecourtial authored Aug 7, 2022
1 parent 1e727aa commit 62f8080
Show file tree
Hide file tree
Showing 16 changed files with 107 additions and 40 deletions.
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ jobs:
command: |
mysql -h mysql -u game -pazerty games < test/games_test.sql
nohup gunicorn --workers=1 --bind=0.0.0.0:9000 app:app &
sleep 5
make test_command_python
linter:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ __pycache__/
docker/data/db
test/**/*.pyc
configuration.json
.history/
.vscode/
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Changelog

## 4.1.0

### New features
* The copy entity has a new _is_rom_ field to define if the copy is a ROM or not (for emulation for instance).
A migration file is available in the _migrations_ folder (see [Migrations and update guide](docs/MIGRATIONS.md)).
* The copy _casingType_ field accepts a new value: _Plastic tube_.
19 changes: 11 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
.PHONY: test

test:
make import_db && docker-compose exec python bash -c 'make test_command_python'
make import_db && docker compose exec python bash -c 'make test_command_python'

linter:
docker-compose exec python pylint --rcfile=standard.rc src/ ./app.py
docker compose exec python pylint --rcfile=standard.rc src/ ./app.py

start:
docker-compose up
docker compose up

python:
docker-compose exec python bash
docker compose exec python bash

mysql:
docker-compose exec mysql bash -c 'mysql -u game -pazerty games'
docker compose exec mysql bash -c 'mysql -u game -pazerty games'

import_db:
docker-compose exec mysql bash -c 'cd /code && make import_db_command'
docker compose exec mysql bash -c 'cd /code && make import_db_command'

export_db:
docker-compose exec mysql bash -c 'cd /code && mysqldump -u game -pazerty games > test/games_test.sql'
docker compose exec mysql bash -c 'cd /code && mysqldump -u game -pazerty games > test/games_test.sql'

# updates the requirements from PIPENV (need to rebuild the pyton container after that)
requirements:
docker-compose exec python bash -c "cd docker/python && pipenv lock -r > ./requirements.txt"
docker compose exec python bash -c "cd docker/python && pipenv lock -r > ./requirements.txt"

## Containers internal command
import_db_command:
mysql -u game -pazerty games < test/games_test.sql

test_command_python:
python -m unittest discover .

migration:
docker compose exec mysql bash -c 'cd /code && mysql -u game -pazerty games < migrations/${FILE}.sql'
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ A basic documentation is available:
* [How to install the project](docs/SETUP.md)
* [Introduction to the API](docs/API.md)
* [Resources managed by the application and their API representation](docs/RESOURCES.md)
* [Migrations and update guide](docs/MIGRATIONS.md)

## Stack :light_rail:

Expand All @@ -39,3 +40,7 @@ A basic documentation is available:
* unittest
* pylint
* MySQL 8

## Changelog

The changelog is available [here](CHANGELOG.md)
6 changes: 0 additions & 6 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ services:
build: docker/python
container_name: python_gmg
working_dir: /code
restart: always
volumes:
- .:/code
depends_on:
Expand All @@ -34,8 +33,3 @@ services:
- MYSQL_DATABASE=games
- MYSQL_USER=game
- MYSQL_PASSWORD=azerty

networks:
default:
external:
name: shared-gmg
4 changes: 1 addition & 3 deletions docker/mysql/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# Use the default image. Do not use like those guys who use a Linux distro then install nginx
FROM mysql:8
FROM mysql:8.0-debian

# Install nano because using vi is like using a donkey at the age of intergalactic travel
RUN apt-get update && apt-get -q -y install nano make
2 changes: 1 addition & 1 deletion docker/python/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ RUN pip install pipenv
COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt

RUN pip install pylint
RUN pip install pylint==2.13.9

# --reload: in dev mode, ask gunicorn to restart worker on any source file change
CMD ["gunicorn", "--workers=1", "--threads=2", "--bind=0.0.0.0:9000", "--reload", "app:app"]
9 changes: 9 additions & 0 deletions docs/MIGRATIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Migrations and update guide

* 1) Stop serving the application (just keep MySQL running).
* 2) Get and update the source code form the last version (tip: download everything from Github and replace it in your folder).
* 3) Run all the migrations you need using the following command:
```make migration FILE={migration_file}```
for instance
```make migration FILE=4.1.0```.
* 4) Restart your server.
31 changes: 16 additions & 15 deletions docs/RESOURCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,21 +95,22 @@ The application relies on 6 resources (not including the users).

| Field | Type | Editable | Unique | Role | Notes |
|--------------------------|-------|----------|--------|-----------------------------------------------------------------------------|-----------------------------------------|
| id | int | No | Yes | The version unique id. | |
| versionId | int | Yes | No | The id of the version the story relates to. | |
| original | bool | Yes | No | Is the copy an original (not a copy from an original)? | |
| language | string | Yes | No | Any language value. We recommend to use ISO standards, or _multi_ if mutilanguage. | |
| boxType | string| Yes | No | Type of the box (See allowed types below). | |
| casingType | string| Yes | No | Casing type of the box (See allowed types below). | |
| supportType | string| Yes | No | The game support type (See allowed types below). | |
| onCompilation | bool | Yes | No | Is the copy of the game on a compilation? | |
| reedition | bool | Yes | No | Is the copy of the game on a reedition, like a platinum, a classic one? | |
| hasManual | bool | Yes | No | Does the copy has a manual? | |
| status | string| Yes | No | Do you currently have this copy (See allowed types below)? | |
| type | string| Yes | No | Type of the copy (See allowed types below)? | |
| comments | string| Yes | No | Commments. | |
| platformName | string| No | No | The name of the platform. | |
| gameTitle | string| No | No | The title of the game related to this copy. | |
| id | int | No | Yes | The version unique id. | |
| versionId | int | Yes | No | The id of the version the story relates to. | |
| original | bool | Yes | No | Is the copy an original (not a copy from an original)? | |
| language | string| Yes | No | Any language value. We recommend to use ISO standards, or _multi_ if mutilanguage. | |
| boxType | string| Yes | No | Type of the box (See allowed types below). | |
| casingType | string| Yes | No | Casing type of the box (See allowed types below). | |
| supportType | string| Yes | No | The game support type (See allowed types below). | |
| onCompilation | bool | Yes | No | Is the copy of the game on a compilation? | |
| reedition | bool | Yes | No | Is the copy of the game on a reedition, like a platinum, a classic one? | |
| hasManual | bool | Yes | No | Does the copy has a manual? | |
| status | string| Yes | No | Do you currently have this copy (See allowed types below)? | |
| type | string| Yes | No | Type of the copy (See allowed types below)? | |
| is_rom | bool | Yes | No | Is the copy a ROM? | |
| comments | string| Yes | No | Commments. | |
| platformName | string| No | No | The name of the platform. | |
| gameTitle | string| No | No | The title of the game related to this copy. | |

### Allowed types for _boxType_

Expand Down
7 changes: 6 additions & 1 deletion docs/SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

## Locally (DEV)

In the root folder, copy the file _configuration.json.dist_ to _configuration.json_ and fill it with your values. The MySQL credentials are visible in the _docker-compose.yml_ in the root folder.
In the root folder, copy the file _configuration.json.dist_ to _configuration.json_ and fill it with your values (the Google Captcha values are mandatory). The MySQL credentials are visible in the _docker-compose.yml_ in the root folder.

Next, just do a __make start__, and then run __make test__ to run the tests and import the local DB with test features. You're good to go!

Ther test DB it just imported has a user. You can login with the following credentials :
* username: _mephistophelesz_
* password: _barz_

## Production

_Reminder_: the empty database contains a default user.
Expand All @@ -17,6 +21,7 @@ Change them as soon as your project is running!

The usual process to setup a project is the following:
* Import the empty database (available at the root of the folder).
* Run all the migrations ([see here](./MIGRATIONS.md))
* Deploy the code.
* Configure the application.
* Start the application.
Expand Down
1 change: 1 addition & 0 deletions migrations/4.1.0.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE copies ADD is_rom TINYINT UNSIGNED NOT NULL DEFAULT 0 AFTER type;
15 changes: 15 additions & 0 deletions src/entity/copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Copy(AbstractEntity):
'Cardboard sleeve',
'Paper Sleeve',
'Plastic Sleeve',
'Plastic tube',
'Other',
'None'
}
Expand Down Expand Up @@ -103,6 +104,12 @@ class Copy(AbstractEntity):
'type': 'text',
'default': ''
},
'isROM': {
'field': 'is_rom',
'method': '_is_rom',
'required': False,
'type': 'int'
},
}

authorized_extra_fields_for_filtering = {
Expand Down Expand Up @@ -131,6 +138,7 @@ def __init__(
status,
type,
comments,
is_rom = None,
platform_name = None,
game_title = None,
transaction_count = None,
Expand All @@ -147,6 +155,7 @@ def __init__(
self.has_manual = bool(has_manual)
self.status = status
self.type = type
self.is_rom = bool(is_rom)
self.comments = comments
self.platform_name = platform_name
self.game_title = game_title
Expand Down Expand Up @@ -188,6 +197,9 @@ def get_status(self):
def get_type(self):
return self.type

def get_is_rom(self):
return self.is_rom

def get_comments(self):
return self.comments

Expand Down Expand Up @@ -224,6 +236,9 @@ def set_status(self, status):
def set_type(self, type):
self.type = type

def set_is_rom(self, is_rom):
self.is_rom = bool(is_rom)

def set_comments(self, comments):
self.comments = comments

Expand Down
3 changes: 1 addition & 2 deletions standard.rc
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,7 @@ max-module-lines=1000
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,
dict-separator


# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
Expand Down
25 changes: 25 additions & 0 deletions test/functional/test_copies.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,27 @@ def test_create_invalid_types(self):
self.assertEqual(400, resp.status_code)
self.assertEqual({'message': "The field 'boxType' does not support the value 'Big boxe'. Supported values are: Big box, Cartridge box, None, Other.", 'code': 11}, resp.json())

def test_create_invalid_casing_type(self):
payload = {
"versionId": 1,
"original": True,
'language': 'fr',
"boxType": "Cartridge box",
"casingType": "CD-likesss",
'supportType': 'CD-ROM',
"onCompilation": True,
"reedition": True,
"hasManual": False,
"status": "In",
"comments": "Found it somewhere"
}

resp = self.api_call('post', 'copy', payload, True)

self.assertEqual(400, resp.status_code)
self.assertEqual({'message': "The field 'casingType' does not support the value 'CD-likesss'. Supported values are: CD-like, Cardboard sleeve, DVD-like, None, Other, Paper Sleeve, Plastic Sleeve, Plastic tube.", 'code': 11}, resp.json())


def test_get_copy(self):
# Does not exist
resp = self.api_call('get', 'copy/666', {}, True)
Expand All @@ -85,6 +106,7 @@ def test_get_copy(self):
"status": "In",
'type': 'Physical',
"comments": "Bought it in 2004",
'isROM': False,
'gameTitle': 'Tonic Trouble',
'platformName': 'PC',
'transactionCount': 2,
Expand Down Expand Up @@ -118,6 +140,7 @@ def test_create_update_delete_success(self):
self.assertEqual(200, resp.status_code)
copy_id = str(resp.json()["id"])
payload['id'] = int(copy_id)
payload['isROM'] = False
self.assertEqual(payload, resp.json())

resp = self.api_call('get', 'copy/' + str(copy_id), None, True)
Expand All @@ -136,6 +159,7 @@ def test_create_update_delete_success(self):
"hasManual": False,
"status": "In",
"comments": "Found it somewhere",
"isROM": True,
'platformName': 'PC',
'gameTitle': 'Tonic Trouble',
'transactionCount': 0,
Expand All @@ -144,6 +168,7 @@ def test_create_update_delete_success(self):

resp = self.api_call('patch', 'copy/' + copy_id, payload, True)
payload['id'] = int(copy_id)
payload['isROM'] = True

self.assertEqual(200, resp.status_code)
self.assertEqual(payload, resp.json())
Expand Down
9 changes: 5 additions & 4 deletions test/games_test.sql
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
-- MySQL dump 10.13 Distrib 8.0.28, for Linux (x86_64)
-- MySQL dump 10.13 Distrib 8.0.29, for Linux (x86_64)
--
-- Host: localhost Database: games
-- ------------------------------------------------------
-- Server version 8.0.28
-- Server version 8.0.29

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
Expand Down Expand Up @@ -35,6 +35,7 @@ CREATE TABLE `copies` (
`has_manual` tinyint unsigned NOT NULL,
`status` varchar(255) NOT NULL DEFAULT 'In',
`type` varchar(255) NOT NULL,
`is_rom` tinyint unsigned NOT NULL DEFAULT '0',
`comments` text,
PRIMARY KEY (`copy_id`),
KEY `version_id` (`version_id`),
Expand All @@ -48,7 +49,7 @@ CREATE TABLE `copies` (

LOCK TABLES `copies` WRITE;
/*!40000 ALTER TABLE `copies` DISABLE KEYS */;
INSERT INTO `copies` VALUES (1,348,1,'fr','Big box','CD-like','CD-ROM',0,0,1,'In','Physical','Bought it in 2004'),(2,349,1,'fr','none','Cardboard sleeve','CD-ROM',1,1,0,'In','Physical','Got it with my cereals'),(3,245,1,'fr','None','CD-like','CD-ROM',1,1,0,'In','Physical','pues');
INSERT INTO `copies` VALUES (1,348,1,'fr','Big box','CD-like','CD-ROM',0,0,1,'In','Physical',0,'Bought it in 2004'),(2,349,1,'fr','none','Cardboard sleeve','CD-ROM',1,1,0,'In','Physical',0,'Got it with my cereals'),(3,245,1,'fr','None','CD-like','CD-ROM',1,1,0,'In','Physical',0,'pues');
/*!40000 ALTER TABLE `copies` ENABLE KEYS */;
UNLOCK TABLES;

Expand Down Expand Up @@ -292,4 +293,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2022-06-22 7:43:52
-- Dump completed on 2022-07-21 6:36:31

0 comments on commit 62f8080

Please sign in to comment.