From 1df815f8c96262e9ebd99fb9e9944fca4dd600bf Mon Sep 17 00:00:00 2001 From: n0body Date: Sat, 30 Aug 2025 02:39:49 +0300 Subject: [PATCH] First Commit - Added a script with all FastAPI methods - Added a main.py file to start everything - Generated a config that grabs data from .env --- .gitignore | 179 +++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | Bin 0 -> 836 bytes src/APIapp.py | 72 +++++++++++++++++++ src/DBwork.py | 122 ++++++++++++++++++++++++++++++++ src/config.py | 9 +++ src/main.py | 7 ++ sys.stdout | 118 +++++++++++++++++++++++++++++++ 7 files changed, 507 insertions(+) create mode 100644 .gitignore create mode 100644 requirements.txt create mode 100644 src/APIapp.py create mode 100644 src/DBwork.py create mode 100644 src/config.py create mode 100644 src/main.py create mode 100644 sys.stdout diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..687c658 --- /dev/null +++ b/.gitignore @@ -0,0 +1,179 @@ +# ---> Python +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +############CUSTOM########### +/src/test.py +responseTester.py + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +#uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# Ruff stuff: +.ruff_cache/ + +# PyPI configuration file +.pypirc diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..4ea05502486402145bd2034a8bc45a75e38b7789 GIT binary patch literal 836 zcmZ9K(N4lp5JdOc#81IM3y2SX3#p|*Bed8S6+d1*v)hZrG&hCr%YVXCcH0p;&*S)JX3qHN6ysl?G98!wT7YEobNM7M74y~!LM!05hA0S*#g{(leNXBMwY}gnO>|p-r>0x!Zo1~aqoMFYy@8wAnqJz`aCsbO)BMUO F(7%Osdout4 literal 0 HcmV?d00001 diff --git a/src/APIapp.py b/src/APIapp.py new file mode 100644 index 0000000..fa3f3e0 --- /dev/null +++ b/src/APIapp.py @@ -0,0 +1,72 @@ +import DBwork +from fastapi import FastAPI, Response, status +from pydantic import BaseModel +import psycopg2 +from json import dumps + + +schema_name = 'harticle' +table_name = 'articles' + +app = FastAPI() + +class Entry(BaseModel): + url: str + rating: int | None = None + + +@app.get('/api/ping') +async def ping(): + return {'message': 'pong'} + + +@app.get('/api/rates') +async def get_rates(): + return dumps(DBwork.get_all_entries()) + + +@app.post('/api/article/rate') +async def save_rating(entry: Entry, response: Response): + conn, cur = DBwork.set_connection() + try: + DBwork.add_entry(article_url=entry.url, + rating=entry.rating, + connection=conn, + cursor=cur + ) + message = 'success' + except psycopg2.Error: + response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR + message = 'internal server error' + finally: + DBwork.close_connection(conn, cur) + return {'message': message, + 'url': entry.url, + 'rating': entry.rating + } + + +@app.post('/api/article/remove_rate') +async def remove_rating(entry: Entry, response: Response): + conn, cur = DBwork.set_connection() + try: + DBwork.delete_entry(entry.url, conn, cur) + message = 'success' + except psycopg2.Error: + response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR + message = 'internal server error' + finally: + DBwork.close_connection(conn, cur) + return {'message': message} + + +@app.post('/api/articles/get') +async def megafunc(entry: Entry, response: Response): + ... + + +''' MAIN ''' +async def main(): + DBwork.schema_creator(schema_name) + DBwork.table_creator(schema_name, table_name) + diff --git a/src/DBwork.py b/src/DBwork.py new file mode 100644 index 0000000..825eb19 --- /dev/null +++ b/src/DBwork.py @@ -0,0 +1,122 @@ +import psycopg2 +import config +from loguru import logger + + +logging_level = config.logging_level +logger.add( + "sys.stdout", + format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level} | {file}:{line} - {message}", + colorize=True, + level=logging_level +) + + +#connection stuff +def set_connection(): + try: + connection = psycopg2.connect( + dbname = config.db_name, + user = config.postgres_user, + password = config.postgres_password, + host = config.host_name, + port = config.port + ) + cursor = connection.cursor() + return connection, cursor + except psycopg2.Error as e: + logger.error(f'Failed to set connection to the PostgreSQL DB: {e.pgerror}') + + +def close_connection(connection, cursor): + try: + cursor.close() + connection.close() + except psycopg2.Error as e: + logger.error(f'Failed to close PostgreSQL connection: {e.pgerror}') + + +#actual DB alters +def add_entry(article_url, rating): + connection, cursor = set_connection() + try: + cursor.execute("INSERT INTO harticle.articles (article_url, rating) VALUES (%s, %s);", (article_url, rating,)) + connection.commit() + logger.info('An entry has been written to the PGSQL DB successfully') + except psycopg2.Error as e: + logger.error(f'Failed to write an entry for article \'{article_url}\': {e.pgerror}') + finally: + close_connection(connection, cursor) + + +def delete_entry(article_url, connection, cursor): + connection, cursor = set_connection() + try: + cursor.execute("DELETE FROM harticle.articles WHERE article_url = %s;", (article_url,)) + connection.commit() + logger.info(f'Rating for article \'{article_url}\' was cleared successfully') + except psycopg2.Error as e: + logger.error(f'Failed to clear a rating entry for article \'{article_url}\': {e.pgerror}') + finally: + close_connection(connection, cursor) + + +# def delete_rating(article_url, connection, cursor): +# close_connection(connection, cursor) +# try: +# cursor.execute("UPDATE harticle.articles SET rating = NULL WHERE article_url = %s;", (article_url,)) +# connection.commit() +# logger.info(f'Rating for article \'{article_url}\' was cleared successfully') +# close_connection(connection, cursor) +# except psycopg2.Error as e: +# logger.error(f'Failed to clear a rating entry for article \'{article_url}\': {e.pgerror}') + + +def get_all_entries(): + connection, cursor = set_connection() + try: + cursor.execute('SELECT article_url, rating FROM harticle.articles;') + entries = cursor.fetchall() + logger.info('All entry pairs have been retrieved successfully') + return entries + except psycopg2.Error as e: + logger.error(f'Failed to fetch DB entries: {e.pgerror}') + finally: + close_connection(connection, cursor) + + +#'create if no any' type functions for schema and table +def schema_creator(schema_name): + conn, cur = set_connection() + try: + cur.execute(f'CREATE SCHEMA IF NOT EXISTS {schema_name};') + conn.commit() + logger.info(f'Successfully created schema {schema_name} if it didn\'t exist yet') + except psycopg2.Error as e: + logger.error(f'Error during schema creation: {e}') + finally: + close_connection(conn, cur) + + +def table_creator(schema_name, table_name): + conn, cur = set_connection() + try: + cur.execute(f''' +CREATE TABLE IF NOT EXISTS {schema_name}.{table_name} +( + id SERIAL PRIMARY KEY, + article_url VARCHAR(3000) UNIQUE NOT NULL, + rating INT CHECK (rating < 2) +) + +TABLESPACE pg_default; + +ALTER TABLE IF EXISTS {schema_name}.{table_name} + OWNER to {config.postgres_user}; +''') + conn.commit() + logger.info(f'Successfully created table {table_name} in schema {schema_name} if it didn\'t exist yet') + except psycopg2.Error as e: + logger.error(f'Error during table creation: {e}') + finally: + close_connection(conn, cur) \ No newline at end of file diff --git a/src/config.py b/src/config.py new file mode 100644 index 0000000..4ff096e --- /dev/null +++ b/src/config.py @@ -0,0 +1,9 @@ +from decouple import config + + +db_name = config('DB_NAME') +postgres_user = config('POSTGRES_USER') +postgres_password = config('POSTGRES_PASSWORD') +host_name = config('HOST_NAME') +port = config('PORT') +logging_level = config('LOGGING_LEVEL') \ No newline at end of file diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..8e5f9a7 --- /dev/null +++ b/src/main.py @@ -0,0 +1,7 @@ +import asyncio +import APIapp +import uvicorn + + +asyncio.run(APIapp.main()) +uvicorn.run("APIapp:app", host="127.0.0.1", port=8000, log_level="info") \ No newline at end of file diff --git a/sys.stdout b/sys.stdout new file mode 100644 index 0000000..cb7d7eb --- /dev/null +++ b/sys.stdout @@ -0,0 +1,118 @@ +2025-08-29 20:42:34.367 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 20:47:34.345 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 20:47:34.403 | INFO | DBwork.py:65 - Successfully created schema harticle if it didn't exist yet +2025-08-29 20:47:34.476 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 20:47:34.495 | ERROR | DBwork.py:91 - Error during table creation: syntax error at or near "article_url" +LINE 5: article_url VARCHAR(3000) UNIQUE NOT NULL, + ^ + +2025-08-29 20:48:24.020 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 20:48:24.099 | INFO | DBwork.py:65 - Successfully created schema harticle if it didn't exist yet +2025-08-29 20:48:24.454 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 20:48:24.477 | ERROR | DBwork.py:91 - Error during table creation: syntax error at or near ")" +LINE 7: ) + ^ + +2025-08-29 20:49:37.475 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 20:49:37.498 | INFO | DBwork.py:65 - Successfully created schema harticle if it didn't exist yet +2025-08-29 20:49:37.574 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 20:49:37.602 | ERROR | DBwork.py:91 - Error during table creation: syntax error at or near "to" +LINE 12: OWNER to postgres_user; + ^ + +2025-08-29 20:50:31.676 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 20:50:31.703 | INFO | DBwork.py:65 - Successfully created schema harticle if it didn't exist yet +2025-08-29 20:50:31.790 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 20:50:31.855 | INFO | DBwork.py:89 - Successfully created table articles in schema harticle if it didn't exist yet +2025-08-29 21:08:43.249 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:08:43.274 | INFO | DBwork.py:65 - Successfully created schema harticle if it didn't exist yet +2025-08-29 21:08:43.321 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:08:43.343 | INFO | DBwork.py:89 - Successfully created table articles in schema harticle if it didn't exist yet +2025-08-29 21:09:01.219 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:09:01.253 | INFO | DBwork.py:65 - Successfully created schema harticle if it didn't exist yet +2025-08-29 21:09:01.320 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:09:01.349 | INFO | DBwork.py:89 - Successfully created table articles in schema harticle if it didn't exist yet +2025-08-29 21:12:16.086 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:12:16.109 | INFO | DBwork.py:65 - Successfully created schema harticle if it didn't exist yet +2025-08-29 21:12:16.161 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:12:16.200 | INFO | DBwork.py:89 - Successfully created table articles in schema harticle if it didn't exist yet +2025-08-29 21:12:39.738 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:12:40.970 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:16:42.028 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:16:42.051 | INFO | DBwork.py:66 - Successfully created schema harticle if it didn't exist yet +2025-08-29 21:16:42.052 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-29 21:16:42.176 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:16:42.268 | INFO | DBwork.py:90 - Successfully created table articles in schema harticle if it didn't exist yet +2025-08-29 21:16:42.269 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-29 21:16:47.546 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:45:13.302 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:45:13.348 | INFO | DBwork.py:66 - Successfully created schema harticle if it didn't exist yet +2025-08-29 21:45:13.349 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-29 21:45:13.515 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 21:45:13.573 | INFO | DBwork.py:90 - Successfully created table articles in schema harticle if it didn't exist yet +2025-08-29 21:45:13.573 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-29 22:01:03.641 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 22:01:03.672 | INFO | DBwork.py:66 - Successfully created schema harticle if it didn't exist yet +2025-08-29 22:01:03.673 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-29 22:01:03.801 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-29 22:01:03.882 | INFO | DBwork.py:90 - Successfully created table articles in schema harticle if it didn't exist yet +2025-08-29 22:01:03.884 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-30 00:26:49.887 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 00:32:29.541 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 00:32:29.562 | INFO | DBwork.py:75 - Successfully created schema harticle if it didn't exist yet +2025-08-30 00:32:29.562 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-30 00:32:29.604 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 00:32:29.625 | INFO | DBwork.py:99 - Successfully created table articles in schema harticle if it didn't exist yet +2025-08-30 00:32:29.626 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-30 00:32:35.060 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 00:32:35.075 | ERROR | DBwork.py:66 - Failed to fetch DB entries: ERROR: relation "articles" does not exist +LINE 1: SELECT article_url, rating FROM articles; + ^ + +2025-08-30 01:11:28.088 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 01:13:41.424 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 01:13:41.442 | ERROR | DBwork.py:48 - Failed to write an entry for article 'test': ERROR: relation "articles" does not exist +LINE 1: INSERT INTO articles VALUES ('test', 1); + ^ + +2025-08-30 01:13:41.443 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-30 01:16:21.430 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 01:16:21.450 | ERROR | DBwork.py:48 - Failed to write an entry for article 'test': ERROR: relation "articles" does not exist +LINE 1: INSERT INTO Articles VALUES ('test', 1); + ^ + +2025-08-30 01:16:21.452 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-30 01:27:16.292 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 01:27:16.312 | ERROR | DBwork.py:48 - Failed to write an entry for article 'test': ERROR: invalid input syntax for type integer: "test" +LINE 1: INSERT INTO harticle.articles VALUES ('test', 1); + ^ + +2025-08-30 01:27:16.312 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-30 01:35:20.928 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 01:35:20.965 | INFO | DBwork.py:46 - An entry has been written to the PGSQL DB successfully +2025-08-30 01:35:20.966 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-30 01:38:27.104 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 01:38:27.123 | ERROR | DBwork.py:48 - Failed to write an entry for article 'test': ERROR: duplicate key value violates unique constraint "articles_article_url_key" +DETAIL: Key (article_url)=(test) already exists. + +2025-08-30 01:38:27.124 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-30 01:41:24.219 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 01:41:24.255 | INFO | DBwork.py:46 - An entry has been written to the PGSQL DB successfully +2025-08-30 01:41:24.256 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-30 01:46:31.107 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 01:46:31.137 | INFO | DBwork.py:46 - An entry has been written to the PGSQL DB successfully +2025-08-30 01:50:05.814 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 01:50:05.851 | INFO | DBwork.py:55 - Rating for article 'test2' was cleared successfully +2025-08-30 01:50:05.851 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-30 01:50:32.270 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 01:50:32.301 | INFO | DBwork.py:55 - Rating for article 'test1' was cleared successfully +2025-08-30 01:50:32.301 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-30 01:50:35.079 | INFO | DBwork.py:26 - Successfully set connection to the PostgreSQL DB +2025-08-30 01:50:35.110 | INFO | DBwork.py:55 - Rating for article 'test' was cleared successfully +2025-08-30 01:50:35.110 | INFO | DBwork.py:36 - Successfully closed connection to the PostgreSQL DB +2025-08-30 02:04:55.458 | INFO | DBwork.py:80 - All entry pairs have been retrieved successfully +2025-08-30 02:05:13.018 | INFO | DBwork.py:80 - All entry pairs have been retrieved successfully +2025-08-30 02:06:51.642 | INFO | DBwork.py:80 - All entry pairs have been retrieved successfully +2025-08-30 02:10:40.955 | INFO | DBwork.py:80 - All entry pairs have been retrieved successfully +2025-08-30 02:11:48.088 | INFO | DBwork.py:80 - All entry pairs have been retrieved successfully +2025-08-30 02:12:19.839 | INFO | DBwork.py:80 - All entry pairs have been retrieved successfully