gurudesh/pytracebugs huggingface dataset:
# Buggy code
def add_field(doc, name, value):
    if isinstance(value, (list, set)):
        for v in value:
            add_field(doc, name, v)
        return
    else:
        field = Element("field", name=name)
        if not isinstance(value, six.string_types):
            value = str(value)
        try:
            value = strip_bad_char(value)
            if isinstance(value, str):
                value = value.decode("utf-8")
            field.text = normalize("NFC", value)
        except:
            logger.error("Error in normalizing %r", value)
            raise
        doc.append(field)


# Traceback (AttributeError)
2021-02-04 19:47:02 [420] [openlibrary.solrwriter] [INFO] updating loans/loan-1944642791
2021-02-04 19:47:02 [420] [openlibrary.solrwriter] [ERROR] Error in normalizing 'loans/loan-1944635007'
Traceback (most recent call last):
File "/openlibrary/scripts/openlibrary-server", line 133, in
main()
File "/openlibrary/scripts/openlibrary-server", line 130, in main
start_server()
File "/openlibrary/scripts/openlibrary-server", line 46, in start_server
infogami.run(args)
File "/openlibrary/infogami/init.py", line 151, in run
run_action(args[0], args[1:])
File "/openlibrary/infogami/init.py", line 138, in run_action
a(*args)
File "/openlibrary/openlibrary/actions.py", line 11, in runmain
mod.main(*args)
File "/openlibrary/openlibrary/solr/process_stats.py", line 219, in main
add_events_to_solr(events)
File "/openlibrary/openlibrary/solr/process_stats.py", line 210, in add_events_to_solr
update_solr(solrdocs)
File "/openlibrary/openlibrary/solr/process_stats.py", line 261, in update_solr
solr.update(doc)
File "/openlibrary/openlibrary/solr/solrwriter.py", line 57, in update
self.flush()
File "/openlibrary/openlibrary/solr/solrwriter.py", line 64, in flush
node = dict2element(doc)
File "/openlibrary/openlibrary/solr/solrwriter.py", line 108, in dict2element
add_field(doc, k, v)
File "/openlibrary/openlibrary/solr/solrwriter.py", line 98, in add_field
value = value.decode('utf-8')
AttributeError: 'str' object has no attribute 'decode'

# Fixed code
def add_field(doc, name, value):
    if isinstance(value, (list, set)):
        for v in value:
            add_field(doc, name, v)
        return
    else:
        field = Element("field", name=name)
        if not isinstance(value, six.string_types):
            value = str(value)
        try:
            value = strip_bad_char(value)
            if six.PY2 and isinstance(value, str):
                value = value.decode("utf-8")
            field.text = normalize("NFC", value)
        except:
            logger.error("Error in normalizing %r", value)
            raise
        doc.append(field)
# Buggy code
def __init__(self, http_error):
    self.code = http_error.code
    self.headers = http_error.headers
    msg = http_error.msg + ": " + http_error.read()
    Exception.__init__(self, msg)


# Traceback (HTTPError)
Error using client:
HTTPError                                 Traceback (most recent call last)
<ipython-input-5-d841aca49599> in <module>()
6     save_set.append(ed)
7 response = ol.save_many(save_set, 'moving edition(s) to primary work')
----> 8 response.raise_for_status()
9 response
/usr/local/lib/python3.6/dist-packages/requests/models.py in raise_for_status(self)
939
940         if http_error_msg:
--> 941             raise HTTPError(http_error_msg, response=self)
942
943     def close(self):

# Fixed code
def __init__(self, e):
    self.code = e.response.status_code
    self.headers = e.response.headers
    Exception.__init__(self, "{}. Response: {}".format(e, e.response.text))
# Buggy code
def _request(self, path, method="GET", data=None, headers=None):
    logger.info("%s %s", method, path)
    url = self.base_url + path
    headers = headers or {}
    if self.cookie:
        headers["Cookie"] = self.cookie

    try:
        req = urllib.request.Request(url, data, headers)
        req.get_method = lambda: method
        return urllib.request.urlopen(req)
    except urllib.error.HTTPError as e:
        raise OLError(e)


