Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated supported and tested frameworks and modernized tests and packaging. #455

Merged
merged 12 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 59 additions & 28 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,54 +14,76 @@ jobs:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9, '3.10', 3.11]
framework:
- NONE
- FLASK_VERSION=1.1.4
- FLASK_VERSION=2.2.3
- DJANGO_VERSION=1.11.29
- DJANGO_VERSION=2.2.28
- DJANGO_VERSION=3.2.18
- DJANGO_VERSION=4.0.10
- DJANGO_VERSION=4.1.7
- FLASK_VERSION=2.3.3
- FLASK_VERSION=3.0.3
- DJANGO_VERSION=3.2.25
- DJANGO_VERSION=4.2.15
- DJANGO_VERSION=5.0.8
- TWISTED_VERSION=20.3.0
- TWISTED_VERSION=21.7.0
- TWISTED_VERSION=22.10.0
- PYRAMID_VERSION=1.10.8
- STARLETTE_VERSION=0.12.13 httpx==0.18.1 python-multipart==0.0.5
- STARLETTE_VERSION=0.14.2 httpx==0.18.1 python-multipart==0.0.5
- FASTAPI_VERSION=0.40.0 httpx==0.18.1 python-multipart==0.0.5
- FASTAPI_VERSION=0.50.0 httpx==0.18.1 python-multipart==0.0.5
- FASTAPI_VERSION=0.63.0 httpx==0.18.1 python-multipart==0.0.5
- PYRAMID_VERSION=2.0.2
- STARLETTE_VERSION=0.30.0 httpx==0.24.1 python-multipart==0.0.9
- STARLETTE_VERSION=0.38.2 httpx==0.27.0 python-multipart==0.0.9
- FASTAPI_VERSION=0.101.1 httpx==0.24.1 python-multipart==0.0.9
- FASTAPI_VERSION=0.112.1 httpx==0.27.0 python-multipart==0.0.9
exclude:
# Test frameworks on the python versions they support, according to pypi registry
# Flask
- framework: FLASK_VERSION=2.2.3
- framework: FLASK_VERSION=2.3.3
python-version: 3.6
- framework: FLASK_VERSION=2.3.3
python-version: 3.7
- framework: FLASK_VERSION=3.0.3
python-version: 3.6
- framework: FLASK_VERSION=3.0.3
python-version: 3.7

# Django
- framework: DJANGO_VERSION=1.11.29
python-version: 3.8
- framework: DJANGO_VERSION=1.11.29
python-version: 3.9
- framework: DJANGO_VERSION=1.11.29
python-version: '3.10'
- framework: DJANGO_VERSION=1.11.29
- framework: DJANGO_VERSION=3.2.25
python-version: 3.11
- framework: DJANGO_VERSION=4.0.10
- framework: DJANGO_VERSION=4.2.15
python-version: 3.6
- framework: DJANGO_VERSION=4.0.10
- framework: DJANGO_VERSION=4.2.15
python-version: 3.7
- framework: DJANGO_VERSION=4.1.7
python-version: 3.5
- framework: DJANGO_VERSION=4.1.7
- framework: DJANGO_VERSION=5.0.8
python-version: 3.6
- framework: DJANGO_VERSION=4.1.7
- framework: DJANGO_VERSION=5.0.8
python-version: 3.7
- framework: DJANGO_VERSION=5.0.8
python-version: 3.8
- framework: DJANGO_VERSION=5.0.8
python-version: 3.9

# Twisted
- framework: TWISTED_VERSION=20.3.0
python-version: 3.11
- framework: TWISTED_VERSION=22.10.0
python-version: 3.6

# Starlette
- framework: STARLETTE_VERSION=0.30.0 httpx==0.24.1 python-multipart==0.0.9
python-version: 3.6
- framework: STARLETTE_VERSION=0.30.0 httpx==0.24.1 python-multipart==0.0.9
python-version: 3.7
- framework: STARLETTE_VERSION=0.38.2 httpx==0.27.0 python-multipart==0.0.9
python-version: 3.6
- framework: STARLETTE_VERSION=0.38.2 httpx==0.27.0 python-multipart==0.0.9
python-version: 3.7

# FastAPI
- framework: FASTAPI_VERSION=0.101.1 httpx==0.24.1 python-multipart==0.0.9
python-version: 3.6
- framework: FASTAPI_VERSION=0.101.1 httpx==0.24.1 python-multipart==0.0.9
python-version: 3.7
- framework: FASTAPI_VERSION=0.112.1 httpx==0.27.0 python-multipart==0.0.9
python-version: 3.6
- framework: FASTAPI_VERSION=0.112.1 httpx==0.27.0 python-multipart==0.0.9
python-version: 3.7

steps:
- uses: actions/checkout@v2
with:
Expand All @@ -75,14 +97,15 @@ jobs:
- name: Install Python 3.6 dependencies
if: ${{ contains(matrix.python-version, '3.6') }}
# typing-extensions dropped support for Python 3.6 in version 4.2
run: pip install "typing-extensions<4.2" requests==2.27.0 blinker==1.5 immutables==0.19
run: pip install "typing-extensions<4.2" requests==2.27.0 blinker==1.5 immutables==0.19 webob blinker httpx aiocontextvars

