Repository: boto/botocore
Pull request #1170 (2017-03-23 19:08:24)

Decode config file paths
Fixes aws/aws-cli#2395

This was originally committed in #1144 but the tests failed on Windows due to some file system issues. This was resolved by creating the file on the fly and cleaning it up after.

I've run the tests (including integration) on several python versions on OSX, Linux, and Windows.

cc @kyleknap @jamesls @dstufft @stealthycoin 

codecov-io: # [Codecov](https://codecov.io/gh/boto/botocore/pull/1170?src=pr&el=h1) Report
> Merging [#1170](https://codecov.io/gh/boto/botocore/pull/1170?src=pr&el=desc) into [develop](https://codecov.io/gh/boto/botocore/commit/334daaa256727da97450728397b5f6173f2869e2?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `100%`.


```diff
@@             Coverage Diff             @@
##           develop    #1170      +/-   ##
===========================================
+ Coverage    97.96%   97.96%   +<.01%     
===========================================
  Files           45       45              
  Lines         7122     7127       +5     
===========================================
+ Hits          6977     6982       +5     
  Misses         145      145
```


| [Impacted Files](https://codecov.io/gh/boto/botocore/pull/1170?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [botocore/configloader.py](https://codecov.io/gh/boto/botocore/compare/334daaa256727da97450728397b5f6173f2869e2...50fbfa3d7ed13ef81cd90ed17ed77cd1fdd52eba?src=pr&el=tree#diff-Ym90b2NvcmUvY29uZmlnbG9hZGVyLnB5) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/boto/botocore/pull/1170?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/boto/botocore/pull/1170?src=pr&el=footer). Last update [334daaa...50fbfa3](https://codecov.io/gh/boto/botocore/compare/334daaa256727da97450728397b5f6173f2869e2...50fbfa3d7ed13ef81cd90ed17ed77cd1fdd52eba?src=pr&el=footer&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
JordonPhillips: Ran through the tests again, merging.

Patch:
diff --git a/.changes/1.5.29.json b/.changes/1.5.29.json
deleted file mode 100644
index 7a1a60ea8..000000000
--- a/.changes/1.5.29.json
+++ /dev/null
@@ -1,12 +0,0 @@
-[
-  {
-    "category": "``cloudtrail``", 
-    "description": "Update cloudtrail client to latest version", 
-    "type": "api-change"
-  }, 
-  {
-    "category": "``application-autoscaling``", 
-    "description": "Update application-autoscaling client to latest version", 
-    "type": "api-change"
-  }
-]
\ No newline at end of file
diff --git a/.changes/next-release/bugfix-config-8651.json b/.changes/next-release/bugfix-config-8651.json
new file mode 100644
index 000000000..e1baccb52
--- /dev/null
+++ b/.changes/next-release/bugfix-config-8651.json
@@ -0,0 +1,5 @@
+{
+  "description": "Fix a bug in loading config files from paths that contain non-ascii characters. Fixes aws/aws-cli`#2395 <https://github.com/boto/botocore/issues/2395>`__",
+  "category": "config",
+  "type": "bugfix"
+}
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 2d58487e0..b323ec54b 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,13 +2,6 @@
 CHANGELOG
 =========
 
-1.5.29
-======
-
-* api-change:``cloudtrail``: Update cloudtrail client to latest version
-* api-change:``application-autoscaling``: Update application-autoscaling client to latest version
-
-
 1.5.28
 ======
 
diff --git a/botocore/__init__.py b/botocore/__init__.py
index b206a4392..48986630d 100644
--- a/botocore/__init__.py
+++ b/botocore/__init__.py
@@ -16,7 +16,7 @@ import os
 import re
 import logging
 
-__version__ = '1.5.29'
+__version__ = '1.5.28'
 
 
 class NullHandler(logging.Handler):
diff --git a/botocore/configloader.py b/botocore/configloader.py
index 24d07b1c4..b9a4d542a 100644
--- a/botocore/configloader.py
+++ b/botocore/configloader.py
@@ -14,8 +14,9 @@
 import os
 import shlex
 import copy
+import sys
 
-from six.moves import configparser
+from botocore.compat import six
 
 import botocore.exceptions
 
@@ -142,12 +143,13 @@ def raw_config_parse(config_filename, parse_subsections=True):
         path = os.path.expandvars(path)
         path = os.path.expanduser(path)
         if not os.path.isfile(path):
-            raise botocore.exceptions.ConfigNotFound(path=path)
-        cp = configparser.RawConfigParser()
+            raise botocore.exceptions.ConfigNotFound(path=_unicode_path(path))
+        cp = six.moves.configparser.RawConfigParser()
         try:
-            cp.read(path)
-        except configparser.Error:
-            raise botocore.exceptions.ConfigParseError(path=path)
+            cp.read([path])
+        except six.moves.configparser.Error:
+            raise botocore.exceptions.ConfigParseError(
+                path=_unicode_path(path))
         else:
             for section in cp.sections():
                 config[section] = {}
@@ -161,11 +163,17 @@ def raw_config_parse(config_filename, parse_subsections=True):
                             config_value = _parse_nested(config_value)
                         except ValueError:
                             raise botocore.exceptions.ConfigParseError(
-                                path=path)
+                                path=_unicode_path(path))
                     config[section][option] = config_value
     return config
 
 
+def _unicode_path(path):
+    if isinstance(path, six.text_type):
+        return path
+    return path.decode(sys.getfilesystemencoding(), 'replace')
+
+
 def _parse_nested(config_value):
     # Given a value like this:
     # \n
diff --git a/botocore/data/application-autoscaling/2016-02-06/service-2.json b/botocore/data/application-autoscaling/2016-02-06/service-2.json
index fafcd9c74..443e0d6d1 100644
--- a/botocore/data/application-autoscaling/2016-02-06/service-2.json
+++ b/botocore/data/application-autoscaling/2016-02-06/service-2.json
@@ -186,11 +186,11 @@
         },
         "ResourceId":{
           "shape":"ResourceIdMaxLen1600",
-          "documentation":"<p>The identifier of the resource associated with the scalable target. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> <li> <p>AppStream 2.0 fleet - The resource type is <code>fleet</code> and the unique identifier is the fleet name. Example: <code>fleet/sample-fleet</code>.</p> </li> </ul>"
+          "documentation":"<p>The identifier of the resource associated with the scalable target. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> </ul>"
         },
         "ScalableDimension":{
           "shape":"ScalableDimension",
-          "documentation":"<p>The scalable dimension. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> <li> <p> <code>appstream:fleet:DesiredCapacity</code> - The desired capacity of an AppStream 2.0 fleet.</p> </li> </ul>"
+          "documentation":"<p>The scalable dimension. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> </ul>"
         }
       }
     },