# Traceback (HTTPError)
Error using client:
HTTPError                                 Traceback (most recent call last)
<ipython-input-5-d841aca49599> in <module>()
6     save_set.append(ed)
7 response = ol.save_many(save_set, 'moving edition(s) to primary work')
----> 8 response.raise_for_status()
9 response
/usr/local/lib/python3.6/dist-packages/requests/models.py in raise_for_status(self)
939
940         if http_error_msg:
--> 941             raise HTTPError(http_error_msg, response=self)
942
943     def close(self):

# Fixed code
def _request(self, path, method="GET", data=None, headers=None, params=None):
    logger.info("%s %s", method, path)
    url = self.base_url + path
    headers = headers or {}
    params = params or {}
    if self.cookie:
        headers["Cookie"] = self.cookie

    try:
        response = requests.request(
            method, url, data=data, headers=headers, params=params
        )
        response.raise_for_status()
        return response
    except requests.HTTPError as e:
        raise OLError(e)
# Buggy code
def login(self, username, password):
    """Login to Open Library with given credentials."""
    headers = {"Content-Type": "application/json"}
    try:
        data = json.dumps(dict(username=username, password=password))
        response = self._request(
            "/account/login", method="POST", data=data, headers=headers
        )
    except urllib.error.HTTPError as e:
        response = e

    if "Set-Cookie" in response.headers:
        cookies = response.headers["Set-Cookie"].split(",")
        self.cookie = ";".join([c.split(";")[0] for c in cookies])


# Traceback (HTTPError)
Error using client:
HTTPError                                 Traceback (most recent call last)
<ipython-input-5-d841aca49599> in <module>()
6     save_set.append(ed)
7 response = ol.save_many(save_set, 'moving edition(s) to primary work')
----> 8 response.raise_for_status()
9 response
/usr/local/lib/python3.6/dist-packages/requests/models.py in raise_for_status(self)
939
940         if http_error_msg:
--> 941             raise HTTPError(http_error_msg, response=self)
942
943     def close(self):

# Fixed code
def login(self, username, password):
    """Login to Open Library with given credentials."""
    headers = {"Content-Type": "application/json"}
    try:
        data = json.dumps(dict(username=username, password=password))
        response = self._request(
            "/account/login", method="POST", data=data, headers=headers
        )
    except OLError as e:
        response = e

    if "Set-Cookie" in response.headers:
        cookies = response.headers["Set-Cookie"].split(",")
        self.cookie = ";".join([c.split(";")[0] for c in cookies])
# Buggy code
def get(self, key, v=None):
    data = self._request(key + ".json" + ("?v=%d" % v if v else "")).read()
    return unmarshal(json.loads(data))


# Traceback (HTTPError)
Error using client:
HTTPError                                 Traceback (most recent call last)
<ipython-input-5-d841aca49599> in <module>()
6     save_set.append(ed)
7 response = ol.save_many(save_set, 'moving edition(s) to primary work')
----> 8 response.raise_for_status()
9 response
/usr/local/lib/python3.6/dist-packages/requests/models.py in raise_for_status(self)
939
940         if http_error_msg:
--> 941             raise HTTPError(http_error_msg, response=self)
942
943     def close(self):

# Fixed code
def get(self, key, v=None):
    response = self._request(key + ".json", params={"v": v} if v else {})
    return unmarshal(response.json())
# Buggy code
def _get_many(self, keys):
    response = self._request(
        "/api/get_many?" + urllib.parse.urlencode({"keys": json.dumps(keys)})
    )
    return json.loads(response.read())["result"]


# Traceback (HTTPError)
Error using client:
HTTPError                                 Traceback (most recent call last)
<ipython-input-5-d841aca49599> in <module>()
6     save_set.append(ed)
7 response = ol.save_many(save_set, 'moving edition(s) to primary work')
----> 8 response.raise_for_status()
9 response
/usr/local/lib/python3.6/dist-packages/requests/models.py in raise_for_status(self)
939
940         if http_error_msg:
--> 941             raise HTTPError(http_error_msg, response=self)
942
943     def close(self):

# Fixed code
def _get_many(self, keys):
    response = self._request("/api/get_many", params={"keys": json.dumps(keys)})
    return response.json()["result"]
# Buggy code
def save(self, key, data, comment=None):
    headers = {"Content-Type": "application/json"}
    data = marshal(data)
    if comment:
        headers["Opt"] = '"%s/dev/docs/api"; ns=42' % self.base_url
        headers["42-comment"] = comment
    data = json.dumps(data)
    return self._request(key, method="PUT", data=data, headers=headers).read()


