Python backend for a Slack's kudos plugin.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: refactor project structure and first unit test

+455 -72
+5 -3
Dockerfile
··· 2 2 3 3 RUN apt-get update 4 4 5 + # Installing dependencies using Poetru 5 6 RUN pip install poetry 6 7 COPY ./pyproject.toml /pyproject.toml 7 8 COPY ./poetry.lock /poetry.lock 8 9 RUN poetry config virtualenvs.create false && poetry install -n --no-ansi --no-dev 9 10 RUN rm -rf /pyproject.toml && rm -rf /poetry.lock 10 11 11 - COPY ./app /app 12 - WORKDIR /app/ 12 + # Copies the code 13 + COPY . /app 14 + WORKDIR /app 13 15 14 16 EXPOSE 8000 15 17 16 - ENTRYPOINT [ "gunicorn", "-k", "uvicorn.workers.UvicornWorker", "-b", "0.0.0.0:8000", "main:app" ] 18 + ENTRYPOINT [ "gunicorn", "-k", "uvicorn.workers.UvicornWorker", "-b", "0.0.0.0:8000", "kefi.main:app" ]
app/__init__.py kefi/tests/__init__.py
-9
app/config.py
··· 1 - from pydantic import BaseSettings 2 - 3 - 4 - class Settings(BaseSettings): 5 - APP_NAME: str = "Deko" 6 - SLACK_BOT_TOKEN: str 7 - 8 - class Config: 9 - env_file = ".env"
-55
app/main.py
··· 1 - import random 2 - from functools import lru_cache 3 - 4 - import config 5 - from fastapi import Depends, FastAPI, Form 6 - 7 - app = FastAPI() 8 - 9 - 10 - @app.post("/command/") 11 - async def command( 12 - token: str = Form(...), 13 - team_id: str = Form(...), 14 - team_domain: str = Form(...), 15 - channel_id: str = Form(...), 16 - channel_name: str = Form(...), 17 - user_id: str = Form(...), 18 - user_name: str = Form(...), 19 - command: str = Form(...), 20 - text: str = Form(...), 21 - response_url: str = Form(...), 22 - trigger_id: str = Form(...), 23 - api_app_id: str = Form(...), 24 - ): 25 - if "wallet" in text: 26 - amount = random.randint(1, 100) 27 - return { 28 - "blocks": [ 29 - { 30 - "type": "header", 31 - "text": {"type": "plain_text", "text": f"Cartera de @{user_name}"}, 32 - }, 33 - { 34 - "type": "section", 35 - "fields": [ 36 - { 37 - "type": "mrkdwn", 38 - "text": f"*Pendiente gastar:*\n {amount} dekas", 39 - } 40 - ], 41 - }, 42 - ] 43 - } 44 - return "Comando no reconocido" 45 - 46 - 47 - @lru_cache() 48 - def get_settings(): 49 - return config.Settings() 50 - 51 - 52 - @app.get("/") 53 - def read_root(settings: config.Settings = Depends(get_settings)): 54 - token = settings.SLACK_BOT_TOKEN 55 - return {"data": token}
+1
kefi/__init__.py
··· 1 + __version__ = "1.0.0"
+22
kefi/config/__init__.py
··· 1 + import os 2 + from functools import lru_cache 3 + from importlib import import_module 4 + 5 + from pydantic import BaseSettings 6 + 7 + 8 + class Settings(BaseSettings): 9 + APP_NAME: str = "Kefi" 10 + SLACK_BOT_TOKEN: str 11 + 12 + class Config: 13 + env_file = ".env" 14 + 15 + 16 + @lru_cache() 17 + def get_settings(): 18 + """Uses the KEFI_SETTINGS_MODULE environment variable to dinamically load 19 + different Settings class. 20 + """ 21 + settings = import_module(os.getenv("KEFI_SETTINGS_MODULE", "kefi.config.local")) 22 + return settings.Settings()
+5
kefi/config/local.py
··· 1 + from kefi.config import Settings as BaseSettings 2 + 3 + 4 + class Settings(BaseSettings): 5 + ...
+5
kefi/config/production.py
··· 1 + from kefi.config import Settings as BaseSettings 2 + 3 + 4 + class Settings(BaseSettings): 5 + ...
+5
kefi/config/test.py
··· 1 + from kefi.config import Settings as BaseSettings 2 + 3 + 4 + class Settings(BaseSettings): 5 + ...
+31
kefi/dependencies.py
··· 1 + from fastapi import Form 2 + 3 + 4 + class SlashCommandParams: 5 + def __init__( 6 + self, 7 + token: str = Form(...), 8 + team_id: str = Form(...), 9 + team_domain: str = Form(...), 10 + channel_id: str = Form(...), 11 + channel_name: str = Form(...), 12 + user_id: str = Form(...), 13 + user_name: str = Form(...), 14 + command: str = Form(...), 15 + text: str = Form(...), 16 + response_url: str = Form(...), 17 + trigger_id: str = Form(...), 18 + api_app_id: str = Form(...), 19 + ) -> None: 20 + self.token = token 21 + self.team_id = team_id 22 + self.team_domain = team_domain 23 + self.channel_id = channel_id 24 + self.channel_name = channel_name 25 + self.user_id = user_id 26 + self.user_name = user_name 27 + self.command = command 28 + self.text = text 29 + self.response_url = response_url 30 + self.trigger_id = trigger_id 31 + self.api_app_id = api_app_id
+13
kefi/main.py
··· 1 + from fastapi import Depends, FastAPI 2 + 3 + from kefi.config import Settings, get_settings 4 + from kefi.routers import commands 5 + 6 + app = FastAPI() 7 + app.include_router(commands.router) 8 + 9 + 10 + @app.get("/") 11 + def root(settings: Settings = Depends(get_settings)): 12 + token = settings.SLACK_BOT_TOKEN 13 + return {"data": token}
kefi/routers/__init__.py

