prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  How to tell at run time whether libjpeg-turbo version of libjpeg is used?
  tl;dr:
  
  Is there some way to accomplish:  `PIL.Image.libjpeg_turbo_is_enabled()`?
  
  The full story:
  
  Is there a way to tell from a pre-built Pillow whether it was built against `libjpeg-turbo` or not?
  
  This is assuming that all I have is `libjpeg.so.X.X` and no way to tell where it came from.
  
  I see there is a symbol in the library:
  ```
  nm _imaging.cpython-36m-x86_64-linux-gnu.so | grep -I turbo
  000000000007e5a0 D libjpeg_turbo_version
  ```
  but I don't know how to access its value from python.
  
  If there is a way to tell the same from from shell using `ldd`/`nm` or other linker tools, it'd do too.
  
  The intention is to be able to tell a user at run-time to re-build Pillow after installing `libjpeg-turbo` to gain speed. The problem is that It's not enough to build Pillow against  `libjpeg-turbo`. Given how conda/pip dependencies work, a new prebuilt package of `Pillow` could get swapped in as a dependency for some other package and the user won't know that they now run a less efficient `Pillow` unless they watch closely any install/update logs.
  
  Currently the only solution I can think of (in conda env) is to take the output of:
  
      cd ~/anaconda3/envs/pytorch-dev/lib/python3.6/site-packages/PIL
      ldd  _imaging.cpython-36m-x86_64-linux-gnu.so | grep libjpeg
  
  which wold give me something like:
  
      libjpeg.so.8 => ~/anaconda3/envs/pytorch-dev/lib/libjpeg.so.8
  
  And then to try to match it to:
  
      grep libjpeg  ~/anaconda3/envs/pytorch-dev/conda-meta/libjpeg-turbo-2.0.1-h470a237_0.json
  
  which may work. There is a problem with this approach
  
  It's very likely that conda is going to reinstall `jpeg` since many packages depend on it, and when it does, there is going to be 2 libjpeg libs.
  
      ldd  _imaging.cpython-36m-x86_64-linux-gnu.so | grep libjpeg
          libjpeg.so.8 => /home/stas/anaconda3/envs/pytorch-dev/lib/libjpeg.so.8 (0x00007f92628c8000)
          libjpeg.so.9 => /home/stas/anaconda3/envs/pytorch-dev/lib/./libjpeg.so.9 (0x00007f9261c4e000)
  
  And now I can no longer tell which is which, since I can no longer tell which of the two Pillow will load at run time. Well, I can go one step further and check /proc/<pid>/maps to get the library, but it's getting more and more convoluted. And I won't even know how to do the same on non-linux platform. And this is just for the conda setup, for pip setup it'd be something else.
  
  Also what happens if `libjpeg-turbo` and `libjpeg` are the same version?
  
  Perhaps there is an easier way? Any chance to have `PIL.Image.libjpeg_turbo_is_enabled()`?
  
  Thank you.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `src/PIL/features.py`
  Content:
  ```
  1 from . import Image
  2 
  3 modules = {
  4     "pil": "PIL._imaging",
  5     "tkinter": "PIL._tkinter_finder",
  6     "freetype2": "PIL._imagingft",
  7     "littlecms2": "PIL._imagingcms",
  8     "webp": "PIL._webp",
  9 }
  10 
  11 
  12 def check_module(feature):
  13     if not (feature in modules):
  14         raise ValueError("Unknown module %s" % feature)
  15 
  16     module = modules[feature]
  17 
  18     try:
  19         __import__(module)
  20         return True
  21     except ImportError:
  22         return False
  23 
  24 
  25 def get_supported_modules():
  26     return [f for f in modules if check_module(f)]
  27 
  28 
  29 codecs = {
  30     "jpg": "jpeg",
  31     "jpg_2000": "jpeg2k",
  32     "zlib": "zip",
  33     "libtiff": "libtiff"
  34 }
  35 
  36 
  37 def check_codec(feature):
  38     if feature not in codecs:
  39         raise ValueError("Unknown codec %s" % feature)
  40 
  41     codec = codecs[feature]
  42 
  43     return codec + "_encoder" in dir(Image.core)
  44 
  45 
  46 def get_supported_codecs():
  47     return [f for f in codecs if check_codec(f)]
  48 
  49 
  50 features = {
  51     "webp_anim": ("PIL._webp", 'HAVE_WEBPANIM'),
  52     "webp_mux": ("PIL._webp", 'HAVE_WEBPMUX'),
  53     "transp_webp": ("PIL._webp", "HAVE_TRANSPARENCY"),
  54     "raqm": ("PIL._imagingft", "HAVE_RAQM")
  55 }
  56 
  57 
  58 def check_feature(feature):
  59     if feature not in features:
  60         raise ValueError("Unknown feature %s" % feature)
  61 
  62     module, flag = features[feature]
  63 
  64     try:
  65         imported_module = __import__(module, fromlist=['PIL'])
  66         return getattr(imported_module, flag)
  67     except ImportError:
  68         return None
  69 
  70 
  71 def get_supported_features():
  72     return [f for f in features if check_feature(f)]
  73 
  74 
  75 def check(feature):
  76     return (feature in modules and check_module(feature) or
  77             feature in codecs and check_codec(feature) or
  78             feature in features and check_feature(feature))
  79 
  80 
  81 def get_supported():
  82     ret = get_supported_modules()
  83     ret.extend(get_supported_features())
  84     ret.extend(get_supported_codecs())
  85     return ret
  86
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/src/PIL/features.py b/src/PIL/features.py
  --- a/src/PIL/features.py
  +++ b/src/PIL/features.py
  @@ -51,7 +51,8 @@
       "webp_anim": ("PIL._webp", 'HAVE_WEBPANIM'),
       "webp_mux": ("PIL._webp", 'HAVE_WEBPMUX'),
       "transp_webp": ("PIL._webp", "HAVE_TRANSPARENCY"),
  -    "raqm": ("PIL._imagingft", "HAVE_RAQM")
  +    "raqm": ("PIL._imagingft", "HAVE_RAQM"),
  +    "libjpeg_turbo": ("PIL._imaging", "HAVE_LIBJPEGTURBO"),
   }
  
verification_info: {"golden_diff": "diff --git a/src/PIL/features.py b/src/PIL/features.py\n--- a/src/PIL/features.py\n+++ b/src/PIL/features.py\n@@ -51,7 +51,8 @@\n     \"webp_anim\": (\"PIL._webp\", 'HAVE_WEBPANIM'),\n     \"webp_mux\": (\"PIL._webp\", 'HAVE_WEBPMUX'),\n     \"transp_webp\": (\"PIL._webp\", \"HAVE_TRANSPARENCY\"),\n-    \"raqm\": (\"PIL._imagingft\", \"HAVE_RAQM\")\n+    \"raqm\": (\"PIL._imagingft\", \"HAVE_RAQM\"),\n+    \"libjpeg_turbo\": (\"PIL._imaging\", \"HAVE_LIBJPEGTURBO\"),\n }\n", "issue": "How to tell at run time whether libjpeg-turbo version of libjpeg is used?\ntl;dr:\r\n\r\nIs there some way to accomplish:  `PIL.Image.libjpeg_turbo_is_enabled()`?\r\n\r\nThe full story:\r\n\r\nIs there a way to tell from a pre-built Pillow whether it was built against `libjpeg-turbo` or not?\r\n\r\nThis is assuming that all I have is `libjpeg.so.X.X` and no way to tell where it came from.\r\n\r\nI see there is a symbol in the library:\r\n```\r\nnm _imaging.cpython-36m-x86_64-linux-gnu.so | grep -I turbo\r\n000000000007e5a0 D libjpeg_turbo_version\r\n```\r\nbut I don't know how to access its value from python.\r\n\r\nIf there is a way to tell the same from from shell using `ldd`/`nm` or other linker tools, it'd do too.\r\n\r\nThe intention is to be able to tell a user at run-time to re-build Pillow after installing `libjpeg-turbo` to gain speed. The problem is that It's not enough to build Pillow against  `libjpeg-turbo`. Given how conda/pip dependencies work, a new prebuilt package of `Pillow` could get swapped in as a dependency for some other package and the user won't know that they now run a less efficient `Pillow` unless they watch closely any install/update logs.\r\n\r\nCurrently the only solution I can think of (in conda env) is to take the output of:\r\n\r\n    cd ~/anaconda3/envs/pytorch-dev/lib/python3.6/site-packages/PIL\r\n    ldd  _imaging.cpython-36m-x86_64-linux-gnu.so | grep libjpeg\r\n\r\nwhich wold give me something like:\r\n\r\n    libjpeg.so.8 => ~/anaconda3/envs/pytorch-dev/lib/libjpeg.so.8\r\n\r\nAnd then to try to match it to:\r\n\r\n    grep libjpeg  ~/anaconda3/envs/pytorch-dev/conda-meta/libjpeg-turbo-2.0.1-h470a237_0.json\r\n\r\nwhich may work. There is a problem with this approach\r\n\r\nIt's very likely that conda is going to reinstall `jpeg` since many packages depend on it, and when it does, there is going to be 2 libjpeg libs.\r\n\r\n    ldd  _imaging.cpython-36m-x86_64-linux-gnu.so | grep libjpeg\r\n        libjpeg.so.8 => /home/stas/anaconda3/envs/pytorch-dev/lib/libjpeg.so.8 (0x00007f92628c8000)\r\n        libjpeg.so.9 => /home/stas/anaconda3/envs/pytorch-dev/lib/./libjpeg.so.9 (0x00007f9261c4e000)\r\n\r\nAnd now I can no longer tell which is which, since I can no longer tell which of the two Pillow will load at run time. Well, I can go one step further and check /proc/<pid>/maps to get the library, but it's getting more and more convoluted. And I won't even know how to do the same on non-linux platform. And this is just for the conda setup, for pip setup it'd be something else.\r\n\r\nAlso what happens if `libjpeg-turbo` and `libjpeg` are the same version?\r\n\r\nPerhaps there is an easier way? Any chance to have `PIL.Image.libjpeg_turbo_is_enabled()`?\r\n\r\nThank you.\r\n\n", "before_files": [{"content": "from . import Image\n\nmodules = {\n    \"pil\": \"PIL._imaging\",\n    \"tkinter\": \"PIL._tkinter_finder\",\n    \"freetype2\": \"PIL._imagingft\",\n    \"littlecms2\": \"PIL._imagingcms\",\n    \"webp\": \"PIL._webp\",\n}\n\n\ndef check_module(feature):\n    if not (feature in modules):\n        raise ValueError(\"Unknown module %s\" % feature)\n\n    module = modules[feature]\n\n    try:\n        __import__(module)\n        return True\n    except ImportError:\n        return False\n\n\ndef get_supported_modules():\n    return [f for f in modules if check_module(f)]\n\n\ncodecs = {\n    \"jpg\": \"jpeg\",\n    \"jpg_2000\": \"jpeg2k\",\n    \"zlib\": \"zip\",\n    \"libtiff\": \"libtiff\"\n}\n\n\ndef check_codec(feature):\n    if feature not in codecs:\n        raise ValueError(\"Unknown codec %s\" % feature)\n\n    codec = codecs[feature]\n\n    return codec + \"_encoder\" in dir(Image.core)\n\n\ndef get_supported_codecs():\n    return [f for f in codecs if check_codec(f)]\n\n\nfeatures = {\n    \"webp_anim\": (\"PIL._webp\", 'HAVE_WEBPANIM'),\n    \"webp_mux\": (\"PIL._webp\", 'HAVE_WEBPMUX'),\n    \"transp_webp\": (\"PIL._webp\", \"HAVE_TRANSPARENCY\"),\n    \"raqm\": (\"PIL._imagingft\", \"HAVE_RAQM\")\n}\n\n\ndef check_feature(feature):\n    if feature not in features:\n        raise ValueError(\"Unknown feature %s\" % feature)\n\n    module, flag = features[feature]\n\n    try:\n        imported_module = __import__(module, fromlist=['PIL'])\n        return getattr(imported_module, flag)\n    except ImportError:\n        return None\n\n\ndef get_supported_features():\n    return [f for f in features if check_feature(f)]\n\n\ndef check(feature):\n    return (feature in modules and check_module(feature) or\n            feature in codecs and check_codec(feature) or\n            feature in features and check_feature(feature))\n\n\ndef get_supported():\n    ret = get_supported_modules()\n    ret.extend(get_supported_features())\n    ret.extend(get_supported_codecs())\n    return ret\n", "path": "src/PIL/features.py"}], "after_files": [{"content": "from . import Image\n\nmodules = {\n    \"pil\": \"PIL._imaging\",\n    \"tkinter\": \"PIL._tkinter_finder\",\n    \"freetype2\": \"PIL._imagingft\",\n    \"littlecms2\": \"PIL._imagingcms\",\n    \"webp\": \"PIL._webp\",\n}\n\n\ndef check_module(feature):\n    if not (feature in modules):\n        raise ValueError(\"Unknown module %s\" % feature)\n\n    module = modules[feature]\n\n    try:\n        __import__(module)\n        return True\n    except ImportError:\n        return False\n\n\ndef get_supported_modules():\n    return [f for f in modules if check_module(f)]\n\n\ncodecs = {\n    \"jpg\": \"jpeg\",\n    \"jpg_2000\": \"jpeg2k\",\n    \"zlib\": \"zip\",\n    \"libtiff\": \"libtiff\"\n}\n\n\ndef check_codec(feature):\n    if feature not in codecs:\n        raise ValueError(\"Unknown codec %s\" % feature)\n\n    codec = codecs[feature]\n\n    return codec + \"_encoder\" in dir(Image.core)\n\n\ndef get_supported_codecs():\n    return [f for f in codecs if check_codec(f)]\n\n\nfeatures = {\n    \"webp_anim\": (\"PIL._webp\", 'HAVE_WEBPANIM'),\n    \"webp_mux\": (\"PIL._webp\", 'HAVE_WEBPMUX'),\n    \"transp_webp\": (\"PIL._webp\", \"HAVE_TRANSPARENCY\"),\n    \"raqm\": (\"PIL._imagingft\", \"HAVE_RAQM\"),\n    \"libjpeg_turbo\": (\"PIL._imaging\", \"HAVE_LIBJPEGTURBO\"),\n}\n\n\ndef check_feature(feature):\n    if feature not in features:\n        raise ValueError(\"Unknown feature %s\" % feature)\n\n    module, flag = features[feature]\n\n    try:\n        imported_module = __import__(module, fromlist=['PIL'])\n        return getattr(imported_module, flag)\n    except ImportError:\n        return None\n\n\ndef get_supported_features():\n    return [f for f in features if check_feature(f)]\n\n\ndef check(feature):\n    return (feature in modules and check_module(feature) or\n            feature in codecs and check_codec(feature) or\n            feature in features and check_feature(feature))\n\n\ndef get_supported():\n    ret = get_supported_modules()\n    ret.extend(get_supported_features())\n    ret.extend(get_supported_codecs())\n    return ret\n", "path": "src/PIL/features.py"}]}