# Traceback (HTTPError)
Error using client:
HTTPError                                 Traceback (most recent call last)
<ipython-input-5-d841aca49599> in <module>()
6     save_set.append(ed)
7 response = ol.save_many(save_set, 'moving edition(s) to primary work')
----> 8 response.raise_for_status()
9 response
/usr/local/lib/python3.6/dist-packages/requests/models.py in raise_for_status(self)
939
940         if http_error_msg:
--> 941             raise HTTPError(http_error_msg, response=self)
942
943     def close(self):

# Fixed code
def save(self, key, data, comment=None):
    headers = {"Content-Type": "application/json"}
    data = marshal(data)
    if comment:
        headers["Opt"] = '"%s/dev/docs/api"; ns=42' % self.base_url
        headers["42-comment"] = comment
    data = json.dumps(data)
    return self._request(key, method="PUT", data=data, headers=headers).content
# Buggy code
def _call_write(self, name, query, comment, action):
    headers = {"Content-Type": "application/json"}
    query = marshal(query)

    # use HTTP Extension Framework to add custom headers. see RFC 2774 for more details.
    if comment or action:
        headers["Opt"] = '"%s/dev/docs/api"; ns=42' % self.base_url
    if comment:
        headers["42-comment"] = comment
    if action:
        headers["42-action"] = action

    response = self._request(
        "/api/" + name, method="POST", data=json.dumps(query), headers=headers
    )
    return json.loads(response.read())


# Traceback (HTTPError)
Error using client:
HTTPError                                 Traceback (most recent call last)
<ipython-input-5-d841aca49599> in <module>()
6     save_set.append(ed)
7 response = ol.save_many(save_set, 'moving edition(s) to primary work')
----> 8 response.raise_for_status()
9 response
/usr/local/lib/python3.6/dist-packages/requests/models.py in raise_for_status(self)
939
940         if http_error_msg:
--> 941             raise HTTPError(http_error_msg, response=self)
942
943     def close(self):

# Fixed code
def _call_write(self, name, query, comment, action):
    headers = {"Content-Type": "application/json"}
    query = marshal(query)

    # use HTTP Extension Framework to add custom headers. see RFC 2774 for more details.
    if comment or action:
        headers["Opt"] = '"%s/dev/docs/api"; ns=42' % self.base_url
    if comment:
        headers["42-comment"] = comment
    if action:
        headers["42-action"] = action

    response = self._request(
        "/api/" + name, method="POST", data=json.dumps(query), headers=headers
    )
    return response.json()
# Buggy code
def query(self, q=None, **kw):
    """Query Open Library.

    Open Library always limits the result to 1000 items due to
    performance issues. Pass limit=False to fetch all matching
    results by making multiple requests to the server. Please note
    that an iterator is returned instead of list when limit=False is
    passed.::

        >>> ol.query({'type': '/type/type', 'limit': 2}) #doctest: +SKIP
        [{'key': '/type/property'}, {'key': '/type/type'}]

        >>> ol.query(type='/type/type', limit=2) #doctest: +SKIP
        [{'key': '/type/property'}, {'key': '/type/type'}]
    """
    q = dict(q or {})
    q.update(kw)
    q = marshal(q)

    def unlimited_query(q):
        q["limit"] = 1000
        q.setdefault("offset", 0)
        q.setdefault("sort", "key")

        while True:
            result = self.query(q)
            for r in result:
                yield r
            if len(result) < 1000:
                break
            q["offset"] += len(result)

    if "limit" in q and q["limit"] == False:
        return unlimited_query(q)
    else:
        q = json.dumps(q)
        response = self._request("/query.json?" + urllib.parse.urlencode(dict(query=q)))
        return unmarshal(json.loads(response.read()))


# Traceback (HTTPError)
Error using client:
HTTPError                                 Traceback (most recent call last)
<ipython-input-5-d841aca49599> in <module>()
6     save_set.append(ed)
7 response = ol.save_many(save_set, 'moving edition(s) to primary work')
----> 8 response.raise_for_status()
9 response
/usr/local/lib/python3.6/dist-packages/requests/models.py in raise_for_status(self)
939
940         if http_error_msg:
--> 941             raise HTTPError(http_error_msg, response=self)
942
943     def close(self):

