-
Notifications
You must be signed in to change notification settings - Fork 1
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
PPB InfoSec Engineering
committed
Jan 17, 2022
0 parents
commit a40b1fc
Showing
25 changed files
with
612 additions
and
0 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,12 @@ | ||
# file set with Dockerfile.tests (for run_tests script) in mind - review if used for anything else | ||
.jenkins | ||
**/.coverage | ||
**/__pycache__ | ||
**/*.pyc | ||
dist | ||
*.egg-info | ||
.git | ||
.reports | ||
.dockerignore | ||
**/.pytest_cache | ||
**/.vscode |
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,29 @@ | ||
# This workflows will upload a Python Package using Twine when a release is created | ||
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries | ||
|
||
name: publish | ||
|
||
on: | ||
release: | ||
types: [created] | ||
|
||
jobs: | ||
deploy: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Set up Python | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: '3.x' | ||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install setuptools wheel twine | ||
- name: Build and publish | ||
env: | ||
TWINE_USERNAME: __token__ | ||
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} | ||
run: | | ||
python setup.py sdist bdist_wheel | ||
twine upload dist/* |
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,29 @@ | ||
# This workflows will upload a Python Package using Twine when a release is created | ||
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries | ||
|
||
name: publish test | ||
|
||
on: | ||
push: | ||
branches: testpypi | ||
|
||
jobs: | ||
deploy: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Set up Python | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: '3.x' | ||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install setuptools wheel twine | ||
- name: Build and publish | ||
env: | ||
TWINE_USERNAME: __token__ | ||
TWINE_PASSWORD: ${{ secrets.PYPI_TEST_TOKEN }} | ||
run: | | ||
python setup.py sdist bdist_wheel | ||
twine upload --repository testpypi dist/* |
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 @@ | ||
*.pyc | ||
__pycache__ | ||
/dist | ||
*.egg-info | ||
.coverage | ||
.reports | ||
.pytest_cache | ||
.vscode |
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,22 @@ | ||
MIT License | ||
|
||
Copyright (c) 2021 PaddyPowerBetfair | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
|
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 @@ | ||
include README.md | ||
include LICENSE |
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,22 @@ | ||
.PHONY: style | ||
style: | ||
black --target-version=py36 \ | ||
--line-length=120 \ | ||
--skip-string-normalization \ | ||
logbasecommand testapp setup.py | ||
|
||
.PHONY: style_check | ||
style_check: | ||
black --target-version=py36 \ | ||
--line-length=120 \ | ||
--skip-string-normalization \ | ||
--check \ | ||
logbasecommand testapp setup.py | ||
|
||
test: | ||
testapp/manage.py test $${TEST_ARGS:-tests} | ||
|
||
coverage: | ||
PYTHONPATH="testapp" \ | ||
python -b -W always -m coverage run testapp/manage.py test $${TEST_ARGS:-tests} | ||
coverage report |
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,87 @@ | ||
# django-logbasecommand | ||
|
||
Minimal package to add logging helpers to Django management commands | ||
|
||
## Usage | ||
|
||
Replace | ||
|
||
``` | ||
from django.core.management.base import BaseCommand | ||
class YourCommand(BaseCommand): | ||
``` | ||
|
||
with | ||
|
||
``` | ||
from logbasecommand.base import LogBaseCommand | ||
class LogBaseCommand(BaseCommand): | ||
``` | ||
|
||
and now you can use the drop-in methods to replace `self.stdout`/`self.stderr`: | ||
* `log` | ||
* `log_debug` | ||
* `log_warning` | ||
* `log_error` | ||
* `log_exception` | ||
|
||
Or access `self.logger` directly. | ||
|
||
|
||
All command logger names are derived from the command module name and prefixed with `logbasecommand.base` (by default, use `LOGBASECOMMAND_PREFIX` setting to change it), so logging can be configured from your project settings.py, with `LOGGING`, ie (full example, check the `loggers` part): | ||
|
||
```python | ||
LOGGING = { | ||
'version': 1, | ||
'disable_existing_loggers': False, | ||
'filters': { | ||
'require_debug_false': {'()': 'django.utils.log.RequireDebugFalse'}, | ||
'require_debug_true': {'()': 'django.utils.log.RequireDebugTrue'}, | ||
}, | ||
'formatters': { | ||
'verbose': {'format': '[%(asctime)s] [%(process)s] [%(levelname)s] [%(name)s] %(message)s'}, | ||
'minimal': {'format': '[%(levelname)s] [%(name)s] %(message)s'}, | ||
}, | ||
'handlers': { | ||
'console': { | ||
'level': 'INFO', | ||
'filters': ['require_debug_false'], | ||
'class': 'logging.StreamHandler', | ||
'formatter': 'verbose', | ||
}, | ||
'console_debug': { | ||
'level': 'DEBUG', | ||
'filters': ['require_debug_true'], | ||
'class': 'logging.StreamHandler', | ||
'formatter': 'verbose', | ||
}, | ||
'console_minimal': { | ||
'level': 'INFO', | ||
'filters': ['require_debug_false'], | ||
'class': 'logging.StreamHandler', | ||
'formatter': 'minimal', | ||
}, | ||
'console_debug_minimal': { | ||
'level': 'DEBUG', | ||
'filters': ['require_debug_true'], | ||
'class': 'logging.StreamHandler', | ||
'formatter': 'minimal', | ||
}, | ||
'mail_admins': { | ||
'level': 'ERROR', | ||
'filters': ['require_debug_false'], | ||
'class': 'django.utils.log.AdminEmailHandler', | ||
}, | ||
}, | ||
'loggers': { | ||
'': {'handlers': ['console', 'console_debug'], 'level': 'INFO', 'propagate': True}, | ||
'logbasecommand.base': { | ||
'handlers': ['console_minimal', 'console_debug_minimal'], | ||
'level': 'DEBUG', | ||
'propagate': False, | ||
}, | ||
}, | ||
} | ||
``` |
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 @@ | ||
__version__ = '0.0.1' |
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,64 @@ | ||
import logging | ||
|
||
from django.core.management.base import ( | ||
BaseCommand, | ||
CommandError, # noqa - to make it on subclasses to import from only one place | ||
) | ||
from django.conf import settings | ||
|
||
|
||
class LogBaseCommand(BaseCommand): | ||
verbosity = 1 | ||
custom_stdout = False | ||
custom_stderr = False | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
prefix = getattr(settings, 'LOGBASECOMMAND_PREFIX', None) or __name__ | ||
self.logger = logging.getLogger(prefix + '.' + self.__module__.split('.')[-1]) | ||
|
||
def __handle_custom_std(self, ifstd, std, msg, *args): | ||
if ifstd: | ||
std.write(str(msg) if not args else msg % args) | ||
|
||
def __custom_stderr(self, msg, *args): | ||
self.__handle_custom_std(self.custom_stderr, self.stderr, msg, *args) | ||
|
||
def __custom_stdout(self, msg, *args): | ||
self.__handle_custom_std(self.custom_stdout, self.stdout, msg, *args) | ||
|
||
def log_debug(self, msg, *args, **kwargs): | ||
if self.verbosity >= 2: | ||
self.__custom_stdout(msg, *args) | ||
return self.logger.debug(msg, *args, **kwargs) | ||
|
||
def log(self, msg, *args, **kwargs): | ||
self.__custom_stdout(msg, *args) | ||
return self.logger.info(msg, *args, **kwargs) | ||
|
||
def log_warning(self, msg, *args, **kwargs): | ||
self.__custom_stderr(msg, *args) | ||
return self.logger.warning(msg, *args, **kwargs) | ||
|
||
def log_error(self, msg, *args, **kwargs): | ||
self.__custom_stderr(msg, *args) | ||
return self.logger.error(msg, *args, **kwargs) | ||
|
||
def log_exception(self, msg, *args, **kwargs): | ||
self.__custom_stderr(msg, *args) | ||
return self.logger.exception(msg, *args, **kwargs) | ||
|
||
def execute(self, *args, **options): | ||
self.verbosity = options['verbosity'] | ||
self.logger.setLevel( | ||
[logging.ERROR, max(self.logger.getEffectiveLevel(), logging.INFO), logging.DEBUG, logging.DEBUG][ | ||
self.verbosity | ||
] | ||
) | ||
|
||
if options.get('stdout') is not None: | ||
self.custom_stdout = True | ||
if options.get('stderr') is not None: | ||
self.custom_stderr = True | ||
|
||
super().execute(*args, **options) |
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 @@ | ||
[pytest] | ||
DJANGO_SETTINGS_MODULE = testapp.settings | ||
python_files = tests.py test_*.py |
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,41 @@ | ||
[metadata] | ||
name = django-logbasecommand | ||
version = attr: logbasecommand.__version__ | ||
description = Minimal package to add logging helpers to Django management commands | ||
author = PPB - InfoSec Engineering | ||
author_email = [email protected] | ||
url = https://github.com/surface-security/django-logbasecommand/ | ||
long_description = file: README.md | ||
long_description_content_type = text/markdown | ||
license = MIT | ||
classifiers = | ||
Development Status :: 5 - Production/Stable | ||
Framework :: Django | ||
License :: OSI Approved :: MIT License | ||
Intended Audience :: Developers | ||
Operating System :: OS Independent | ||
Programming Language :: Python | ||
Programming Language :: Python :: 3.9 | ||
Environment :: Web Environment | ||
Topic :: Software Development | ||
|
||
[options] | ||
zip_safe = False | ||
include_package_data = True | ||
packages = find: | ||
install_requires = | ||
Django >= 3.0, < 4 | ||
|
||
python_requires = >=3.6 | ||
|
||
[options.packages.find] | ||
exclude = | ||
tests | ||
tests.* | ||
|
||
[coverage:run] | ||
source = logbasecommand | ||
|
||
[coverage:report] | ||
show_missing = True | ||
skip_covered = 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,3 @@ | ||
from setuptools import setup | ||
|
||
setup() |
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,22 @@ | ||
#!/usr/bin/env python | ||
"""Django's command-line utility for administrative tasks.""" | ||
import os | ||
import sys | ||
|
||
|
||
def main(): | ||
"""Run administrative tasks.""" | ||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testapp.settings') | ||
try: | ||
from django.core.management import execute_from_command_line | ||
except ImportError as exc: | ||
raise ImportError( | ||
"Couldn't import Django. Are you sure it's installed and " | ||
"available on your PYTHONPATH environment variable? Did you " | ||
"forget to activate a virtual environment?" | ||
) from exc | ||
execute_from_command_line(sys.argv) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
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,5 @@ | ||
-e .. | ||
pytest==6.2.5 | ||
pytest-cov==2.12.1 | ||
pytest-django==4.4.0 | ||
black==20.8b1 |
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,16 @@ | ||
""" | ||
ASGI config for testapp project. | ||
It exposes the ASGI callable as a module-level variable named ``application``. | ||
For more information on this file, see | ||
https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/ | ||
""" | ||
|
||
import os | ||
|
||
from django.core.asgi import get_asgi_application | ||
|
||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testapp.settings') | ||
|
||
application = get_asgi_application() |
Empty file.
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,12 @@ | ||
from logbasecommand.base import LogBaseCommand | ||
|
||
|
||
class Command(LogBaseCommand): | ||
def handle(self, *args, **options): | ||
self.log('info message') | ||
self.log_debug('debug message') | ||
self.log_error('error message') | ||
try: | ||
1 / 0 | ||
except ZeroDivisionError: | ||
self.log_exception('exception handled') |
Oops, something went wrong.