From 71eb922c33d40a760903d95dfe009397d8ad7c21 Mon Sep 17 00:00:00 2001 From: masklinn Date: Thu, 5 May 2022 15:37:18 +0200 Subject: [PATCH] Deprecate js override bits They were a feature for testing whose need was removed in 2015 (ua-parser/uap-core#58). They are *entirely* unnecessary, it is possible a user somewhere is leveraging them for some reason. So remove the override bits from the docstrings, and have them trigger a `DeprecationWarning`. Also: - add tests that they do trigger - remove support for them from the yaml testing functions - update the pytest invocations to raise on all warnings - while at it remove the apparently dead makePGTSComparisonYAML test utility method (?) - and add pypy to the envlist Note: `simplefilter` has to be updated to `"always"` for 2.7's dumb ass: the new tests triggers the same warning multiple times and of course `"default"` only yields them once. final --- .github/workflows/ci.yml | 2 +- tox.ini | 4 +- ua_parser/user_agent_parser.py | 22 ++++++++-- ua_parser/user_agent_parser_test.py | 65 ++++++++--------------------- 4 files changed, 39 insertions(+), 54 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd2b51b..5cdbe87 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,7 @@ jobs: - name: install package in environment run: python setup.py develop - name: run tests - run: pytest -v + run: pytest -v -Werror - name: run doctests # pprint formatting was changed a lot in 3.5 if: ${{ matrix.python-version != '2.7' }} diff --git a/tox.ini b/tox.ini index 596de5c..3267bb9 100644 --- a/tox.ini +++ b/tox.ini @@ -1,12 +1,12 @@ [tox] -envlist = py27, py36, py37, py38, py39, py310, docs, flake8, black +envlist = py27, py36, py37, py38, py39, py310, pypy3.8, docs, flake8, black skipsdist = True [testenv] usedevelop = True deps = -rrequirements_dev.txt commands = - pytest {posargs} + pytest -Werror {posargs} python -mdoctest README.rst [testenv:py27] diff --git a/ua_parser/user_agent_parser.py b/ua_parser/user_agent_parser.py index 8f55b82..2c3d1bc 100644 --- a/ua_parser/user_agent_parser.py +++ b/ua_parser/user_agent_parser.py @@ -244,7 +244,6 @@ def Parse(user_agent_string, **jsParseBits): """Parse all the things Args: user_agent_string: the full user agent string - jsParseBits: javascript override bits Returns: A dictionary containing all parsed bits """ @@ -268,7 +267,6 @@ def ParseUserAgent(user_agent_string, **jsParseBits): """Parses the user-agent string for user agent (browser) info. Args: user_agent_string: The full user-agent string. - jsParseBits: javascript override bits. Returns: A dictionary containing parsed bits. """ @@ -276,6 +274,12 @@ def ParseUserAgent(user_agent_string, **jsParseBits): def _ParseUserAgent(user_agent_string, jsParseBits): + if jsParseBits: + warnings.warn( + "javascript overrides are deprecated and will be removed next release", + category=DeprecationWarning, + stacklevel=2, + ) if ( "js_user_agent_family" in jsParseBits and jsParseBits["js_user_agent_family"] != "" @@ -318,7 +322,6 @@ def ParseOS(user_agent_string, **jsParseBits): """Parses the user-agent string for operating system info Args: user_agent_string: The full user-agent string. - jsParseBits: javascript override bits. Returns: A dictionary containing parsed bits. """ @@ -326,6 +329,12 @@ def ParseOS(user_agent_string, **jsParseBits): def _ParseOS(user_agent_string, jsParseBits): + if jsParseBits: + warnings.warn( + "javascript overrides are deprecated and will be removed next release", + category=DeprecationWarning, + stacklevel=2, + ) for osParser in OS_PARSERS: os, os_v1, os_v2, os_v3, os_v4 = osParser.Parse(user_agent_string) if os: @@ -344,7 +353,6 @@ def ParseDevice(user_agent_string, **jsParseBits): """Parses the user-agent string for device info. Args: user_agent_string: The full user-agent string. - ua_family: The parsed user agent family name. Returns: A dictionary containing parsed bits. """ @@ -352,6 +360,12 @@ def ParseDevice(user_agent_string, **jsParseBits): def _ParseDevice(user_agent_string, jsParseBits): + if jsParseBits: + warnings.warn( + "javascript overrides are deprecated and will be removed next release", + category=DeprecationWarning, + stacklevel=2, + ) for deviceParser in DEVICE_PARSERS: device, brand, model = deviceParser.Parse(user_agent_string) if device: diff --git a/ua_parser/user_agent_parser_test.py b/ua_parser/user_agent_parser_test.py index 570718d..6658cb3 100644 --- a/ua_parser/user_agent_parser_test.py +++ b/ua_parser/user_agent_parser_test.py @@ -1,5 +1,3 @@ -#!/usr/bin/python2.5 -# # Copyright 2008 Google Inc. # # Licensed under the Apache License, Version 2.0 (the 'License') @@ -121,38 +119,6 @@ def testParseAll(self): ), ) - # Make a YAML file for manual comparsion with pgts_browser_list-orig.yaml - def makePGTSComparisonYAML(self): - import codecs - - outfile = codecs.open("outfile.yaml", "w", "utf-8") - print >> outfile, "test_cases:" - - yamlFile = open(os.path.join(TEST_RESOURCES_DIR, "pgts_browser_list.yaml")) - yamlContents = yaml.load(yamlFile, Loader=SafeLoader) - yamlFile.close() - - for test_case in yamlContents["test_cases"]: - user_agent_string = test_case["user_agent_string"] - kwds = {} - if "js_ua" in test_case: - kwds = eval(test_case["js_ua"]) - - (family, major, minor, patch) = user_agent_parser.ParseUserAgent( - user_agent_string, **kwds - ) - - # Escape any double-quotes in the UA string - user_agent_string = re.sub(r'"', '\\"', user_agent_string) - print >> outfile, ' - user_agent_string: "' + user_agent_string + '"' + "\n" + ' family: "' + family + '"\n' + " major: " + ( - "" if (major is None) else "'" + major + "'" - ) + "\n" + " minor: " + ( - "" if (minor is None) else "'" + minor + "'" - ) + "\n" + " patch: " + ( - "" if (patch is None) else "'" + patch + "'" - ) - outfile.close() - # Run a set of test cases from a YAML file def runUserAgentTestsFromYAML(self, file_name): yamlFile = open(os.path.join(TEST_RESOURCES_DIR, file_name)) @@ -162,9 +128,6 @@ def runUserAgentTestsFromYAML(self, file_name): for test_case in yamlContents["test_cases"]: # Inputs to Parse() user_agent_string = test_case["user_agent_string"] - kwds = {} - if "js_ua" in test_case: - kwds = eval(test_case["js_ua"]) # The expected results expected = { @@ -175,7 +138,7 @@ def runUserAgentTestsFromYAML(self, file_name): } result = {} - result = user_agent_parser.ParseUserAgent(user_agent_string, **kwds) + result = user_agent_parser.ParseUserAgent(user_agent_string) self.assertEqual( result, expected, @@ -205,9 +168,6 @@ def runOSTestsFromYAML(self, file_name): for test_case in yamlContents["test_cases"]: # Inputs to Parse() user_agent_string = test_case["user_agent_string"] - kwds = {} - if "js_ua" in test_case: - kwds = eval(test_case["js_ua"]) # The expected results expected = { @@ -218,7 +178,7 @@ def runOSTestsFromYAML(self, file_name): "patch_minor": test_case["patch_minor"], } - result = user_agent_parser.ParseOS(user_agent_string, **kwds) + result = user_agent_parser.ParseOS(user_agent_string) self.assertEqual( result, expected, @@ -245,9 +205,6 @@ def runDeviceTestsFromYAML(self, file_name): for test_case in yamlContents["test_cases"]: # Inputs to Parse() user_agent_string = test_case["user_agent_string"] - kwds = {} - if "js_ua" in test_case: - kwds = eval(test_case["js_ua"]) # The expected results expected = { @@ -256,7 +213,7 @@ def runDeviceTestsFromYAML(self, file_name): "model": test_case["model"], } - result = user_agent_parser.ParseDevice(user_agent_string, **kwds) + result = user_agent_parser.ParseDevice(user_agent_string) self.assertEqual( result, expected, @@ -308,7 +265,7 @@ def setUp(self): seems to work out of the box. """ super(TestDeprecationWarnings, self).setUp() - warnings.simplefilter("default", DeprecationWarning) + warnings.simplefilter("always", DeprecationWarning) def tearDown(self): # not ideal as it discards all other warnings updates from the @@ -329,6 +286,20 @@ def test_printer_deprecation(self): self.assertEqual(len(ws), 1) self.assertEqual(ws[0].category, DeprecationWarning) + def test_js_bits_deprecation(self): + for parser, count in [ + (user_agent_parser.Parse, 3), + (user_agent_parser.ParseUserAgent, 1), + (user_agent_parser.ParseOS, 1), + (user_agent_parser.ParseDevice, 1), + ]: + user_agent_parser._PARSE_CACHE.clear() + with warnings.catch_warnings(record=True) as ws: + parser("some random thing", js_attribute=True) + self.assertEqual(len(ws), count) + for w in ws: + self.assertEqual(w.category, DeprecationWarning) + if __name__ == "__main__": unittest.main()