We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Instances of `tempfile.TemporaryFile` fail when used as an upload file.
When using `tempfile.TemporaryFile` the `file.name` attribute returns an integer, rather than the usual path string, which causes a breakage for us further down the line...

```shell
venv/lib/python3.7/site-packages/httpx/client.py:484: in post
    trust_env=trust_env,
venv/lib/python3.7/site-packages/httpx/client.py:616: in request
    cookies=cookies,
venv/lib/python3.7/site-packages/httpx/client.py:356: in build_request
    cookies=cookies,
venv/lib/python3.7/site-packages/httpx/models.py:696: in __init__
    content, content_type = self.encode_data(data, files, json)
venv/lib/python3.7/site-packages/httpx/models.py:619: in encode_data
    content, content_type = multipart_encode(data or {}, files)
venv/lib/python3.7/site-packages/httpx/multipart.py:100: in multipart_encode
    for field in iter_fields(data, files):
venv/lib/python3.7/site-packages/httpx/multipart.py:93: in iter_fields
    yield FileField(name=name, value=value)
venv/lib/python3.7/site-packages/httpx/multipart.py:51: in __init__
    self.filename = Path(getattr(value, "name", "upload")).name
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/pathlib.py:994: in __new__
    self = cls._from_parts(args, init=False)
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/pathlib.py:649: in _from_parts
    drv, root, parts = self._parse_args(args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

cls = <class 'pathlib.PosixPath'>, args = (29,)

    @classmethod
    def _parse_args(cls, args):
        # This is useful when you don't want to create an instance, just
        # canonicalize some constructor arguments.
        parts = []
        for a in args:
            if isinstance(a, PurePath):
                parts += a._parts
            else:
>               a = os.fspath(a)
E               TypeError: expected str, bytes or os.PathLike object, not int
```

Have also confirmed that the issue *doesn't* occur with `tempfile.NamedTemporaryFile`.

I believe the resolution will be on this line...

https://github.com/encode/httpx/blob/1a32cf036a825f6eb35395af5388a3b23180a82e/httpx/multipart.py#L51

I assume that this would be sufficient...