@@ -213,11 +213,11 @@
         },
         "ResourceId":{
           "shape":"ResourceIdMaxLen1600",
-          "documentation":"<p>The identifier of the resource associated with the scalable target. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> <li> <p>AppStream 2.0 fleet - The resource type is <code>fleet</code> and the unique identifier is the fleet name. Example: <code>fleet/sample-fleet</code>.</p> </li> </ul>"
+          "documentation":"<p>The identifier of the resource associated with the scalable target. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> </ul>"
         },
         "ScalableDimension":{
           "shape":"ScalableDimension",
-          "documentation":"<p>The scalable dimension associated with the scalable target. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> <li> <p> <code>appstream:fleet:DesiredCapacity</code> - The desired capacity of an AppStream 2.0 fleet.</p> </li> </ul>"
+          "documentation":"<p>The scalable dimension associated with the scalable target. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> </ul>"
         }
       }
     },
@@ -236,11 +236,11 @@
         },
         "ResourceIds":{
           "shape":"ResourceIdsMaxLen1600",
-          "documentation":"<p>The identifier of the resource associated with the scalable target. This string consists of the resource type and unique identifier. If you specify a scalable dimension, you must also specify a resource ID.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> <li> <p>AppStream 2.0 fleet - The resource type is <code>fleet</code> and the unique identifier is the fleet name. Example: <code>fleet/sample-fleet</code>.</p> </li> </ul>"
+          "documentation":"<p>The identifier of the resource associated with the scalable target. This string consists of the resource type and unique identifier. If you specify a scalable dimension, you must also specify a resource ID.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> </ul>"
         },
         "ScalableDimension":{
           "shape":"ScalableDimension",
-          "documentation":"<p>The scalable dimension associated with the scalable target. This string consists of the service namespace, resource type, and scaling property. If you specify a scalable dimension, you must also specify a resource ID.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> <li> <p> <code>appstream:fleet:DesiredCapacity</code> - The desired capacity of an AppStream 2.0 fleet.</p> </li> </ul>"
+          "documentation":"<p>The scalable dimension associated with the scalable target. This string consists of the service namespace, resource type, and scaling property. If you specify a scalable dimension, you must also specify a resource ID.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> </ul>"
         },
         "MaxResults":{
           "shape":"MaxResults",
@@ -275,11 +275,11 @@
         },
         "ResourceId":{
           "shape":"ResourceIdMaxLen1600",
-          "documentation":"<p>The identifier of the resource associated with the scaling activity. This string consists of the resource type and unique identifier. If you specify a scalable dimension, you must also specify a resource ID.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> <li> <p>AppStream 2.0 fleet - The resource type is <code>fleet</code> and the unique identifier is the fleet name. Example: <code>fleet/sample-fleet</code>.</p> </li> </ul>"
+          "documentation":"<p>The identifier of the resource associated with the scaling activity. This string consists of the resource type and unique identifier. If you specify a scalable dimension, you must also specify a resource ID.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> </ul>"
         },
         "ScalableDimension":{
           "shape":"ScalableDimension",
-          "documentation":"<p>The scalable dimension. This string consists of the service namespace, resource type, and scaling property. If you specify a scalable dimension, you must also specify a resource ID.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> <li> <p> <code>appstream:fleet:DesiredCapacity</code> - The desired capacity of an AppStream 2.0 fleet.</p> </li> </ul>"
+          "documentation":"<p>The scalable dimension. This string consists of the service namespace, resource type, and scaling property. If you specify a scalable dimension, you must also specify a resource ID.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> </ul>"
         },
         "MaxResults":{
           "shape":"MaxResults",
@@ -318,11 +318,11 @@
         },
         "ResourceId":{
           "shape":"ResourceIdMaxLen1600",
-          "documentation":"<p>The identifier of the resource associated with the scaling policy. This string consists of the resource type and unique identifier. If you specify a scalable dimension, you must also specify a resource ID.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> <li> <p>AppStream 2.0 fleet - The resource type is <code>fleet</code> and the unique identifier is the fleet name. Example: <code>fleet/sample-fleet</code>.</p> </li> </ul>"
+          "documentation":"<p>The identifier of the resource associated with the scaling policy. This string consists of the resource type and unique identifier. If you specify a scalable dimension, you must also specify a resource ID.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> </ul>"
         },
         "ScalableDimension":{
           "shape":"ScalableDimension",
-          "documentation":"<p>The scalable dimension. This string consists of the service namespace, resource type, and scaling property. If you specify a scalable dimension, you must also specify a resource ID.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> <li> <p> <code>appstream:fleet:DesiredCapacity</code> - The desired capacity of an AppStream 2.0 fleet.</p> </li> </ul>"
+          "documentation":"<p>The scalable dimension. This string consists of the service namespace, resource type, and scaling property. If you specify a scalable dimension, you must also specify a resource ID.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> </ul>"
         },
         "MaxResults":{
           "shape":"MaxResults",
@@ -428,11 +428,11 @@
         },
         "ResourceId":{
           "shape":"ResourceIdMaxLen1600",
-          "documentation":"<p>The identifier of the resource associated with the scaling policy. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> <li> <p>AppStream 2.0 fleet - The resource type is <code>fleet</code> and the unique identifier is the fleet name. Example: <code>fleet/sample-fleet</code>.</p> </li> </ul>"
+          "documentation":"<p>The identifier of the resource associated with the scaling policy. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> </ul>"
         },
         "ScalableDimension":{
           "shape":"ScalableDimension",
-          "documentation":"<p>The scalable dimension. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> <li> <p> <code>appstream:fleet:DesiredCapacity</code> - The desired capacity of an AppStream 2.0 fleet.</p> </li> </ul>"
+          "documentation":"<p>The scalable dimension. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> </ul>"
         },
         "PolicyType":{
           "shape":"PolicyType",
@@ -468,11 +468,11 @@
         },
         "ResourceId":{
           "shape":"ResourceIdMaxLen1600",
-          "documentation":"<p>The identifier of the resource associated with the scalable target. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> <li> <p>AppStream 2.0 fleet - The resource type is <code>fleet</code> and the unique identifier is the fleet name. Example: <code>fleet/sample-fleet</code>.</p> </li> </ul>"
+          "documentation":"<p>The identifier of the resource associated with the scalable target. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> </ul>"
         },
         "ScalableDimension":{
           "shape":"ScalableDimension",
-          "documentation":"<p>The scalable dimension associated with the scalable target. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> <li> <p> <code>appstream:fleet:DesiredCapacity</code> - The desired capacity of an AppStream 2.0 fleet.</p> </li> </ul>"
+          "documentation":"<p>The scalable dimension associated with the scalable target. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> </ul>"
         },
         "MinCapacity":{
           "shape":"ResourceCapacity",
@@ -513,8 +513,7 @@
       "enum":[
         "ecs:service:DesiredCount",
         "ec2:spot-fleet-request:TargetCapacity",
-        "elasticmapreduce:instancegroup:InstanceCount",
-        "appstream:fleet:DesiredCapacity"
+        "elasticmapreduce:instancegroup:InstanceCount"
       ]
     },
     "ScalableTarget":{
@@ -535,11 +534,11 @@
         },
         "ResourceId":{
           "shape":"ResourceIdMaxLen1600",
-          "documentation":"<p>The identifier of the resource associated with the scalable target. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> <li> <p>AppStream 2.0 fleet - The resource type is <code>fleet</code> and the unique identifier is the fleet name. Example: <code>fleet/sample-fleet</code>.</p> </li> </ul>"
+          "documentation":"<p>The identifier of the resource associated with the scalable target. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> </ul>"
         },
         "ScalableDimension":{
           "shape":"ScalableDimension",
-          "documentation":"<p>The scalable dimension associated with the scalable target. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> <li> <p> <code>appstream:fleet:DesiredCapacity</code> - The desired capacity of an AppStream 2.0 fleet.</p> </li> </ul>"
+          "documentation":"<p>The scalable dimension associated with the scalable target. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> </ul>"
         },
         "MinCapacity":{
           "shape":"ResourceCapacity",
@@ -591,11 +590,11 @@
         },
         "ResourceId":{
           "shape":"ResourceIdMaxLen1600",
-          "documentation":"<p>The identifier of the resource associated with the scaling activity. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> <li> <p>AppStream 2.0 fleet - The resource type is <code>fleet</code> and the unique identifier is the fleet name. Example: <code>fleet/sample-fleet</code>.</p> </li> </ul>"
+          "documentation":"<p>The identifier of the resource associated with the scaling activity. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> </ul>"
         },
         "ScalableDimension":{
           "shape":"ScalableDimension",
-          "documentation":"<p>The scalable dimension. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> <li> <p> <code>appstream:fleet:DesiredCapacity</code> - The desired capacity of an AppStream 2.0 fleet.</p> </li> </ul>"
+          "documentation":"<p>The scalable dimension. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> </ul>"
         },
         "Description":{
           "shape":"XmlString",
@@ -670,11 +669,11 @@
         },
         "ResourceId":{
           "shape":"ResourceIdMaxLen1600",
-          "documentation":"<p>The identifier of the resource associated with the scaling policy. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> <li> <p>AppStream 2.0 fleet - The resource type is <code>fleet</code> and the unique identifier is the fleet name. Example: <code>fleet/sample-fleet</code>.</p> </li> </ul>"
+          "documentation":"<p>The identifier of the resource associated with the scaling policy. This string consists of the resource type and unique identifier.</p> <ul> <li> <p>ECS service - The resource type is <code>service</code> and the unique identifier is the cluster name and service name. Example: <code>service/default/sample-webapp</code>.</p> </li> <li> <p>Spot fleet request - The resource type is <code>spot-fleet-request</code> and the unique identifier is the Spot fleet request ID. Example: <code>spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE</code>.</p> </li> <li> <p>EMR cluster - The resource type is <code>instancegroup</code> and the unique identifier is the cluster ID and instance group ID. Example: <code>instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0</code>.</p> </li> </ul>"
         },
         "ScalableDimension":{
           "shape":"ScalableDimension",
-          "documentation":"<p>The scalable dimension. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> <li> <p> <code>appstream:fleet:DesiredCapacity</code> - The desired capacity of an AppStream 2.0 fleet.</p> </li> </ul>"
+          "documentation":"<p>The scalable dimension. This string consists of the service namespace, resource type, and scaling property.</p> <ul> <li> <p> <code>ecs:service:DesiredCount</code> - The desired task count of an ECS service.</p> </li> <li> <p> <code>ec2:spot-fleet-request:TargetCapacity</code> - The target capacity of a Spot fleet request.</p> </li> <li> <p> <code>elasticmapreduce:instancegroup:InstanceCount</code> - The instance count of an EMR Instance Group.</p> </li> </ul>"
         },
         "PolicyType":{
           "shape":"PolicyType",
@@ -700,8 +699,7 @@
       "enum":[
         "ecs",
         "elasticmapreduce",
-        "ec2",
-        "appstream"
+        "ec2"
       ]
     },
     "StepAdjustment":{
@@ -767,5 +765,5 @@
       "pattern":"[\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDC00-\\uDBFF\\uDFFF\\r\\n\\t]*"
     }
   },