# Fixed code
def query(self, q=None, **kw):
    """Query Open Library.

    Open Library always limits the result to 1000 items due to
    performance issues. Pass limit=False to fetch all matching
    results by making multiple requests to the server. Please note
    that an iterator is returned instead of list when limit=False is
    passed.::

        >>> ol.query({'type': '/type/type', 'limit': 2}) #doctest: +SKIP
        [{'key': '/type/property'}, {'key': '/type/type'}]

        >>> ol.query(type='/type/type', limit=2) #doctest: +SKIP
        [{'key': '/type/property'}, {'key': '/type/type'}]
    """
    q = dict(q or {})
    q.update(kw)
    q = marshal(q)

    def unlimited_query(q):
        q["limit"] = 1000
        q.setdefault("offset", 0)
        q.setdefault("sort", "key")

        while True:
            result = self.query(q)
            for r in result:
                yield r
            if len(result) < 1000:
                break
            q["offset"] += len(result)

    if "limit" in q and q["limit"] == False:
        return unlimited_query(q)
    else:
        response = self._request("/query.json", params=dict(query=json.dumps(q)))
        return unmarshal(response.json())
# Buggy code
def import_ocaid(self, ocaid, require_marc=True):
    data = {"identifier": ocaid, "require_marc": "true" if require_marc else "false"}
    return self._request(
        "/api/import/ia", method="POST", data=urllib.parse.urlencode(data)
    ).read()


# Traceback (HTTPError)
Error using client:
HTTPError                                 Traceback (most recent call last)
<ipython-input-5-d841aca49599> in <module>()
6     save_set.append(ed)
7 response = ol.save_many(save_set, 'moving edition(s) to primary work')
----> 8 response.raise_for_status()
9 response
/usr/local/lib/python3.6/dist-packages/requests/models.py in raise_for_status(self)
939
940         if http_error_msg:
--> 941             raise HTTPError(http_error_msg, response=self)
942
943     def close(self):

# Fixed code
def import_ocaid(self, ocaid, require_marc=True):
    data = {"identifier": ocaid, "require_marc": "true" if require_marc else "false"}
    return self._request("/api/import/ia", method="POST", data=data).content
# Buggy code
def save_many(self, sitename, data):
    return self.conn.request(sitename, "/save_many", "POST", data)


# Traceback (HTTPError)
Error using client:
HTTPError                                 Traceback (most recent call last)
<ipython-input-5-d841aca49599> in <module>()
6     save_set.append(ed)
7 response = ol.save_many(save_set, 'moving edition(s) to primary work')
----> 8 response.raise_for_status()
9 response
/usr/local/lib/python3.6/dist-packages/requests/models.py in raise_for_status(self)
939
940         if http_error_msg:
--> 941             raise HTTPError(http_error_msg, response=self)
942
943     def close(self):

# Fixed code
def save_many(self, sitename, data):
    # Work-around for https://github.com/internetarchive/openlibrary/issues/4285
    # Infogami seems to read encoded bytes as a string with a byte literal inside
    # of it, which is invalid JSON and also can't be decode()'d.
    if isinstance(data.get("query"), bytes):
        data["query"] = data["query"].decode()
    return self.conn.request(sitename, "/save_many", "POST", data)
# Buggy code
def parse_args():
    parser = OptionParser(
        "usage: %s [options] path1 path2" % sys.argv[0],
        description=desc,
        version=__version__,
    )
    parser.add_option("-c", "--comment", dest="comment", default="", help="comment")
    parser.add_option(
        "--src",
        dest="src",
        metavar="SOURCE_URL",
        default="http://openlibrary.org/",
        help="URL of the source server (default: %default)",
    )
    parser.add_option(
        "--dest",
        dest="dest",
        metavar="DEST_URL",
        default="http://localhost",
        help="URL of the destination server (default: %default)",
    )
    parser.add_option(
        "-r",
        "--recursive",
        dest="recursive",
        action="store_true",
        default=False,
        help="Recursively fetch all the referred docs.",
    )
    parser.add_option(
        "-l",
        "--list",
        dest="lists",
        action="append",
        default=[],
        help="copy docs from a list.",
    )
    return parser.parse_args()


# Traceback (HTTPError)
Error using client:
HTTPError                                 Traceback (most recent call last)
<ipython-input-5-d841aca49599> in <module>()
6     save_set.append(ed)
7 response = ol.save_many(save_set, 'moving edition(s) to primary work')
----> 8 response.raise_for_status()
9 response
/usr/local/lib/python3.6/dist-packages/requests/models.py in raise_for_status(self)
939
940         if http_error_msg:
--> 941             raise HTTPError(http_error_msg, response=self)
942
943     def close(self):