This is a binary file and will not be displayed.

+34
kefi/routers/commands.py
··· 1 + import random 2 + 3 + from fastapi import APIRouter, Depends 4 + 5 + from kefi.dependencies import SlashCommandParams 6 + 7 + router = APIRouter() 8 + 9 + 10 + @router.post("/command/", tags=["command"]) 11 + async def handle_command(command: SlashCommandParams = Depends(SlashCommandParams)): 12 + if "wallet" in command.text: 13 + amount = random.randint(1, 100) 14 + return { 15 + "blocks": [ 16 + { 17 + "type": "header", 18 + "text": { 19 + "type": "plain_text", 20 + "text": f"Cartera de @{command.user_name}", 21 + }, 22 + }, 23 + { 24 + "type": "section", 25 + "fields": [ 26 + { 27 + "type": "mrkdwn", 28 + "text": f"*Pendiente gastar:*\n {amount} dekas", 29 + } 30 + ], 31 + }, 32 + ] 33 + } 34 + return "Comando no reconocido"
+28
kefi/tests/test_commands.py
··· 1 + from fastapi.testclient import TestClient 2 + from kefi.main import app 3 + 4 + client = TestClient(app) 5 + 6 + 7 + def test_wallet_commad(): 8 + """Test command /kefi wallet""" 9 + response = client.post( 10 + "/command/", 11 + data={ 12 + "token": "token", 13 + "team_id": "team_id", 14 + "team_domain": "team_domain", 15 + "channel_id": "channel_id", 16 + "channel_name": "channel_name", 17 + "user_id": "user_id", 18 + "user_name": "dummy", 19 + "command": "/kefi", 20 + "text": "wallet", 21 + "response_url": "response_url", 22 + "trigger_id": "trigger_id", 23 + "api_app_id": "api_app_id", 24 + }, 25 + ) 26 + assert response.status_code == 200 27 + data = response.json() 28 + assert "blocks" in data
+297 -2
poetry.lock
··· 16 16 trio = ["trio (>=0.16)"] 17 17 18 18 [[package]] 19 + name = "appnope" 20 + version = "0.1.2" 21 + description = "Disable App Nap on macOS >= 10.9" 22 + category = "main" 23 + optional = false 24 + python-versions = "*" 25 + 26 + [[package]] 19 27 name = "asgiref" 20 28 version = "3.4.1" 21 29 description = "ASGI specs, helper code, and adapters" ··· 62 70 tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] 63 71 64 72 [[package]] 73 + name = "backcall" 74 + version = "0.2.0" 75 + description = "Specifications for callback functions passed in to an API" 76 + category = "main" 77 + optional = false 78 + python-versions = "*" 79 + 80 + [[package]] 65 81 name = "black" 66 82 version = "21.10b0" 67 83 description = "The uncompromising code formatter." ··· 89 105 uvloop = ["uvloop (>=0.15.2)"] 90 106 91 107 [[package]] 108 + name = "certifi" 109 + version = "2021.10.8" 110 + description = "Python package for providing Mozilla's CA Bundle." 111 + category = "main" 112 + optional = false 113 + python-versions = "*" 114 + 115 + [[package]] 116 + name = "charset-normalizer" 117 + version = "2.0.7" 118 + description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 119 + category = "main" 120 + optional = false 121 + python-versions = ">=3.5.0" 122 + 123 + [package.extras] 124 + unicode_backport = ["unicodedata2"] 125 + 126 + [[package]] 92 127 name = "click" 93 128 version = "8.0.3" 94 129 description = "Composable command line interface toolkit" ··· 108 143 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 109 144 110 145 [[package]] 146 + name = "decorator" 147 + version = "5.1.0" 148 + description = "Decorators for Humans" 149 + category = "main" 150 + optional = false 151 + python-versions = ">=3.5" 152 + 153 + [[package]] 111 154 name = "fastapi" 112 155 version = "0.70.0" 113 156 description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" ··· 173 216 category = "dev" 174 217 optional = false 175 218 python-versions = "*" 219 + 220 + [[package]] 221 + name = "ipython" 222 + version = "7.29.0" 223 + description = "IPython: Productive Interactive Computing" 224 + category = "main" 225 + optional = false 226 + python-versions = ">=3.7" 227 + 228 + [package.dependencies] 229 + appnope = {version = "*", markers = "sys_platform == \"darwin\""} 230 + backcall = "*" 231 + colorama = {version = "*", markers = "sys_platform == \"win32\""} 232 + decorator = "*" 233 + jedi = ">=0.16" 234 + matplotlib-inline = "*" 235 + pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} 236 + pickleshare = "*" 237 + prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" 238 + pygments = "*" 239 + traitlets = ">=4.2" 240 + 241 + [package.extras] 242 + all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.17)", "pygments", "qtconsole", "requests", "testpath"] 243 + doc = ["Sphinx (>=1.3)"] 244 + kernel = ["ipykernel"] 245 + nbconvert = ["nbconvert"] 246 + nbformat = ["nbformat"] 247 + notebook = ["notebook", "ipywidgets"] 248 + parallel = ["ipyparallel"] 249 + qtconsole = ["qtconsole"] 250 + test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.17)"] 176 251 177 252 [[package]] 178 253 name = "isort" ··· 189 264 plugins = ["setuptools"] 190 265 191 266 [[package]] 267 + name = "jedi" 268 + version = "0.18.0" 269 + description = "An autocompletion tool for Python that can be used for text editors." 270 + category = "main" 271 + optional = false 272 + python-versions = ">=3.6" 273 + 274 + [package.dependencies] 275 + parso = ">=0.8.0,<0.9.0" 276 + 277 + [package.extras] 278 + qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 279 + testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<6.0.0)"] 280 + 281 + [[package]] 192 282 name = "lazy-object-proxy" 193 283 version = "1.6.0" 194 284 description = "A fast and thorough lazy object proxy." 195 285 category = "dev" 196 286 optional = false 197 287 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 288 + 289 + [[package]] 290 + name = "matplotlib-inline" 291 + version = "0.1.3" 292 + description = "Inline Matplotlib backend for Jupyter" 293 + category = "main" 294 + optional = false 295 + python-versions = ">=3.5" 296 + 297 + [package.dependencies] 298 + traitlets = "*" 198 299 199 300 [[package]] 200 301 name = "mccabe" ··· 239 340 240 341 [package.dependencies] 241 342 pyparsing = ">=2.0.2,<3" 343 + 344 + [[package]] 345 + name = "parso" 346 + version = "0.8.2" 347 + description = "A Python Parser" 348 + category = "main" 349 + optional = false 350 + python-versions = ">=3.6" 351 + 352 + [package.extras] 353 + qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 354 + testing = ["docopt", "pytest (<6.0.0)"] 242 355 243 356 [[package]] 244 357 name = "pathspec" ··· 249 362 python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 250 363 251 364 [[package]] 365 + name = "pexpect" 366 + version = "4.8.0" 367 + description = "Pexpect allows easy control of interactive console applications." 368 + category = "main" 369 + optional = false 370 + python-versions = "*" 371 + 372 + [package.dependencies] 373 + ptyprocess = ">=0.5" 374 + 375 + [[package]] 376 + name = "pickleshare" 377 + version = "0.7.5" 378 + description = "Tiny 'shelve'-like database with concurrency support" 379 + category = "main" 380 + optional = false 381 + python-versions = "*" 382 + 383 + [[package]] 252 384 name = "platformdirs" 253 385 version = "2.4.0" 254 386 description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." ··· 273 405 testing = ["pytest", "pytest-benchmark"] 274 406 275 407 [[package]] 408 + name = "prompt-toolkit" 409 + version = "3.0.22" 410 + description = "Library for building powerful interactive command lines in Python" 411 + category = "main" 412 + optional = false 413 + python-versions = ">=3.6.2" 414 + 415 + [package.dependencies] 416 + wcwidth = "*" 417 + 418 + [[package]] 419 + name = "ptyprocess" 420 + version = "0.7.0" 421 + description = "Run a subprocess in a pseudo terminal" 422 + category = "main" 423 + optional = false 424 + python-versions = "*" 425 + 426 + [[package]] 276 427 name = "py" 277 428 version = "1.10.0" 278 429 description = "library with cross-python path, ini-parsing, io, code, log facilities" ··· 294 445 [package.extras] 295 446 dotenv = ["python-dotenv (>=0.10.4)"] 296 447 email = ["email-validator (>=1.0.3)"] 448 + 449 + [[package]] 450 + name = "pygments" 451 + version = "2.10.0" 452 + description = "Pygments is a syntax highlighting package written in Python." 453 + category = "main" 454 + optional = false 455 + python-versions = ">=3.5" 297 456 298 457 [[package]] 299 458 name = "pylint" ··· 342 501 testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] 343 502 344 503 [[package]] 504 + name = "pytest-env" 505 + version = "0.6.2" 506 + description = "py.test plugin that allows you to add environment variables." 507 + category = "dev" 508 + optional = false 509 + python-versions = "*" 510 + 511 + [package.dependencies] 512 + pytest = ">=2.6.0" 513 + 514 + [[package]] 345 515 name = "python-dotenv" 346 516 version = "0.19.1" 347 517 description = "Read key-value pairs from a .env file and set them as environment variables" ··· 370 540 category = "dev" 371 541 optional = false 372 542 python-versions = "*" 543 + 544 + [[package]] 545 + name = "requests" 546 + version = "2.26.0" 547 + description = "Python HTTP for Humans." 548 + category = "main" 549 + optional = false 550 + python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 551 + 552 + [package.dependencies] 553 + certifi = ">=2017.4.17" 554 + charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} 555 + idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} 556 + urllib3 = ">=1.21.1,<1.27" 557 + 558 + [package.extras] 559 + socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] 560 + use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] 373 561 374 562 [[package]] 375 563 name = "six" ··· 486 674 python-versions = ">=3.6" 487 675 488 676 [[package]] 677 + name = "traitlets" 678 + version = "5.1.1" 679 + description = "Traitlets Python configuration system" 680 + category = "main" 681 + optional = false 682 + python-versions = ">=3.7" 683 + 684 + [package.extras] 685 + test = ["pytest"] 686 + 687 + [[package]] 489 688 name = "typing-extensions" 490 689 version = "3.10.0.2" 491 690 description = "Backported and Experimental Type Hints for Python 3.5+" ··· 494 693 python-versions = "*" 495 694 496 695 [[package]] 696 + name = "urllib3" 697 + version = "1.26.7" 698 + description = "HTTP library with thread-safe connection pooling, file post, and more." 699 + category = "main" 700 + optional = false 701 + python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 702 + 703 + [package.extras] 704 + brotli = ["brotlipy (>=0.6.0)"] 705 + secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] 706 + socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 707 + 708 + [[package]] 497 709 name = "uvicorn" 498 710 version = "0.15.0" 499 711 description = "The lightning-fast ASGI server." ··· 510 722 standard = ["websockets (>=9.1)", "httptools (>=0.2.0,<0.3.0)", "watchgod (>=0.6)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"] 511 723 512 724 [[package]] 725 + name = "wcwidth" 726 + version = "0.2.5" 727 + description = "Measures the displayed width of unicode strings in a terminal" 728 + category = "main" 729 + optional = false 730 + python-versions = "*" 731 + 732 + [[package]] 513 733 name = "wrapt" 514 734 version = "1.13.3" 515 735 description = "Module for decorators, wrappers and monkey patching." ··· 519 739 520 740 [metadata] 521 741 lock-version = "1.1" 522 - python-versions = ">=3.9,<4.0.0" 523 - content-hash = "d315669f1bcf74639a1c173dd49b8851fd0d90194c164619418e93e8e5227d78" 742 + python-versions = "^3.9" 743 + content-hash = "6207e36971576a6079fe4920d63d2e767ef1b8fce3381fee8c052ceee0113d08" 524 744 525 745 [metadata.files] 526 746 anyio = [ 527 747 {file = "anyio-3.3.4-py3-none-any.whl", hash = "sha256:4fd09a25ab7fa01d34512b7249e366cd10358cdafc95022c7ff8c8f8a5026d66"}, 528 748 {file = "anyio-3.3.4.tar.gz", hash = "sha256:67da67b5b21f96b9d3d65daa6ea99f5d5282cb09f50eb4456f8fb51dffefc3ff"}, 529 749 ] 750 + appnope = [ 751 + {file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"}, 752 + {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"}, 753 + ] 530 754 asgiref = [ 531 755 {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, 532 756 {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"}, ··· 543 767 {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, 544 768 {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, 545 769 ] 770 + backcall = [ 771 + {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, 772 + {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, 773 + ] 546 774 black = [ 547 775 {file = "black-21.10b0-py3-none-any.whl", hash = "sha256:6eb7448da9143ee65b856a5f3676b7dda98ad9abe0f87fce8c59291f15e82a5b"}, 548 776 {file = "black-21.10b0.tar.gz", hash = "sha256:a9952229092e325fe5f3dae56d81f639b23f7131eb840781947e4b2886030f33"}, 549 777 ] 778 + certifi = [ 779 + {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, 780 + {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, 781 + ] 782 + charset-normalizer = [ 783 + {file = "charset-normalizer-2.0.7.tar.gz", hash = "sha256:e019de665e2bcf9c2b64e2e5aa025fa991da8720daa3c1138cadd2fd1856aed0"}, 784 + {file = "charset_normalizer-2.0.7-py3-none-any.whl", hash = "sha256:f7af805c321bfa1ce6714c51f254e0d5bb5e5834039bc17db7ebe3a4cec9492b"}, 785 + ] 550 786 click = [ 551 787 {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, 552 788 {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, ··· 554 790 colorama = [ 555 791 {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 556 792 {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 793 + ] 794 + decorator = [ 795 + {file = "decorator-5.1.0-py3-none-any.whl", hash = "sha256:7b12e7c3c6ab203a29e157335e9122cb03de9ab7264b137594103fd4a683b374"}, 796 + {file = "decorator-5.1.0.tar.gz", hash = "sha256:e59913af105b9860aa2c8d3272d9de5a56a4e608db9a2f167a8480b323d529a7"}, 557 797 ] 558 798 fastapi = [ 559 799 {file = "fastapi-0.70.0-py3-none-any.whl", hash = "sha256:a36d5f2fad931aa3575c07a3472c784e81f3e664e3bb5c8b9c88d0ec1104f59c"}, ··· 627 867 {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, 628 868 {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, 629 869 ] 870 + ipython = [ 871 + {file = "ipython-7.29.0-py3-none-any.whl", hash = "sha256:a658beaf856ce46bc453366d5dc6b2ddc6c481efd3540cb28aa3943819caac9f"}, 872 + {file = "ipython-7.29.0.tar.gz", hash = "sha256:4f69d7423a5a1972f6347ff233e38bbf4df6a150ef20fbb00c635442ac3060aa"}, 873 + ] 630 874 isort = [ 631 875 {file = "isort-5.10.0-py3-none-any.whl", hash = "sha256:1a18ccace2ed8910bd9458b74a3ecbafd7b2f581301b0ab65cfdd4338272d76f"}, 632 876 {file = "isort-5.10.0.tar.gz", hash = "sha256:e52ff6d38012b131628cf0f26c51e7bd3a7c81592eefe3ac71411e692f1b9345"}, 877 + ] 878 + jedi = [ 879 + {file = "jedi-0.18.0-py2.py3-none-any.whl", hash = "sha256:18456d83f65f400ab0c2d3319e48520420ef43b23a086fdc05dff34132f0fb93"}, 880 + {file = "jedi-0.18.0.tar.gz", hash = "sha256:92550a404bad8afed881a137ec9a461fed49eca661414be45059329614ed0707"}, 633 881 ] 634 882 lazy-object-proxy = [ 635 883 {file = "lazy-object-proxy-1.6.0.tar.gz", hash = "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726"}, ··· 655 903 {file = "lazy_object_proxy-1.6.0-cp39-cp39-win32.whl", hash = "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61"}, 656 904 {file = "lazy_object_proxy-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b"}, 657 905 ] 906 + matplotlib-inline = [ 907 + {file = "matplotlib-inline-0.1.3.tar.gz", hash = "sha256:a04bfba22e0d1395479f866853ec1ee28eea1485c1d69a6faf00dc3e24ff34ee"}, 908 + {file = "matplotlib_inline-0.1.3-py3-none-any.whl", hash = "sha256:aed605ba3b72462d64d475a21a9296f400a19c4f74a31b59103d2a99ffd5aa5c"}, 909 + ] 658 910 mccabe = [ 659 911 {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 660 912 {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ··· 692 944 {file = "packaging-21.2-py3-none-any.whl", hash = "sha256:14317396d1e8cdb122989b916fa2c7e9ca8e2be9e8060a6eff75b6b7b4d8a7e0"}, 693 945 {file = "packaging-21.2.tar.gz", hash = "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966"}, 694 946 ] 947 + parso = [ 948 + {file = "parso-0.8.2-py2.py3-none-any.whl", hash = "sha256:a8c4922db71e4fdb90e0d0bc6e50f9b273d3397925e5e60a717e719201778d22"}, 949 + {file = "parso-0.8.2.tar.gz", hash = "sha256:12b83492c6239ce32ff5eed6d3639d6a536170723c6f3f1506869f1ace413398"}, 950 + ] 695 951 pathspec = [ 696 952 {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, 697 953 {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, 698 954 ] 955 + pexpect = [ 956 + {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, 957 + {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, 958 + ] 959 + pickleshare = [ 960 + {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, 961 + {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, 962 + ] 699 963 platformdirs = [ 700 964 {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"}, 701 965 {file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"}, ··· 704 968 {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, 705 969 {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, 706 970 ] 971 + prompt-toolkit = [ 972 + {file = "prompt_toolkit-3.0.22-py3-none-any.whl", hash = "sha256:48d85cdca8b6c4f16480c7ce03fd193666b62b0a21667ca56b4bb5ad679d1170"}, 973 + {file = "prompt_toolkit-3.0.22.tar.gz", hash = "sha256:449f333dd120bd01f5d296a8ce1452114ba3a71fae7288d2f0ae2c918764fa72"}, 974 + ] 975 + ptyprocess = [ 976 + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, 977 + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, 978 + ] 707 979 py = [ 708 980 {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, 709 981 {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, ··· 732 1004 {file = "pydantic-1.8.2-py3-none-any.whl", hash = "sha256:fec866a0b59f372b7e776f2d7308511784dace622e0992a0b59ea3ccee0ae833"}, 733 1005 {file = "pydantic-1.8.2.tar.gz", hash = "sha256:26464e57ccaafe72b7ad156fdaa4e9b9ef051f69e175dbbb463283000c05ab7b"}, 734 1006 ] 1007 + pygments = [ 1008 + {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, 1009 + {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, 1010 + ] 735 1011 pylint = [ 736 1012 {file = "pylint-2.11.1-py3-none-any.whl", hash = "sha256:0f358e221c45cbd4dad2a1e4b883e75d28acdcccd29d40c76eb72b307269b126"}, 737 1013 {file = "pylint-2.11.1.tar.gz", hash = "sha256:2c9843fff1a88ca0ad98a256806c82c5a8f86086e7ccbdb93297d86c3f90c436"}, ··· 744 1020 {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, 745 1021 {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, 746 1022 ] 1023 + pytest-env = [ 1024 + {file = "pytest-env-0.6.2.tar.gz", hash = "sha256:7e94956aef7f2764f3c147d216ce066bf6c42948bb9e293169b1b1c880a580c2"}, 1025 + ] 747 1026 python-dotenv = [ 748 1027 {file = "python-dotenv-0.19.1.tar.gz", hash = "sha256:14f8185cc8d494662683e6914addcb7e95374771e707601dfc70166946b4c4b8"}, 749 1028 {file = "python_dotenv-0.19.1-py2.py3-none-any.whl", hash = "sha256:bbd3da593fc49c249397cbfbcc449cf36cb02e75afc8157fcc6a81df6fb7750a"}, ··· 801 1080 {file = "regex-2021.11.2-cp39-cp39-win32.whl", hash = "sha256:30fe317332de0e50195665bc61a27d46e903d682f94042c36b3f88cb84bd7958"}, 802 1081 {file = "regex-2021.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:85289c25f658e3260b00178757c87f033f3d4b3e40aa4abdd4dc875ff11a94fb"}, 803 1082 {file = "regex-2021.11.2.tar.gz", hash = "sha256:5e85dcfc5d0f374955015ae12c08365b565c6f1eaf36dd182476a4d8e5a1cdb7"}, 1083 + ] 1084 + requests = [ 1085 + {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"}, 1086 + {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"}, 804 1087 ] 805 1088 six = [ 806 1089 {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, ··· 872 1155 {file = "tomli-1.2.2-py3-none-any.whl", hash = "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade"}, 873 1156 {file = "tomli-1.2.2.tar.gz", hash = "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee"}, 874 1157 ] 1158 + traitlets = [ 1159 + {file = "traitlets-5.1.1-py3-none-any.whl", hash = "sha256:2d313cc50a42cd6c277e7d7dc8d4d7fedd06a2c215f78766ae7b1a66277e0033"}, 1160 + {file = "traitlets-5.1.1.tar.gz", hash = "sha256:059f456c5a7c1c82b98c2e8c799f39c9b8128f6d0d46941ee118daace9eb70c7"}, 1161 + ] 875 1162 typing-extensions = [ 876 1163 {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, 877 1164 {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, 878 1165 {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, 1166 + ] 1167 + urllib3 = [ 1168 + {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"}, 1169 + {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"}, 879 1170 ] 880 1171 uvicorn = [ 881 1172 {file = "uvicorn-0.15.0-py3-none-any.whl", hash = "sha256:17f898c64c71a2640514d4089da2689e5db1ce5d4086c2d53699bf99513421c1"}, 882 1173 {file = "uvicorn-0.15.0.tar.gz", hash = "sha256:d9a3c0dd1ca86728d3e235182683b4cf94cd53a867c288eaeca80ee781b2caff"}, 1174 + ] 1175 + wcwidth = [ 1176 + {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, 1177 + {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, 883 1178 ] 884 1179 wrapt = [ 885 1180 {file = "wrapt-1.13.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:e05e60ff3b2b0342153be4d1b597bbcfd8330890056b9619f4ad6b8d5c96a81a"},
+6 -3
pyproject.toml
··· 1 1 [tool.poetry] 2 - name = "deko" 3 - version = "0.1.0" 2 + name = "Kefi" 3 + version = "1.0.0" 4 4 description = "An awesome project from Deka" 5 5 authors = ["Dekalabs <backend@dekalabs.com>"] 6 6 7 7 [tool.poetry.dependencies] 8 - python = ">=3.9,<4.0.0" 8 + python = "^3.9" 9 9 fastapi = "^0.70.0" 10 10 sqlmodel = "^0.0.4" 11 11 uvicorn = "^0.15.0" ··· 14 14 pydantic = "^1.8.2" 15 15 python-multipart = "^0.0.5" 16 16 python-dotenv = "^0.19.1" 17 + ipython = "^7.29.0" 18 + requests = "^2.26.0" 17 19 18 20 [tool.poetry.dev-dependencies] 19 21 black = "^21.10b0" ··· 21 23 isort = "^5.10.0" 22 24 pytest = "^6.2.5" 23 25 pylint = "^2.11.1" 26 + pytest-env = "^0.6.2" 24 27 25 28 [build-system] 26 29 requires = ["poetry-core>=1.0.0"]
+3
pytest.ini
··· 1 + [pytest] 2 + env = 3 + KEFI_SETTINGS_MODULE = kefi.config.test