-  "documentation":"<p>With Application Auto Scaling, you can automatically scale your AWS resources. The experience similar to that of <a href=\"https://aws.amazon.com/autoscaling/\">Auto Scaling</a>. You can use Application Auto Scaling to accomplish the following tasks:</p> <ul> <li> <p>Define scaling policies to automatically scale your AWS resources</p> </li> <li> <p>Scale your resources in response to CloudWatch alarms</p> </li> <li> <p>View the history of your scaling events</p> </li> </ul> <p>Application Auto Scaling can scale the following AWS resources:</p> <ul> <li> <p>Amazon ECS services. For more information, see <a href=\"http://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-auto-scaling.html\">Service Auto Scaling</a> in the <i>Amazon EC2 Container Service Developer Guide</i>.</p> </li> <li> <p>Amazon EC2 Spot fleets. For more information, see <a href=\"http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/fleet-auto-scaling.html\">Automatic Scaling for Spot Fleet</a> in the <i>Amazon EC2 User Guide</i>.</p> </li> <li> <p>Amazon EMR clusters. For more information, see <a href=\"http://docs.aws.amazon.com/ElasticMapReduce/latest/ManagementGuide/emr-automatic-scaling.html\">Using Automatic Scaling in Amazon EMR</a> in the <i>Amazon EMR Management Guide</i>.</p> </li> <li> <p>AppStream 2.0 fleets. For more information, see <a href=\"http://docs.aws.amazon.com/appstream2/latest/developerguide/autoscaling.html\">Autoscaling Amazon AppStream 2.0 Resources</a> in the <i>Amazon AppStream 2.0 Developer Guide</i>.</p> </li> </ul> <p>For a list of supported regions, see <a href=\"http://docs.aws.amazon.com/general/latest/gr/rande.html#as-app_region\">AWS Regions and Endpoints: Application Auto Scaling</a> in the <i>AWS General Reference</i>.</p>"
+  "documentation":"<p>With Application Auto Scaling, you can automatically scale your AWS resources. The experience similar to that of <a href=\"https://aws.amazon.com/autoscaling/\">Auto Scaling</a>. You can use Application Auto Scaling to accomplish the following tasks:</p> <ul> <li> <p>Define scaling policies to automatically scale your AWS resources</p> </li> <li> <p>Scale your resources in response to CloudWatch alarms</p> </li> <li> <p>View the history of your scaling events</p> </li> </ul> <p>Application Auto Scaling can scale the following AWS resources:</p> <ul> <li> <p>Amazon ECS services. For more information, see <a href=\"http://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-auto-scaling.html\">Service Auto Scaling</a> in the <i>Amazon EC2 Container Service Developer Guide</i>.</p> </li> <li> <p>Amazon EC2 Spot fleets. For more information, see <a href=\"http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/fleet-auto-scaling.html\">Automatic Scaling for Spot Fleet</a> in the <i>Amazon EC2 User Guide</i>.</p> </li> <li> <p>Amazon EMR clusters. For more information, see <a href=\"http://docs.aws.amazon.com/ElasticMapReduce/latest/ManagementGuide/emr-automatic-scaling.html\">Using Automatic Scaling in Amazon EMR</a> in the <i>Amazon EMR Management Guide</i>.</p> </li> </ul> <p>For a list of supported regions, see <a href=\"http://docs.aws.amazon.com/general/latest/gr/rande.html#as-app_region\">AWS Regions and Endpoints: Application Auto Scaling</a> in the <i>AWS General Reference</i>.</p>"
 }
