Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ca4a98a
Add files via upload
Wudext Nov 5, 2022
b5088fb
Add files via upload
Wudext Nov 5, 2022
bf5a4b2
Update
Wudext Nov 14, 2022
bc8d686
s
Wudext Nov 14, 2022
d010667
FastApi
Wudext Nov 17, 2022
a0753a8
фыв
Wudext Nov 17, 2022
2eca50d
Update main_fastapi.py
Wudext Nov 17, 2022
cf2d10f
Update main_fastapi.py
Wudext Nov 17, 2022
82534c9
Optimisation + cleaning
Wudext Nov 18, 2022
0b6b69d
Delete .idea directory
Wudext Nov 18, 2022
fc7ba7c
Delete models/__pycache__ directory
Wudext Nov 19, 2022
500bcc7
Delete trash directory
Wudext Nov 19, 2022
7af0548
Delete desktop.ini
Wudext Nov 19, 2022
501227f
Delete buttons.sqlite
Wudext Nov 19, 2022
08642cf
Шаблон
Wudext Nov 20, 2022
8814599
Merge branch 'main' of https://github.com/Wudext/services-api
Wudext Nov 20, 2022
c677da6
Structure
Wudext Nov 25, 2022
0f5b0df
Update .gitignore
Wudext Nov 25, 2022
8266925
Merge branch 'main' of https://github.com/Wudext/services-api
Wudext Nov 25, 2022
041eae8
Delete .idea directory
Wudext Nov 25, 2022
8ac4c84
Delete trash directory
Wudext Nov 25, 2022
40f06a7
Cleaning
Wudext Nov 25, 2022
4a1a1c2
Update requirements.txt
Wudext Nov 25, 2022
2df7e09
Bugcreating (xD)
Wudext Nov 29, 2022
ed9d429
Merge branch 'main' of https://github.com/Wudext/services-api
Wudext Nov 29, 2022
25ba41e
Bugfixing 1.0
Wudext Dec 1, 2022
bae663a
Fix alembic
dyakovri Dec 1, 2022
719dae5
Fix db
dyakovri Dec 1, 2022
f00b4e3
Merge pull request #1 from Wudext/fixes-by-dyakov
Wudext Dec 1, 2022
6c78dda
Alembic
Wudext Dec 1, 2022
ff9c977
Bugfixing 2.0
Wudext Dec 1, 2022
78c012e
Bugfixes 3.0
Wudext Dec 1, 2022
d0f3645
Bugfixes 4.0
Wudext Dec 5, 2022
6c59285
Bugfixes 4.0
Wudext Dec 5, 2022
5bd0469
Release
Wudext Dec 5, 2022
e02afce
Cleaning
Wudext Dec 7, 2022
9f41f77
Release v1.1
Wudext Dec 7, 2022
e36adc7
Update category.py
Wudext Dec 7, 2022
d09bae4
Bugfixing 5.0
Wudext Dec 7, 2022
880fb70
Bugfixing 6.0
Wudext Dec 7, 2022
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,4 @@ venv.bak/
dmypy.json

# Pyre type checker
.pyre/
.pyre/
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 /app/
RUN pip install --no-cache-dir -r /app/requirements.txt

ADD gunicorn_conf.py alembic.ini /app/
ADD migrations /app/migrations
ADD services-backend /app/services-backend

CMD [ "gunicorn", "-k", "uvicorn.workers.UvicornWorker", "-c", "/app/gunicorn_conf.py", "services-backend.routes.base:app" ]
8 changes: 6 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
BSD 2-Clause License
BSD 3-Clause License

Copyright (c) 2022, Профком студентов физфака МГУ
All rights reserved.
Expand All @@ -13,6 +13,10 @@ modification, are permitted provided that the following conditions are met:
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Expand All @@ -22,4 +26,4 @@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
run:
source ./venv/bin/activate && uvicorn --reload --log-level debug services_backend.routes.base:app

db:
docker run -d -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust --name db-services-backend postgres:15

migrate:
alembic upgrade head
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# services-api

Бэкэдн сервисов приложения Твой ФФ для профкома ФФ МГУ

## Запуск

1) Перейдите в папку проекта

2) Создайте виртуальное окружение командой:
```console
foo@bar:~$ python3 -m venv ./venv/
```

3) Установите библиотеки
```console
foo@bar:~$ pip install -m requirements.txt
```
4) Запускайте приложение!
```console
foo@bar:~$ python -m services-backend
```

## ENV-file description

DB_DSN=

---
99 changes: 99 additions & 0 deletions alembic.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# A generic, single database configuration.

[alembic]
# path to migration scripts
script_location = migrations

# template used to generate migration files
# file_template = %%(rev)s_%%(slug)s

# sys.path path, will be prepended to sys.path if present.
# defaults to the current working directory.
prepend_sys_path = .

# timezone to use when rendering the date within the migration file
# as well as the filename.
# If specified, requires the python-dateutil library that can be
# installed by adding `alembic[tz]` to the pip requirements
# string value is passed to dateutil.tz.gettz()
# leave blank for localtime
# timezone =

# max length of characters to apply to the
# "slug" field
# truncate_slug_length = 40

# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false

# set to 'true' to allow .pyc and .pyo files without
# a source .py file to be detected as revisions in the
# versions/ directory
# sourceless = false

# version location specification; This defaults
# to migrations/versions. When using multiple version
# directories, initial revisions must be specified with --version-path.
# The path separator used here should be the separator specified by "version_path_separator" below.
# version_locations = %(here)s/bar:%(here)s/bat:migrations/versions

