diff --git a/create_aio_app/template/{{cookiecutter.project_name}}/Makefile b/create_aio_app/template/{{cookiecutter.project_name}}/Makefile index 3843a11f..e233c661 100644 --- a/create_aio_app/template/{{cookiecutter.project_name}}/Makefile +++ b/create_aio_app/template/{{cookiecutter.project_name}}/Makefile @@ -35,7 +35,9 @@ bash: ## Upgrade your python's dependencies: upgrade: - docker-compose run --rm $(PROJECT_NAME)_app python3 -m $(PROJECT_NAME).utils.check-requirements + docker-compose run --rm $(PROJECT_NAME)_app python3 -m piptools compile $(PROJECT_NAME)/requirements/development.in --output-file=$(PROJECT_NAME)/requirements/development.txt + docker-compose run --rm $(PROJECT_NAME)_app python3 -m piptools compile $(PROJECT_NAME)/requirements/production.in --output-file=$(PROJECT_NAME)/requirements/production.txt + docker-compose run --rm $(PROJECT_NAME)_app python3 -m piptools compile $(PROJECT_NAME)/requirements/documentation.in --output-file=$(PROJECT_NAME)/requirements/documentation.txt ## Create profile sampling of application. profile: @@ -125,4 +127,4 @@ adev: {%- if cookiecutter.use_postgres == 'y' or cookiecutter.use_redis == 'y' % ## Runs application with specified postgres and redis. wait_resources: python3 -m $(PROJECT_NAME).utils.wait_script -{%- endif %} \ No newline at end of file +{%- endif %} diff --git a/create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in b/create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in new file mode 100644 index 00000000..a2e70f87 --- /dev/null +++ b/create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in @@ -0,0 +1,25 @@ +aiohttp==3.6.2 +aiohttp_jinja2==1.2.0 +trafaret_config==2.0.2 +markdown2==2.3.7 +aiopg[sa]==1.0.0 +psycopg2-binary==2.8.4 +alembic==1.4.1 +aioredis==1.3.1 +uvloop==0.14.0 + +Sphinx==2.4.4 +sphinx-autodoc-typehints==1.10.3 +sphinxcontrib-websupport==1.2.0 +doc8==0.8.0 + +mypy==0.770 +flake8==3.7.9 +pytest==5.4.1 +pytest-cov==2.8.1 +pytest-aiohttp==0.3.0 +black==19.10b0 +py-spy==0.3.3 + +aiohttp-devtools==0.13.1 +aiohttp-debugtoolbar==0.6.0 diff --git a/create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.txt b/create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.txt index fc89567f..3cc19286 100644 --- a/create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.txt +++ b/create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.txt @@ -1,13 +1,87 @@ --r production.txt --r documentation.txt +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile --output-file='create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.txt' 'create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in' +# +aiohttp-debugtoolbar==0.6.0 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +aiohttp-devtools==0.13.1 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +aiohttp==3.6.2 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in, aiohttp-debugtoolbar, aiohttp-devtools, aiohttp-jinja2, pytest-aiohttp +aiohttp_jinja2==1.2.0 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in, aiohttp-debugtoolbar +aiopg[sa]==1.0.0 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +aioredis==1.3.1 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +alabaster==0.7.12 # via sphinx +alembic==1.4.1 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +appdirs==1.4.4 # via black +async-timeout==3.0.1 # via aiohttp, aioredis +attrs==19.3.0 # via aiohttp, black, pytest +babel==2.8.0 # via sphinx +black==19.10b0 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +certifi==2020.6.20 # via requests +chardet==3.0.4 # via aiohttp, doc8, requests +click==7.1.2 # via aiohttp-devtools, black +coverage==5.2 # via pytest-cov +devtools==0.5.1 # via aiohttp-devtools +doc8==0.8.0 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +docutils==0.16 # via doc8, restructuredtext-lint, sphinx +entrypoints==0.3 # via flake8 +flake8==3.7.9 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +hiredis==1.1.0 # via aioredis +idna==2.10 # via requests, yarl +imagesize==1.2.0 # via sphinx +jinja2==2.11.2 # via aiohttp-jinja2, sphinx +mako==1.1.3 # via alembic +markdown2==2.3.7 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +markupsafe==1.1.1 # via jinja2, mako +mccabe==0.6.1 # via flake8 +more-itertools==8.4.0 # via pytest +multidict==4.7.6 # via aiohttp, yarl +mypy-extensions==0.4.3 # via mypy +mypy==0.770 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +packaging==20.4 # via pytest, sphinx +pathspec==0.8.0 # via black +pbr==5.4.5 # via stevedore +pluggy==0.13.1 # via pytest +psycopg2-binary==2.8.4 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in, aiopg, sqlalchemy +py-spy==0.3.3 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +py==1.9.0 # via pytest +pycodestyle==2.5.0 # via flake8 +pyflakes==2.1.1 # via flake8 +pygments==2.6.1 # via aiohttp-devtools, sphinx +pyparsing==2.4.7 # via packaging +pytest-aiohttp==0.3.0 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +pytest-cov==2.8.1 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +pytest==5.4.1 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in, pytest-aiohttp, pytest-cov +python-dateutil==2.8.1 # via alembic +python-editor==1.0.4 # via alembic +pytz==2020.1 # via babel +pyyaml==5.3.1 # via trafaret-config +regex==2020.7.14 # via black +requests==2.24.0 # via sphinx +restructuredtext-lint==1.3.1 # via doc8 +six==1.15.0 # via doc8, packaging, python-dateutil +snowballstemmer==2.0.0 # via sphinx +sphinx-autodoc-typehints==1.10.3 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +sphinx==2.4.4 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in, sphinx-autodoc-typehints +sphinxcontrib-applehelp==1.0.2 # via sphinx +sphinxcontrib-devhelp==1.0.2 # via sphinx +sphinxcontrib-htmlhelp==1.0.3 # via sphinx +sphinxcontrib-jsmath==1.0.1 # via sphinx +sphinxcontrib-qthelp==1.0.3 # via sphinx +sphinxcontrib-serializinghtml==1.1.4 # via sphinx +sphinxcontrib-websupport==1.2.0 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +sqlalchemy[postgresql_psycopg2binary]==1.3.18 # via aiopg, alembic +stevedore==3.2.0 # via doc8 +toml==0.10.1 # via black +trafaret==2.0.2 # via trafaret-config +trafaret_config==2.0.2 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +typed-ast==1.4.1 # via black, mypy +typing-extensions==3.7.4.2 # via mypy +urllib3==1.25.9 # via requests +uvloop==0.14.0 # via -r create_aio_app/template/{{cookiecutter.project_name}}/requirements/development.in +watchgod==0.6 # via aiohttp-devtools +wcwidth==0.2.5 # via pytest +yarl==1.4.2 # via aiohttp -mypy==0.770 -flake8==3.7.9 -pytest==5.4.1 -pytest-cov==2.8.1 -pytest-aiohttp==0.3.0 -black==19.10b0 -py-spy==0.3.3 - -aiohttp-devtools==0.13.1 -aiohttp-debugtoolbar==0.6.0 +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/create_aio_app/template/{{cookiecutter.project_name}}/requirements/documentation.in b/create_aio_app/template/{{cookiecutter.project_name}}/requirements/documentation.in new file mode 100644 index 00000000..cf4f81a8 --- /dev/null +++ b/create_aio_app/template/{{cookiecutter.project_name}}/requirements/documentation.in @@ -0,0 +1,39 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile documentation.txt +# +alabaster==0.7.12 # via -r documentation.txt, sphinx +babel==2.8.0 # via -r documentation.txt, sphinx +certifi==2020.6.20 # via -r documentation.txt, requests +chardet==3.0.4 # via -r documentation.txt, doc8, requests +doc8==0.8.0 # via -r documentation.txt +docutils==0.16 # via -r documentation.txt, doc8, restructuredtext-lint, sphinx +idna==2.10 # via -r documentation.txt, requests +imagesize==1.2.0 # via -r documentation.txt, sphinx +jinja2==2.11.2 # via -r documentation.txt, sphinx +markupsafe==1.1.1 # via -r documentation.txt, jinja2 +packaging==20.4 # via -r documentation.txt, sphinx +pbr==5.4.5 # via -r documentation.txt, stevedore +pygments==2.6.1 # via -r documentation.txt, sphinx +pyparsing==2.4.7 # via -r documentation.txt, packaging +pytz==2020.1 # via -r documentation.txt, babel +requests==2.24.0 # via -r documentation.txt, sphinx +restructuredtext-lint==1.3.1 # via -r documentation.txt, doc8 +six==1.15.0 # via -r documentation.txt, doc8, packaging +snowballstemmer==2.0.0 # via -r documentation.txt, sphinx +sphinx-autodoc-typehints==1.10.3 # via -r documentation.txt +sphinx==2.4.4 # via -r documentation.txt, sphinx-autodoc-typehints +sphinxcontrib-applehelp==1.0.2 # via -r documentation.txt, sphinx +sphinxcontrib-devhelp==1.0.2 # via -r documentation.txt, sphinx +sphinxcontrib-htmlhelp==1.0.3 # via -r documentation.txt, sphinx +sphinxcontrib-jsmath==1.0.1 # via -r documentation.txt, sphinx +sphinxcontrib-qthelp==1.0.3 # via -r documentation.txt, sphinx +sphinxcontrib-serializinghtml==1.1.4 # via -r documentation.txt, sphinx +sphinxcontrib-websupport==1.2.0 # via -r documentation.txt +stevedore==3.2.0 # via -r documentation.txt, doc8 +urllib3==1.25.9 # via -r documentation.txt, requests + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/create_aio_app/template/{{cookiecutter.project_name}}/requirements/documentation.txt b/create_aio_app/template/{{cookiecutter.project_name}}/requirements/documentation.txt index 83ddf8dc..bb68c4d8 100644 --- a/create_aio_app/template/{{cookiecutter.project_name}}/requirements/documentation.txt +++ b/create_aio_app/template/{{cookiecutter.project_name}}/requirements/documentation.txt @@ -1,4 +1,39 @@ -Sphinx==2.4.4 -sphinx-autodoc-typehints==1.10.3 -sphinxcontrib-websupport==1.2.0 -doc8==0.8.0 +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile --output-file=../../requirements/documentation.txt documentation.in +# +alabaster==0.7.12 # via -r documentation.in, sphinx +babel==2.8.0 # via -r documentation.in, sphinx +certifi==2020.6.20 # via -r documentation.in, requests +chardet==3.0.4 # via -r documentation.in, doc8, requests +doc8==0.8.0 # via -r documentation.in +docutils==0.16 # via -r documentation.in, doc8, restructuredtext-lint, sphinx +idna==2.10 # via -r documentation.in, requests +imagesize==1.2.0 # via -r documentation.in, sphinx +jinja2==2.11.2 # via -r documentation.in, sphinx +markupsafe==1.1.1 # via -r documentation.in, jinja2 +packaging==20.4 # via -r documentation.in, sphinx +pbr==5.4.5 # via -r documentation.in, stevedore +pygments==2.6.1 # via -r documentation.in, sphinx +pyparsing==2.4.7 # via -r documentation.in, packaging +pytz==2020.1 # via -r documentation.in, babel +requests==2.24.0 # via -r documentation.in, sphinx +restructuredtext-lint==1.3.1 # via -r documentation.in, doc8 +six==1.15.0 # via -r documentation.in, doc8, packaging +snowballstemmer==2.0.0 # via -r documentation.in, sphinx +sphinx-autodoc-typehints==1.10.3 # via -r documentation.in +sphinx==2.4.4 # via -r documentation.in, sphinx-autodoc-typehints +sphinxcontrib-applehelp==1.0.2 # via -r documentation.in, sphinx +sphinxcontrib-devhelp==1.0.2 # via -r documentation.in, sphinx +sphinxcontrib-htmlhelp==1.0.3 # via -r documentation.in, sphinx +sphinxcontrib-jsmath==1.0.1 # via -r documentation.in, sphinx +sphinxcontrib-qthelp==1.0.3 # via -r documentation.in, sphinx +sphinxcontrib-serializinghtml==1.1.4 # via -r documentation.in, sphinx +sphinxcontrib-websupport==1.2.0 # via -r documentation.in +stevedore==3.2.0 # via -r documentation.in, doc8 +urllib3==1.25.9 # via -r documentation.in, requests + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/create_aio_app/template/{{cookiecutter.project_name}}/requirements/production.in b/create_aio_app/template/{{cookiecutter.project_name}}/requirements/production.in new file mode 100644 index 00000000..5fe2ad23 --- /dev/null +++ b/create_aio_app/template/{{cookiecutter.project_name}}/requirements/production.in @@ -0,0 +1,9 @@ +aiohttp==3.6.2 +aiohttp_jinja2==1.2.0 +trafaret_config==2.0.2 +markdown2==2.3.7 +aiopg[sa]==1.0.0 +psycopg2-binary==2.8.4 +alembic==1.4.1 +aioredis==1.3.1 +uvloop==0.14.0 diff --git a/create_aio_app/template/{{cookiecutter.project_name}}/requirements/production.txt b/create_aio_app/template/{{cookiecutter.project_name}}/requirements/production.txt index 567a0e48..aba81772 100644 --- a/create_aio_app/template/{{cookiecutter.project_name}}/requirements/production.txt +++ b/create_aio_app/template/{{cookiecutter.project_name}}/requirements/production.txt @@ -1,15 +1,31 @@ -aiohttp==3.6.2 -aiohttp_jinja2==1.2.0 -trafaret_config==2.0.2 -markdown2==2.3.7 -{%- if cookiecutter.use_postgres == 'y' %} -aiopg[sa]==1.0.0 -psycopg2-binary==2.8.4 -alembic==1.4.1 -{%- endif %} -{%- if cookiecutter.use_redis == 'y' %} -aioredis==1.3.1 -{%- endif %} -{%- if cookiecutter.use_uvloop == 'y' %} -uvloop==0.14.0 -{%- endif %} +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile --output-file=requirements/production.txt requirements/production.in +# +aiohttp==3.6.2 # via -r requirements/production.in, aiohttp-jinja2 +aiohttp_jinja2==1.2.0 # via -r requirements/production.in +aiopg[sa]==1.0.0 # via -r requirements/production.in +aioredis==1.3.1 # via -r requirements/production.in +alembic==1.4.1 # via -r requirements/production.in +async-timeout==3.0.1 # via aiohttp, aioredis +attrs==19.3.0 # via aiohttp +chardet==3.0.4 # via aiohttp +hiredis==1.1.0 # via aioredis +idna==2.10 # via yarl +jinja2==2.11.2 # via aiohttp-jinja2 +mako==1.1.3 # via alembic +markdown2==2.3.7 # via -r requirements/production.in +markupsafe==1.1.1 # via jinja2, mako +multidict==4.7.6 # via aiohttp, yarl +psycopg2-binary==2.8.4 # via -r requirements/production.in, aiopg, sqlalchemy +python-dateutil==2.8.1 # via alembic +python-editor==1.0.4 # via alembic +pyyaml==5.3.1 # via trafaret-config +six==1.15.0 # via python-dateutil +sqlalchemy[postgresql_psycopg2binary]==1.3.18 # via aiopg, alembic +trafaret==2.0.2 # via trafaret-config +trafaret_config==2.0.2 # via -r requirements/production.in +uvloop==0.14.0 # via -r requirements/production.in +yarl==1.4.2 # via aiohttp diff --git a/create_aio_app/template/{{cookiecutter.project_name}}/{{cookiecutter.project_name}}/utils/check-requirements.py b/create_aio_app/template/{{cookiecutter.project_name}}/{{cookiecutter.project_name}}/utils/check-requirements.py deleted file mode 100644 index 9a1fea0f..00000000 --- a/create_aio_app/template/{{cookiecutter.project_name}}/{{cookiecutter.project_name}}/utils/check-requirements.py +++ /dev/null @@ -1,58 +0,0 @@ -from typing import Dict -import subprocess # nosec -import click -import re -from functools import partial -from pathlib import Path - -req_dir = Path('.').parent.parent / 'requirements' -pip_list = "pip list -o --format=freeze" - - -def upgrade_requirements() -> None: - warning_message = False - req_files = [ - req_file for req_file in req_dir.iterdir() if req_file.is_file() - ] - - for req_file in req_files: - with req_file.open() as f: - old_req = f.read() - fresh_version = subprocess\ - .check_output( - pip_list, - shell=True # nosec - )\ - .decode("utf-8").split("\n") - - packages: Dict[str, str] = dict( - package.split('==') # type: ignore - for package in fresh_version if package - ) - - with req_file.open('w') as f: - new_req = old_req - for name, version in packages.items(): - new_req = re.sub( - fr'{name}==[\d .]*', - f'{name}=={version}', - new_req, - ) - f.seek(0) - f.write(new_req) - f.truncate() - - if old_req != new_req: - warning_message = True - - if warning_message: - echo = partial(click.echo, err=True) - echo( - click.style( - "Please rebuild your docker container with ", - fg='bright_green') + - click.style("'make build'", fg='bright_blue')) - - -if __name__ == '__main__': - upgrade_requirements() diff --git a/create_aio_app/utils/__init__.py b/create_aio_app/utils/__init__.py index e69de29b..465085d1 100644 --- a/create_aio_app/utils/__init__.py +++ b/create_aio_app/utils/__init__.py @@ -0,0 +1,7 @@ +from pkg_resources import get_distribution, DistributionNotFound + + +try: + __version__ = get_distribution(__name__).version +except DistributionNotFound: + __version__ = 'unknown' diff --git a/create_aio_app/utils/constants.py b/create_aio_app/utils/constants.py new file mode 100644 index 00000000..b68422a9 --- /dev/null +++ b/create_aio_app/utils/constants.py @@ -0,0 +1,15 @@ +import pathlib + +__all__ = [ + 'TEMPLATE_DIR', + 'DATABASE_TEMPLATE_DIRS', + 'DATABASE_TEMPLATE_FILES', + 'WAIT_SCRIPT_FILE', +] + + +TEMPLATE_NAME = 'template_project' +TEMPLATE_DIR = pathlib.Path(__file__).parent / TEMPLATE_NAME +DATABASE_TEMPLATE_DIRS = ['users', 'migrations', ] +DATABASE_TEMPLATE_FILES = ['alembic.ini', ] +WAIT_SCRIPT_FILE = 'utils/wait_script.py' diff --git a/create_aio_app/utils/main.py b/create_aio_app/utils/main.py new file mode 100644 index 00000000..37860686 --- /dev/null +++ b/create_aio_app/utils/main.py @@ -0,0 +1,58 @@ +from functools import partial +from pathlib import Path + +import click +import os + +from cookiecutter.exceptions import FailedHookException +from cookiecutter.exceptions import OutputDirExistsException +from cookiecutter.main import cookiecutter + +from create_aio_app.utils.config import parse_arguments + +parent = Path(__file__).parent + +echo = partial(click.echo, err=True) + + +def show_commands(folder): + try: + os.chdir(f"{folder}/") # nosec + os.system(f"make help") # nosec + except Exception as e: + echo(f'{e}') + echo(click.style("\nFailed to show commands\n", fg="red",)) + + +def main(): + args = parse_arguments() + template_path = str(parent / "template") + + kwargs = {} + + if args.get("name"): + kwargs = { + "no_input": True, + "extra_context": { + "project_name": args.get("name"), + "use_postgres": "n" if args.get("without_postgres") else "y", + "use_redis": "y" if args.get("redis") else "n", + "use_uvloop": "y" if args.get("uvloop") else "n", + }, + } + + try: + result = cookiecutter(template_path, **kwargs) + except (FailedHookException, OutputDirExistsException) as exc: + if isinstance(exc, OutputDirExistsException): + echo( + click.style( + "\n\nDirectory with such name already exists!\n", fg="red") + ) + return + + folder = Path(result).name + + echo(click.style("\n\nSuccessfully generated!\n", fg="bright_green",)) + echo("cd " + click.style(f"{folder}/", fg="bright_blue")) + show_commands(folder)