Skip to content

alvertogit/codetest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

93 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CODE TEST

This repository stores a code test compose of two exercises to demonstrate skills mainly with Python, Django, Gunicorn, NGINX, PostgreSQL, Docker, Jupyter Notebook, microservices and REST API.

DEPENDENCIES

The code has been tested using:

  • Python (3.12): an interpreted high-level programming language for general-purpose programming.
  • Jupyter Lab (4.2): a web-based interactive development environment for Jupyter Notebooks, code and data.
  • Django (5.0): a high-level Python Web framework that encourages rapid development and clean, pragmatic design.
  • Gunicorn (22.0): a Python WSGI HTTP Server for UNIX.
  • NGINX (1.25): a free, open-source, high-performance HTTP server, reverse proxy, and IMAP/POP3 proxy server.
  • PostgreSQL (16): an object-relational database management system (ORDBMS) with an emphasis on extensibility and standards compliance.
  • Docker (26.1): an open platform for developers and sysadmins to build, ship, and run distributed applications, whether on laptops, data center VMs, or the cloud.
  • Docker Compose (2.27): a tool for defining and running multi-container Docker applications.

Virtual environment (<env_name>=.venv) can be generated with requirements.txt file found in codetest main folder.

Command to configure virtual environment with venv:

~/codetest$ python3 -m venv .venv
~/codetest$ source .venv/bin/activate
(.venv)~/codetest$ python3 -m pip install pip==24.0
(.venv)~/codetest$ python3 -m pip install setuptools==69.5.1
(.venv)~/codetest$ python3 -m pip install -r requirements.txt

CODE TEST CONTENT

Codetest main folder contains two folders for Exercise 1 and Exercise 2.

codetest
├── exercise1
├── exercise2
├── README.md
└── requirements.txt

EXERCISE 1: PYTHON

EXERCISE 1 REQUIREMENTS

Write a small app that takes an integer and return a string representation of that integer with commas separating groups of 3 digits. For example:

print(translate(1234))
'1,234'
print(translate(123456789))
'123,456,789'

EXERCISE 1 NOTES

• Use Python as programming language.

• Input/output methods doesn’t matter.

EXERCISE 1 FOLDER CONTENT

The exercise1 folder contains three files:

  • function.py: It contents translate functions code for Exercise 1 including one solution with regular expression.

  • main.py: It is used to test translate functions.

  • Exercise1.ipynb: Jupyter Notebook to test translate functions.

exercise1
├── docs
├── Exercise1.ipynb
├── function.py
└── main.py

HOW TO RUN EXERCISE 1

The way to run Exercise 1 is simple. Just go to exercise1 folder and execute:

(.venv)~/codetest/exercise1$ python3 main.py

A good way to play with the translate and translate_regex functions is through a Jupyter Lab. One notebook is stored in the same exercise1 folder, to run it use the command shown below:

(.venv)~/codetest/exercise1$ jupyter lab Exercise1.ipynb

Jupyter notebook translate function

EXERCISE 2: DATA & API TEST

EXERCISE 2 REQUIREMENTS

Write a small app that publish an REST API with these endpoints using data from test.xml:

• Give me 20 products ordered by price.

• Give me 20 products ordered by discount (price - custom_label_0).

• Give me the most discounted 20 products.

• Give me all products under the “Comedy” product type.

EXERCISE 2 NOTES

• Use Python as programming language (Django framework preferred).

• Don’t waste time in how consume the API or in the authentication. If it can be tested with Curl or Requests, is totally valid.

BONUS

• Use Docker Compose to setup and run the Django/PostgreSQL app.

EXERCISE 2 FOLDER CONTENT

The exercise2 folder contains:

exercise2
├── docker-compose.yml
├── docs
├── mysite
│   ├── .env.example
│   ├── Dockerfile
│   ├── manage.py
│   ├── mysite
│   │   ├── __init__.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   ├── wsgi.py
│   ├── products
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── __init__.py
│   │   ├── models.py
│   │   ├── serializers.py
│   │   ├── tests.py
│   │   ├── urls.py
│   │   ├── views.py
│   └── requirements.txt
├── nginx
│   └── conf.d
│       └── local.conf
└── postgresql
    ├── codetest.sql
    ├── Dockerfile
    ├── importer.py
    └── test.xml
  • docker-compose.yml: creates the Django and PostgreSQL Docker containers in which the applications shall run.

  • docs: It stores Exercise 2 documentation.

  • mysite: It stores Django's products app code.

  • nginx: It stores NGINX's configuration.

  • postgresql: It stores the test.xml with data to be inserted into PostgreSQL and the importer app to do this process.

EXERCISE 2 ARCHITECTURE

The architecture created with Docker Compose uses three different Docker containers for:

The following diagram illustrates the architecture in blocks:

flowchart LR;
   Client<-->NGINX;
   NGINX<--brigde-->Gunicorn;
   subgraph web;
   Gunicorn<-->Django;
   end;
   Django<--brigde-->id1[(PostgreSQL)]

HOW TO RUN EXERCISE 2 WITH DOCKER COMPOSE

The steps and commands to run Exercise 2 with Docker Compose are described below.

First create environment .env file using .env.example file as template inside mysite folder. Exercise 2 should run fine with default template settings.

Then Docker Compose can be executed to build services.

~/codetest/exercise2$ docker compose build