- name: Install Python 3.7 dependencies
if: ${{ contains(matrix.python-version, '3.7') }}
# immutables dropped support for Python<3.8 in version 0.20
run: pip install immutables==0.19

- name: Set the framework
if: ${{ matrix.framework != 'NONE' }}
run: echo ${{ matrix.framework }} >> $GITHUB_ENV

- name: Install Flask
Expand All @@ -109,5 +132,13 @@ jobs:
if: ${{ contains(matrix.framework, 'FASTAPI_VERSION') }}
run: pip install fastapi==$FASTAPI_VERSION

- name: Run tests
run: python setup.py test
- name: Install Tox
run: pip install tox

- name: Run tests (skip on Python 3.6)
if: ${{ !contains(matrix.python-version, '3.6') }}
run: tox

- name: Run tests (Python 3.6)
if: ${{ contains(matrix.python-version, '3.6') }}
run: python -m unittest rollbar.test.discover
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ Pipfile
Pipfile.lock
.pytest_cache/
.python-version
.tox/
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Python notifier for reporting exceptions, errors, and log messages to [Rollbar](
- **Advanced search:** Filter items by many different properties. <a href="https://docs.rollbar.com/docs/search-items">Learn more about search</a>.
- **Customizable notifications:** Rollbar supports several messaging and incident management tools where your team can get notified about errors and important events by real-time alerts. <a href="https://docs.rollbar.com/docs/notifications">Learn more about Rollbar notifications</a>.

## Versions Supported
## Python Versions Supported

| PyRollbar Version | Python Version Compatibility | Support Level |
|-------------------|-----------------------------------------------|---------------------|
Expand All @@ -33,6 +33,26 @@ Python notifier for reporting exceptions, errors, and log messages to [Rollbar](

**Security Fixes Only** - We will only provide critical security fixes for the library.

## Frameworks Supported

Generally, PyRollbar can be used with any Python framework. However, we have official support for the following frameworks:

| Framework | Support Duration | Tested Versions |
|-----------|----------------------------|-----------------|
| Celery | Release +1 year | None |
| Django | Release or LTS end +1 year | 3.2, 4.2, 5.0 |
| FastAPI | Release +1 year | 0.101, 0.112 |
| Flask | Release +1 year | 1.1, 2.3, 3.0 |
| Pyramid | Release +1 year | 1.10, 2.0 |

Official support means that we ship and maintain integrations for these frameworks. It also means that we test against these frameworks as part of our CI pipeline.

Generally, we will support the last year of releases for a framework. If a framework has a defined support period (including LTS releases), we will support the release for the duration of that period plus one year.

### Community Supported

There are also a number of community-supported integrations available. For more information, see the [Python SDK docs](https://docs.rollbar.com/docs/python-community-supported-sdks).

## Setup Instructions

1. [Sign up for a Rollbar account](https://rollbar.com/signup)
Expand Down
54 changes: 54 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
[project]
name = "rollbar"
dynamic = ["version"]
description = "Easy and powerful exception tracking with Rollbar. Send messages and exceptions with arbitrary context, get back aggregates, and debug production issues quickly."
readme = "README.md"
license = {file = "LICENSE"}
maintainers = [{name = "Rollbar, Inc.", email = "[email protected]"}]
classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3 :: Only",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Framework :: AsyncIO",
"Framework :: Bottle",
"Framework :: Django",
"Framework :: Flask",
"Framework :: Pylons",
"Framework :: Pyramid",
"Framework :: Twisted",
"Intended Audience :: Developers",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Software Development",
"Topic :: Software Development :: Bug Tracking",
"Topic :: Software Development :: Testing",
"Topic :: Software Development :: Quality Assurance",
"Topic :: System :: Logging",
"Topic :: System :: Monitoring",
]
requires-python = ">=3.6"
dependencies = [
"requests>=0.12.1",
]

[project.urls]
Homepage = "https://rollbar.com/"
Documentation = "https://docs.rollbar.com/docs/python"
Changes = "https://github.com/rollbar/pyrollbar/blob/master/CHANGELOG.md"
Source = "https://github.com/rollbar/pyrollbar/"

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[tool.setuptools.dynamic]
version = {attr = "rollbar.__version__"}
6 changes: 5 additions & 1 deletion rollbar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1372,7 +1372,7 @@ def _build_starlette_request_data(request):
'params': dict(request.path_params),
}

if hasattr(request, '_form'):
if hasattr(request, '_form') and request._form is not None:
request_data['POST'] = {
k: v.filename if isinstance(v, UploadFile) else v
for k, v in request._form.items()
Expand Down Expand Up @@ -1772,4 +1772,8 @@ def _wsgi_extract_user_ip(environ):


def _starlette_extract_user_ip(request):
if not hasattr(request, 'client'):
return _extract_user_ip_from_headers(request)
if not hasattr(request.client, 'host'):
return _extract_user_ip_from_headers(request)
return request.client.host or _extract_user_ip_from_headers(request)
2 changes: 2 additions & 0 deletions rollbar/lib/transforms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ def transform(obj, transforms, key=None, batch_transforms=False):
transforms = [BatchedTransform(transforms)]

for transform in transforms:
if not isinstance(transform, Transform):
continue
obj = _transform(obj, transform, key=key)

return obj
Expand Down
5 changes: 3 additions & 2 deletions rollbar/test/fastapi_tests/test_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def test_should_add_framework_version_to_payload(self, mock_send_payload, *mocks

app = FastAPI()
app.add_middleware(LoggerMiddleware)
app.build_middleware_stack()

rollbar.report_exc_info()

Expand Down Expand Up @@ -70,10 +71,10 @@ def test_should_store_current_request(self, store_current_request):
'client': ['testclient', 50000],
'headers': [
(b'host', b'testserver'),
(b'user-agent', b'testclient'),
(b'accept-encoding', b'gzip, deflate'),
(b'accept', b'*/*'),
(b'accept-encoding', b'gzip, deflate'),
(b'connection', b'keep-alive'),
(b'user-agent', b'testclient'),
],
'http_version': '1.1',
'method': 'GET',
Expand Down
8 changes: 5 additions & 3 deletions rollbar/test/fastapi_tests/test_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import rollbar
from rollbar.lib._async import AsyncMock
from rollbar.test import BaseTest
from rollbar.test.utils import get_public_attrs

ALLOWED_PYTHON_VERSION = sys.version_info >= (3, 6)

Expand Down Expand Up @@ -152,6 +153,7 @@ def test_should_add_framework_version_to_payload(self, mock_send_payload, *mocks

app = FastAPI()
app.add_middleware(ReporterMiddleware)
app.build_middleware_stack()

rollbar.report_exc_info()

Expand Down Expand Up @@ -272,10 +274,10 @@ def test_should_store_current_request(self, store_current_request):
'client': ['testclient', 50000],
'headers': [
(b'host', b'testserver'),
(b'user-agent', b'testclient'),
(b'accept-encoding', b'gzip, deflate'),
(b'accept', b'*/*'),
(b'accept-encoding', b'gzip, deflate'),
(b'connection', b'keep-alive'),
(b'user-agent', b'testclient'),
],
'http_version': '1.1',
'method': 'GET',
Expand Down Expand Up @@ -324,7 +326,7 @@ def test_should_return_current_request(self):
async def read_root(original_request: Request):
request = get_current_request()

self.assertEqual(request, original_request)
self.assertEqual(get_public_attrs(request), get_public_attrs(original_request))

client = TestClient(app)
client.get('/')
Expand Down
5 changes: 3 additions & 2 deletions rollbar/test/starlette_tests/test_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def test_should_add_framework_version_to_payload(self, mock_send_payload, *mocks

app = Starlette()
app.add_middleware(LoggerMiddleware)
app.build_middleware_stack()

rollbar.report_exc_info()

Expand Down Expand Up @@ -67,10 +68,10 @@ def test_should_store_current_request(self, store_current_request):
'client': ['testclient', 50000],
'headers': [
(b'host', b'testserver'),
(b'user-agent', b'testclient'),
(b'accept-encoding', b'gzip, deflate'),
(b'accept', b'*/*'),
(b'accept-encoding', b'gzip, deflate'),
(b'connection', b'keep-alive'),
(b'user-agent', b'testclient'),
],
'http_version': '1.1',
'method': 'GET',
Expand Down
8 changes: 5 additions & 3 deletions rollbar/test/starlette_tests/test_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import rollbar
from rollbar.lib._async import AsyncMock
from rollbar.test import BaseTest
from rollbar.test.utils import get_public_attrs

ALLOWED_PYTHON_VERSION = sys.version_info >= (3, 6)

Expand Down Expand Up @@ -138,6 +139,7 @@ def test_should_add_framework_version_to_payload(self, mock_send_payload, *mocks

app = Starlette()
app.add_middleware(ReporterMiddleware)
app.build_middleware_stack()

rollbar.report_exc_info()

Expand Down Expand Up @@ -243,10 +245,10 @@ def test_should_store_current_request(self, store_current_request):
'client': ['testclient', 50000],
'headers': [
(b'host', b'testserver'),
(b'user-agent', b'testclient'),
(b'accept-encoding', b'gzip, deflate'),
(b'accept', b'*/*'),
(b'accept-encoding', b'gzip, deflate'),
(b'connection', b'keep-alive'),
(b'user-agent', b'testclient'),
],
'http_version': '1.1',
'method': 'GET',
Expand Down Expand Up @@ -290,7 +292,7 @@ def test_should_return_current_request(self):
async def root(original_request):
request = get_current_request()

self.assertEqual(request, original_request)
self.assertEqual(get_public_attrs(request), get_public_attrs(original_request))

return PlainTextResponse('OK')

Expand Down
Loading
Loading