{"id":2680,"date":"2020-10-24T13:00:00","date_gmt":"2020-10-24T12:00:00","guid":{"rendered":"https:\/\/chewett.co.uk\/blog\/?p=2680"},"modified":"2020-12-12T15:29:31","modified_gmt":"2020-12-12T15:29:31","slug":"raspberry-pi-cluster-node-16-python-3-codebase-refactor","status":"publish","type":"post","link":"https:\/\/chewett.co.uk\/blog\/2680\/raspberry-pi-cluster-node-16-python-3-codebase-refactor\/","title":{"rendered":"Raspberry Pi Cluster Node \u2013 16 Python 3 Codebase Refactor"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"678\" height=\"254\" data-attachment-id=\"2703\" data-permalink=\"https:\/\/chewett.co.uk\/blog\/2680\/raspberry-pi-cluster-node-16-python-3-codebase-refactor\/raspi_cluster_16_refactor\/\" data-orig-file=\"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_refactor.jpg?fit=800%2C300&amp;ssl=1\" data-orig-size=\"800,300\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"raspi_cluster_16_refactor\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_refactor.jpg?fit=300%2C113&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_refactor.jpg?fit=678%2C254&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_refactor.jpg?resize=678%2C254&#038;ssl=1\" alt=\"\" class=\"wp-image-2703\" srcset=\"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_refactor.jpg?w=800&amp;ssl=1 800w, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_refactor.jpg?resize=300%2C113&amp;ssl=1 300w, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_refactor.jpg?resize=768%2C288&amp;ssl=1 768w, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_refactor.jpg?resize=50%2C19&amp;ssl=1 50w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/figure>\n\n\n\n<p>This post builds on&nbsp;<a href=\"https:\/\/chewett.co.uk\/blog\/2179\/raspberry-pi-cluster-node-15-a-more-complex-webserver\/\" data-type=\"post\" data-id=\"2179\">my previous posts in the Raspberry Pi Cluster series<\/a>&nbsp;by improving the codebase for Python 3.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Moving to Python 3<\/h2>\n\n\n\n<p>Python 2 was marked end of life on January 1st, 2020 and therefore applications should ideally be no longer using Python 2. There will still be a lot of applications still using it, but really they should have been migrated away by now.<\/p>\n\n\n\n<p>In this case, I am using this tutorial to migrate the code from Python 2 and perform some refactoring.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Changing Hashbangs<\/h3>\n\n\n\n<p>The first change is to replace all the hashbangs with a python 3 compatible one. This means all the hashbangs that are as follows.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><em>#!\/usr\/bin\/env python2.7<\/em><\/pre>\n\n\n\n<p>Will be converted to<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><em>#!\/usr\/bin\/env python3<\/em><\/pre>\n\n\n\n<p>For now I am just marking them up with python3 and not a specific minor version. This is because while I would like to use the most recent python version, I want to keep this open to a variety of systems and therefore will keep the code generic to python 3.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Changing relative imports<\/h3>\n\n\n\n<p>Previously I used implicit relative imports which meant that Python looked in the current package level for anything referenced if it could not be initially found. This means if ModuleA refers to ModuleB, python 2 will find it if it is in the same directory.<\/p>\n\n\n\n<p>Python 3 no longer searches for implicit relative imports which means it will no longer file ModuleB even if it is in the same directory as ModuleA.<\/p>\n\n\n\n<p>You are able to use a relatively import by prefixing the import name with a dot. For example<\/p>\n\n\n\n<p>Python 2 &#8211; <code>import ModuleB<\/code><br>Python 3 &#8211; <code>import .ModuleB<\/code><\/p>\n\n\n\n<p>Both will work the same, however in Python 3 we now have to be explicit about the relative import. I am going to go through and be explicit about the location of modules.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Unicode Handling<\/h3>\n\n\n\n<p>Python 3 handles unicode in a much better way, however it means now a number of functions expect binary data instead of strings. An example is that the socket handling code to receive and send data now must be encoded in binary before being sent.<\/p>\n\n\n\n<p>This can be done using the encode function available on strings, and decode function available on binary data. This function requires a character set to encode\/decode as when it is called.<\/p>\n\n\n\n<p>I am going to be using utf-8 to transfer data back and forth on the nodes so will encode\/decode with utf-8. This means by socket handling code requires a small tweak as below:<\/p>\n\n\n\n<p>Sending data and encoding as utf-8:<br><code>self.sock.send(payload.encode(<strong>\"utf-8\"<\/strong>))<\/code><\/p>\n\n\n\n<p>Recieving data and decoding as utf-8:<br><code>self._buffered_string += data.decode(<strong>\"utf-8\"<\/strong>)<\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Removing References to Master \/ Slave<\/h2>\n\n\n\n<p>Since I last worked on the cluster the world has moved on and various reflection has been made on the world. The terms master\/slave are steeped in racial undertones and therefore I am removing them.<\/p>\n\n\n\n<p>If renaming the scripts makes one person feel more included, it is for the best.<\/p>\n\n\n\n<p>The three main scripts have been renamed to the following.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>basic_primary.py<\/li><li>basic_secondary.py<\/li><li>basic_webserver.py<\/li><\/ul>\n\n\n\n<p>All references in the code to master\/slave have been replaced with primary\/secondary.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Python Doc Comments<\/h2>\n\n\n\n<p>I previously, wrongfully, neglected python dock blocks opting for detailed descriptions in the tutorials.  While documentation in the tutorials is helpful adding docblocks to the code will also be useful.<\/p>\n\n\n\n<p>I am going through all the code adding doc blocks. This shouldn&#8217;t be a massive undertaking as the code was already commented, just the functions\/classes did not have a description on them.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Misc Code changes<\/h2>\n\n\n\n<p>There are a few changes made that PEP 8 stuff<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>pep8 &#8211; two spaces before inline block<\/li><li>pep8 &#8211; Inline block must have space between # and comment<\/li><li>Variables should be python case not camel case<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Refactoring the DataPackager<\/h2>\n\n\n\n<p>The DataPackager is a small set of functions used to create the payload to send over the socket. In addition it handles receiving data from the socket and piecing the payload back together.<\/p>\n\n\n\n<p>After reviewing the code I found that since partial messages are stored in the class and not the object, using multiple data packagers on multiple slots may cause message corruption.<\/p>\n\n\n\n<p>In addition to this, it was expected that to send messages with the DataPackager you needed to format the messages first. This is now handled directly by the DataPackager and means you just pass in the payload to send.<\/p>\n\n\n\n<p>These changes, including moving it to its own object should make it easier to use and possible to use multiple in the same script.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary of improving the codebase<\/h2>\n\n\n\n<p>In this tutorial the cluster codebase is moved to python 3 and generally cleaned up and improved. This will allow the latest languages and tools to be used with the cluster and improve development.<\/p>\n\n\n\n<p>In addition the increased comments and improvements should make it easier to add further functionality to the cluster.<\/p>\n\n\n\n<p>The full code is\u00a0<a href=\"https:\/\/github.com\/chewett\/RaspberryPiCluster\/releases\/tag\/v16.1\" target=\"_blank\" rel=\"noreferrer noopener\">available on Github<\/a>, any comments or questions can be raised there as issues or posted below.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This post builds on&nbsp;my previous posts in the Raspberry Pi Cluster series&nbsp;by improving the codebase for Python 3.<\/p>\n","protected":false},"author":1,"featured_media":2702,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Today I write about the 16th tutorial in the #RaspberryPi Cluster, Python 3 Codebase Refactor","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[122],"tags":[102,184,198,37,101,393],"class_list":["post-2680","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-raspberry-pi-cluster","tag-distributed-computing","tag-python","tag-python-3","tag-raspberry-pi","tag-raspberry-pi-cluster","tag-raspberry-pi-os"],"wppr_data":{"cwp_meta_box_check":"No"},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2020\/10\/raspi_cluster_16_python3refactor_posticon_OUTPUT.png?fit=1200%2C628&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/p2toWX-He","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":1001,"url":"https:\/\/chewett.co.uk\/blog\/1001\/raspberry-pi-cluster-node-04-configuration-files-configparser\/","url_meta":{"origin":2680,"position":0},"title":"Raspberry Pi Cluster Node \u2013 04 Configuration Files with ConfigParser","author":"Chewett","date":"February 10, 2018","format":false,"excerpt":"This post builds on the\u00a0third step to create a Raspberry Pi Cluster Node\u00a0to store our configuration settings in a config file. Here we move all the configuration settings in our script into a useful .cfg file using the python ConfigParser. Why use Configuration Files? When developing a system there will\u2026","rel":"","context":"In &quot;Raspberry Pi Cluster&quot;","block_context":{"text":"Raspberry Pi Cluster","link":"https:\/\/chewett.co.uk\/blog\/category\/raspberry-pi-cluster\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/02\/rpi_cluster_04_config_parser.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/02\/rpi_cluster_04_config_parser.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/02\/rpi_cluster_04_config_parser.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/02\/rpi_cluster_04_config_parser.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":2766,"url":"https:\/\/chewett.co.uk\/blog\/2766\/updating-the-raspberrypivcgencmd-library-to-python-3\/","url_meta":{"origin":2680,"position":1},"title":"Updating the RaspberryPiVcgencmd library to Python 3","author":"Chewett","date":"January 16, 2021","format":false,"excerpt":"This post talks quickly about the updates performed to the RaspberryPiVcgencmd library for porting to Python 3. Porting RaspberryPiVcgencmd to Python 3 Originally this library was written for Python 2 but now that has been retired it was time to update it. The main work that needed to be done\u2026","rel":"","context":"In &quot;Raspberry Pi Cluster&quot;","block_context":{"text":"Raspberry Pi Cluster","link":"https:\/\/chewett.co.uk\/blog\/category\/raspberry-pi-cluster\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/01\/rpi_vcgencmd_lib_OUTPUT.png?fit=1200%2C628&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/01\/rpi_vcgencmd_lib_OUTPUT.png?fit=1200%2C628&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/01\/rpi_vcgencmd_lib_OUTPUT.png?fit=1200%2C628&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/01\/rpi_vcgencmd_lib_OUTPUT.png?fit=1200%2C628&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/01\/rpi_vcgencmd_lib_OUTPUT.png?fit=1200%2C628&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":343,"url":"https:\/\/chewett.co.uk\/blog\/343\/raspberrypivcgencmd-python-library-access-raspberry-pi-vcgencmd-command\/","url_meta":{"origin":2680,"position":2},"title":"RaspberryPiVcgencmd A python library to access Raspberry Pi vcgencmd command","author":"Chewett","date":"May 31, 2017","format":false,"excerpt":"To access some of the lower level aspects of the Raspberry Pi's config you can use the built in command vcgencmd. This is a useful on the command line but to easily access it in a program you need to parse the output. I am planning to use this command\u2026","rel":"","context":"In &quot;Raspberry Pi Cluster&quot;","block_context":{"text":"Raspberry Pi Cluster","link":"https:\/\/chewett.co.uk\/blog\/category\/raspberry-pi-cluster\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2017\/05\/vcgencmd.png?fit=628%2C288&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2017\/05\/vcgencmd.png?fit=628%2C288&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2017\/05\/vcgencmd.png?fit=628%2C288&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":2780,"url":"https:\/\/chewett.co.uk\/blog\/2780\/raspberry-pi-cluster-node-18-raspberry-pi-temperature-monitoring\/","url_meta":{"origin":2680,"position":3},"title":"Raspberry Pi Cluster Node \u2013 18 Raspberry Pi Temperature Monitoring","author":"Chewett","date":"February 20, 2021","format":false,"excerpt":"This post builds on\u00a0my previous posts in the Raspberry Pi Cluster series\u00a0by starting to log temperature with the RaspberryPiVcgencmd Python module. Installing RaspberryPiVcgencmd RaspberryPiVcgencmd is a small python module aimed to control vcgencmd and allow programmatic access to it. This can be installed with the following command. python3 -m pip\u2026","rel":"","context":"In &quot;Raspberry Pi Cluster&quot;","block_context":{"text":"Raspberry Pi Cluster","link":"https:\/\/chewett.co.uk\/blog\/category\/raspberry-pi-cluster\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/02\/raspi_cluster_18_cputemperature_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/02\/raspi_cluster_18_cputemperature_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/02\/raspi_cluster_18_cputemperature_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/02\/raspi_cluster_18_cputemperature_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/02\/raspi_cluster_18_cputemperature_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":2952,"url":"https:\/\/chewett.co.uk\/blog\/2952\/running-a-python-script-on-boot-with-systemd\/","url_meta":{"origin":2680,"position":4},"title":"Running a Python Script on Boot with Systemd","author":"Chewett","date":"August 7, 2021","format":false,"excerpt":"This short blog post details how you can run a python script on boot using systemd. Using Systemd to manage the python script Systemd is a daemon that is used to control various aspects of services and initialization scripts that run on and after boot. It is used by a\u2026","rel":"","context":"In &quot;Informational&quot;","block_context":{"text":"Informational","link":"https:\/\/chewett.co.uk\/blog\/category\/informational\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/07\/systemd_bootup_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/07\/systemd_bootup_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/07\/systemd_bootup_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/07\/systemd_bootup_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2021\/07\/systemd_bootup_posticon_OUTPUT.png?fit=1200%2C628&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":2127,"url":"https:\/\/chewett.co.uk\/blog\/2127\/raspberry-pi-cluster-node-14-a-simple-webserver\/","url_meta":{"origin":2680,"position":5},"title":"Raspberry Pi Cluster Node \u2013 14 A simple webserver","author":"Chewett","date":"April 17, 2019","format":false,"excerpt":"This tutorial focuses on creating a simple webserver that displays the status of the master using python Bottle. What will the webserver be used for? To interact with the cluster I am planning on making a small set of webpages. Initially these will just display information about the cluster but\u2026","rel":"","context":"In &quot;Raspberry Pi Cluster&quot;","block_context":{"text":"Raspberry Pi Cluster","link":"https:\/\/chewett.co.uk\/blog\/category\/raspberry-pi-cluster\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2019\/04\/rpi_cluster_14_a_simple_webserver.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2019\/04\/rpi_cluster_14_a_simple_webserver.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2019\/04\/rpi_cluster_14_a_simple_webserver.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2019\/04\/rpi_cluster_14_a_simple_webserver.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/posts\/2680","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/comments?post=2680"}],"version-history":[{"count":4,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/posts\/2680\/revisions"}],"predecessor-version":[{"id":2711,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/posts\/2680\/revisions\/2711"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/media\/2702"}],"wp:attachment":[{"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/media?parent=2680"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/categories?post=2680"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/tags?post=2680"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}