```python
self.filename = Path(str(getattr(value, "name", "upload")).name 
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `httpx/multipart.py`
Content:
```
1 import binascii
2 import mimetypes
3 import os
4 import re
5 import typing
6 from io import BytesIO
7 from pathlib import Path
8 
9 _HTML5_FORM_ENCODING_REPLACEMENTS = {'"': "%22", "\\": "\\\\"}
10 _HTML5_FORM_ENCODING_REPLACEMENTS.update(
11     {chr(c): "%{:02X}".format(c) for c in range(0x00, 0x1F + 1) if c != 0x1B}
12 )
13 _HTML5_FORM_ENCODING_RE = re.compile(
14     r"|".join([re.escape(c) for c in _HTML5_FORM_ENCODING_REPLACEMENTS.keys()])
15 )
16 
17 
18 class Field:
19     def render_headers(self) -> bytes:
20         raise NotImplementedError()  # pragma: nocover
21 
22     def render_data(self) -> bytes:
23         raise NotImplementedError()  # pragma: nocover
24 
25 
26 class DataField(Field):
27     def __init__(self, name: str, value: typing.Union[str, bytes]) -> None:
28         if not isinstance(name, str):
29             raise TypeError("Invalid type for name. Expected str.")
30         if not isinstance(value, (str, bytes)):
31             raise TypeError("Invalid type for value. Expected str or bytes.")
32         self.name = name
33         self.value = value
34 
35     def render_headers(self) -> bytes:
36         name = _format_param("name", self.name)
37         return b"".join([b"Content-Disposition: form-data; ", name, b"\r\n\r\n"])
38 
39     def render_data(self) -> bytes:
40         return (
41             self.value if isinstance(self.value, bytes) else self.value.encode("utf-8")
42         )
43 
44 
45 class FileField(Field):
46     def __init__(
47         self, name: str, value: typing.Union[typing.IO[typing.AnyStr], tuple]
48     ) -> None:
49         self.name = name
50         if not isinstance(value, tuple):
51             self.filename = Path(getattr(value, "name", "upload")).name
52             self.file = value  # type: typing.Union[typing.IO[str], typing.IO[bytes]]
53             self.content_type = self.guess_content_type()
54         else:
55             self.filename = value[0]
56             self.file = value[1]
57             self.content_type = (
58                 value[2] if len(value) > 2 else self.guess_content_type()
59             )
60 
61     def guess_content_type(self) -> str:
62         if self.filename:
63             return mimetypes.guess_type(self.filename)[0] or "application/octet-stream"
64         else:
65             return "application/octet-stream"
66 
67     def render_headers(self) -> bytes:
68         parts = [b"Content-Disposition: form-data; ", _format_param("name", self.name)]
69         if self.filename:
70             filename = _format_param("filename", self.filename)
71             parts.extend([b"; ", filename])
72         content_type = self.content_type.encode()
73         parts.extend([b"\r\nContent-Type: ", content_type, b"\r\n\r\n"])
74         return b"".join(parts)
75 
76     def render_data(self) -> bytes:
77         if isinstance(self.file, str):
78             content = self.file
79         else:
80             content = self.file.read()
81         return content.encode("utf-8") if isinstance(content, str) else content
82 
83 
84 def iter_fields(data: dict, files: dict) -> typing.Iterator[Field]:
85     for name, value in data.items():
86         if isinstance(value, (list, dict)):
87             for item in value:
88                 yield DataField(name=name, value=item)
89         else:
90             yield DataField(name=name, value=value)
91 
92     for name, value in files.items():
93         yield FileField(name=name, value=value)
94 
95 
96 def multipart_encode(data: dict, files: dict) -> typing.Tuple[bytes, str]:
97     body = BytesIO()
98     boundary = binascii.hexlify(os.urandom(16))
99 
100     for field in iter_fields(data, files):
101         body.write(b"--%s\r\n" % boundary)
102         body.write(field.render_headers())
103         body.write(field.render_data())
104         body.write(b"\r\n")
105 
106     body.write(b"--%s--\r\n" % boundary)
107 
108     content_type = "multipart/form-data; boundary=%s" % boundary.decode("ascii")
109 
110     return body.getvalue(), content_type
111 
112 
113 def _format_param(name: str, value: typing.Union[str, bytes]) -> bytes:
114     if isinstance(value, bytes):
115         value = value.decode()
116 
117     def replacer(match: typing.Match[str]) -> str:
118         return _HTML5_FORM_ENCODING_REPLACEMENTS[match.group(0)]
119 
120     value = _HTML5_FORM_ENCODING_RE.sub(replacer, value)
121     return f'{name}="{value}"'.encode()
122
```
--- 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()

```

diff --git a/httpx/multipart.py b/httpx/multipart.py
--- a/httpx/multipart.py
+++ b/httpx/multipart.py
@@ -48,7 +48,7 @@
     ) -> None:
         self.name = name
         if not isinstance(value, tuple):
-            self.filename = Path(getattr(value, "name", "upload")).name
+            self.filename = Path(str(getattr(value, "name", "upload"))).name
             self.file = value  # type: typing.Union[typing.IO[str], typing.IO[bytes]]
             self.content_type = self.guess_content_type()
         else:

