c2cwsgiutils 6.1.7.dev4__tar.gz → 6.2.0.dev54__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/PKG-INFO +74 -12
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/README.md +58 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/acceptance/__init__.py +1 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/acceptance/connection.py +3 -2
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/acceptance/image.py +5 -3
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/acceptance/package-lock.json +110 -248
- c2cwsgiutils-6.2.0.dev54/c2cwsgiutils/acceptance/package.json +7 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/acceptance/print.py +1 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/acceptance/utils.py +2 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/auth.py +9 -8
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/broadcast/__init__.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/broadcast/local.py +4 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/broadcast/redis.py +8 -2
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/client_info.py +2 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/coverage_setup.py +2 -2
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/db.py +11 -2
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/db_maintenance_view.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/debug/__init__.py +4 -2
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/debug/_views.py +22 -4
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/errors.py +7 -2
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/health_check.py +39 -29
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/index.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/loader.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/logging_view.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/models_graph.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/pretty_json.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/profiler.py +1 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/prometheus.py +58 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/pyramid.py +1 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/pyramid_logging.py +4 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/redis_stats.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/redis_utils.py +2 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/request_tracking/__init__.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/scripts/genversion.py +4 -2
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/scripts/stats_db.py +1 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/scripts/test_print.py +4 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/sentry.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/setup_process.py +5 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/sql_profiler/__init__.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/sql_profiler/_impl.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/sqlalchemylogger/handlers.py +18 -12
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/stats_pyramid/__init__.py +2 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/stats_pyramid/_pyramid_spy.py +1 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/version.py +1 -1
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/pyproject.toml +40 -19
- c2cwsgiutils-6.1.7.dev4/c2cwsgiutils/acceptance/package.json +0 -7
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/LICENSE +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/__init__.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/acceptance/screenshot.js +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/broadcast/interface.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/broadcast/utils.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/config_utils.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/debug/_listeners.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/debug/utils.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/py.typed +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/request_tracking/_sql.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/scripts/__init__.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/services.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/sqlalchemylogger/README.md +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/sqlalchemylogger/__init__.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/sqlalchemylogger/_filters.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/sqlalchemylogger/_models.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/sqlalchemylogger/examples/example.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/static/favicon-16x16.png +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/static/favicon-32x32.png +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/stats_pyramid/_db_spy.py +0 -0
- {c2cwsgiutils-6.1.7.dev4 → c2cwsgiutils-6.2.0.dev54}/c2cwsgiutils/templates/index.html.mako +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: c2cwsgiutils
|
3
|
-
Version: 6.
|
3
|
+
Version: 6.2.0.dev54
|
4
4
|
Summary: Common utilities for Camptocamp WSGI applications
|
5
5
|
Home-page: https://github.com/camptocamp/c2cwsgiutils
|
6
6
|
License: BSD-2-Clause
|
@@ -33,22 +33,26 @@ Provides-Extra: sentry
|
|
33
33
|
Provides-Extra: standard
|
34
34
|
Provides-Extra: test-images
|
35
35
|
Provides-Extra: tests
|
36
|
+
Provides-Extra: waitress
|
36
37
|
Provides-Extra: webserver
|
37
|
-
Requires-Dist:
|
38
|
-
Requires-Dist: SQLAlchemy
|
38
|
+
Requires-Dist: Paste ; extra == "standard" or extra == "waitress" or extra == "all"
|
39
|
+
Requires-Dist: SQLAlchemy ; extra == "standard" or extra == "webserver" or extra == "waitress" or extra == "all"
|
40
|
+
Requires-Dist: SQLAlchemy-Utils ; extra == "standard" or extra == "webserver" or extra == "waitress" or extra == "all"
|
39
41
|
Requires-Dist: alembic ; extra == "standard" or extra == "alembic" or extra == "all"
|
40
42
|
Requires-Dist: boltons ; extra == "tests" or extra == "all"
|
41
43
|
Requires-Dist: cee_syslog_handler
|
42
|
-
Requires-Dist: cornice ; extra == "standard" or extra == "webserver" or extra == "all"
|
44
|
+
Requires-Dist: cornice ; extra == "standard" or extra == "webserver" or extra == "waitress" or extra == "all"
|
45
|
+
Requires-Dist: coverage ; extra == "debug" or extra == "all"
|
43
46
|
Requires-Dist: gunicorn ; extra == "standard" or extra == "webserver" or extra == "all"
|
44
47
|
Requires-Dist: lxml ; extra == "tests" or extra == "all"
|
45
48
|
Requires-Dist: objgraph ; extra == "debug" or extra == "all"
|
46
|
-
Requires-Dist: prometheus-client ; extra == "standard" or extra == "webserver" or extra == "all"
|
47
|
-
Requires-Dist:
|
49
|
+
Requires-Dist: prometheus-client ; extra == "standard" or extra == "webserver" or extra == "waitress" or extra == "all"
|
50
|
+
Requires-Dist: psutil ; extra == "debug" or extra == "all"
|
51
|
+
Requires-Dist: psycopg2 ; extra == "standard" or extra == "webserver" or extra == "waitress" or extra == "all"
|
48
52
|
Requires-Dist: pyjwt ; extra == "standard" or extra == "oauth2" or extra == "all"
|
49
|
-
Requires-Dist: pyramid ; extra == "standard" or extra == "webserver" or extra == "all"
|
50
|
-
Requires-Dist: pyramid-tm ; extra == "standard" or extra == "webserver" or extra == "all"
|
51
|
-
Requires-Dist: pyramid_mako ; extra == "standard" or extra == "webserver" or extra == "all"
|
53
|
+
Requires-Dist: pyramid ; extra == "standard" or extra == "webserver" or extra == "waitress" or extra == "all"
|
54
|
+
Requires-Dist: pyramid-tm ; extra == "standard" or extra == "webserver" or extra == "waitress" or extra == "all"
|
55
|
+
Requires-Dist: pyramid_mako ; extra == "standard" or extra == "webserver" or extra == "waitress" or extra == "all"
|
52
56
|
Requires-Dist: pyyaml
|
53
57
|
Requires-Dist: redis ; extra == "standard" or extra == "broadcast" or extra == "all"
|
54
58
|
Requires-Dist: requests
|
@@ -56,9 +60,9 @@ Requires-Dist: requests-oauthlib ; extra == "standard" or extra == "oauth2" or e
|
|
56
60
|
Requires-Dist: scikit-image ; extra == "test-images"
|
57
61
|
Requires-Dist: sentry-sdk ; extra == "standard" or extra == "sentry" or extra == "all"
|
58
62
|
Requires-Dist: ujson
|
59
|
-
Requires-Dist: waitress ; extra == "dev" or extra == "all"
|
60
|
-
Requires-Dist: zope.interface ; extra == "standard" or extra == "webserver" or extra == "all"
|
61
|
-
Requires-Dist: zope.sqlalchemy ; extra == "standard" or extra == "webserver" or extra == "all"
|
63
|
+
Requires-Dist: waitress ; extra == "standard" or extra == "dev" or extra == "waitress" or extra == "all"
|
64
|
+
Requires-Dist: zope.interface ; extra == "standard" or extra == "webserver" or extra == "waitress" or extra == "all"
|
65
|
+
Requires-Dist: zope.sqlalchemy ; extra == "standard" or extra == "webserver" or extra == "waitress" or extra == "all"
|
62
66
|
Project-URL: Repository, https://github.com/camptocamp/c2cwsgiutils
|
63
67
|
Description-Content-Type: text/markdown
|
64
68
|
|
@@ -672,6 +676,64 @@ def hello_get(request):
|
|
672
676
|
return {'hello': True}
|
673
677
|
```
|
674
678
|
|
679
|
+
## Waitress
|
680
|
+
|
681
|
+
In production mode we usually use Gunicorn but we can also use Waitress.
|
682
|
+
|
683
|
+
The advantage to use Waitress is that it creates only one process, that makes it easier to manage especially on Kubernetes:
|
684
|
+
|
685
|
+
- The memory is more stable.
|
686
|
+
- The OOM killer will restart the container.
|
687
|
+
- Prometheus didn't request trick to aggregate the metrics.
|
688
|
+
|
689
|
+
Then to migrate from Gunicorn to Waitress you should do:
|
690
|
+
|
691
|
+
Add call to `c2cwsgiutils.prometheus.start_single_process()` on your application main function.
|
692
|
+
|
693
|
+
Changes to do in your docker file:
|
694
|
+
|
695
|
+
```diff
|
696
|
+
|
697
|
+
ENV \
|
698
|
+
- GUNICORN_LOG_LEVEL=WARNING \
|
699
|
+
+ WAITRESS_LOG_LEVEL=WARNING \
|
700
|
+
+ WAITRESS_THREADS=10 \
|
701
|
+
|
702
|
+
-RUN mkdir -p /prometheus-metrics \
|
703
|
+
- && chmod a+rwx /prometheus-metrics
|
704
|
+
-ENV PROMETHEUS_MULTIPROC_DIR=/prometheus-metrics
|
705
|
+
|
706
|
+
|
707
|
+
-CMD ["/venv/bin/gunicorn", "--paste=/app/production.ini"]
|
708
|
+
+CMD ["/venv/bin/pserve", "c2c:///app/production.ini"]
|
709
|
+
```
|
710
|
+
|
711
|
+
Remove the no more needed file `gunicorn.conf.py`.
|
712
|
+
|
713
|
+
Update the `production.ini` file:
|
714
|
+
|
715
|
+
```diff
|
716
|
+
|
717
|
+
-# this file should be used by gunicorn.
|
718
|
+
|
719
|
+
[server:main]
|
720
|
+
+threads = %(WAITRESS_THREADS)s
|
721
|
+
+trusted_proxy = True
|
722
|
+
+clear_untrusted_proxy_headers = False
|
723
|
+
|
724
|
+
[loggers]
|
725
|
+
-keys = root, gunicorn, sqlalchemy, c2cwsgiutils, c2cwsgiutils_app
|
726
|
+
+keys = root, waitress, sqlalchemy, c2cwsgiutils, c2cwsgiutils_app
|
727
|
+
|
728
|
+
-[logger_gunicorn]
|
729
|
+
-level = %(GUNICORN_LOG_LEVEL)s
|
730
|
+
+[logger_waitress]
|
731
|
+
+level = %(WAITRESS_LOG_LEVEL)s
|
732
|
+
handlers =
|
733
|
+
-qualname = gunicorn.error
|
734
|
+
+qualname = waitress
|
735
|
+
```
|
736
|
+
|
675
737
|
# Exception handling
|
676
738
|
|
677
739
|
c2cwsgiutils can install exception handling views that will catch any exception raised by the
|
@@ -608,6 +608,64 @@ def hello_get(request):
|
|
608
608
|
return {'hello': True}
|
609
609
|
```
|
610
610
|
|
611
|
+
## Waitress
|
612
|
+
|
613
|
+
In production mode we usually use Gunicorn but we can also use Waitress.
|
614
|
+
|
615
|
+
The advantage to use Waitress is that it creates only one process, that makes it easier to manage especially on Kubernetes:
|
616
|
+
|
617
|
+
- The memory is more stable.
|
618
|
+
- The OOM killer will restart the container.
|
619
|
+
- Prometheus didn't request trick to aggregate the metrics.
|
620
|
+
|
621
|
+
Then to migrate from Gunicorn to Waitress you should do:
|
622
|
+
|
623
|
+
Add call to `c2cwsgiutils.prometheus.start_single_process()` on your application main function.
|
624
|
+
|
625
|
+
Changes to do in your docker file:
|
626
|
+
|
627
|
+
```diff
|
628
|
+
|
629
|
+
ENV \
|
630
|
+
- GUNICORN_LOG_LEVEL=WARNING \
|
631
|
+
+ WAITRESS_LOG_LEVEL=WARNING \
|
632
|
+
+ WAITRESS_THREADS=10 \
|
633
|
+
|
634
|
+
-RUN mkdir -p /prometheus-metrics \
|
635
|
+
- && chmod a+rwx /prometheus-metrics
|
636
|
+
-ENV PROMETHEUS_MULTIPROC_DIR=/prometheus-metrics
|
637
|
+
|
638
|
+
|
639
|
+
-CMD ["/venv/bin/gunicorn", "--paste=/app/production.ini"]
|
640
|
+
+CMD ["/venv/bin/pserve", "c2c:///app/production.ini"]
|
641
|
+
```
|
642
|
+
|
643
|
+
Remove the no more needed file `gunicorn.conf.py`.
|
644
|
+
|
645
|
+
Update the `production.ini` file:
|
646
|
+
|
647
|
+
```diff
|
648
|
+
|
649
|
+
-# this file should be used by gunicorn.
|
650
|
+
|
651
|
+
[server:main]
|
652
|
+
+threads = %(WAITRESS_THREADS)s
|
653
|
+
+trusted_proxy = True
|
654
|
+
+clear_untrusted_proxy_headers = False
|
655
|
+
|
656
|
+
[loggers]
|
657
|
+
-keys = root, gunicorn, sqlalchemy, c2cwsgiutils, c2cwsgiutils_app
|
658
|
+
+keys = root, waitress, sqlalchemy, c2cwsgiutils, c2cwsgiutils_app
|
659
|
+
|
660
|
+
-[logger_gunicorn]
|
661
|
+
-level = %(GUNICORN_LOG_LEVEL)s
|
662
|
+
+[logger_waitress]
|
663
|
+
+level = %(WAITRESS_LOG_LEVEL)s
|
664
|
+
handlers =
|
665
|
+
-qualname = gunicorn.error
|
666
|
+
+qualname = waitress
|
667
|
+
```
|
668
|
+
|
611
669
|
# Exception handling
|
612
670
|
|
613
671
|
c2cwsgiutils can install exception handling views that will catch any exception raised by the
|
@@ -20,6 +20,7 @@ def retry(
|
|
20
20
|
tries: number of times to try (not retry) before giving up
|
21
21
|
delay: initial delay between retries in seconds
|
22
22
|
backoff: backoff multiplier e.g. value of 2 will double the delay each retry
|
23
|
+
|
23
24
|
"""
|
24
25
|
|
25
26
|
def deco_retry(f: typing.Callable[..., typing.Any]) -> typing.Callable[..., typing.Any]:
|
@@ -20,6 +20,7 @@ class Connection:
|
|
20
20
|
"""The connection."""
|
21
21
|
|
22
22
|
def __init__(self, base_url: str, origin: str) -> None:
|
23
|
+
"""Initialize the connection."""
|
23
24
|
self.base_url = base_url
|
24
25
|
if not self.base_url.endswith("/"):
|
25
26
|
self.base_url += "/"
|
@@ -93,10 +94,10 @@ class Connection:
|
|
93
94
|
check_response(r, expected_status, cache_expected=cache_expected)
|
94
95
|
self._check_cors(cors, r)
|
95
96
|
r.raw.decode_content = True
|
96
|
-
doc = etree.parse(r.raw) #
|
97
|
+
doc = etree.parse(r.raw) # noqa: S320
|
97
98
|
if schema is not None:
|
98
99
|
with open(schema, encoding="utf-8") as schema_file:
|
99
|
-
xml_schema = etree.XMLSchema(etree.parse(schema_file)) #
|
100
|
+
xml_schema = etree.XMLSchema(etree.parse(schema_file)) # noqa: S320
|
100
101
|
xml_schema.assertValid(doc)
|
101
102
|
return doc
|
102
103
|
|
@@ -10,7 +10,7 @@ import skimage.metrics # pylint: disable=import-error
|
|
10
10
|
import skimage.transform # pylint: disable=import-error
|
11
11
|
|
12
12
|
if TYPE_CHECKING:
|
13
|
-
from
|
13
|
+
from typing_extensions import TypeAlias
|
14
14
|
|
15
15
|
NpNdarrayInt: TypeAlias = np.ndarray[np.uint8, Any]
|
16
16
|
else:
|
@@ -89,6 +89,7 @@ def check_image( # pylint: disable=too-many-locals,too-many-statements
|
|
89
89
|
level: The minimum similarity level (between 0.0 and 1.0), default to 1.0
|
90
90
|
generate_expected_image: If `True` generate the expected image instead of checking it
|
91
91
|
use_mask: If `False` don't use the mask event if the file exists
|
92
|
+
|
92
93
|
"""
|
93
94
|
assert image_to_check is not None, "Image required"
|
94
95
|
image_file_basename = os.path.splitext(os.path.basename(expected_filename))[0]
|
@@ -129,7 +130,7 @@ def check_image( # pylint: disable=too-many-locals,too-many-statements
|
|
129
130
|
if np.issubdtype(mask.dtype, np.floating):
|
130
131
|
mask = (mask * 255).astype("uint8")
|
131
132
|
|
132
|
-
assert ((
|
133
|
+
assert ((mask > 0) & (mask < 255)).sum() == 0, "Mask should be only black and white image"
|
133
134
|
|
134
135
|
# Convert to boolean
|
135
136
|
mask = mask == 0
|
@@ -146,7 +147,7 @@ def check_image( # pylint: disable=too-many-locals,too-many-statements
|
|
146
147
|
return
|
147
148
|
if not os.path.isfile(expected_filename):
|
148
149
|
skimage.io.imsave(expected_filename, image_to_check)
|
149
|
-
|
150
|
+
raise AssertionError("Expected image not found: " + expected_filename)
|
150
151
|
expected = skimage.io.imread(expected_filename)
|
151
152
|
assert expected is not None, "Wrong image: " + expected_filename
|
152
153
|
expected = normalize_image(expected)
|
@@ -208,6 +209,7 @@ def check_screenshot(
|
|
208
209
|
level: See `check_image`
|
209
210
|
generate_expected_image: See `check_image`
|
210
211
|
use_mask: See `check_image`
|
212
|
+
|
211
213
|
"""
|
212
214
|
if headers is None:
|
213
215
|
headers = {}
|