Repository: networkx/networkx

Issue:
Cannot read graph6
I have a basic script that I used a year ago to convert graph6 strings into PACE-format graph files; it doesn't work now with networkx version 2.4: 
`in from_graph6_bytes
    if string.startswith(b'>>graph6<<'):
TypeError: startswith first arg must be str or a tuple of str, not bytes`


Discussion:
Perhaps you've switched from Python 2 to Python 3 over the last year? It seems that `from_graph6_bytes` expects a bytes-like object, not a string. An update to the `Parameters` section of the docstring could perhaps make this more clear.

If this is indeed a Python 2/3 issue you could try encoding your Python3 string to produce a sequence of bytes, e.g. something like `from_graph6_bytes(<your_string>.encode('ascii'))` in your script.
> 
> 
> Perhaps you've switched from Python 2 to Python 3 over the last year? It seems that `from_graph6_bytes` expects a bytes-like object, not a string. An update to the `Parameters` section of the docstring could perhaps make this more clear.
> 
> If this is indeed a Python 2/3 issue you could try encoding your Python3 string to produce a sequence of bytes, e.g. something like `from_graph6_bytes(<your_string>.encode('ascii'))` in your script.

I believe that the error is coming from within NetworkX's code - the call to `string.startswith()` with is made within the `from_graph6_bytes` function. 

Or maybe... I'm passing a String object to it, which it is internally naming 'string' but expecting that it is actually a sequence of bytes? And String's `startswith` function expects a String argument, whereas Byte's expects a Byte argument? Does that make sense?
> I believe that the error is coming from within NetworkX's code - the call to string.startswith() with is made within the from_graph6_bytes function.

This is what I was referring to before - it's confusing because the variable `string` in the function `from_graph6_bytes` is not actually a string - there is a mismatch between the function name (which implies that the input should be bytes) and the naming convention *inside* the function (argument name is string). This is likely an artifact from when the function was originally written (pre-Python3) as the naming convention would have made sense for Python 2.

Here's a quick example to illustrate the root of the problem:

```python
>>> s = '>>graph6<<A_'
>>> type(s)
str
>>> b = s.encode('ascii')
>>> type(b)
bytes
>>> type(b'>>graph6<<')
bytes
# This produces the error because the str.startswith method expects strings,
# not bytes
>>> s.startswith(b'>>graph6<<')
Traceback (most recent call last)
   ...
TypeError: startswith first arg must be str or a tuple of str, not bytes
# But a comparison of bytes to bytes is fine
>>> b.startswith(b'>>graph6<<')
True
```
And with `nx.from_graph6_bytes`:
```python
>>> import networkx as nx
>>> nx.from_graph6_bytes(s)
Traceback (most recent call last)
   ...
TypeError: startswith first arg must be str or a tuple of str, not bytes
>>> G =  nx.from_graph6_bytes(b)
>>> G.edges
EdgeView([(0, 1)])
```

Long story short - `from_graph6_bytes` needs a bytes-like input, *not* a string.

I think updating the argument name, docstring, and maybe touching up the exceptions would help resolve some of this confusion.

Resolving patch:
diff --git a/networkx/readwrite/graph6.py b/networkx/readwrite/graph6.py
--- a/networkx/readwrite/graph6.py
+++ b/networkx/readwrite/graph6.py
@@ -60,12 +60,12 @@ def _generate_graph6_bytes(G, nodes, header):
     yield b'\n'
 
 
-def from_graph6_bytes(string):
-    """Read a simple undirected graph in graph6 format from string.
+def from_graph6_bytes(bytes_in):
+    """Read a simple undirected graph in graph6 format from bytes.
 
     Parameters
     ----------
-    string : string
+    bytes_in : bytes
        Data in graph6 format, without a trailing newline.
 
     Returns
@@ -75,10 +75,10 @@ def from_graph6_bytes(string):
     Raises
     ------
     NetworkXError
-        If the string is unable to be parsed in graph6 format
+        If bytes_in is unable to be parsed in graph6 format
 
     ValueError
-        If any character ``c`` in the input string does not satisfy
+        If any character ``c`` in bytes_in does not satisfy
         ``63 <= ord(c) < 127``.
 
     Examples
@@ -104,10 +104,10 @@ def bits():
             for i in [5, 4, 3, 2, 1, 0]:
                 yield (d >> i) & 1
 
-    if string.startswith(b'>>graph6<<'):
-        string = string[10:]
+    if bytes_in.startswith(b'>>graph6<<'):
+        bytes_in = bytes_in[10:]
 
-    data = [c - 63 for c in string]
+    data = [c - 63 for c in bytes_in]
     if any(c > 63 for c in data):
         raise ValueError('each input character must be in range(63, 127)')
 


Test patch: