prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Specify a User Agent for HTTP requests
  Right now it's python-urllib/someversion, and Cloudflare sites (tested on medium protection site) blocks it and returns 403 status code.
  Testing the same url with curl works without it blocking, so I'm guessing Cloudflare checks the request UA.
  
  </issue>
  <code>
  [start of lutris/util/http.py]
  1 import json
  2 import socket
  3 import urllib.request
  4 import urllib.error
  5 import urllib.parse
  6 from ssl import CertificateError
  7 
  8 from lutris.settings import SITE_URL
  9 from lutris.util.log import logger
  10 
  11 
  12 class Request(object):
  13     def __init__(self, url, timeout=5, stop_request=None,
  14                  thread_queue=None, headers={}):
  15 
  16         if not url:
  17             raise ValueError('An URL is required!')
  18 
  19         if url.startswith('//'):
  20             url = 'https:' + url
  21 
  22         if url.startswith('/'):
  23             url = SITE_URL + url
  24 
  25         self.url = url
  26         self.content = ''
  27         self.timeout = timeout
  28         self.stop_request = stop_request
  29         self.thread_queue = thread_queue
  30         self.buffer_size = 32 * 1024  # Bytes
  31         self.downloaded_size = 0
  32         self.headers = headers
  33 
  34     def get(self, data=None):
  35         req = urllib.request.Request(url=self.url, data=data, headers=self.headers)
  36         try:
  37             request = urllib.request.urlopen(req, timeout=self.timeout)
  38         except (urllib.error.HTTPError, CertificateError) as e:
  39             logger.error("Unavailable url (%s): %s", self.url, e)
  40         except (socket.timeout, urllib.error.URLError) as e:
  41             logger.error("Unable to connect to server (%s): %s", self.url, e)
  42         else:
  43             try:
  44                 total_size = request.info().get('Content-Length').strip()
  45                 total_size = int(total_size)
  46             except AttributeError:
  47                 total_size = 0
  48 
  49             chunks = []
  50             while 1:
  51                 if self.stop_request and self.stop_request.is_set():
  52                     self.content = ''
  53                     return self
  54                 try:
  55                     chunk = request.read(self.buffer_size)
  56                 except socket.timeout as e:
  57                     logger.error("Request timed out")
  58                     self.content = ''
  59                     return self
  60                 self.downloaded_size += len(chunk)
  61                 if self.thread_queue:
  62                     self.thread_queue.put(
  63                         (chunk, self.downloaded_size, total_size)
  64                     )
  65                 else:
  66                     chunks.append(chunk)
  67                 if not chunk:
  68                     break
  69             request.close()
  70             self.content = b''.join(chunks)
  71         return self
  72 
  73     def post(self, data):
  74         raise NotImplementedError
  75 
  76     def write_to_file(self, path):
  77         content = self.content
  78         if content:
  79             with open(path, 'wb') as dest_file:
  80                 dest_file.write(content)
  81 
  82     @property
  83     def json(self):
  84         if self.content:
  85             return json.loads(self.text)
  86 
  87     @property
  88     def text(self):
  89         if self.content:
  90             return self.content.decode()
  91
  [end of lutris/util/http.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/lutris/util/http.py b/lutris/util/http.py
  --- a/lutris/util/http.py
  +++ b/lutris/util/http.py
  @@ -5,6 +5,8 @@
   import urllib.parse
   from ssl import CertificateError
   
  +from lutris.settings import PROJECT
  +from lutris.settings import VERSION
   from lutris.settings import SITE_URL
   from lutris.util.log import logger
   
  @@ -29,6 +31,8 @@
           self.thread_queue = thread_queue
           self.buffer_size = 32 * 1024  # Bytes
           self.downloaded_size = 0
  +        if not headers.get('User-Agent'):
  +            headers['User-Agent'] = PROJECT + '/' + VERSION
           self.headers = headers
   
       def get(self, data=None):
  
verification_info: {"golden_diff": "diff --git a/lutris/util/http.py b/lutris/util/http.py\n--- a/lutris/util/http.py\n+++ b/lutris/util/http.py\n@@ -5,6 +5,8 @@\n import urllib.parse\n from ssl import CertificateError\n \n+from lutris.settings import PROJECT\n+from lutris.settings import VERSION\n from lutris.settings import SITE_URL\n from lutris.util.log import logger\n \n@@ -29,6 +31,8 @@\n         self.thread_queue = thread_queue\n         self.buffer_size = 32 * 1024  # Bytes\n         self.downloaded_size = 0\n+        if not headers.get('User-Agent'):\n+            headers['User-Agent'] = PROJECT + '/' + VERSION\n         self.headers = headers\n \n     def get(self, data=None):\n", "issue": "Specify a User Agent for HTTP requests\nRight now it's python-urllib/someversion, and Cloudflare sites (tested on medium protection site) blocks it and returns 403 status code.\r\nTesting the same url with curl works without it blocking, so I'm guessing Cloudflare checks the request UA.\n", "before_files": [{"content": "import json\nimport socket\nimport urllib.request\nimport urllib.error\nimport urllib.parse\nfrom ssl import CertificateError\n\nfrom lutris.settings import SITE_URL\nfrom lutris.util.log import logger\n\n\nclass Request(object):\n    def __init__(self, url, timeout=5, stop_request=None,\n                 thread_queue=None, headers={}):\n\n        if not url:\n            raise ValueError('An URL is required!')\n\n        if url.startswith('//'):\n            url = 'https:' + url\n\n        if url.startswith('/'):\n            url = SITE_URL + url\n\n        self.url = url\n        self.content = ''\n        self.timeout = timeout\n        self.stop_request = stop_request\n        self.thread_queue = thread_queue\n        self.buffer_size = 32 * 1024  # Bytes\n        self.downloaded_size = 0\n        self.headers = headers\n\n    def get(self, data=None):\n        req = urllib.request.Request(url=self.url, data=data, headers=self.headers)\n        try:\n            request = urllib.request.urlopen(req, timeout=self.timeout)\n        except (urllib.error.HTTPError, CertificateError) as e:\n            logger.error(\"Unavailable url (%s): %s\", self.url, e)\n        except (socket.timeout, urllib.error.URLError) as e:\n            logger.error(\"Unable to connect to server (%s): %s\", self.url, e)\n        else:\n            try:\n                total_size = request.info().get('Content-Length').strip()\n                total_size = int(total_size)\n            except AttributeError:\n                total_size = 0\n\n            chunks = []\n            while 1:\n                if self.stop_request and self.stop_request.is_set():\n                    self.content = ''\n                    return self\n                try:\n                    chunk = request.read(self.buffer_size)\n                except socket.timeout as e:\n                    logger.error(\"Request timed out\")\n                    self.content = ''\n                    return self\n                self.downloaded_size += len(chunk)\n                if self.thread_queue:\n                    self.thread_queue.put(\n                        (chunk, self.downloaded_size, total_size)\n                    )\n                else:\n                    chunks.append(chunk)\n                if not chunk:\n                    break\n            request.close()\n            self.content = b''.join(chunks)\n        return self\n\n    def post(self, data):\n        raise NotImplementedError\n\n    def write_to_file(self, path):\n        content = self.content\n        if content:\n            with open(path, 'wb') as dest_file:\n                dest_file.write(content)\n\n    @property\n    def json(self):\n        if self.content:\n            return json.loads(self.text)\n\n    @property\n    def text(self):\n        if self.content:\n            return self.content.decode()\n", "path": "lutris/util/http.py"}]}