### Example: Serialise Entire Module to JSON Source: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md This example demonstrates serialising an entire PyangBind module instance to a JSON string using `pyangbindJSON.dumps` with default settings. ```python pyangbindJSON.dumps(existing_instance, filter=True) ``` -------------------------------- ### Install PyangBind Source: https://github.com/robshakir/pyangbind/blob/master/README.md Install PyangBind using pip. This command installs both the Pyang plugin and library modules. ```bash pip install pyangbind ``` -------------------------------- ### Example: JSON Output of Entire Module Source: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md The resulting JSON output when serialising an entire PyangBind module instance. ```json { "a-list": { "entry-two": { "the-key": "entry-two" }, "entry-three": { "the-key": "entry-three" }, "entry-one": { "the-key": "entry-one" } } } ``` -------------------------------- ### Example: Serialise Subset to IETF JSON Source: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md This example shows how to serialise a specific list entry to IETF-encoded JSON using the `select` argument to filter by a leaf's value. ```python pbJ.dumps(existing_instance.a_list, select={'the-key': 'entry-one'}, mode="ietf") ``` -------------------------------- ### Example: Loading Additional Data to an Existing List Source: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md Demonstrates loading additional JSON data into an existing PyangBind instance, specifically adding an element to a list. The `existing_instance` is modified directly. ```python data_to_load = json.load(open('json/simple-instance-additional.json','r')) pybindJSONDecoder.load_json(data_to_load, None, None, obj=existing_instance) ``` ```python pp.pprint(existing_instance.a_list.keys()) # Outputs: # [u'entry-two', u'entry-three', u'entry-one'] ``` -------------------------------- ### YANG Leafref and Augment Example Source: https://github.com/robshakir/pyangbind/blob/master/docs/xpathhelper.md Illustrates the use of XPATH expressions within YANG models for defining leaf references and augmenting existing nodes. This is a conceptual example showing how XPATH is used in YANG syntax. ```yang leaf reference { type leafref { path "/path/to/another/node"; } } augment "/bgp" { uses some-new-grouping; } ``` -------------------------------- ### View Data with get() and tostring() Source: https://github.com/robshakir/pyangbind/blob/master/docs/xpathhelper.md Retrieve data from a PyangBind object using its .get() method, and view the internal XML structure of the YANGPathHelper instance using its tostring() method. ```python print peer.get(filter=True) print ph.tostring(pretty_print=True) ``` -------------------------------- ### Example: IETF JSON Output of Selected Entry Source: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md The resulting IETF-encoded JSON output when selecting a specific entry from a list. ```json [ { "simple_serialise:the-key": "entry-one" } ] ``` -------------------------------- ### Retrieve Data using XPath Expressions Source: https://github.com/robshakir/pyangbind/blob/master/docs/xpathhelper.md Utilize the get() and get_unique() methods of the YANGPathHelper instance to retrieve data by specifying XPath expressions. get() returns a list, while get_unique() returns a single object or raises an exception. ```python ph.get("/bgp/neighbors/neighbor/neighbor-address") ph.get("/bgp/neighbors/neighbor[neighbor-address='192.0.2.1']/config/peer-as") ph.get_unique("/bgp/neighbors/neighbor[neighbor-address='10.0.0.1']/config/peer-as") ``` -------------------------------- ### Get Dictionary Representation of Data Source: https://github.com/robshakir/pyangbind/blob/master/README.md Utilizes the `get()` method to obtain a dictionary representation of a data object. Use the `filter=True` argument to include only modified or non-default values. ```python print(ocni.network_instances.network_instance['a'].protocols.protocol['STATIC DEFAULT'].static_routes.static["192.0.2.1/32"].get(filter=True)) # returns {'prefix': '192.0.2.1/32', 'config': {'set-tag': 42}} ``` -------------------------------- ### Accessing YANG Extensions in Python Source: https://github.com/robshakir/pyangbind/blob/master/docs/usage.md When the --interesting-extension option is used, YANG extensions are stored in a dictionary accessible via the _extensions() method. This example shows how to retrieve and print these extensions. ```python >>> print(cls.description._extensions()) {u'example-extensions': {u'descr-flag': u'd', u'descr-order': u'100'}} ``` -------------------------------- ### Delete BGP Neighbor and Verify Source: https://github.com/robshakir/pyangbind/blob/master/docs/xpathhelper.md Remove an entry from the PyangBind data tree using the delete() method. The YANGPathHelper automatically unregisters the object, and subsequent get() calls reflect the change. ```python ob.bgp.neighbors.neighbor.delete("10.0.0.1") ph.get("/bgp/neighbors/neighbor/neighbor-address") ``` -------------------------------- ### Manipulate Deserialized Data Source: https://github.com/robshakir/pyangbind/blob/master/README.md Access and modify data within a PyangBind object after it has been deserialized from JSON. This example shows retrieving and incrementing a 'set-tag' value. ```python # Manipulate the data loaded print("Current tag: %d" % new_ocni.network_instances.network_instance['a'].protocols.protocol['STATIC DEFAULT'].static_routes.static['192.0.2.1/32'].config.set_tag) new_ocni.network_instances.network_instance['a'].protocols.protocol['STATIC DEFAULT'].static_routes.static['192.0.2.1/32'].config.set_tag += 1 print("New tag: %d" % new_ocni.network_instances.network_instance['a'].protocols.protocol['STATIC DEFAULT'].static_routes.static['192.0.2.1/32'].config.set_tag) ``` -------------------------------- ### Get Container Elements with Filter Source: https://github.com/robshakir/pyangbind/blob/master/docs/generic_methods.md Retrieves a nested dictionary representing the container's elements. Use the filter argument to include only modified elements. ```python import pprint pp = pprint.PrettyPrinter(indent=4) pp.pprint(r.tables.get(filter=True)) ``` -------------------------------- ### Dump PyangBind to JSON String Source: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md Use the `dumps` function to get a JSON string representation of a PyangBind object. The `select` argument allows filtering based on specific element values, and `mode` controls JSON encoding. ```python dumps(obj, indent=4, filter=True, skip_subtrees=[], select=False, mode="default") ``` -------------------------------- ### Import and Instantiate RPC Input Source: https://github.com/robshakir/pyangbind/blob/master/docs/rpc.md Shows how to import the generated input class for an RPC and instantiate it. ```python from rbindings.simple_rpc_rpc.test.input import input rpc_input = input() rpc_input.input_container.argument_one = "test_call" rpc_input.input_container.argument_two = 32 ``` -------------------------------- ### Create Network Instance and Static Route Source: https://github.com/robshakir/pyangbind/blob/master/README.md Demonstrates adding a network instance, a protocol, and a static route to a YANG data tree. Use the `add` method for list entries and specify identifiers and names. ```python ocni.network_instances.network_instance.add('a') ocni.network_instances.network_instance['a'].protocols ocni.network_instances.network_instance['a'].protocols.protocol.add(identifier='STATIC', name='DEFAULT') rt = ocni.network_instances.network_instance['a'].protocols.protocol['STATIC DEFAULT'].static_routes.static.add("192.0.2.1/32") ``` -------------------------------- ### Initialize PyangBind with Extension Methods Source: https://github.com/robshakir/pyangbind/blob/master/docs/extmethods.md Generate PyangBind bindings with the `--use-extmethods` flag. Then, create an `extmethods` dictionary mapping XPaths to your helper class instances and pass it to the PyangBind class constructor. ```python bgp_helper = BGPNeighborHelper() extmethods = { '/bgp/neighbors/neighbor/neighbor/config/enabled': bgp_helper } ocbgp = openconfig_bgp(extmethods=extmethods) ``` -------------------------------- ### Initialize YANGPathHelper and PyangBind Object Source: https://github.com/robshakir/pyangbind/blob/master/docs/xpathhelper.md Instantiate YANGPathHelper and pass it to a PyangBind-generated class during initialization. Ensure bindings were generated with the --use-xpathhelper flag. ```python from openconfig import openconfig_bgp from pyangbind.lib.xpathhelper import YANGPathHelper ph = YANGPathHelper() ob = openconfig_bgp(path_helper=ph) ``` -------------------------------- ### Importing PyangBind generated BGP module Source: https://github.com/robshakir/pyangbind/blob/master/docs/usage.md Demonstrates how to import the top-level BGP module generated by PyangBind when using the --split-class-dir option. ```python from openconfig import bgp ocbgp = bgp() ``` -------------------------------- ### Importing PyangBind generated BGP global config module Source: https://github.com/robshakir/pyangbind/blob/master/docs/usage.md Shows how to import classes from deeper levels of the module hierarchy, specifically the global config class within the BGP module, when using --split-class-dir. Note that 'global' is a reserved word and is handled by appending an underscore. ```python from openconfig.bgp import global_ # global is a reserved word from openconfig.bgp.global_ import config bgp_global = global_.global_() bgp_global_config = config.config() ``` -------------------------------- ### Parse RPC Output from JSON Source: https://github.com/robshakir/pyangbind/blob/master/docs/rpc.md Illustrates parsing an RPC output from a JSON file into a PyangBind output object. ```python import os import json from rbindings.simple_rpc_rpc.test.output import output from pyangbind.lib.pybindJSON import pybindJSONDecoder rpc_output = output() fn = os.path.join("json", "rpc-output.json") json_obj = json.load(open(fn, 'r')) pybindJSONDecoder.load_ietf_json(json_obj, None, None, obj=rpc_output) ``` -------------------------------- ### Generate Python Bindings with Pyang Source: https://github.com/robshakir/pyangbind/blob/master/README.md Generate Python bindings from a YANG module using the pyang command with the PyangBind plugin. Specify the plugin directory, output file, and the YANG module. ```bash pyang --plugindir $PYBINDPLUGIN -f pybind -o binding.py tests/base-test.yang ``` -------------------------------- ### Call Extension Methods on Data Instances Source: https://github.com/robshakir/pyangbind/blob/master/docs/extmethods.md Initiate a soft or hard reset by calling the prefixed extension methods on the relevant data instance. These calls are proxied to the associated helper class instance. ```python ocbgp.bgp.neighbors.neighbor["192.0.2.1"].config.enabled._hard_reset() ocbgp.bgp.neighbors.neighbor["192.0.2.1"].config.enabled._soft_reset() ``` -------------------------------- ### Set Tag on Static Route Source: https://github.com/robshakir/pyangbind/blob/master/README.md Shows how to set a configuration value, like a tag, on a created data object. The change is reflected immediately on the object. ```python rt.config.set_tag = 42 ``` -------------------------------- ### Add and Iterate Next Hops Source: https://github.com/robshakir/pyangbind/blob/master/README.md Demonstrates adding multiple items to a list-like object (e.g., `next_hops`) using its `add` method and then iterating through the added items using `items()`. ```python # Add a set of next_hops for nhop in [(0, "192.168.0.1"), (1, "10.0.0.1")]: nh = rt.next_hops.next_hop.add(nhop[0]) nh.config.next_hop = nhop[1] # Iterate through the next-hops added for index, nh in rt.next_hops.next_hop.items(): print("{}: {}".format(index, nh.config.next_hop)) ``` -------------------------------- ### Serialise PyangBind Instance to OpenConfig-suggested JSON Source: https://github.com/robshakir/pyangbind/blob/master/README.md Use pybindJSON.dumps() to serialise a PyangBind instance into OpenConfig-suggested JSON format. The 'indent' parameter can be used for pretty-printing. Ensure pyangbind.lib.pybindJSON is imported. ```python import pyangbind.lib.pybindJSON as pybindJSON print(pybindJSON.dumps(ocni, indent=2)) ``` -------------------------------- ### Serialize RPC Input to JSON Source: https://github.com/robshakir/pyangbind/blob/master/docs/rpc.md Demonstrates serializing an RPC input object to IETF JSON format using `dumps`. ```python from pyangbind.lib.pybindJSON import dumps >> print(dumps(rpc_input, mode="ietf")) { "simple_rpc:input-container": { "argument-two": 32, "argument-one": "test_call" } } ``` -------------------------------- ### Export PyangBind Plugin Path Source: https://github.com/robshakir/pyangbind/blob/master/README.md Export the path to the PyangBind plugin for use with the pyang command. This is necessary to tell pyang where to find the plugin. ```bash export PYBINDPLUGIN=`/usr/bin/env python -c 'import pyangbind; import os; print ("{}/plugin".format(os.path.dirname(pyangbind.__file__))) '` echo $PYBINDPLUGIN ``` -------------------------------- ### Use Generated PyangBind Classes in Python Source: https://github.com/robshakir/pyangbind/blob/master/README.md Import and instantiate a class generated by PyangBind from a YANG module. Ensure the generated binding file is in the current working directory or accessible via PYTHONPATH. ```python # Using the binding file generated by the `generate_bindings.sh` script # Note that CWD is the file containing the binding.py file. # Alternatively, you can use sys.path.append to add the CWD to the PYTHONPATH from binding import openconfig_network_instance ocni = openconfig_network_instance() ``` -------------------------------- ### PyangbindXpathHelper Interface Methods Source: https://github.com/robshakir/pyangbind/blob/master/docs/xpathhelper.md Defines the core methods expected by PyangBind classes from an XPathHelper implementation. These methods are used for registering, unregistering, and retrieving data nodes based on their XPATH. ```python class PyangbindXpathHelper: def register(self, path, object_ptr, caller=False): # ... implementation ... pass def unregister(self, path, caller=False): # ... implementation ... pass def get(self, path, caller=False): # ... implementation ... pass ``` -------------------------------- ### YANG RPC Definition Source: https://github.com/robshakir/pyangbind/blob/master/docs/rpc.md Defines a simple RPC named 'test' with a container input and a list output. ```yang rpc test { input { container input-container { leaf argument-one { type string; } leaf argument-two { type uint8; } } } output { leaf response-id { type uint32; } list elements { leaf response-value { type string; } } } } ``` -------------------------------- ### Add and Modify BGP Neighbor Source: https://github.com/robshakir/pyangbind/blob/master/docs/xpathhelper.md After initializing YANGPathHelper, use standard PyangBind methods to add and configure data. The YANGPathHelper automatically updates its internal XML representation. ```python peer = ob.bgp.neighbors.neighbor.add("192.0.2.1") peer.config.peer_as = 15169 ``` -------------------------------- ### Define a Class for Extension Methods Source: https://github.com/robshakir/pyangbind/blob/master/docs/extmethods.md Define a helper class with methods that will be bound to data instances. These methods will be prefixed with an underscore when called on the data instance. ```python from openconfig import openconfig_bgp class BgpNeighborHelper(object): def soft_reset(self, *args, **kwargs): # Do a soft reset of the neighbor pass def hard_reset(self, *args, **kwargs): # Do a hard reset of the neighbor pass ``` -------------------------------- ### Load JSON into Existing PyangBind Object Source: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md Use `load_json` or `load_ietf_json` with the `obj` parameter to load data into an existing PyangBind instance. This modifies the instance in-place. ```python load_json(input_data, None, None, obj=existing_object, path_helper=path_helper, extmethods=extmethods, overwrite=overwrite) ``` ```python load_ietf_json(input_data, None, None, obj=existing_object, path_helper=path_helper, extmethods=extmethods, overwrite=overwrite) ``` -------------------------------- ### Setting 'config false' Elements in PyangBind Source: https://github.com/robshakir/pyangbind/blob/master/docs/yang.md To set a 'config false' leaf, use the private setter method `_set_X` where X is the Python-safe name of the element. Direct assignment will raise an AttributeError. ```python >>>ocbgp.bgp.global_.state.total_paths = 500 Traceback (most recent call last): File "", line 1, in AttributeError: can't set attribute >>> ocbgp.bgp.global_.state._set_total_paths(500) >>> ocbgp.bgp.global_.state.total_paths 500 ``` -------------------------------- ### Retrieve Tag Value Source: https://github.com/robshakir/pyangbind/blob/master/README.md Illustrates accessing a configuration value directly from the object or through the root data object. Both methods refer to the same in-memory object. ```python # Retrieve the tag value print(rt.config.set_tag) # output: 42 # Retrieve the tag value through the original object print(ocni.network_instances.network_instance['a'].protocols.protocol['STATIC DEFAULT'].static_routes.static["192.0.2.1/32"].config.set_tag) # output: 42 ``` -------------------------------- ### Dump PyangBind to JSON File Source: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md Use the `dump` function to write a PyangBind object to a JSON file. Specify the `mode` argument for IETF-encoded JSON. The `skip_subtrees` argument can prune specific paths from the output. ```python dump(obj, filename, indent=, filter=, skip_subtrees=, mode="default") ``` -------------------------------- ### Serialise PyangBind Instance to RFC 7950 XML Source: https://github.com/robshakir/pyangbind/blob/master/README.md Use pybindIETFXMLEncoder.serialise() to convert an entire PyangBind instance to RFC 7950 XML format. Ensure the pyangbind.lib.serialise module is imported. ```python from pyangbind.lib.serialise import pybindIETFXMLEncoder # Dump the entire instance as RFC 7950 XML print(pybindIETFXMLEncoder.serialise(ocni)) ``` -------------------------------- ### Access Parsed RPC Output Source: https://github.com/robshakir/pyangbind/blob/master/docs/rpc.md Shows how to access data from a parsed RPC output object in Python. ```python >>> print(rpc_output.response_id) 32 ``` -------------------------------- ### Iterate Through Loaded Routes Source: https://github.com/robshakir/pyangbind/blob/master/README.md After loading JSON data, iterate through the defined routes within the PyangBind object to access their properties, such as the prefix and tag. ```python # Iterate through the classes - both the 192.0.2.1/32 prefix and 192.0.2.2/32 # prefix are now in the objects for prefix, route in new_ocni.network_instances.network_instance['a'].protocols.protocol['STATIC DEFAULT'].static_routes.static.items(): print("Prefix: {}, tag: {}".format(prefix, route.config.set_tag)) ``` -------------------------------- ### Serialise PyangBind to XML String Source: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md Use `pybindIETFXMLEncoder.serialise` to convert a PyangBind object into an XML string. The `pretty_print` argument controls indentation and newlines. ```python pybindIETFXMLEncoder.serialise(obj, filter=, pretty_print=) ``` -------------------------------- ### Traverse Up the Tree using _parent Source: https://github.com/robshakir/pyangbind/blob/master/docs/xpathhelper.md Access parent objects in the YANG data tree by using the _parent attribute of a PyangBind object. This allows retrieval of wider objects from a specific data point. ```python peer_as = ph.get_unique("/bgp/neighbors/neighbor[neighbor-address='10.0.0.1']/config/peer-as") peer_as._parent._parent.get(filter=True) ``` -------------------------------- ### Load JSON into a New PyangBind Object Source: https://github.com/robshakir/pyangbind/blob/master/README.md Use `pybindJSON.load` to deserialize a JSON file into a new PyangBind object. This is useful when receiving data from a remote system. ```python import binding new_ocni = pybindJSON.load(os.path.join("json", "oc-ni.json"), binding, "openconfig_network_instance") ``` -------------------------------- ### Handling PyangBind ValueError Source: https://github.com/robshakir/pyangbind/blob/master/docs/errors.md This snippet demonstrates how to catch and inspect a ValueError raised by PyangBind. It checks if the error arguments are a dictionary to handle potential old binding formats and iterates through the dictionary to print error details. ```python try: pybindobj.value = "anInvalidValue" except ValueError as e: # Check the args and types, just in case we have # old bindings if len(e.args) and isinstance(e.args[0], dict): print "Hit a PyangBind ValueError" for k, v in e.args[0].iteritems(): print "%s->%s" % (k, v) else: print unicode(e) ``` -------------------------------- ### Encode PyangBind to lxml Object Source: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md Use `pybindIETFXMLEncoder.encode` to convert a PyangBind object into an `lxml.objectify` instance. This is useful for further manipulation with the lxml library. ```python pybindIETFXMLEncoder.encode(obj, filter=, pretty_print=) ``` -------------------------------- ### Serialise Subset of PyangBind Instance to IETF JSON Source: https://github.com/robshakir/pyangbind/blob/master/README.md Serialise a specific part of a PyangBind instance (e.g., a list or container) into IETF JSON format using pybindJSON.dumps() with mode='ietf'. This allows for selective data export. ```python # Dump the static-routes instance as JSON in IETF format print(pybindJSON.dumps(ocni.network_instances.network_instance['a'].protocols.protocol['STATIC DEFAULT'], mode='ietf', indent=2)) ``` -------------------------------- ### Add Metadata to PyangBind Object Source: https://github.com/robshakir/pyangbind/blob/master/docs/generic_methods.md Use _add_metadata to store arbitrary metadata associated with a data instance. The metadata is stored in the _metadata dictionary. ```python config.router_id._add_metadata("inactive", True) ``` -------------------------------- ### PyangBind JSON Loading Source: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md Load PyangBind-formatted JSON data from a file or string into a PyangBind object. Ensure the correct Python module and YANG module name are provided. ```yang module simple_serialise { yang-version "1"; namespace "http://rob.sh/yang/test/ss"; prefix "ss"; container a-container { leaf a-value { type int8; } } list a-list { key "the-key"; leaf the-key { type string; } } } ``` ```bash $ pyang --plugindir $PYBINDPLUGIN -f pybind -o sbindings.py simple_serialise.yang ``` ```json { "a-container": { "a-value": 8 }, "a-list": { "entry-one": { "the-key": "entry-one" }, "entry-two": { "the-key": "entry-two" } } } ``` ```python #!/usr/bin/env python import pprint import pyangbind.lib.pybindJSON as pbJ import sbindings pp = pprint.PrettyPrinter(indent=4) loaded_object = pbJ.load("json/simple-instance.json", sbindings, "simple_serialise") pp.pprint(loaded_object.get(filter=True)) string_to_load = open('json/simple-instance.json', 'r').read().replace('\n', '') loaded_object_two = pbJ.loads(string_to_load, sbindings, "simple_serialise") pp.pprint(loaded_object_two.get(filter=True)) ``` ```python { 'a-container': { 'a-value': 8 }, 'a-list': { u'entry-one': { 'the-key': u'entry-one' }, u'entry-two': { 'the-key': u'entry-two' } } } ``` -------------------------------- ### Load JSON into an Existing PyangBind Object Source: https://github.com/robshakir/pyangbind/blob/master/README.md Use `pybindJSONDecoder.load_ietf_json` to load JSON data into an already existing PyangBind object structure. The `obj=` argument specifies the target object for the load. ```python # Load JSON into an existing class structure from pyangbind.lib.serialise import pybindJSONDecoder import json ietf_json = json.load(open(os.path.join("json", "oc-ni_ietf.json"), 'r')) pybindJSONDecoder.load_ietf_json(ietf_json, None, None, obj=new_ocni.network_instances.network_instance['a'].protocols.protocol['STATIC DEFAULT']) ``` -------------------------------- ### IETF JSON Loading Source: https://github.com/robshakir/pyangbind/blob/master/docs/serialisation.md Load IETF-formatted JSON data from a file or string using `load_ietf` and `loads_ietf`. This method handles the IETF JSON structure, which includes module prefixes and list representations. ```json { "simple_serialise:a-container": { "a-value": 8 }, "simple_serialise:a-list": [ {"the-key": "entry-one"}, {"the-key": "entry-two"} ] } ``` ```python # Load an instance from an IETF-JSON file loaded_ietf_obj = pbJ.load_ietf("simple-instance-ietf.json", sbindings, "simple_serialise") pp.pprint(loaded_ietf_obj.get(filter=True)) # Load an instance from an IETF-JSON string string_to_load = open('json/simple-instance-ietf.json', 'r').read().replace('\n', '') loaded_ietf_obj_two = pbJ.loads_ietf(string_to_load, sbindings, "simple_serialise") pp.pprint(loaded_ietf_obj_two.get(filter=True)) ``` -------------------------------- ### Handle Invalid Value Assignment Source: https://github.com/robshakir/pyangbind/blob/master/README.md Shows how Pyangbind raises a `ValueError` when attempting to assign an invalid value to a YANG leaf that has type restrictions. ```python # Try and set an invalid tag type try: rt.config.set_tag = "INVALID-TAG" except ValueError as m: print("Cannot set tag: {}".format(m)) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.