Skip to content

Commit 8690fe3

Browse files
committed
Fix unicode tests and some pylint errors
1 parent af8791b commit 8690fe3

File tree

5 files changed

+89
-94
lines changed

5 files changed

+89
-94
lines changed

newrelic/api/transaction.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import newrelic.core.error_node
3030
import newrelic.core.root_node
3131
import newrelic.core.transaction_node
32-
import newrelic.packages.six as six
3332
from newrelic.api.application import application_instance
3433
from newrelic.api.time_trace import TimeTrace, get_linking_metadata
3534
from newrelic.common.encoding_utils import (
@@ -71,6 +70,7 @@
7170
TraceCacheNoActiveTraceError,
7271
trace_cache,
7372
)
73+
from newrelic.packages import six
7474

7575
_logger = logging.getLogger(__name__)
7676

@@ -120,7 +120,7 @@ def complete_root(self):
120120
self.exited = True
121121

122122
@staticmethod
123-
def complete_trace():
123+
def complete_trace(): # pylint: disable=arguments-differ
124124
pass
125125

126126
@property
@@ -832,7 +832,7 @@ def trace_intrinsics(self):
832832

833833
# Add in special CPU time value for UI to display CPU burn.
834834

835-
# XXX Disable cpu time value for CPU burn as was
835+
# TODO: Disable cpu time value for CPU burn as was
836836
# previously reporting incorrect value and we need to
837837
# fix it, at least on Linux to report just the CPU time
838838
# for the executing thread.
@@ -1571,7 +1571,7 @@ def _create_error_node(self, settings, fullname, message, expected, custom_param
15711571
source=source,
15721572
)
15731573

1574-
# TODO Errors are recorded in time order. If
1574+
# TODO: Errors are recorded in time order. If
15751575
# there are two exceptions of same type and
15761576
# different message, the UI displays the first
15771577
# one. In the PHP agent it was recording the

newrelic/core/attribute.py

Lines changed: 75 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -13,82 +13,81 @@
1313
# limitations under the License.
1414

1515
import logging
16-
1716
from collections import namedtuple
1817

18+
from newrelic.core.attribute_filter import (
19+
DST_ALL,
20+
DST_ERROR_COLLECTOR,
21+
DST_SPAN_EVENTS,
22+
DST_TRANSACTION_EVENTS,
23+
DST_TRANSACTION_SEGMENTS,
24+
DST_TRANSACTION_TRACER,
25+
)
1926
from newrelic.packages import six
2027

21-
from newrelic.core.attribute_filter import (DST_ALL, DST_ERROR_COLLECTOR,
22-
DST_TRANSACTION_TRACER, DST_TRANSACTION_EVENTS, DST_SPAN_EVENTS,
23-
DST_TRANSACTION_SEGMENTS)
24-
25-
2628
_logger = logging.getLogger(__name__)
2729

28-
_Attribute = namedtuple('_Attribute',
29-
['name', 'value', 'destinations'])
30+
_Attribute = namedtuple("_Attribute", ["name", "value", "destinations"])
3031

3132
# The following destinations are created here, never changed, and only
3233
# used in create_agent_attributes. It is placed at the module level here
3334
# as an optimization.
3435

3536
# All agent attributes go to transaction traces and error traces by default.
3637

37-
_DESTINATIONS = (DST_ERROR_COLLECTOR |
38-
DST_TRANSACTION_TRACER |
39-
DST_TRANSACTION_SEGMENTS)
40-
_DESTINATIONS_WITH_EVENTS = (_DESTINATIONS |
41-
DST_TRANSACTION_EVENTS |
42-
DST_SPAN_EVENTS)
38+
_DESTINATIONS = DST_ERROR_COLLECTOR | DST_TRANSACTION_TRACER | DST_TRANSACTION_SEGMENTS
39+
_DESTINATIONS_WITH_EVENTS = _DESTINATIONS | DST_TRANSACTION_EVENTS | DST_SPAN_EVENTS
4340

4441
# The following subset goes to transaction events by default.
4542

