-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6e04f10
commit 3ee1ef2
Showing
10 changed files
with
1,880 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# Python Poetry Template | ||
|
||
This template is designed to make it easy to set up a Python project that is well-structured, organized, and easy to maintain. It comes pre-configured with several tools that will help you develop your project more efficiently, including: | ||
|
||
- Visual Studio Code integration: with the `RunOnSave`, `even-better-toml` and `ruff` extensions installed, you can format, lint, and type-check your code automatically every time you save a file. | ||
- Type checking: this template is configured to use `mypy` and `pyright` to automatically infer types when possible, without imposing strict typing requirements on your code. | ||
- Linting: `ruff`, an extremely fast Python linter, written in Rust is configured well to help you catch and fix code style issues. | ||
- Formatting: `yapf`, `ruff`, and `unify` are configured to help you keep your code clean and well-organized. | ||
- Testing: `pytest` is configured to make it easy to run tests, and `pytest-cov` is configured to help you measure code coverage. | ||
- Dependency management: `poetry` is configured to help you manage your project's dependencies. | ||
- Toolkits: `invoke` is configured to provide a range of useful tasks, such as running your code, running tests, formatting your code, and checking your code style and types. These tasks are fully configurable in the [tasks.py](tasks.py) file. | ||
|
||
## Installation | ||
|
||
To install this template, simply follow these steps: | ||
|
||
```sh | ||
git clone [email protected]:code-yeongyu/Python-Poetry-Template.git | ||
cd Python-Poetry-Template | ||
poetry install | ||
code --install-extension emeraldwalk.RunOnSave | ||
code --install-extension tamasfe.even-better-toml | ||
code --install-extension charliermarsh.ruff | ||
``` | ||
|
||
## Usage | ||
|
||
To use this template, you can follow these steps: | ||
|
||
### Open Shell | ||
|
||
To open a shell in the project directory, use the following command: | ||
|
||
```sh | ||
poetry shell | ||
``` | ||
|
||
### Name your project | ||
|
||
```sh | ||
invoke rename-project <your-project-name> | ||
``` | ||
|
||
### Run Code | ||
|
||
To run your code, use the following command: | ||
|
||
```sh | ||
poetry run invoke run | ||
``` | ||
|
||
### Run Tests | ||
|
||
To run your tests, use the following command: | ||
|
||
```sh | ||
poetry run invoke test | ||
``` | ||
|
||
### Run Formatters | ||
|
||
To run the code formatters, use the following command: | ||
|
||
```sh | ||
poetry run invoke format_code | ||
``` | ||
|
||
### Run Checking Code Style & Type hint | ||
|
||
To check your code style and type hints, use the following command: | ||
|
||
```sh | ||
poetry run invoke check | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import inspect | ||
import types | ||
from typing import Any, Callable, Dict, List, Tuple, Union | ||
|
||
from invoke.context import Context | ||
from invoke.tasks import NO_DEFAULT, Task | ||
|
||
|
||
def monkey_patch_invoke() -> None: | ||
|
||
def _patched_argspec( | ||
self: Any, # pylint: disable=unused-argument | ||
body: Union[Callable[[Context], None], Context], | ||
) -> Tuple[List[str], Dict[str, object]]: | ||
""" | ||
A monkey patching code for supporting python3 | ||
from: https://github.com/pyinvoke/invoke/issues/357#issuecomment-1250744013 | ||
""" | ||
signature: inspect.Signature = inspect.Signature() | ||
if isinstance(body, types.FunctionType): | ||
signature = inspect.signature(body) | ||
elif isinstance(body, types.MethodType): | ||
signature = inspect.signature(body.__call__) | ||
|
||
parameter_names = [name for name, _ in signature.parameters.items()] | ||
argument_specs: dict[str, object] = {} | ||
for key, value in signature.parameters.items(): | ||
value = value.default if not value.default == signature.empty else NO_DEFAULT | ||
argument_specs[key] = value | ||
|
||
# Pop context argument | ||
try: | ||
context_arg = parameter_names.pop(0) | ||
except IndexError as error: | ||
raise TypeError('Tasks must have an initial Context argument!') from error | ||
|
||
del argument_specs[context_arg] | ||
return parameter_names, argument_specs | ||
|
||
Task.argspec = _patched_argspec | ||
|
||
|
||
monkey_patch_invoke() |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[virtualenvs] | ||
create = true | ||
in-project = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
[build-system] | ||
requires = ["poetry-core"] | ||
build-backend = "poetry.core.masonry.api" | ||
|
||
[tool.poetry] | ||
name = "ygka" | ||
version = "0.0.0" | ||
description = "" | ||
authors = [] | ||
readme = "README.md" | ||
|
||
[tool.pyright] | ||
typeCheckingMode = "strict" | ||
|
||
# Python environment settings | ||
pythonPlatform = "All" | ||
venvPath = "./.venv" | ||
stubPath = "./.type_stubs" | ||
include = ["./*"] | ||
exclude = ["**/node_modules", "**/__pycache__"] | ||
|
||
# For untyped modules | ||
useLibraryCodeForTypes = true # Attempt to read and infer types from third-party modules if no stub files are present | ||
reportMissingTypeStubs = false # Ignore errors from modules without type stubs | ||
reportUnknownMemberType = false # Ignore errors from untyped function calls in third-party modules | ||
reportUnknownVariableType = false # Ignore errors from untyped function calls in third-party modules | ||
|
||
pythonVersion = "3.9" | ||
|
||
[tool.yapf] | ||
based_on_style = "pep8" | ||
spaces_before_comment = 2 | ||
split_before_logical_operator = true | ||
column_limit = 119 | ||
allow_split_before_dict_value = false | ||
|
||
[tool.ruff] | ||
line-length = 119 | ||
select = ["PLE", "PLR", "PLW", "E", "W", "F", "I", "Q", "C", "B"] | ||
|
||
[tool.pytest.ini_options] | ||
addopts = ["--cov=ygka"] | ||
|
||
|
||
[tool.poetry.dependencies] | ||
python = "^3.9" | ||
poetry = "^1.4.0" | ||
|
||
[tool.poetry.scripts] | ||
ygka = "ygka:main" | ||
|
||
[tool.ruff.flake8-quotes] | ||
inline-quotes = "single" | ||
docstring-quotes = "single" | ||
multiline-quotes = "single" | ||
|
||
[tool.poetry.group.dev.dependencies] | ||
toml = "^0.10.2" | ||
yapf = "^0.32.0" | ||
pytest = "^7.2.2" | ||
pytest-cov = "^4.0.0" | ||
invoke = "^1.7.3" | ||
ruff = "^0.0.199" | ||
types-invoke = "^1.7.3.16" | ||
types-toml = "^0.10.8.5" | ||
pyright = "^1.1.296" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# type: ignore | ||
import shutil | ||
|
||
import toml | ||
from invoke import Context, task | ||
from invoke.exceptions import UnexpectedExit | ||
|
||
import monkey_patch_invoke as _ # noqa: F401 | ||
|
||
|
||
def get_pep8_compliant_name(project_name: str) -> str: | ||
return project_name.replace('-', '_') | ||
|
||
|
||
def get_project_path(): | ||
with open('pyproject.toml', encoding='utf-8') as file: | ||
data = toml.load(file) | ||
project_name = get_pep8_compliant_name(data['tool']['poetry']['name']) | ||
return project_name | ||
|
||
|
||
@task | ||
def run(context: Context): | ||
context.run(f'python -m {get_project_path()}', pty=True) | ||
|
||
|
||
@task | ||
def test(context: Context): | ||
context.run('pytest . --cov=. --cov-report=xml', pty=True) | ||
|
||
|
||
@task | ||
def format_code(context: Context, verbose: bool = False): | ||
commands = [ | ||
f'pautoflake {get_project_path()}', | ||
f'ruff --fix {get_project_path()}', | ||
f'yapf --in-place --recursive --parallel {get_project_path()}', | ||
] | ||
|
||
for command in commands: | ||
context.run(command, pty=True) | ||
|
||
|
||
@task | ||
def check(context: Context): | ||
check_code_style(context) | ||
check_types(context) | ||
|
||
|
||
@task | ||
def check_code_style(context: Context): | ||
commands = [ | ||
f'ruff {get_project_path()}', | ||
f'yapf --diff --recursive --parallel {get_project_path()}', | ||
] | ||
|
||
for command in commands: | ||
context.run(command, pty=True) | ||
|
||
|
||
@task | ||
def check_types(context: Context): | ||
context.run(f'pyright {get_project_path()}', pty=True) | ||
|
||
|
||
@task | ||
def rename_project(_context: Context, project_name: str): | ||
# Get the current project path | ||
current_project_path = get_project_path() | ||
|
||
# Rename the directory | ||
shutil.move(get_pep8_compliant_name(current_project_path), get_pep8_compliant_name(project_name)) | ||
|
||
# Update the project name in pyproject.toml | ||
with open('pyproject.toml', 'r', encoding='utf-8') as file: | ||
data = toml.load(file) | ||
|
||
data['tool']['poetry']['name'] = project_name | ||
|
||
with open('pyproject.toml', 'w', encoding='utf-8') as file: | ||
toml.dump(data, file) | ||
|
||
|
||
@task | ||
def release(context: Context, version: str) -> None: | ||
'''Build & Publish to PyPI.''' | ||
|
||
# load pyproject | ||
pyproject_path = 'pyproject.toml' | ||
pyproject_string = '' | ||
with open(pyproject_path, 'r', encoding='utf-8') as pyproject_file: | ||
pyproject_string = pyproject_file.read() | ||
pyproject = toml.loads(pyproject_string) | ||
# change version to today datetime | ||
pyproject['tool']['poetry']['version'] = version | ||
with open(pyproject_path, 'w', encoding='utf-8') as pyproject_file: | ||
toml.dump(pyproject, pyproject_file) | ||
|
||
# build & publish | ||
try: | ||
context.run( | ||
''' | ||
poetry build --no-interaction | ||
poetry publish --no-interaction | ||
''', | ||
pty=True, | ||
) | ||
except UnexpectedExit as exception: | ||
with open(pyproject_path, 'w', encoding='utf-8') as pyproject_file: | ||
pyproject_file.write(pyproject_string) | ||
raise exception from exception | ||
|
||
# recover to original | ||
with open(pyproject_path, 'w', encoding='utf-8') as pyproject_file: | ||
pyproject_file.write(pyproject_string) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
def main(): | ||
print('Hello, World!') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import ygka | ||
|
||
if __name__ == '__main__': # to make the project executable by `python3 -m ygka <query>` | ||
ygka.main() |
Empty file.