68: Generative AI you need to check its working outs


I’ve mentioned a couple of times that I’ve been playing with ChatGTP to assist with a piece of development work I’m doing.

Today, I validated a new piece of code it presented me with, which looked great and was exactly what I wanted but completely wrong.

I asked it

How do I move a SharePoint folder using Microsoft Graph API in python?

It replied (initially with the correct answer)

import json
import requests

folder_id = "123"
new_parent_id = "456"

url = f"https://graph.microsoft.com/v1.0/drive/items/{folder_id}"
headers = {
    "Authorization": "Bearer your_access_token",
    "Content-Type": "application/json"
data = {
    "parentReference": {
        "id": new_parent_id

response = requests.patch(url, headers=headers, json=data)

if response.status_code == 200:
    print("Folder moved successfully.")
    print(f"Error moving folder: {response.json()}")

Then I asked Can I move a folder using a path rather than IDs

Where it replied as follows

Yes, it is possible to move a folder in SharePoint using a path rather than IDs using the Microsoft Graph API.

You can use the Move API to move the folder by passing the path of the folder and the new parent folder.

Here is an example of how you can use the requests library to move a folder located at “path/to/folder” to a new parent folder located at “path/to/newparentfolder” :

and supplied the following code

import json
import requests

folder_path = "path/to/folder"
new_parent_path = "path/to/newparentfolder"

url = f"https://graph.microsoft.com/v1.0/drive/root:/{folder_path}:/move"
headers = {
    "Authorization": "Bearer your_access_token",
    "Content-Type": "application/json"
data = {
    "destination": {
        "path": new_parent_path

response = requests.post(url, headers=headers, json=data)

if response.status_code == 200:
    print("Folder moved successfully.")
    print(f"Error moving folder: {response.json()}")

Unfortunately, this code is not correct! In fact, the official Microsoft Graph API Documentation for the Move method says

Request body

In the request body, supply the new value for the parentReference property. Existing properties that are not included in the request body will maintain their previous values or be recalculated based on changes to other property values. For best performance you shouldn’t include existing values that haven’t changed.

Note: When moving items to the root of a drive, your app cannot use the "id:" "root" syntax. Your app needs to provide the actual ID of the root folder for the parent reference.

Truthfully I’m gutted the code didn’t work because it would have made my life simpler, but it highlights a key consideration when using Generative AI.

You always need to check the output, whether it’s facts, grammar or code. These systems are not full-proof, and it’s incumbent on you to use your critical thinking skills to validate the information you’ve been given. No matter how reasonable it sounds.

68: Retail App


  • Good news! After months of toil, we received a security sign-off last week, which means that the Retail App is going live in the next couple of days!
  • There is still one feature we’re finishing up, but that doesn’t impact the release.
  • The Retail App has, baring a few curve balls, been a good project, and I’m proud of my team for what they’ve built.
  • I’m looking to see how Three evolve its use over the coming months, but I’m confident it’s an excellent start for their plans to consolidate the retail employee digital experience.
  • Thank you! Callum Ilett, Adam Auckland, Josh Browning, Dave Inoc, Dan Maxwell, Nat Patemkina, Eleanor Morgan and Marcus Woodbridge

67: JavaScript templates strings in Python


When I first started learning Python, the one thing I wanted more than anything was to be able to use template strings, like had gotten used to in JavaScript.

language = "JavaScript"
string = `this is a string literal in ${language}`

For some reason, I couldn’t find a decent article telling me how to do them.

Then on Sunday, when I asked ChatGTP to generate a piece of code for me, I was struck by something in the output.

url = f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token"

So I asked ChatGTP what the ‘f’ meant, and it told me about ‘f-strings’ for ‘formatted string literals` in python, which is exactly what I was I was looking for.

So here you are. If you want to use template strings in python, then prefix the string with an f, and you’re done!

66: Python: MS Graph API Authentication (Without a user)

I’m writing a script to migrate files from one location to another in Sharepoint using MS Graph API.

To use the Graph API, you have to get an authentication token from Azure AD, and there are two ways to do this: 1) Acting on behalf of a user and 2) acting without a user.

Both approaches require you to create an Azure AD App in the Azure portal, but acting on behalf of a user will require an intermediate step of displaying a browser window, so the user can consent to the app acting on their behalf.

For this piece of work, I needed to be able to authenticate without any user involvement. Trying to find good examples of how to do this in Python is devilishly hard, and for a while, I’ve been using option 1, and it’s irked me.

As part of some research into an article I’m writing on Generative AI, I thought I’d see if it could offer a suggestion I could work with.

It did. It gave me the exact answer I was looking for but couldn’t find using GoogleFu!

So here’s the code, in case you’re also looking for it.

import requests

CLIENT_ID = "{your client id}"
TENANT_ID = "{your tenant id}"
CLIENT_SECRET = "{your client secret}" #Don't save this in your code, espically if you're using a public git repo.

url = f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token"
headers = {
    "Content-Type": "application/x-www-form-urlencoded"
data = {
    "grant_type": "client_credentials",
    "client_id": CLIENT_ID,
    "client_secret": CLIENT_SECRET,
    "scope": "https://graph.microsoft.com/.default"

response = requests.post(url, headers=headers, data=data)

if response.status_code == 200:
    token = response.json()["access_token"]
    print(f"Error getting token: {response.json()}")

The token that’s returned from the /oauth2/v2.0/token will be added as an authorization header to any subsequent call you make to the MS Graph API.

headers = {"AUTHORIZATION": f"Bearer {token}", "Content-type": "application/json"}

What I like about this solution is that it simply uses the request library, making what’s going on more obvious and understandable.

NOTE: I’ve added it to the code, but please don’t keep your client secret in the code. Anyone with access to this can access everything with the scopes allocated to Azure AD App.

65: Craig can retire!


  • My good friend Craig turned 55 today! As he’s told me several times, he can now retire.
  • He won’t, though, because about 10 years ago, he retrained from being an infrastructure engineer to a FE Lecturer.
  • Industries lost, was educations gain!
  • He’s a very conscientious lecturer; he thinks deeply about how to give his students the education they need now, not after Uni, to get a job in digital delivery.
  • Most of his students go on to Uni, but Craig focuses on helping his students to bridge the gap between theoretical knowledge to practical application.
  • He taught a collaborative, agile development process before many companies I know started.
  • I’m very grateful to know Craig and to count on him as a friend, and I wish him a very Happy Birthday

64: Polly’s Home


  • Polly returned home from the animal hospital today!
  • She’s doing well.
  • Tam and I have both noticed that she already seems to be doing a lot better walking and going to the toilet, which before the operation was awful.
  • She’s still weak and spend most of the evening sleeping.
  • We’re hopeful and very grateful to Colin Driver and Dorothy Hajdu at Lumbry park for the wonderful care she received.

Reading: The case for working with your hands by Matthew B Crawford. (100% Complete)

63: One thing at a time


  • A good friend of mine recently wrote an article on focus (in product delivery), aka limiting the work in progress and focusing on one thing to completion.
  • Today I had a salient reminder of why it’s so important.
  • Let me start by saying that I know how valuable it is to limit your work in progress (WIP) and focus on one thing until completion.
  • I purposefully structure my teams to achieve this and manage our backlogs to ensure that the team can follow this maxim.
  • However, life rarely runs smoothly when you’re running an agency, and more times than I’d like, we have to manage competing requirements and sometimes, the teams have split objectives.
  • We work hard continually to prevent this but sometimes, usually for financial reasons, this isn’t always possible.
  • The story I’m telling isn’t in my team directly but with another team, we work closely with.
  • In this team, there has been a problem with the deployment pipeline, and the test environment is blocked.
  • This has meant the work we’ve been doing has backed up and has impacted some timescales around some quite essential security releases.
  • Also, two separate teams have been working on competing outcomes that conflicted with each other.
  • When the test environment broke, the other team couldn’t fix it and didn’t reach out for help.
  • Rather than stop, reset and figure it out, they doubled down on continuing to make their changes in the hope the next release would fix the issue.
  • It didn’t, and the situation worsened.
  • We now had more untested code, a broken test environment and a whole bunch of other changes languishing in GitHub branches.
  • Eventually, the dam broke, and we got everything unblocked but not in a positive way.
  • One impact of all these issues contributed to a member of the other team being signed off work for two weeks with stress. (It wasn’t the only issue, but it contributed to that person being overwhelmed)
  • Unfortunately, that person has all the tacit knowledge of how the build and deployment systems work, which meant that the Hail Mary approach to deploying new code to fix the issue couldn’t be deployed!
  • It was at this point I was able to step in and reset the work effort.
  • We asked a member of our team to investigate the original issue blocking test.
  • Three hours later, we found a config file with an error. Once that was fixed, everything else became unblocked.
  • The momentum of the other team’s work had narrowed their vision. They decided against the obvious thing and continued with a strategy which compounded the issue.
  • There are several significant issues here.
  • 1. The configuration issue was in a part of the stack the first team was unfamiliar with. Rather than ask for and accept help, they decided to work around the problems.
  • 2. The knowledge needed to complete the critical task was in someone’s head, not the world, for someone else to pick up and resolve.
  • 3. The wrong thing was prioritised in the first place. The issue on Test could have only been a config issue, this was apparent weeks earlier when the changes were rolled back to some code known to have worked, and it still didn’t work.
  • It’s so easy when you’re in the thick of it to continue regardless. Movement is good, right?
  • No, movement isn’t good, momentum is good, and we weren’t building up any.
  • It’s better to stop and have some team members under-utilised so the priority issue can be focused on and fixed than to keep going in the hope that it’ll be alright.
  • Sometimes it might be alright, but in my experience, you usually end up weeks down the line fixing the thing you should have fixed much earlier.
  • We now have two things:
  • 1) a working test system to test and deploy the backed-up changes to Prod. Freeing intellectual capacity in the team.
  • 2) time to ensure the code written in haste to fix the test environment issue is properly working and tested.

Reading: The case for working with your hands by Matthew B Crawford. (64% Complete)

62: Monday, blur-day


  • Polly had her surgery today! The vet rung to say that so far everything looked good. The surgery went well, and he’ll call again tomorrow to let us know how Polly is recovering.

  • Today went by in a blur. I realised that I had low-level anxiety about Polly’s surgery, which made concentrating a little tricky.
  • However, we’re making good progress on our projects.
  • The data migration is coming together nicely. The script to reorganise the content is taking longer than expected, but I’m still confident it’ll do what we want it to do.
  • The retail app is moving ahead, and we should be able to go live early Feb. We’re still waiting on Info. Sec to sign off, but our plan to resolve the low-impact bugs has been approved in principle, so it’s only a matter of time.
  • All in all, things are going well, so there is nothing to grumble about there.
  • I think our most significant success is the control we now have over the backlog. It’s now obvious what’s happening and if we have any issues.

Reading: The case for working with your hands by Matthew B Crawford. (64% Complete)

Wordle: 572 5/6

61: Polly Update


  • Today I took Polly, our pug, to the neuro-specialist to find out what’s going wrong with her back end.
  • The vet hypothesised 1 of 3 things. 1) Disk problems, 2) Cyst (SAD) or 3) Constrictive myelopathy.
  • It turns out after the MRI that she has a little from columns 2 and 3.
  • Her immediate problems are caused by a cyst, but she has malformation in the spine which causes the cyat to form.
  • So we’ve been given a few choices. 1) do nothing, prognosis, complete immobility and double incontinence in 6-12 months. 2) steroids, which will relieve the symptoms but not resolve the problem 3) surgery,
  • Lucky we’re insured so we opted for the surgery.
  • I’m anxious for her, I have all the usual worries about the surgery, but I’m also nervous about her being at the hospital for the week. Will she sleep well etc.
  • So, to whoever is reading these posts. Send some good thoughts.

Reading: The case for working with your hands by Matthew B Crawford. (64% Complete)

Wordle: 572 5/6

60: Sunday code day:


  • This morning my good friend Craig popped over this morning.
  • Before the Pandemic, he used to pop over every Saturday or Sunday, and we’d chew the fat and usually end up doing some coding together, but it’s been about 3 years since we did that… until today.
  • In the week, Craig and I were discussing how most systems have terrible reporting.
  • They usually have some high-level stats that doesn’t really help you to answer the real questions you have.
  • So today, we took one of the reports from his college MIS system and tried to see if we could generate some more appropriate insights.
  • While working on the data, we found some pretty cool things in Pandas.
  • I will write a post with all the tips and tricks I need.

Reading: The case for working with your hands by Matthew B Crawford. (32% Complete)

Wordle: 572 5/6