{"golden_diff": "diff --git a/httpx/multipart.py b/httpx/multipart.py\n--- a/httpx/multipart.py\n+++ b/httpx/multipart.py\n@@ -48,7 +48,7 @@\n     ) -> None:\n         self.name = name\n         if not isinstance(value, tuple):\n-            self.filename = Path(getattr(value, \"name\", \"upload\")).name\n+            self.filename = Path(str(getattr(value, \"name\", \"upload\"))).name\n             self.file = value  # type: typing.Union[typing.IO[str], typing.IO[bytes]]\n             self.content_type = self.guess_content_type()\n         else:\n", "issue": "Instances of `tempfile.TemporaryFile` fail when used as an upload file.\nWhen using `tempfile.TemporaryFile` the `file.name` attribute returns an integer, rather than the usual path string, which causes a breakage for us further down the line...\r\n\r\n```shell\r\nvenv/lib/python3.7/site-packages/httpx/client.py:484: in post\r\n    trust_env=trust_env,\r\nvenv/lib/python3.7/site-packages/httpx/client.py:616: in request\r\n    cookies=cookies,\r\nvenv/lib/python3.7/site-packages/httpx/client.py:356: in build_request\r\n    cookies=cookies,\r\nvenv/lib/python3.7/site-packages/httpx/models.py:696: in __init__\r\n    content, content_type = self.encode_data(data, files, json)\r\nvenv/lib/python3.7/site-packages/httpx/models.py:619: in encode_data\r\n    content, content_type = multipart_encode(data or {}, files)\r\nvenv/lib/python3.7/site-packages/httpx/multipart.py:100: in multipart_encode\r\n    for field in iter_fields(data, files):\r\nvenv/lib/python3.7/site-packages/httpx/multipart.py:93: in iter_fields\r\n    yield FileField(name=name, value=value)\r\nvenv/lib/python3.7/site-packages/httpx/multipart.py:51: in __init__\r\n    self.filename = Path(getattr(value, \"name\", \"upload\")).name\r\n/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/pathlib.py:994: in __new__\r\n    self = cls._from_parts(args, init=False)\r\n/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/pathlib.py:649: in _from_parts\r\n    drv, root, parts = self._parse_args(args)\r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\r\n\r\ncls = <class 'pathlib.PosixPath'>, args = (29,)\r\n\r\n    @classmethod\r\n    def _parse_args(cls, args):\r\n        # This is useful when you don't want to create an instance, just\r\n        # canonicalize some constructor arguments.\r\n        parts = []\r\n        for a in args:\r\n            if isinstance(a, PurePath):\r\n                parts += a._parts\r\n            else:\r\n>               a = os.fspath(a)\r\nE               TypeError: expected str, bytes or os.PathLike object, not int\r\n```\r\n\r\nHave also confirmed that the issue *doesn't* occur with `tempfile.NamedTemporaryFile`.\r\n\r\nI believe the resolution will be on this line...\r\n\r\nhttps://github.com/encode/httpx/blob/1a32cf036a825f6eb35395af5388a3b23180a82e/httpx/multipart.py#L51\r\n\r\nI assume that this would be sufficient...\r\n\r\n```python\r\nself.filename = Path(str(getattr(value, \"name\", \"upload\")).name \r\n```\r\n\n", "before_files": [{"content": "import binascii\nimport mimetypes\nimport os\nimport re\nimport typing\nfrom io import BytesIO\nfrom pathlib import Path\n\n_HTML5_FORM_ENCODING_REPLACEMENTS = {'\"': \"%22\", \"\\\\\": \"\\\\\\\\\"}\n_HTML5_FORM_ENCODING_REPLACEMENTS.update(\n    {chr(c): \"%{:02X}\".format(c) for c in range(0x00, 0x1F + 1) if c != 0x1B}\n)\n_HTML5_FORM_ENCODING_RE = re.compile(\n    r\"|\".join([re.escape(c) for c in _HTML5_FORM_ENCODING_REPLACEMENTS.keys()])\n)\n\n\nclass Field:\n    def render_headers(self) -> bytes:\n        raise NotImplementedError()  # pragma: nocover\n\n    def render_data(self) -> bytes:\n        raise NotImplementedError()  # pragma: nocover\n\n\nclass DataField(Field):\n    def __init__(self, name: str, value: typing.Union[str, bytes]) -> None:\n        if not isinstance(name, str):\n            raise TypeError(\"Invalid type for name. Expected str.\")\n        if not isinstance(value, (str, bytes)):\n            raise TypeError(\"Invalid type for value. Expected str or bytes.\")\n        self.name = name\n        self.value = value\n\n    def render_headers(self) -> bytes:\n        name = _format_param(\"name\", self.name)\n        return b\"\".join([b\"Content-Disposition: form-data; \", name, b\"\\r\\n\\r\\n\"])\n\n    def render_data(self) -> bytes:\n        return (\n            self.value if isinstance(self.value, bytes) else self.value.encode(\"utf-8\")\n        )\n\n\nclass FileField(Field):\n    def __init__(\n        self, name: str, value: typing.Union[typing.IO[typing.AnyStr], tuple]\n    ) -> None:\n        self.name = name\n        if not isinstance(value, tuple):\n            self.filename = Path(getattr(value, \"name\", \"upload\")).name\n            self.file = value  # type: typing.Union[typing.IO[str], typing.IO[bytes]]\n            self.content_type = self.guess_content_type()\n        else:\n            self.filename = value[0]\n            self.file = value[1]\n            self.content_type = (\n                value[2] if len(value) > 2 else self.guess_content_type()\n            )\n\n    def guess_content_type(self) -> str:\n        if self.filename:\n            return mimetypes.guess_type(self.filename)[0] or \"application/octet-stream\"\n        else:\n            return \"application/octet-stream\"\n\n    def render_headers(self) -> bytes:\n        parts = [b\"Content-Disposition: form-data; \", _format_param(\"name\", self.name)]\n        if self.filename:\n            filename = _format_param(\"filename\", self.filename)\n            parts.extend([b\"; \", filename])\n        content_type = self.content_type.encode()\n        parts.extend([b\"\\r\\nContent-Type: \", content_type, b\"\\r\\n\\r\\n\"])\n        return b\"\".join(parts)\n\n    def render_data(self) -> bytes:\n        if isinstance(self.file, str):\n            content = self.file\n        else:\n            content = self.file.read()\n        return content.encode(\"utf-8\") if isinstance(content, str) else content\n\n\ndef iter_fields(data: dict, files: dict) -> typing.Iterator[Field]:\n    for name, value in data.items():\n        if isinstance(value, (list, dict)):\n            for item in value:\n                yield DataField(name=name, value=item)\n        else:\n            yield DataField(name=name, value=value)\n\n    for name, value in files.items():\n        yield FileField(name=name, value=value)\n\n\ndef multipart_encode(data: dict, files: dict) -> typing.Tuple[bytes, str]:\n    body = BytesIO()\n    boundary = binascii.hexlify(os.urandom(16))\n\n    for field in iter_fields(data, files):\n        body.write(b\"--%s\\r\\n\" % boundary)\n        body.write(field.render_headers())\n        body.write(field.render_data())\n        body.write(b\"\\r\\n\")\n\n    body.write(b\"--%s--\\r\\n\" % boundary)\n\n    content_type = \"multipart/form-data; boundary=%s\" % boundary.decode(\"ascii\")\n\n    return body.getvalue(), content_type\n\n\ndef _format_param(name: str, value: typing.Union[str, bytes]) -> bytes:\n    if isinstance(value, bytes):\n        value = value.decode()\n\n    def replacer(match: typing.Match[str]) -> str:\n        return _HTML5_FORM_ENCODING_REPLACEMENTS[match.group(0)]\n\n    value = _HTML5_FORM_ENCODING_RE.sub(replacer, value)\n    return f'{name}=\"{value}\"'.encode()\n", "path": "httpx/multipart.py"}], "after_files": [{"content": "import binascii\nimport mimetypes\nimport os\nimport re\nimport typing\nfrom io import BytesIO\nfrom pathlib import Path\n\n_HTML5_FORM_ENCODING_REPLACEMENTS = {'\"': \"%22\", \"\\\\\": \"\\\\\\\\\"}\n_HTML5_FORM_ENCODING_REPLACEMENTS.update(\n    {chr(c): \"%{:02X}\".format(c) for c in range(0x00, 0x1F + 1) if c != 0x1B}\n)\n_HTML5_FORM_ENCODING_RE = re.compile(\n    r\"|\".join([re.escape(c) for c in _HTML5_FORM_ENCODING_REPLACEMENTS.keys()])\n)\n\n\nclass Field:\n    def render_headers(self) -> bytes:\n        raise NotImplementedError()  # pragma: nocover\n\n    def render_data(self) -> bytes:\n        raise NotImplementedError()  # pragma: nocover\n\n\nclass DataField(Field):\n    def __init__(self, name: str, value: typing.Union[str, bytes]) -> None:\n        if not isinstance(name, str):\n            raise TypeError(\"Invalid type for name. Expected str.\")\n        if not isinstance(value, (str, bytes)):\n            raise TypeError(\"Invalid type for value. Expected str or bytes.\")\n        self.name = name\n        self.value = value\n\n    def render_headers(self) -> bytes:\n        name = _format_param(\"name\", self.name)\n        return b\"\".join([b\"Content-Disposition: form-data; \", name, b\"\\r\\n\\r\\n\"])\n\n    def render_data(self) -> bytes:\n        return (\n            self.value if isinstance(self.value, bytes) else self.value.encode(\"utf-8\")\n        )\n\n\nclass FileField(Field):\n    def __init__(\n        self, name: str, value: typing.Union[typing.IO[typing.AnyStr], tuple]\n    ) -> None:\n        self.name = name\n        if not isinstance(value, tuple):\n            self.filename = Path(str(getattr(value, \"name\", \"upload\"))).name\n            self.file = value  # type: typing.Union[typing.IO[str], typing.IO[bytes]]\n            self.content_type = self.guess_content_type()\n        else:\n            self.filename = value[0]\n            self.file = value[1]\n            self.content_type = (\n                value[2] if len(value) > 2 else self.guess_content_type()\n            )\n\n    def guess_content_type(self) -> str:\n        if self.filename:\n            return mimetypes.guess_type(self.filename)[0] or \"application/octet-stream\"\n        else:\n            return \"application/octet-stream\"\n\n    def render_headers(self) -> bytes:\n        parts = [b\"Content-Disposition: form-data; \", _format_param(\"name\", self.name)]\n        if self.filename:\n            filename = _format_param(\"filename\", self.filename)\n            parts.extend([b\"; \", filename])\n        content_type = self.content_type.encode()\n        parts.extend([b\"\\r\\nContent-Type: \", content_type, b\"\\r\\n\\r\\n\"])\n        return b\"\".join(parts)\n\n    def render_data(self) -> bytes:\n        if isinstance(self.file, str):\n            content = self.file\n        else:\n            content = self.file.read()\n        return content.encode(\"utf-8\") if isinstance(content, str) else content\n\n\ndef iter_fields(data: dict, files: dict) -> typing.Iterator[Field]:\n    for name, value in data.items():\n        if isinstance(value, (list, dict)):\n            for item in value:\n                yield DataField(name=name, value=item)\n        else:\n            yield DataField(name=name, value=value)\n\n    for name, value in files.items():\n        yield FileField(name=name, value=value)\n\n\ndef multipart_encode(data: dict, files: dict) -> typing.Tuple[bytes, str]:\n    body = BytesIO()\n    boundary = binascii.hexlify(os.urandom(16))\n\n    for field in iter_fields(data, files):\n        body.write(b\"--%s\\r\\n\" % boundary)\n        body.write(field.render_headers())\n        body.write(field.render_data())\n        body.write(b\"\\r\\n\")\n\n    body.write(b\"--%s--\\r\\n\" % boundary)\n\n    content_type = \"multipart/form-data; boundary=%s\" % boundary.decode(\"ascii\")\n\n    return body.getvalue(), content_type\n\n\ndef _format_param(name: str, value: typing.Union[str, bytes]) -> bytes:\n    if isinstance(value, bytes):\n        value = value.decode()\n\n    def replacer(match: typing.Match[str]) -> str:\n        return _HTML5_FORM_ENCODING_REPLACEMENTS[match.group(0)]\n\n    value = _HTML5_FORM_ENCODING_RE.sub(replacer, value)\n    return f'{name}=\"{value}\"'.encode()\n", "path": "httpx/multipart.py"}]}