46-
_TRANSACTION_EVENT_DEFAULT_ATTRIBUTES = set((
47-
'host.displayName',
48-
'request.method',
49-
'request.headers.contentType',
50-
'request.headers.contentLength',
51-
'request.uri',
52-
'response.status',
53-
'request.headers.accept',
54-
'response.headers.contentLength',
55-
'response.headers.contentType',
56-
'request.headers.host',
57-
'request.headers.userAgent',
58-
'message.queueName',
59-
'message.routingKey',
60-
'http.url',
61-
'http.statusCode',
62-
'aws.requestId',
63-
'aws.operation',
64-
'aws.lambda.arn',
65-
'aws.lambda.coldStart',
66-
'aws.lambda.eventSource.arn',
43+
_TRANSACTION_EVENT_DEFAULT_ATTRIBUTES = set(
44+
(
45+
"host.displayName",
46+
"request.method",
47+
"request.headers.contentType",
48+
"request.headers.contentLength",
49+
"request.uri",
50+
"response.status",
51+
"request.headers.accept",
52+
"response.headers.contentLength",
53+
"response.headers.contentType",
54+
"request.headers.host",
55+
"request.headers.userAgent",
56+
"message.queueName",
57+
"message.routingKey",
58+
"http.url",
59+
"http.statusCode",
60+
"aws.requestId",
61+
"aws.operation",
62+
"aws.lambda.arn",
63+
"aws.lambda.coldStart",
64+
"aws.lambda.eventSource.arn",
6765
"db.collection",
68-
'db.instance',
69-
'db.operation',
70-
'db.statement',
71-
'error.class',
72-
'error.message',
73-
'error.expected',
74-
'peer.hostname',
75-
'peer.address',
76-
'graphql.field.name',
77-
'graphql.field.parentType',
78-
'graphql.field.path',
79-
'graphql.field.returnType',
80-
'graphql.operation.name',
81-
'graphql.operation.type',
82-
'graphql.operation.query',
66+
"db.instance",
67+
"db.operation",
68+
"db.statement",
69+
"error.class",
70+
"error.message",
71+
"error.expected",
72+
"peer.hostname",
73+
"peer.address",
74+
"graphql.field.name",
75+
"graphql.field.parentType",
76+
"graphql.field.path",
77+
"graphql.field.returnType",
78+
"graphql.operation.name",
79+
"graphql.operation.type",
80+
"graphql.operation.query",
8381
"code.filepath",
8482
"code.function",
8583
"code.lineno",
8684
"code.namespace",
87-
))
85+
)
86+
)
8887

8988
MAX_NUM_USER_ATTRIBUTES = 128
9089
MAX_ATTRIBUTE_LENGTH = 255
91-
MAX_64_BIT_INT = 2 ** 63 - 1
90+
MAX_64_BIT_INT = 2**63 - 1
9291
MAX_LOG_MESSAGE_LENGTH = 32768
9392

9493

@@ -109,10 +108,8 @@ class CastingFailureException(Exception):
109108

110109

111110
class Attribute(_Attribute):
112-
113111
def __repr__(self):
114-
return "Attribute(name=%r, value=%r, destinations=%r)" % (
115-
self.name, self.value, bin(self.destinations))
112+
return "Attribute(name=%r, value=%r, destinations=%r)" % (self.name, self.value, bin(self.destinations))
116113

117114

118115
def create_attributes(attr_dict, destinations, attribute_filter):
@@ -142,8 +139,7 @@ def create_agent_attributes(attr_dict, attribute_filter):
142139
return attributes
143140

144141

145-
def resolve_user_attributes(
146-
attr_dict, attribute_filter, target_destination, attr_class=dict):
142+
def resolve_user_attributes(attr_dict, attribute_filter, target_destination, attr_class=dict):
147143
u_attrs = attr_class()
148144