# Fixed code
def parse_args():
    parser = OptionParser(
        "usage: %s [options] path1 path2" % sys.argv[0],
        description=desc,
        version=__version__,
    )
    parser.add_option("-c", "--comment", dest="comment", default="", help="comment")
    parser.add_option(
        "--src",
        dest="src",
        metavar="SOURCE_URL",
        default="http://openlibrary.org/",
        help="URL of the source server (default: %default)",
    )
    parser.add_option(
        "--dest",
        dest="dest",
        metavar="DEST_URL",
        default="http://localhost",
        help="URL of the destination server (default: %default)",
    )
    parser.add_option(
        "-r",
        "--recursive",
        dest="recursive",
        action="store_true",
        default=True,
        help="Recursively fetch all the referred docs.",
    )
    parser.add_option(
        "-l",
        "--list",
        dest="lists",
        action="append",
        default=[],
        help="copy docs from a list.",
    )
    return parser.parse_args()
# Buggy code
def GET(self, key):
    page = web.ctx.site.get(key)
    if not page:
        raise web.notfound("")
    else:
        from infogami.utils import template
        import opds

        try:
            result = template.typetemplate("opds")(page, opds)
        except:
            raise web.notfound("")
        else:
            return delegate.RawText(
                result, content_type=" application/atom+xml;profile=opds"
            )


# Traceback (ImportError)
Traceback (most recent call last):
...
File "/opt/openlibrary/deploys/openlibrary/openlibrary/openlibrary/plugins/openlibrary/code.py", line 445, in GET
import opds
ImportError: No module named opds

# Fixed code
def GET(self, key):
    page = web.ctx.site.get(key)
    if not page:
        raise web.notfound("")
    else:
        from infogami.utils import template
        from openlibrary.plugins.openlibrary import opds

        try:
            result = template.typetemplate("opds")(page, opds)
        except:
            raise web.notfound("")
        else:
            return delegate.RawText(
                result, content_type=" application/atom+xml;profile=opds"
            )
# Buggy code
def get_diff_input(self, pin, p_port, n_port, attrs, invert):
    self._check_feature(
        "differential input", pin, attrs, valid_xdrs=(), valid_attrs=None
    )


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_diff_input(self, pin, port, attrs, invert):
    self._check_feature(
        "differential input", pin, attrs, valid_xdrs=(), valid_attrs=None
    )
# Buggy code
def get_diff_output(self, pin, p_port, n_port, attrs, invert):
    self._check_feature(
        "differential output", pin, attrs, valid_xdrs=(), valid_attrs=None
    )


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_diff_output(self, pin, port, attrs, invert):
    self._check_feature(
        "differential output", pin, attrs, valid_xdrs=(), valid_attrs=None
    )
# Buggy code
def get_diff_tristate(self, pin, p_port, n_port, attrs, invert):
    self._check_feature(
        "differential tristate", pin, attrs, valid_xdrs=(), valid_attrs=None
    )


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_diff_tristate(self, pin, port, attrs, invert):
    self._check_feature(
        "differential tristate", pin, attrs, valid_xdrs=(), valid_attrs=None
    )
# Buggy code
def get_diff_input_output(self, pin, p_port, n_port, attrs, invert):
    self._check_feature(
        "differential input/output", pin, attrs, valid_xdrs=(), valid_attrs=None
    )


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_diff_input_output(self, pin, port, attrs, invert):
    self._check_feature(
        "differential input/output", pin, attrs, valid_xdrs=(), valid_attrs=None
    )
# Buggy code
def iter_single_ended_pins(self):
    for res, pin, port, attrs in self._ports:
        if pin is None:
            continue
        if isinstance(res.ios[0], Pins):
            yield pin, port.io, attrs, res.ios[0].invert


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def iter_single_ended_pins(self):
    for res, pin, port, attrs in self._ports:
        if pin is None:
            continue
        if isinstance(res.ios[0], Pins):
            yield pin, port, attrs, res.ios[0].invert
# Buggy code
def iter_differential_pins(self):
    for res, pin, port, attrs in self._ports:
        if pin is None:
            continue
        if isinstance(res.ios[0], DiffPairs):
            yield pin, port.p, port.n, attrs, res.ios[0].invert


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def iter_differential_pins(self):
    for res, pin, port, attrs in self._ports:
        if pin is None:
            continue
        if isinstance(res.ios[0], DiffPairs):
            yield pin, port, attrs, res.ios[0].invert