# version path separator; As mentioned above, this is the character used to split
# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
# Valid values for version_path_separator are:
#
# version_path_separator = :
# version_path_separator = ;
# version_path_separator = space
version_path_separator = os # Use os.pathsep. Default configuration used for new projects.

# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8

[post_write_hooks]
# post_write_hooks defines scripts or Python functions that are run
# on newly generated revision scripts. See the documentation for further
# detail and examples

# format using "black" - use the console_scripts runner, against the "black" entrypoint
# hooks = black
# black.type = console_scripts
# black.entrypoint = black
# black.options = -l 79 REVISION_SCRIPT_FILENAME

# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic

[handlers]
keys = console

[formatters]
keys = generic

[logger_root]
level = WARN
handlers = console
qualname =

[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine

[logger_alembic]
level = INFO
handlers =
qualname = alembic

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
20 changes: 20 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: "1.0"

services:
db:
image: postgres:13.3
ports:
- "127.0.0.1:5432:5432"
environment:
- POSTGRES_PASSWORD=123

api:
build: .
env_file: .env.
command: bash -c "alembic upgrade head && uvicorn services_backend.__main__:app --reload"
volumes:
- .:/app
ports:
- "127.0.0.1:8000:8000"
depends_on:
- db
35 changes: 35 additions & 0 deletions flake8.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[flake8]
select =
E, W, # pep8 errors and warnings
F, # pyflakes
C9, # McCabe
N8, # Naming Conventions
#B, S, # bandit
#C, # commas
#D, # docstrings
#P, # string-format
#Q, # quotes

ignore =
E122, # continuation line missing indentation or outdented
E123, # closing bracket does not match indentation of opening bracket's line
E127, # continuation line over-indented for visual indent
E131, # continuation line unaligned for hanging
E203, # whitespace before ':'
E225, # missing whitespace around operator
E226, # missing whitespace around arithmetic operator
E24, # multiple spaces after ',' or tab after ','
E275, # missing whitespace after keyword
E305, # expected 2 blank lines after end of function or class
E306, # expected 1 blank line before a nested definition
E402, # module level import not at top of file
E722, # do not use bare except, specify exception instead
E731, # do not assign a lambda expression, use a def
E741, # do not use variables named 'l', 'O', or 'I'

F722, # syntax error in forward annotation

W503, # line break before binary operator
W504, # line break after binary operator

max-line-length = 120
64 changes: 64 additions & 0 deletions gunicorn_conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import json
import multiprocessing
import os

workers_per_core_str = os.getenv("WORKERS_PER_CORE", "1")
max_workers_str = os.getenv("MAX_WORKERS")
use_max_workers = None
if max_workers_str:
use_max_workers = int(max_workers_str)
web_concurrency_str = os.getenv("WEB_CONCURRENCY", None)

host = os.getenv("HOST", "0.0.0.0")
port = os.getenv("PORT", "80")
bind_env = os.getenv("BIND", None)
use_loglevel = os.getenv("LOG_LEVEL", "info")
if bind_env:
use_bind = bind_env
else:
use_bind = f"{host}:{port}"

cores = multiprocessing.cpu_count()
workers_per_core = float(workers_per_core_str)
default_web_concurrency = workers_per_core * cores
if web_concurrency_str:
web_concurrency = int(web_concurrency_str)
assert web_concurrency > 0
else:
web_concurrency = max(int(default_web_concurrency), 2)
if use_max_workers:
web_concurrency = min(web_concurrency, use_max_workers)
accesslog_var = os.getenv("ACCESS_LOG", "-")
use_accesslog = accesslog_var or None
errorlog_var = os.getenv("ERROR_LOG", "-")
use_errorlog = errorlog_var or None
graceful_timeout_str = os.getenv("GRACEFUL_TIMEOUT", "120")
timeout_str = os.getenv("TIMEOUT", "120")
keepalive_str = os.getenv("KEEP_ALIVE", "5")

loglevel = use_loglevel
workers = web_concurrency
bind = use_bind
errorlog = use_errorlog
worker_tmp_dir = "/dev/shm"
accesslog = use_accesslog
graceful_timeout = int(graceful_timeout_str)
timeout = int(timeout_str)
keepalive = int(keepalive_str)


log_data = {
"loglevel": loglevel,
"workers": workers,
"bind": bind,
"graceful_timeout": graceful_timeout,
"timeout": timeout,
"keepalive": keepalive,
"errorlog": errorlog,
"accesslog": accesslog,
"workers_per_core": workers_per_core,
"use_max_workers": use_max_workers,
"host": host,
"port": port,
}
print(json.dumps(log_data))
1 change: 1 addition & 0 deletions migrations/README
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Generic single-database configuration.
71 changes: 71 additions & 0 deletions migrations/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from logging.config import fileConfig

from sqlalchemy import engine_from_config
from sqlalchemy import pool

from alembic import context
from services_backend.models.base import Base
from services_backend.settings import get_settings


config = context.config
settings = get_settings()


if config.config_file_name is not None:
fileConfig(config.config_file_name)


target_metadata = Base.metadata


def run_migrations_offline():
"""Run migrations in 'offline' mode.

This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.

Calls to context.execute() here emit the given string to the
script output.

"""
url = config.get_main_option("sqlalchemy.url")
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)

with context.begin_transaction():
context.run_migrations()


def run_migrations_online():
"""Run migrations in 'online' mode.

In this scenario we need to create an Engine
and associate a connection with the context.

"""
configuration = config.get_section(config.config_ini_section)
configuration['sqlalchemy.url'] = settings.DB_DSN
connectable = engine_from_config(
configuration,
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)

with connectable.connect() as connection:
context.configure(connection=connection, target_metadata=target_metadata)

with context.begin_transaction():
context.run_migrations()


if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
Loading