Next step consists in executing Docker Compose up command.

~/codetest/exercise2$ docker compose up

It is possible that for the first time the command keeps stopped at one point as shown below:

...
postgres_db_1_81cb47c30feg | 2018-12-11 09:59:15.676 UTC [42] ERROR:  role "postgres" does not exist
postgres_db_1_81cb47c30feg | 2018-12-11 09:59:15.676 UTC [42] STATEMENT:  REVOKE ALL ON SCHEMA public FROM postgres;
exercise2_postgres_db_1_81cb47c30feg exited with code 3

If this happens simply press 'Control+C', wait patiently to return to shell and repeat again the same command. If everything goes fine at the end it should appear something similar to:

...
postgres_db_1_81cb47c30feg | 2018-12-11 09:59:27.670 UTC [1] LOG:  database system is ready to accept connections

There are different ways to check that the server is running properly. One is opening a web browser such as Chrome or Firefox and paste the following URL:

http://127.0.0.1/products/

The web browser should show something similar to:

HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "price": "http://127.0.0.1/products/price/",
    "discount": "http://127.0.0.1/products/discount/",
    "mostdiscounted": "http://127.0.0.1/products/mostdiscounted/",
    "typecomedy": "http://127.0.0.1/products/typecomedy/"
}

The description of the URLs that are above:

  • "price" URL: Gets 20 products ordered by price.
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "product_id": "AF5TW2",
        "title": "Maxi-Cosi - AxissFix Autostol (61-105 cm)",
        "product_type": "Car Seats > Child car seats > Child benefit",
        "price": "3299.00",
        "custom_label_0": "3135.00"
    },
    {
        "product_id": "AN3WT9",
        "title": "Maxi-Cosi - AxissFix Autostol (61-105 cm)",
        "product_type": "Car Seats > Child car seats > Child benefit",
        "price": "3299.00",
        "custom_label_0": "3135.00"
    },
    ...
    ...
    ...
    {
        "product_id": "AG286U",
        "title": "Maxi-Cosi - Citi Autostol (0-13 kg)",
        "product_type": "Car Seats > Child car seats > Child benefit",
        "price": "890.00",
        "custom_label_0": "846.00"
    }
]
  • "discount" URL: Gets 20 products ordered by discount (price - custom_label_0).
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "product_id": "AF84CU",
        "title": "Sisley - Daily Line Reducer 30 ml",
        "product_type": "Skincare > Face > Oils & Serums",
        "price": "2399.00",
        "custom_label_0": "2199.00"
    },
    {
        "product_id": "AD529V",
        "title": "Maxi-Cosi - AxissFix Autostol (61-105 cm)",
        "product_type": "Car Seats > Child car seats > Child benefit",
        "price": "3299.00",
        "custom_label_0": "3135.00"
    },
    ...
    ...
    ...
    {
        "product_id": "AJ79SB",
        "title": "Escentric Molecules - Escentric 04 EDT 100 ml",
        "product_type": "Perfume > Eau de Toilette",
        "price": "679.00",
        "custom_label_0": "612.00"
    }
]
  • "mostdiscounted" URL: Gets the most discounted 20 products.
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "product_id": "AJ43CN",
        "title": "Grusomme mig 2 - DVD",
        "product_type": "Movies > DVD > Standard > Adventure > 7",
        "price": "69.00",
        "custom_label_0": "29.00"
    },
    {
        "product_id": "AF75JP",
        "title": "Marley & Me - DVD",
        "product_type": "Movies > DVD > Standard > Comedy > Owen Wilson > 7",
        "price": "69.00",
        "custom_label_0": "29.00"
    },
    ...
    ...
    ...
    {
        "product_id": "AC8M7R",
        "title": "Melton - Numbers Rib Drenge Boxershorts 2 pk",
        "product_type": "Apparel & Accessories > Clothing",
        "price": "99.00",
        "custom_label_0": "59.00"
    }
]
  • "typecomedy" URL: Gets all products under “Comedy” product type.
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "product_id": "AK628C",
        "title": "Men in Black 3 (3D Blu-Ray)",
        "product_type": "Movies > 3D Blu-Ray > Standard > Comedy > Will Smith",
        "price": "109.00",
        "custom_label_0": "79.00"
    },
    {
        "product_id": "AC39B4",
        "title": "Men in Black 3 (4K Blu-Ray)",
        "product_type": "Movies > 4K Blu-Ray > Standard > Comedy > Will Smith",
        "price": "269.00",
        "custom_label_0": "229.00"
    },
    ...
    ...
    ...
    {
        "product_id": "AF52KX",
        "title": "Glee: Hele Sæson 5 (6-disc) - DVD",
        "product_type": "TV Series > DVD > Complete Edition > Comedy > Lea Michele > 15",
        "price": "109.00",
        "custom_label_0": "69.00"
    }
]

TESTS

To run tests execute inside web container the command to launch tests:

~/codetest/exercise2$ docker compose exec web bash
root@8800eecc88:/mysite# python manage.py test
Found 6 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
......
----------------------------------------------------------------------
Ran 6 tests in 0.056s

OK
Destroying test database for alias 'default'...

CREDITS

author: alvertogit copyright: 2018-2024

About

Code test Python Django Django5 PostgreSQL Docker NGINX Gunicorn microservices REST API Jupyter Lab Notebook

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published