diff --git a/botocore/data/cloudtrail/2013-11-01/service-2.json b/botocore/data/cloudtrail/2013-11-01/service-2.json
index d3bf58732..93e19c501 100644
--- a/botocore/data/cloudtrail/2013-11-01/service-2.json
+++ b/botocore/data/cloudtrail/2013-11-01/service-2.json
@@ -559,7 +559,6 @@
     },
     "GetEventSelectorsRequest":{
       "type":"structure",
-      "required":["TrailName"],
       "members":{
         "TrailName":{
           "shape":"String",
@@ -870,10 +869,7 @@
     "ListTagsResponse":{
       "type":"structure",
       "members":{
-        "ResourceTagList":{
-          "shape":"ResourceTagList",
-          "documentation":"<p>A list of resource tags.</p>"
-        },
+        "ResourceTagList":{"shape":"ResourceTagList"},
         "NextToken":{
           "shape":"String",
           "documentation":"<p>Reserved for future use.</p>"
@@ -1002,10 +998,6 @@
     },
     "PutEventSelectorsRequest":{
       "type":"structure",
-      "required":[
-        "TrailName",
-        "EventSelectors"
-      ],
       "members":{
         "TrailName":{
           "shape":"String",
@@ -1096,16 +1088,14 @@
           "shape":"String",
           "documentation":"<p>Specifies the ARN of the resource.</p>"
         },
-        "TagsList":{
-          "shape":"TagsList",
-          "documentation":"<p>A list of tags.</p>"
-        }
+        "TagsList":{"shape":"TagsList"}
       },
       "documentation":"<p>A resource tag.</p>"
     },
     "ResourceTagList":{
       "type":"list",
-      "member":{"shape":"ResourceTag"}
+      "member":{"shape":"ResourceTag"},
+      "documentation":"<p>A list of resource tags.</p>"
     },
     "ResourceTypeNotSupportedException":{
       "type":"structure",
diff --git a/botocore/docs/client.py b/botocore/docs/client.py
index f69bf1f47..bbb06d7a9 100644
--- a/botocore/docs/client.py
+++ b/botocore/docs/client.py
@@ -56,10 +56,8 @@ class ClientDocumenter(object):
         section.style.new_line()
         section.write('These are the available methods:')
         section.style.new_line()
-        class_name = self._client.__class__.__name__
         for method_name in sorted(client_methods):
-            section.style.li(':py:meth:`~%s.Client.%s`' % (
-                class_name, method_name))
+            section.style.li(':py:meth:`%s`' % (method_name))
 
     def _add_class_signature(self, section):
         section.style.start_sphinx_py_class(
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 45be033a7..e67e7bda9 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -54,7 +54,7 @@ copyright = u'2013, Mitch Garnaat'
 # The short X.Y version.
 version = '1.5.'
 # The full version, including alpha/beta/rc tags.
-release = '1.5.29'
+release = '1.5.28'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.


Test patch:
diff --git a/tests/unit/docs/test_client.py b/tests/unit/docs/test_client.py
index d50b75687..f041a3cff 100644
--- a/tests/unit/docs/test_client.py
+++ b/tests/unit/docs/test_client.py
@@ -31,10 +31,10 @@ class TestClientDocumenter(BaseDocsTest):
             '  A low-level client representing AWS MyService::',
             '    client = session.create_client(\'myservice\')',
             '  These are the available methods:',
-            '  *   :py:meth:`~MyService.Client.can_paginate`',
-            '  *   :py:meth:`~MyService.Client.get_paginator`',
-            '  *   :py:meth:`~MyService.Client.get_waiter`',
-            '  *   :py:meth:`~MyService.Client.sample_operation`',
+            '  *   :py:meth:`can_paginate`',
+            '  *   :py:meth:`get_paginator`',
+            '  *   :py:meth:`get_waiter`',
+            '  *   :py:meth:`sample_operation`',
             '  .. py:method:: can_paginate(operation_name)',
             '  .. py:method:: get_paginator(operation_name)',
             '  .. py:method:: get_waiter(waiter_name)',
diff --git a/tests/unit/docs/test_service.py b/tests/unit/docs/test_service.py
index 8eb896c63..f43f5a627 100644
--- a/tests/unit/docs/test_service.py
+++ b/tests/unit/docs/test_service.py
@@ -47,7 +47,7 @@ class TestServiceDocumenter(BaseDocsTest):
             '  A low-level client representing AWS MyService::',
             '    client = session.create_client(\'myservice\')',
             '  These are the available methods:',
-            '  *   :py:meth:`~MyService.Client.sample_operation`',
+            '  *   :py:meth:`sample_operation`',
             '  .. py:method:: sample_operation(**kwargs)',
             '    **Examples** ',
             '    Sample Description.',
diff --git a/tests/unit/test_configloader.py b/tests/unit/test_configloader.py
index e20aba72f..6757cff0f 100644
--- a/tests/unit/test_configloader.py
+++ b/tests/unit/test_configloader.py
@@ -14,16 +14,49 @@
 # language governing permissions and limitations under the License.
 from tests import unittest, BaseEnvVar
 import os
+import mock
+import tempfile
+import shutil
+
 import botocore.exceptions
 from botocore.configloader import raw_config_parse, load_config, \
     multi_file_load_config
+from botocore.compat import six
 
 
 def path(filename):
-    return os.path.join(os.path.dirname(__file__), 'cfg', filename)
+    directory = os.path.join(os.path.dirname(__file__), 'cfg')
+    if isinstance(filename, six.binary_type):
+        directory = six.b(directory)
+    return os.path.join(directory, filename)
 
 
 class TestConfigLoader(BaseEnvVar):
+    def setUp(self):
+        self.tempdir = tempfile.mkdtemp()
+
+    def tearDown(self):
+        shutil.rmtree(self.tempdir)
+
+    def create_config_file(self, filename):
+        contents = (
+            '[default]\n'
+            'aws_access_key_id = foo\n'
+            'aws_secret_access_key = bar\n\n'
+            '[profile "personal"]\n'
+            'aws_access_key_id = fie\n'
+            'aws_secret_access_key = baz\n'
+            'aws_security_token = fiebaz\n'
+        )
+
+        directory = self.tempdir
+        if isinstance(filename, six.binary_type):
+            directory = six.b(directory)
+        full_path = os.path.join(directory, filename)
+
+        with open(full_path, 'w') as f:
+            f.write(contents)
+        return full_path
 
     def test_config_not_found(self):
         with self.assertRaises(botocore.exceptions.ConfigNotFound):
@@ -103,6 +136,20 @@ class TestConfigLoader(BaseEnvVar):
         self.assertEqual(third_config['aws_secret_access_key'], 'third_baz')
         self.assertEqual(third_config['aws_security_token'], 'third_fiebaz')
 
+    def test_unicode_bytes_path_not_found(self):
+        with self.assertRaises(botocore.exceptions.ConfigNotFound):
+            with mock.patch('sys.getfilesystemencoding') as encoding:
+                encoding.return_value = 'utf-8'
+                load_config(path(b'\xe2\x9c\x93'))
+
+    def test_unicode_bytes_path(self):
+        filename = self.create_config_file(b'aws_config_unicode\xe2\x9c\x93')
+        with mock.patch('sys.getfilesystemencoding') as encoding:
+            encoding.return_value = 'utf-8'
+            loaded_config = load_config(filename)
+        self.assertIn('default', loaded_config['profiles'])
+        self.assertIn('personal', loaded_config['profiles'])
+
 
 if __name__ == "__main__":
     unittest.main()