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

Removed support for Python 2 for upcoming v1.0.0 #435

Merged
merged 5 commits into from
Aug 23, 2023
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
40 changes: 7 additions & 33 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: [3.5, 3.6, 3.7, 3.8, 3.9, '3.10', 3.11]
python-version: [3.6, 3.7, 3.8, 3.9, '3.10', 3.11]
framework:
- FLASK_VERSION=0.12.5 Werkzeug\>=0.7,\<1.0
- FLASK_VERSION=1.1.4
- FLASK_VERSION=2.2.3
- DJANGO_VERSION=1.11.29
Expand All @@ -34,8 +33,6 @@ jobs:
exclude:
# Test frameworks on the python versions they support, according to pypi registry
# Flask
- framework: FLASK_VERSION=2.2.3
python-version: 3.5
- framework: FLASK_VERSION=2.2.3
python-version: 3.6

Expand All @@ -48,10 +45,6 @@ jobs:
python-version: '3.10'
- framework: DJANGO_VERSION=1.11.29
python-version: 3.11
- framework: DJANGO_VERSION=3.2.18
python-version: 3.5
- framework: DJANGO_VERSION=4.0.10
python-version: 3.5
- framework: DJANGO_VERSION=4.0.10
python-version: 3.6
- framework: DJANGO_VERSION=4.0.10
Expand All @@ -66,28 +59,9 @@ jobs:
# Twisted
- framework: TWISTED_VERSION=20.3.0
python-version: 3.11
- framework: TWISTED_VERSION=21.7.0
python-version: 3.5
- framework: TWISTED_VERSION=22.10.0
python-version: 3.5
- framework: TWISTED_VERSION=22.10.0
python-version: 3.6


# Starlette
- framework: STARLETTE_VERSION=0.12.13 httpx==0.18.1 python-multipart==0.0.5
python-version: 3.5
- framework: STARLETTE_VERSION=0.14.2 httpx==0.18.1 python-multipart==0.0.5
python-version: 3.5

# Fastapi
- framework: FASTAPI_VERSION=0.40.0 httpx==0.18.1 python-multipart==0.0.5
python-version: 3.5
- framework: FASTAPI_VERSION=0.50.0 httpx==0.18.1 python-multipart==0.0.5
python-version: 3.5
- framework: FASTAPI_VERSION=0.63.0 httpx==0.18.1 python-multipart==0.0.5
python-version: 3.5

steps:
- uses: actions/checkout@v2
with:
Expand All @@ -98,15 +72,15 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install Python 3.5 dependencies
if: ${{ contains(matrix.python-version, '3.5') }}
# typing-extensions dropped support for Python 3.5 in version 4
run: pip install six==1.16.0 "typing-extensions<4" requests==2.24.0 blinker==1.5 WebOb==1.8.7

- 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 six==1.16.0 "typing-extensions<4.2" requests==2.27.0 blinker==1.5
run: pip install "typing-extensions<4.2" requests==2.27.0 blinker==1.5 immutables==0.19

- 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
run: echo ${{ matrix.framework }} >> $GITHUB_ENV
Expand Down
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,29 @@ 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

# Setup Instructions
| PyRollbar Version | Python Version Compatibility | Support Level |
|-------------------|-----------------------------------------------|---------------------|
| 0.17.0 | 3.6, 3.7. 3.8, 3.9, 3.10, 3.11 | Full |
| 0.16.3 | 2.7, 3.4, 3.5, 3.6, 3.7. 3.8, 3.9, 3.10, 3.11 | Security Fixes Only |

#### Support Level Definitions

**Full** - We will support new features of the library and test against all supported versions.

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

## Setup Instructions

