forked from danhper/python-i18n
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from Krutyi-4el/dev2
v0.8.1
- Loading branch information
Showing
30 changed files
with
578 additions
and
123 deletions.
There are no files selected for viewing
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,13 @@ | ||
[run] | ||
command_line = -m i18n.tests | ||
branch = true | ||
# omit temporary file | ||
omit = memoize.en.py | ||
|
||
[report] | ||
# in case omitting doesn't quite work | ||
ignore_errors = true | ||
exclude_lines = | ||
^.*# pragma: no cover | ||
# overloaded methods are only for documentation purposes | ||
^[\s]*@(typing\.)?overload$ |
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 @@ | ||
[flake8] | ||
max-line-length = 100 | ||
extend-exclude = build,dev_env |
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
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 |
---|---|---|
|
@@ -7,3 +7,5 @@ dist/ | |
.python-version | ||
.idea/ | ||
.pytest_cache/ | ||
.coverage | ||
dev_env |
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,8 @@ | ||
[mypy] | ||
files = . | ||
exclude = build | ||
check_untyped_defs = true | ||
warn_unused_ignores = true | ||
warn_redundant_casts = true | ||
disallow_incomplete_defs = true | ||
# no_implicit_reexport = 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
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,196 @@ | ||
import os | ||
import sys | ||
import stat | ||
import shlex | ||
import sysconfig | ||
import subprocess | ||
from contextlib import contextmanager | ||
|
||
|
||
VENV_DIR = "dev_env" | ||
REQUIREMENTS = "dev-requirements.txt" | ||
|
||
|
||
def get_root(): | ||
return subprocess.check_output( | ||
("git", "rev-parse", "--show-toplevel"), | ||
universal_newlines=True, | ||
).strip() | ||
|
||
|
||
os.chdir(get_root()) | ||
sys.argv[0] = os.path.basename(sys.argv[0]) | ||
|
||
|
||
def ensure_venv(packages): | ||
venv_dir = os.path.join(os.getcwd(), VENV_DIR) | ||
if sys.prefix == venv_dir: | ||
# already in venv | ||
return | ||
if os.getenv("SKIP_VENV") != "1": | ||
if not os.path.isdir(venv_dir): | ||
print("Creating virtual environment...") | ||
subprocess.run((sys.executable, "-m", "venv", venv_dir), check=True) | ||
python_path = os.path.join( | ||
sysconfig.get_path("scripts", "venv", {"base": venv_dir}), | ||
"python", | ||
) | ||
pip_install(python_path, packages) | ||
sys.exit( | ||
subprocess.run( | ||
(python_path, sys.argv[0], *sys.argv[1:]), | ||
).returncode, | ||
) | ||
else: | ||
pip_install(sys.executable, packages) | ||
|
||
|
||
def pip_install(python, args): | ||
subprocess.run((python, "-m", "pip", "install", *args), check=True) | ||
|
||
|
||
def get_packages(profile=None): | ||
result = [] | ||
collect = profile is None | ||
with open(REQUIREMENTS) as f: | ||
for line in f: | ||
if line.startswith("#"): | ||
collect = profile is None or line.lstrip("#").strip() == profile | ||
continue | ||
if collect: | ||
result.append(line) | ||
return result | ||
|
||
|
||
@contextmanager | ||
def stash_unstaged(): | ||
if subprocess.check_output(("git", "ls-files", "--exclude-standard", "-om")) == b"": | ||
# nothing to stash | ||
yield | ||
return | ||
subprocess.run( | ||
("git", "stash", "--keep-index", "--include-untracked", "-m", "temp"), | ||
check=True, | ||
) | ||
file_list = subprocess.check_output( | ||
("git", "diff", "stash", "--name-only"), | ||
universal_newlines=True, | ||
).splitlines() | ||
diffs = [ | ||
subprocess.check_output(("git", "diff", "--binary", "-R", "stash", file)) | ||
for file in file_list | ||
] | ||
try: | ||
yield | ||
finally: | ||
# restore all files from stash | ||
for file, diff in zip(file_list, diffs): | ||
if subprocess.run(("git", "apply"), input=diff).returncode != 0: | ||
# revert changes made by script | ||
subprocess.run(("git", "checkout", "--", file)) | ||
subprocess.run(("git", "apply"), input=diff, check=True) | ||
# pop untracked files | ||
if subprocess.run(("git", "stash", "pop")).returncode != 0: | ||
subprocess.run(("git", "stash", "drop"), check=True) | ||
|
||
|
||
def _format_file(file): | ||
success = True | ||
if not os.path.exists(file): | ||
# file was removed | ||
return True | ||
with open(file) as f: | ||
try: | ||
data = f.readlines() | ||
except UnicodeDecodeError: | ||
return True | ||
for i, line in enumerate(data): | ||
if line.endswith((" \n", "\t\n")): | ||
success = False | ||
data[i] = line.rstrip(" \t\n") + "\n" | ||
if data and not data[-1].endswith("\n"): | ||
success = False | ||
data[-1] += "\n" | ||
if not success: | ||
with open(file, "w") as f: | ||
f.writelines(data) | ||
return success | ||
|
||
|
||
def format_files(): | ||
files = subprocess.check_output( | ||
("git", "diff", "--staged", "--name-only") | ||
if "-a" not in sys.argv | ||
else ("git", "ls-files"), | ||
universal_newlines=True, | ||
).splitlines() | ||
results = [_format_file(f) for f in files] | ||
return all(results) | ||
|
||
|
||
def run_flake8(): | ||
return subprocess.run((sys.executable, "-m", "flake8")).returncode == 0 | ||
|
||
|
||
def run_mypy(): | ||
return subprocess.run((sys.executable, "-m", "mypy")).returncode == 0 | ||
|
||
|
||
def check_coverage(): | ||
from runpy import run_module | ||
from coverage import Coverage # type: ignore[import] | ||
|
||
cov = Coverage() | ||
cov.start() | ||
|
||
run_module("i18n.tests", run_name="__main__") | ||
|
||
cov.stop() | ||
return ( | ||
cov.report() == 100.0 | ||
# always succeed on GA | ||
or os.getenv("SKIP_VENV") == "1" | ||
) | ||
|
||
|
||
def install(): | ||
file = os.path.join(os.getcwd(), ".git", "hooks", "pre-commit") | ||
with open(file, "w") as f: | ||
print(shlex.quote(sys.executable), shlex.quote(sys.argv[0]), file=f) | ||
mode = os.stat(file).st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH | ||
os.chmod(file, mode) | ||
|
||
|
||
FUNCS = { | ||
"tests": (check_coverage,), | ||
"checks": (format_files, run_flake8, run_mypy), | ||
} | ||
|
||
|
||
def main(): | ||
args = sys.argv[1:] | ||
if not args or args[0].startswith(("run-", "-")): | ||
if args and args[0].startswith("run-"): | ||
_, _, profile = args[0].partition("-") | ||
funcs = FUNCS[profile] | ||
pkgs = get_packages(profile) | ||
else: | ||
funcs = sum(FUNCS.values(), start=()) | ||
pkgs = get_packages() | ||
ensure_venv(pkgs) | ||
with stash_unstaged(): | ||
for func in funcs: | ||
print("running", func.__name__) | ||
if not func(): | ||
return 1, func.__name__ + " failed" | ||
elif args[0] == "install": | ||
install() | ||
else: | ||
return 1, "Unknown command: " + args[0] | ||
return 0, "ok" | ||
|
||
|
||
if __name__ == "__main__": | ||
code, text = main() | ||
print(text) | ||
sys.exit(code) |
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,9 @@ | ||
# tests | ||
.[YAML] | ||
coverage==6.2; python_version<'3.7' | ||
coverage==6.5.0; python_version>='3.7' | ||
# checks | ||
flake8==6.1.0 | ||
mypy==1.5.0 | ||
types-PyYAML==6.0.12.11 | ||
types-setuptools==68.0.0.3 |
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
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
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 |
---|---|---|
@@ -1,18 +1,20 @@ | ||
from collections import defaultdict | ||
from typing import Optional, Callable | ||
from typing import Optional, Callable, Dict | ||
|
||
|
||
global_functions = {} | ||
locales_functions = defaultdict(dict) | ||
Function = Callable[..., int] | ||
global_functions: Dict[str, Function] = {} | ||
locales_functions: Dict[str, Dict[str, Function]] = defaultdict(dict) | ||
|
||
|
||
def add_function(name: str, func: Callable[..., int], locale: Optional[str] = None): | ||
def add_function(name: str, func: Function, locale: Optional[str] = None) -> None: | ||
if locale: | ||
locales_functions[locale][name] = func | ||
else: | ||
global_functions[name] = func | ||
|
||
def get_function(name, locale=None): | ||
|
||
def get_function(name: str, locale: Optional[str] = None) -> Optional[Function]: | ||
if locale and name in locales_functions[locale]: | ||
return locales_functions[locale][name] | ||
return global_functions.get(name) |
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
Oops, something went wrong.