Skip to content

Commit

Permalink
[Update] build: better checks
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastien committed Sep 5, 2024
1 parent 77e4f7e commit 3e9e55a
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 20 deletions.
101 changes: 90 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,109 @@ MODULES_PY:=$(filter-out %/__main__,$(filter-out %/__init__,$(SOURCES_PY:$(PATH_
PATH_LOCAL_PY=$(firstword $(shell python -c "import sys,pathlib;sys.stdout.write(' '.join([_ for _ in sys.path if _.startswith(str(pathlib.Path.home()))] ))"))
PATH_LOCAL_BIN=$(HOME)/.local/bin

REQUIRE_PY=flake8 bandit mypy
PREP_ALL=$(REQUIRE_PY:%=build/require-py-%.task)
# Commands
BANDIT=python -m bandit
FLAKE8=python -m flake8
MYPY=python -m mypy
MYPYC=mypyc

cmd-check=if ! $$(which $1 &> /dev/null ); then echo "ERR Could not find command $1"; exit 1; fi; $1

.PHONY: prep
prep: $(PREP_ALL)
@

.PHONY: run
run:
@

.PHONY: ci
ci: check test
@



audit: require-py-bandit
bandit -r $(PATH_SOURCES_PY)


.PHONY: audit
audit: check-bandit
@echo "=== $@"

# NOTE: The compilation seems to create many small modules instead of a big single one
.PHONY: compile
compile:
@
@echo "=== $@"
echo "Compiling $(MODULES_PY): $(SOURCES_PY)"
# NOTE: Output is going to be like 'extra/__init__.cpython-310-x86_64-linux-gnu.so'

mkdir -p "build"
$(foreach M,$(MODULES_PY),mkdir -p build/$M;)
env -C build MYPYPATH=$(realpath .)/src/py mypyc -p extra

check: lint
@
.PHONY: check
check: check-bandit check-flakes check-strict
echo "=== $@"

.PHONY: check-compiled
check-compiled:
@COMPILED=$$(PYTHONPATH=build python -c "import extra;print(extra)")
@
echo "=== $@"
COMPILED=$$(PYTHONPATH=build python -c "import extra;print(extra)")
echo "Extra compiled at: $$COMPILED"

.PHONY: check-bandit
check-bandit: $(PREP_ALL)
@echo "=== $@"
$(BANDIT) -r -s B101 src/py/coda

.PHONY: check-flakes
check-flakes: $(PREP_ALL)
@echo "=== $@"
$(FLAKE8) --ignore=E1,E203,E302,E401,E501,E704,E741,E266,F821,W $(SOURCES_PY)

lint:
@flake8 --ignore=E1,E202,E203,E231,E227,E252,E302,E401,E501,E704,E741,F821,W $(SOURCES_PY)
.PHONY: check-mypyc
check-mypyc: $(PREP_ALL)
@$(call cmd-check,mypyc) $(SOURCES_PY)

.PHONY: check-strict
check-strict: $(PREP_ALL)
@
count_ok=0
count_err=0
files_err=
for item in $(SOURCES_PY); do
if $(MYPY) --strict $$item; then
count_ok=$$(($$count_ok+1))
else
count_err=$$(($$count_err+1))
files_err+=" $$item"
fi
done
summary="OK $$count_ok ERR $$count_err TOTAL $$(($$count_err + $$count_ok))"
if [ "$$count_err" != "0" ]; then
for item in $$files_err; do
echo "ERR $$item"
done
echo "EOS FAIL $$summary"
exit 1
else
echo "EOS OK $$summary"
fi




.PHONY: lint
lint: check-flakes
@

.PHONY: format
format:
@black $(SOURCES_PY)

.PHONY: install
install:
@for file in $(SOURCES_BIN); do
echo "Installing $(PATH_LOCAL_BIN)/$$(basename $$file)"
Expand All @@ -60,6 +135,7 @@ install:
fi


.PHONY: try-install
try-uninstall:
@for file in $(SOURCES_BIN); do
unlink $(PATH_LOCAL_BIN)/$$(basename $$file)
Expand All @@ -70,8 +146,12 @@ try-uninstall:
done
fi

require-py-%:
@if [ -z "$$(which '$*' 2> /dev/null)" ]; then $(PYTHON) -mpip install --user --upgrade '$*'; fi
build/require-py-%.task:
@
if $(PYTHON) -mpip install --user --upgrade '$*'; then
mkdir -p "$(dir $@)"
touch "$@"
fi

data/csic_2010-normalTrafficTraining.txt:
curl -o "$@" 'https://gitlab.fing.edu.uy/gsi/web-application-attacks-datasets/-/raw/master/csic_2010/normalTrafficTest.txt?inline=false'
Expand All @@ -82,7 +162,6 @@ data/csic_2010-anomalousTrafficTraining.txt:
print-%:
$(info $*=$($*))

.PHONY: audit
.ONESHELL:
# EOF
#
5 changes: 4 additions & 1 deletion src/py/extra/features/cors.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ def cors(


def setCORSHeaders(
request: HTTPRequest | HTTPResponse, *, origin=None, allowAll=True
request: HTTPRequest | HTTPResponse,
*,
origin: str | None = None,
allowAll: bool = True
) -> HTTPResponse:
"""Takes the given request or response, and return (a response) with the CORS headers set properly.
Expand Down
6 changes: 3 additions & 3 deletions src/py/extra/http/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def cookies(self) -> Iterable[str]:
for _ in self._cookies.keys():
yield _

def cookie(self, name: str) -> Morsel | None:
def cookie(self, name: str) -> Morsel[str] | None:
return self._cookies.get(name)

# FIXME: Should be header
Expand Down Expand Up @@ -291,7 +291,7 @@ def respond(
# API
# =========================================================================

def __str__(self):
def __str__(self) -> str:
return f"Request({self.method} {self.path}{f'?{self.query}' if self.query else ''} {self.headers})"


Expand Down Expand Up @@ -432,7 +432,7 @@ def head(self) -> bytes:
# TODO: UTF8 maybe? Why ASCII?
return "\r\n".join(lines).encode("ascii")

def __str__(self):
def __str__(self) -> str:
return f"Response({self.protocol} {self.status} {self.message} {self.headers} {self.body})"


Expand Down
2 changes: 1 addition & 1 deletion src/py/extra/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@


class ServerOptions(NamedTuple):
host: str = "0.0.0.0"
host: str = "0.0.0.0" # nosec: B104
port: int = 8000
backlog: int = 10_000
timeout: float = 10.0
Expand Down
4 changes: 3 additions & 1 deletion src/py/extra/utils/htmpl.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,9 @@ def f(*children: TNodeContent, **attributes: TAttributeContent):
(
v
if isinstance(v, list)
else list(v) if isinstance(v, tuple) else [v]
else (
[_ for _ in cast(tuple, v)] if isinstance(v, tuple) else [v]
)
),
)
elif k == "_":
Expand Down
6 changes: 3 additions & 3 deletions src/py/extra/utils/json.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from typing import Any
from typing import Any, TypeAlias, cast
import json as basejson
from .primitives import asPrimitive


# TODO: We do want to use ORJSON when available: https://github.com/tktech/json_benchmark

TJSON = None | int | float | bool | list | dict
TJSON: TypeAlias = None | int | float | bool | list[Any] | dict[str, Any]


def json(value: Any) -> bytes:
Expand All @@ -15,7 +15,7 @@ def json(value: Any) -> bytes:

def unjson(value: bytes | str) -> TJSON:
"""Converts JSON-encoded to a string."""
return basejson.loads(value)
return cast(TJSON, basejson.loads(value))


# EOF

0 comments on commit 3e9e55a

Please sign in to comment.