1. [Sign up for a Rollbar account](https://rollbar.com/signup)
2. Follow the [Quick Start](https://docs.rollbar.com/docs/python#section-quick-start) instructions in our [Python SDK docs](https://docs.rollbar.com/docs/python) to install pyrollbar and configure it for your platform.

# Usage and Reference
## Usage and Reference

For complete usage instructions and configuration reference, see our [Python SDK docs](https://docs.rollbar.com/docs/python).

# Release History & Changelog
## Release History & Changelog

See our [Releases](https://github.com/rollbar/pyrollbar/releases) page for a list of all releases, including changes.

Expand Down
53 changes: 15 additions & 38 deletions rollbar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,18 @@
import uuid
import wsgiref.util
import warnings
import queue
from urllib.parse import parse_qs, urljoin

import requests
import six

from rollbar.lib import events, filters, dict_merge, parse_qs, text, transport, urljoin, iteritems, defaultJSONEncode
from rollbar.lib import events, filters, dict_merge, transport, defaultJSONEncode


__version__ = '0.16.4beta2'
__version__ = '1.0.0b0'
__log_name__ = 'rollbar'
log = logging.getLogger(__log_name__)

try:
# 2.x
import Queue as queue
except ImportError:
# 3.x
import queue

# import request objects from various frameworks, if available
try:
Expand Down Expand Up @@ -86,7 +81,7 @@

try:
from google.appengine.api.urlfetch import fetch as AppEngineFetch
except ImportError:
except (ImportError, KeyError):
AppEngineFetch = None

try:
Expand Down Expand Up @@ -691,7 +686,7 @@ def prev_page(self):

def _resolve_exception_class(idx, filter):
cls, level = filter
if isinstance(cls, six.string_types):
if isinstance(cls, str):
# Lazily resolve class name
parts = cls.split('.')
module = '.'.join(parts[:-1])
Expand Down Expand Up @@ -830,7 +825,7 @@ def _trace_data(cls, exc, trace):
'frames': frames,
'exception': {
'class': getattr(cls, '__name__', cls.__class__.__name__),
'message': text(exc),
'message': str(exc),
}
}

Expand Down Expand Up @@ -960,7 +955,7 @@ def _build_base_data(request, level='error'):
'level': level,
'language': 'python %s' % '.'.join(str(x) for x in sys.version_info[:3]),
'notifier': SETTINGS['notifier'],
'uuid': text(uuid.uuid4()),
'uuid': str(uuid.uuid4()),
}

if SETTINGS.get('code_version'):
Expand Down Expand Up @@ -1015,9 +1010,9 @@ def hasuser(request): return True
else:
retval = {}
if getattr(user, 'id', None):
retval['id'] = text(user.id)
retval['id'] = str(user.id)
elif getattr(user, 'user_id', None):
retval['id'] = text(user.user_id)
retval['id'] = str(user.user_id)

# id is required, so only include username/email if we have an id
if retval.get('id'):
Expand All @@ -1034,7 +1029,7 @@ def hasuser(request): return True
user_id = user_id_prop() if callable(user_id_prop) else user_id_prop
if not user_id:
return None
return {'id': text(user_id)}
return {'id': str(user_id)}


def _get_func_from_frame(frame):
Expand All @@ -1049,16 +1044,6 @@ def _get_func_from_frame(frame):
return func


def _flatten_nested_lists(l):
ret = []
for x in l:
if isinstance(x, list):
ret.extend(_flatten_nested_lists(x))
else:
ret.append(x)
return ret


def _add_locals_data(trace_data, exc_info):
if not SETTINGS['locals']['enabled']:
return
Expand Down Expand Up @@ -1093,15 +1078,7 @@ def _add_locals_data(trace_data, exc_info):
# Optionally fill in locals for this frame
if arginfo.locals and _check_add_locals(cur_frame, frame_num, num_frames):
# Get all of the named args
#
# args can be a nested list of args in the case where there
# are anonymous tuple args provided.
# e.g. in Python 2 you can:
# def func((x, (a, b), z)):
# return x + a + b + z
#
# func((1, (1, 2), 3))
argspec = _flatten_nested_lists(arginfo.args)
argspec = arginfo.args

if arginfo.varargs is not None:
varargspec = arginfo.varargs
Expand Down Expand Up @@ -1131,7 +1108,7 @@ def _add_locals_data(trace_data, exc_info):
cur_frame['keywordspec'] = keywordspec
if _locals:
try:
cur_frame['locals'] = dict((k, _serialize_frame_data(v)) for k, v in iteritems(_locals))
cur_frame['locals'] = {k: _serialize_frame_data(v) for k, v in _locals.items()}
except Exception:
log.exception('Error while serializing frame data.')

Expand Down Expand Up @@ -1419,7 +1396,7 @@ def _build_wsgi_request_data(request):
if 'QUERY_STRING' in request:
request_data['GET'] = parse_qs(request['QUERY_STRING'], keep_blank_values=True)
# Collapse single item arrays
request_data['GET'] = dict((k, v[0] if len(v) == 1 else v) for k, v in request_data['GET'].items())
request_data['GET'] = {k: (v[0] if len(v) == 1 else v) for k, v in request_data['GET'].items()}

request_data['headers'] = _extract_wsgi_headers(request.items())

Expand Down Expand Up @@ -1548,7 +1525,7 @@ def _build_payload(data):
Returns the full payload as a string.
"""

for k, v in iteritems(data):
for k, v in data.items():
data[k] = _transform(v, key=(k,))

payload = {
Expand Down
5 changes: 3 additions & 2 deletions rollbar/contrib/django/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ def get_payload_data(self, request, exc):
from django.core.exceptions import MiddlewareNotUsed
from django.conf import settings
from django.http import Http404
from six import reraise

try:
from django.urls import resolve
Expand Down Expand Up @@ -311,7 +310,9 @@ def process_response(self, request, response):
try:
if hasattr(request, '_rollbar_notifier_original_http404_exc_info'):
exc_type, exc_value, exc_traceback = request._rollbar_notifier_original_http404_exc_info
reraise(exc_type, exc_value, exc_traceback)
if exc_value is None:
exc_value = Http404()
raise exc_value.with_traceback(exc_traceback)
else:
raise Http404()
except Exception as exc:
Expand Down
2 changes: 1 addition & 1 deletion rollbar/contrib/pyramid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def hook(request, data):
environment = kw.pop('environment', 'production')

if kw.get('scrub_fields'):
kw['scrub_fields'] = set([str.strip(x) for x in kw.get('scrub_fields').split('\n') if x])
kw['scrub_fields'] = {str.strip(x) for x in kw.get('scrub_fields').split('\n') if x}

if kw.get('exception_level_filters'):
r = DottedNameResolver()
Expand Down
Loading
Loading