# Buggy code
def get_input(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended input", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        port.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_in",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="FALSE",
        i_datain=port,
        o_dataout=self._get_ireg(m, pin, invert),
    )
    return m


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_input(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended input", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        port.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_in",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="FALSE",
        i_datain=port.io,
        o_dataout=self._get_ireg(m, pin, invert),
    )
    return m
# Buggy code
def get_output(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended output", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        port.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_out",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="FALSE",
        p_use_oe="FALSE",
        i_datain=self._get_oreg(m, pin, invert),
        o_dataout=port,
    )
    return m


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_output(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended output", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        port.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_out",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="FALSE",
        p_use_oe="FALSE",
        i_datain=self._get_oreg(m, pin, invert),
        o_dataout=port.io,
    )
    return m
# Buggy code
def get_tristate(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended tristate", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        port.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_out",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="FALSE",
        p_use_oe="TRUE",
        i_datain=self._get_oreg(m, pin, invert),
        o_dataout=port,
        i_oe=self._get_oereg(m, pin),
    )
    return m


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_tristate(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended tristate", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        port.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_out",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="FALSE",
        p_use_oe="TRUE",
        i_datain=self._get_oreg(m, pin, invert),
        o_dataout=port.io,
        i_oe=self._get_oereg(m, pin),
    )
    return m
# Buggy code
def get_input_output(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended input/output", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        port.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_bidir",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="FALSE",
        i_datain=self._get_oreg(m, pin, invert),
        io_dataio=port,
        o_dataout=self._get_ireg(m, pin, invert),
        i_oe=self._get_oereg(m, pin),
    )
    return m


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_input_output(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended input/output", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        port.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_bidir",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="FALSE",
        i_datain=self._get_oreg(m, pin, invert),
        io_dataio=port.io,
        o_dataout=self._get_ireg(m, pin, invert),
        i_oe=self._get_oereg(m, pin),
    )
    return m
# Buggy code
def get_diff_input(self, pin, p_port, n_port, attrs, invert):
    self._check_feature(
        "differential input", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        p_port.attrs["useioff"] = 1
        n_port.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_in",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="TRUE",
        i_datain=p_port,
        i_datain_b=n_port,
        o_dataout=self._get_ireg(m, pin, invert),
    )
    return m


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_diff_input(self, pin, port, attrs, invert):
    self._check_feature(
        "differential input", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        port.p.attrs["useioff"] = 1
        port.n.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_in",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="TRUE",
        i_datain=port.p,
        i_datain_b=port.n,
        o_dataout=self._get_ireg(m, pin, invert),
    )
    return m
# Buggy code
def get_diff_output(self, pin, p_port, n_port, attrs, invert):
    self._check_feature(
        "differential output", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        p_port.attrs["useioff"] = 1
        n_port.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_out",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="TRUE",
        p_use_oe="FALSE",
        i_datain=self._get_oreg(m, pin, invert),
        o_dataout=p_port,
        o_dataout_b=n_port,
    )
    return m


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_diff_output(self, pin, port, attrs, invert):
    self._check_feature(
        "differential output", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        port.p.attrs["useioff"] = 1
        port.n.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_out",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="TRUE",
        p_use_oe="FALSE",
        i_datain=self._get_oreg(m, pin, invert),
        o_dataout=port.p,
        o_dataout_b=port.n,
    )
    return m
# Buggy code
def get_diff_tristate(self, pin, p_port, n_port, attrs, invert):
    self._check_feature(
        "differential tristate", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        p_port.attrs["useioff"] = 1
        n_port.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_out",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="TRUE",
        p_use_oe="TRUE",
        i_datain=self._get_oreg(m, pin, invert),
        o_dataout=p_port,
        o_dataout_b=n_port,
        i_oe=self._get_oereg(m, pin),
    )
    return m


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_diff_tristate(self, pin, port, attrs, invert):
    self._check_feature(
        "differential tristate", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        port.p.attrs["useioff"] = 1
        port.n.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_out",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="TRUE",
        p_use_oe="TRUE",
        i_datain=self._get_oreg(m, pin, invert),
        o_dataout=port.p,
        o_dataout_b=port.n,
        i_oe=self._get_oereg(m, pin),
    )
    return m
