From 4ae4bac5287a0767983a55a2bcee4384dd91db1b Mon Sep 17 00:00:00 2001 From: James Rosewell Date: Thu, 17 Sep 2026 00:53:46 +0100 Subject: [PATCH 1/2] FIX: read the resource key in the failure to match example the way every other example does The example read only the older 'resource_key' variable, so a reader who had set _51DEGREES_RESOURCE_KEY, which the other examples and this repository's own CI use, was told to create a resource key. It now asks ExampleUtils, which reads both names, and a test runs the example with the current name alone. --- .../cloud/failuretomatch.py | 25 ++++++++-------- .../tests/test_cloudexamples.py | 29 +++++++++++++++++++ 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/fiftyone_devicedetection_examples/src/fiftyone_devicedetection_examples/cloud/failuretomatch.py b/fiftyone_devicedetection_examples/src/fiftyone_devicedetection_examples/cloud/failuretomatch.py index 20c783ddf..e9742d2aa 100644 --- a/fiftyone_devicedetection_examples/src/fiftyone_devicedetection_examples/cloud/failuretomatch.py +++ b/fiftyone_devicedetection_examples/src/fiftyone_devicedetection_examples/cloud/failuretomatch.py @@ -26,20 +26,21 @@ # You need to create a resource key at https://configure.51degrees.com?utm_source=code&utm_medium=example&utm_campaign=device-detection-python&utm_content=fiftyone_devicedetection_examples-src-fiftyone_devicedetection_examples-cloud-failuretomatch.py&utm_term=top # and paste it into the code, replacing !!YOUR_RESOURCE_KEY!! below. -# Alternatively, add a resource_key environment variable -import os -if "resource_key" in os.environ: - resource_key = os.environ["resource_key"] -else: - resource_key = "!!YOUR_RESOURCE_KEY!!" +# Alternatively, set the _51DEGREES_RESOURCE_KEY environment variable. The +# key is read through ExampleUtils, as every other example reads it, so +# this one answers to the same variable names as the rest and a reader who +# has set one of them does not have to work out why only this example says +# it has no key. +from fiftyone_devicedetection_examples.example_utils import ExampleUtils + +resource_key = ExampleUtils.get_resource_key() or "!!YOUR_RESOURCE_KEY!!" if resource_key == "!!YOUR_RESOURCE_KEY!!": - print(""" - You need to create a resource key at - https://configure.51degrees.com?utm_source=code&utm_medium=example&utm_campaign=device-detection-python&utm_content=fiftyone_devicedetection_examples-src-fiftyone_devicedetection_examples-cloud-failuretomatch.py&utm_term=resource-key-required and paste it into the code, - 'replacing !!YOUR_RESOURCE_KEY!! - To include the properties used in this example, go to https://configure.51degrees.com/bxXqZhLT?utm_source=code&utm_medium=example&utm_campaign=device-detection-python&utm_content=fiftyone_devicedetection_examples-src-fiftyone_devicedetection_examples-cloud-failuretomatch.py&utm_term=resource-key-required - """) + print(ExampleUtils.get_missing_resource_key_message()) + # The address stays on one line, because the campaign lint reads a + # line at a time and a split address looks to it like a missing tag. + print(" To include the properties used in this example, go to " + "https://configure.51degrees.com/bxXqZhLT?utm_source=code&utm_medium=example&utm_campaign=device-detection-python&utm_content=fiftyone_devicedetection_examples-src-fiftyone_devicedetection_examples-cloud-failuretomatch.py&utm_term=resource-key-required") else: pipeline = DeviceDetectionCloudPipelineBuilder({ diff --git a/fiftyone_devicedetection_examples/tests/test_cloudexamples.py b/fiftyone_devicedetection_examples/tests/test_cloudexamples.py index 125f972e6..955cc3ad8 100644 --- a/fiftyone_devicedetection_examples/tests/test_cloudexamples.py +++ b/fiftyone_devicedetection_examples/tests/test_cloudexamples.py @@ -22,7 +22,10 @@ import inspect import json5 +import os from pathlib import Path +import subprocess +import sys import unittest from fiftyone_devicedetection_examples.cloud.nativemodellookup_console import NativeModelLookupConsole from fiftyone_devicedetection_examples.cloud.taclookup_console import TacLookupConsole @@ -149,3 +152,29 @@ def test_cloud_configurator_console(self): self.assertIn("device.ismobile: ", output) self.assertNotEqual("device.ismobile:", output.strip()) + + + def test_cloud_failuretomatch(self): + """The failure to match example is a script rather than a class, + so it is run as one. It is run with the current resource key + variable only, because it read the older name alone and told + anyone using the current one that no key was set.""" + + example = os.path.join( + os.path.dirname(os.path.dirname(os.path.abspath(__file__))), + "src", "fiftyone_devicedetection_examples", "cloud", + "failuretomatch.py") + environment = dict(os.environ) + environment.pop(ExampleUtils.LEGACY_RESOURCE_KEY_ENV_VAR, None) + environment[ExampleUtils.RESOURCE_KEY_ENV_VAR] = self.resource_key + + finished = subprocess.run( + [sys.executable, example], capture_output=True, text=True, + env=environment, timeout=120) + + output = finished.stdout + finished.stderr + self.assertEqual(0, finished.returncode, output) + self.assertNotIn("No resource key found", output) + self.assertIn("a mobile device?", output) + for marker in FAULT_MARKERS: + self.assertNotIn(marker, output) From a9c7dff0a477119df8936f645353102be9ba4da9 Mon Sep 17 00:00:00 2001 From: James Rosewell Date: Thu, 17 Sep 2026 01:09:55 +0100 Subject: [PATCH 2/2] CHORE: one blank line between the tests, as the file has elsewhere --- fiftyone_devicedetection_examples/tests/test_cloudexamples.py | 1 - 1 file changed, 1 deletion(-) diff --git a/fiftyone_devicedetection_examples/tests/test_cloudexamples.py b/fiftyone_devicedetection_examples/tests/test_cloudexamples.py index 955cc3ad8..79bf78c56 100644 --- a/fiftyone_devicedetection_examples/tests/test_cloudexamples.py +++ b/fiftyone_devicedetection_examples/tests/test_cloudexamples.py @@ -153,7 +153,6 @@ def test_cloud_configurator_console(self): self.assertIn("device.ismobile: ", output) self.assertNotEqual("device.ismobile:", output.strip()) - def test_cloud_failuretomatch(self): """The failure to match example is a script rather than a class, so it is run as one. It is run with the current resource key