149145
for attr_name, attr_value in attr_dict.items():
@@ -158,8 +154,7 @@ def resolve_user_attributes(
158154
return u_attrs
159155

160156

161-
def resolve_agent_attributes(
162-
attr_dict, attribute_filter, target_destination, attr_class=dict):
157+
def resolve_agent_attributes(attr_dict, attribute_filter, target_destination, attr_class=dict):
163158
a_attrs = attr_class()
164159

165160
for attr_name, attr_value in attr_dict.items():
@@ -182,10 +177,9 @@ def create_user_attributes(attr_dict, attribute_filter):
182177
return create_attributes(attr_dict, destinations, attribute_filter)
183178

184179

185-
def truncate(
186-
text, maxsize=MAX_ATTRIBUTE_LENGTH, encoding='utf-8', ending=None):
180+
def truncate(text, maxsize=MAX_ATTRIBUTE_LENGTH, encoding="utf-8", ending=None):
187181

188-
# Truncate text so that it's byte representation
182+
# Truncate text so that its byte representation
189183
# is no longer than maxsize bytes.
190184

191185
# If text is unicode (Python 2 or 3), return unicode.
@@ -198,21 +192,21 @@ def truncate(
198192
ending = ending and ending.encode(encoding)
199193

200194
if ending and truncated != text:
201-
truncated = truncated[:-len(ending)] + ending
195+
truncated = truncated[: -len(ending)] + ending
202196

203197
return truncated
204198

205199

206-
def _truncate_unicode(u, maxsize, encoding='utf-8'):
200+
def _truncate_unicode(u, maxsize, encoding="utf-8"):
207201
encoded = u.encode(encoding)[:maxsize]
208-
return encoded.decode(encoding, 'ignore')
202+
return encoded.decode(encoding, "ignore")
209203

210204

211205
def _truncate_bytes(s, maxsize):
212206
return s[:maxsize]
213207

214208

215-
def check_name_length(name, max_length=MAX_ATTRIBUTE_LENGTH, encoding='utf-8'):
209+
def check_name_length(name, max_length=MAX_ATTRIBUTE_LENGTH, encoding="utf-8"):
216210
trunc_name = truncate(name, max_length, encoding)
217211
if name != trunc_name:
218212
raise NameTooLongException()
@@ -228,8 +222,7 @@ def check_max_int(value, max_int=MAX_64_BIT_INT):
228222
raise IntTooLargeException()
229223

230224

231-
def process_user_attribute(
232-
name, value, max_length=MAX_ATTRIBUTE_LENGTH, ending=None):
225+
def process_user_attribute(name, value, max_length=MAX_ATTRIBUTE_LENGTH, ending=None):
233226

234227
# Perform all necessary checks on a potential attribute.
235228
#
@@ -250,23 +243,19 @@ def process_user_attribute(
250243
value = sanitize(value)
251244

252245
except NameIsNotStringException:
253-
_logger.debug('Attribute name must be a string. Dropping '
254-
'attribute: %r=%r', name, value)
246+
_logger.debug("Attribute name must be a string. Dropping " "attribute: %r=%r", name, value)
255247
return FAILED_RESULT
256248

257249
except NameTooLongException:
258-
_logger.debug('Attribute name exceeds maximum length. Dropping '
259-
'attribute: %r=%r', name, value)
250+
_logger.debug("Attribute name exceeds maximum length. Dropping " "attribute: %r=%r", name, value)
260251
return FAILED_RESULT
261252

262253
except IntTooLargeException:
263-
_logger.debug('Attribute value exceeds maximum integer value. '
264-
'Dropping attribute: %r=%r', name, value)
254+
_logger.debug("Attribute value exceeds maximum integer value. " "Dropping attribute: %r=%r", name, value)
265255
return FAILED_RESULT
266256

267257
except CastingFailureException:
268-
_logger.debug('Attribute value cannot be cast to a string. '
269-
'Dropping attribute: %r=%r', name, value)
258+
_logger.debug("Attribute value cannot be cast to a string. " "Dropping attribute: %r=%r", name, value)
270259
return FAILED_RESULT
271260

272261
else:
@@ -278,9 +267,12 @@ def process_user_attribute(
278267
if isinstance(value, valid_types_text):
279268
trunc_value = truncate(value, maxsize=max_length, ending=ending)
280269
if value != trunc_value:
281-
_logger.debug('Attribute value exceeds maximum length '
282-
'(%r bytes). Truncating value: %r=%r.',
283-
max_length, name, trunc_value)
270+
_logger.debug(
271+
"Attribute value exceeds maximum length " "(%r bytes). Truncating value: %r=%r.",
272+
max_length,
273+
name,
274+
trunc_value,
275+
)
284276

285277
value = trunc_value
286278

@@ -294,8 +286,7 @@ def sanitize(value):
294286
#
295287
# Raise CastingFailureException, if str(value) somehow fails.
296288

297-
valid_value_types = (six.text_type, six.binary_type, bool, float,
298-
six.integer_types)
289+
valid_value_types = (six.text_type, six.binary_type, bool, float, six.integer_types)
299290

300291
if not isinstance(value, valid_value_types):
301292
original = value
@@ -305,7 +296,8 @@ def sanitize(value):
305296
except Exception:
306297
raise CastingFailureException()
307298
else:
308-
_logger.debug('Attribute value is of type: %r. Casting %r to '
309-
'string: %s', type(original), original, value)
299+
_logger.debug(
300+
"Attribute value is of type: %r. Casting %r to " "string: %s", type(original), original, value
301+
)
310302

311303
return value

tests/agent_features/test_asgi_browser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ def test_footer_attributes():
109109

110110
obfuscation_key = settings.license_key[:13]
111111

112-
assert isinstance(data["transactionName"], str)
113-
# assert type(data["transactionName"]) == type("")
112+
type_transaction_data = unicode if six.PY2 else str # noqa: F821
113+
assert isinstance(data["transactionName"], type_transaction_data)
114114

115115
txn_name = deobfuscate(data["transactionName"], obfuscation_key)
116116

tests/agent_features/test_attribute.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ def test_truncate_bytes():
203203

204204
def test_truncate_unicode_snowman():
205205
# '\u2603' is 'SNOWMAN'
206-
u = "snow\u2603"
206+
# decode("unicode-escape") is used to get Py2 unicode
207+
u = "snow\u2603".decode("unicode-escape") if six.PY2 else "snow\u2603"
207208
assert u.encode("utf-8") == b"snow\xe2\x98\x83"
208209
result = truncate(u, maxsize=5)
209210
assert isinstance(result, six.text_type)
@@ -212,7 +213,8 @@ def test_truncate_unicode_snowman():
212213

213214
def test_truncate_combining_characters():
214215
# '\u0308' is 'COMBINING DIAERESIS' (AKA 'umlaut')
215-
u = "Zoe\u0308"
216+
# decode("unicode-escape") is used to get Py2 unicode
217+
u = "Zoe\u0308".decode("unicode-escape") if six.PY2 else "Zoe\u0308"
216218
assert u.encode("utf-8") == b"Zoe\xcc\x88"
217219

218220
# truncate will chop off 'COMBINING DIAERESIS', which leaves
@@ -238,7 +240,8 @@ def test_truncate_empty_bytes():
238240

239241

240242
def test_truncate_empty_unicode():
241-
u = ""
243+
# decode("unicode-escape") is used to get Py2 unicode
244+
u = "".decode("unicode-escape") if six.PY2 else ""
242245
result = truncate(u, maxsize=5)
243246
assert isinstance(result, six.text_type)
244247
assert result == ""

tests/agent_features/test_browser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ def test_footer_attributes():
106106

107107
obfuscation_key = settings.license_key[:13]
108108

109-
assert isinstance(data["transactionName"], str)
110-
# assert type(data["transactionName"]) == type("")
109+
type_transaction_data = unicode if six.PY2 else str # noqa: F821
110+
assert isinstance(data["transactionName"], type_transaction_data)
111111

112112
txn_name = deobfuscate(data["transactionName"], obfuscation_key)
113113

0 commit comments

Comments
 (0)