# Buggy code
def get_diff_input_output(self, pin, p_port, n_port, attrs, invert):
    self._check_feature(
        "differential input/output", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        p_port.attrs["useioff"] = 1
        n_port.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_bidir",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="TRUE",
        i_datain=self._get_oreg(m, pin, invert),
        io_dataio=p_port,
        io_dataio_b=n_port,
        o_dataout=self._get_ireg(m, pin, invert),
        i_oe=self._get_oereg(m, pin),
    )
    return m


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_diff_input_output(self, pin, port, attrs, invert):
    self._check_feature(
        "differential input/output", pin, attrs, valid_xdrs=(0, 1, 2), valid_attrs=True
    )
    if pin.xdr == 1:
        port.p.attrs["useioff"] = 1
        port.n.attrs["useioff"] = 1

    m = Module()
    m.submodules[pin.name] = Instance(
        "altiobuf_bidir",
        p_enable_bus_hold="FALSE",
        p_number_of_channels=pin.width,
        p_use_differential_mode="TRUE",
        i_datain=self._get_oreg(m, pin, invert),
        io_dataio=port.p,
        io_dataio_b=port.n,
        o_dataout=self._get_ireg(m, pin, invert),
        i_oe=self._get_oereg(m, pin),
    )
    return m
# Buggy code
def get_input(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended input", pin, attrs, valid_xdrs=(0, 1, 2, 4, 7), valid_attrs=True
    )
    m = Module()
    i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
    for bit in range(len(port)):
        m.submodules["{}_{}".format(pin.name, bit)] = Instance(
            "IB", i_I=port[bit], o_O=i[bit]
        )
    return m


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_input(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended input", pin, attrs, valid_xdrs=(0, 1, 2, 4, 7), valid_attrs=True
    )
    m = Module()
    i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
    for bit in range(pin.width):
        m.submodules["{}_{}".format(pin.name, bit)] = Instance(
            "IB", i_I=port.io[bit], o_O=i[bit]
        )
    return m
# Buggy code
def get_output(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended output", pin, attrs, valid_xdrs=(0, 1, 2, 4, 7), valid_attrs=True
    )
    m = Module()
    i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
    for bit in range(len(port)):
        m.submodules["{}_{}".format(pin.name, bit)] = Instance(
            "OB", i_I=o[bit], o_O=port[bit]
        )
    return m


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_output(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended output", pin, attrs, valid_xdrs=(0, 1, 2, 4, 7), valid_attrs=True
    )
    m = Module()
    i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
    for bit in range(pin.width):
        m.submodules["{}_{}".format(pin.name, bit)] = Instance(
            "OB", i_I=o[bit], o_O=port.io[bit]
        )
    return m
# Buggy code
def get_tristate(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended tristate",
        pin,
        attrs,
        valid_xdrs=(0, 1, 2, 4, 7),
        valid_attrs=True,
    )
    m = Module()
    i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
    for bit in range(len(port)):
        m.submodules["{}_{}".format(pin.name, bit)] = Instance(
            "OBZ", i_T=t, i_I=o[bit], o_O=port[bit]
        )
    return m


# Traceback (subprocess.CalledProcessError)
ERROR: IO 'ddr3_0__dqs__n[0]' is unconstrained in LPF (override this error with --lpf-allow-unconstrained)
0 warnings, 1 error
Traceback (most recent call last):
File "diffpairissue.py", line 20, in <module>
ECPIX585Platform().build(Top(), do_program=True)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/plat.py", line 94, in build
products = plan.execute_local(build_dir)
File "/home/jeanthomas/Documents/nmigen/nmigen/build/run.py", line 95, in execute_local
subprocess.check_call(["sh", "{}.sh".format(self.script)])
File "/usr/lib64/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sh', 'build_top.sh']' returned non-zero exit status 255.

# Fixed code
def get_tristate(self, pin, port, attrs, invert):
    self._check_feature(
        "single-ended tristate",
        pin,
        attrs,
        valid_xdrs=(0, 1, 2, 4, 7),
        valid_attrs=True,
    )
    m = Module()
    i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
    for bit in range(pin.width):
        m.submodules["{}_{}".format(pin.name, bit)] = Instance(
            "OBZ", i_T=t, i_I=o[bit], o_O=port.io[bit]
        )
    return m