# sample call: https://en.wikipedia.org/w/api.php?action=query&format=json&list=geosearch&gscoord=37.7891838%7C-122.4033522&gsradius=10000&gslimit=100
Then I defined a variable, base_url = "https://en.wikipedia.org/w/api.php?"
Then, like magic, Copilot suggested all the remaining keys that would go in the query params. It even knew which params were to be kept as-is, and which ones would come from my previous code: action = "query" # action=query
format = "json" # or xml
lat = str(latitude.value) # 37.7891838
lon = str(longitude.value) # -122.4033522
gscoord = lat + "%7C" + lon
...
api_path = base_url + "action=" + action + "&format=" + format + ... + "&gscoord=" + gscoord
As a guy who gets easily distracted while programming, Copilot saves me a lot of time and keeps me engaged with my work. I can only imagine what it'll look like 10 years from now. api_path = base_url + urllib.parse.urlencode({
'action': action,
'format': letThisBeVariable,
...
'gscoord': str(latitude.value) + '|' + str(longitude.value)
})
see: https://docs.python.org/3/library/urllib.parse.html#urllib.p...Mantra: when inserting data into a context (like an url) escape the data for that context.
Use something like URLBuilder, or URIParams, or whatever your platform supports. Don't use string concatenation ever, if at all possible, and if not possible (wtf?), then at least escape strings.
https://docs.python-requests.org/en/latest/user/quickstart/#...
One correlated but ancillary benefit, is that there are fewer variables to simulate the state for in your brain, while you're reading the code. You don't have to wonder if a variable is going to change on you, in-between when it is initialized and when it is used.
It's safer still to use a library (e.g. urllib3) that does encoding for you (allowing you to omit magic strings like `"%7C"` from the logic of this function alltogther).
Like GP said, very handy for one-off scripts or areas of your codebase where quality is "less important". I may be pedantic, but I wouldn't give this a pass on code review.
So I would build the query like so:
from urllib.parse import urlencode
urlencode({
"action": "query",
"format": "json",
...
"gscoord": f"{str(latitude.value)}|{str(longitude.value)}",
})
I think this is orders of magnitude clearer code. But that's a parameter that's subjective that CoPilot can't adjust for (although it can be better).Or did you mean something else?
Remember it doesn't actually know an API or how it should be used: it's putting things together to look like typical code. For me that has meant difficult to spot bugs like linking up incorrect variables from the rest of my code.
I wish it could integrate the first SO answer to a generated question, because I always end up there anyway having to fix things.
They're the only data you can control, and unless they're strings, it's useless for exploitation. Even denormal floats / INF / NAN won't help achieve an objective.
I broadly agree with you, but people are pummeling Copilot for writing code that I saw hundreds of times. Yes, sometimes I was able to exploit some of that code. But the details matter.
>>> import requests, pprint
>>>
>>>
>>> url = "https://en.wikipedia.org/w/api.php"
>>> resp = requests.get(
... url,
... params=dict(
... action="query",
... list="geosearch",
... format="json",
... gsradius=10000,
... gscoord=f"{latitude.value}|{longitude.value}"
... )
... )
>>>
>>> pprint.pprint(resp.json())
{'batchcomplete': '',
'query': {'geosearch': [{'dist': 26.2,
'lat': 37.7868194444444,
'lon': -122.399905555556,
'ns': 0,
...Oxford English Dictionary, for example, is a human version of defining language and a thesaurus is a completion engine.
Human language didn't suffer by having a dictionary and thesaurus. Computer language doesn't suffer either.
Isn't that a pretty big risk though? Specifically, that people will use co-pilot recommendations "as-is" and give little thought to the actual workings of the recommendation?
After all, if you have to intimately understand the code it's recommending are you really saving that much time over vetting a Googled solution yourself?
I typed the following prompt:
def search_wikipedia(lat, lon):
"""
use "requests" to do a geosearch on Wikipedia and pretty-print the resulting JSON
"""
And it completed it with: r = requests.get('https://en.wikipedia.org/w/api.php?action=query&list=geosearch&gsradius=10000&gscoord={0}|{1}&gslimit=20&format=json'.format(lat, lon))
pprint.pprint(r.json())We just had a major failure at work recently because someone decided to not decode URL params and their code worked fine for years because it never mattered… until it did.
Just do it right. It’s so easy. Why risk yourself a ton of headache in the future to save you a few seconds?
One reason I've championed the development of visual programming (flow-based, node diagrams, etc) is that while you don't want to compress a big complex program down into a single layer and become unreadable in the process, graphical methods are a great way for people to see what options they have available and just point at things they want to try out.
Instead of struggling with syntax at the same time as trying to find out what they can do with a new API, they can engage in trial-and-error to find out the capabilities and what makes it worth using, then build up their competency once they are clear about their objectives.
I'm looking forward to trying this now that it's available for my favorite IDE, but I'll probably want to set up a hotkey to switch it on and off as I need it. Once I get fully comfortable with something I often find code completion tools get in the way of my flow.
let coeff = BigUint::from_str(x).unwrap();
let coeff: <<G1Affine as AffineCurve>::ScalarField as PrimeField>::BigInt =
coeff.try_into().unwrap();
let x: <G1Affine as AffineCurve>::ScalarField = coeff.into();
I wrote that, then I wanted to move that code in a function so I wrote: fn string_int_to_field_el(s: &str)
copilot suggested the following one-liner that did exactly the same thing: fn string_int_to_field_el(s: &str) -> <G1Affine as AffineCurve>::ScalarField {
let x: <G1Affine as AffineCurve>::ScalarField = s.parse().unwrap();
x
}
I still don't understand how some heuristics could produce this code. It's mind blowing.The old "just copy-paste from Stack Overflow" approach to development is satirised and ridiculed these days (despite being still in common practice I'm certain), because as we all know so well by now, an accepted answer on SO does not always equate to a correct answer. Yes, the SO guys & community do do their best to improve answer quality iteratively (wiki answers, etc.), but there's still a lot of bad answers, and even many of the "good" ones become outdated or don't keep up with modern best-practice (especially when it comes to security).
Omitting urlencoding isn't the biggest crime, but it is a pretty standard URL-building step, and the fact that a tool released this year is spitting out code that omits something so simple is fairly damning. It's also a micro-example of much larger errors Copilot will surely be responsible for. Missing url encoding can be an injection vector in many applications, even if it's not the most common risk, but miss encoding in other string-building ops and you've made your way into the OWASP Top 10.
The big difference between copilot and SO is there's no community engaging in an open & transparent iterative process to improve the quality of answers.
I've only had it for about a week now but overall I'm happy with it. None of the code I'm writing is crazy cutting-edge stuff and in aggregate I'm sure it saves me more time than takes, including the time I spend reviewing and potentially changing the generated code.
… as a top level comment said, this is optimizing for the wrong problem.