import pandas as pd
import sqlite3
import pooch
from markdown import markdownorg = "voila-dashboards"
# If the template has been converted to pages, then org will not have { org } structure
if "{ org }" in org:
org = "jupyter-book"# Download latest release data for Jupyter Book
file_path = pooch.retrieve(
# URL to one of Pooch's test files
url=f"https://github.com/jupyter/github-data/releases/download/latest/{org}.db",
known_hash=None,
)Downloading data from 'https://github.com/jupyter/github-data/releases/download/latest/voila-dashboards.db' to file '/home/runner/.cache/pooch/b79b4f9f761b55e12a00da9b2a71cd5c-voila-dashboards.db'.
SHA256 hash of downloaded file: edcf9ef6099fa303d3425bc302ba253ffd5440576e8ec8da7a779a9b2b2c8cb6
Use this value as the 'known_hash' argument of 'pooch.retrieve' to ensure that the file hasn't changed if it is downloaded again in the future.
def df_from_sql(query, db):
con = sqlite3.connect(db)
return pd.read_sql(query, con)
con.close()repos = df_from_sql("SELECT * FROM repos;", file_path).set_index("id")
issues = df_from_sql("SELECT * FROM issues;", file_path)
issues = issues.query("state == 'open'")
# Add some metadata that will make the outputs nicer
for ix, irow in issues.iterrows():
# Add number of positive reactions
positive = 0
for ii in ["+1", "heart", "hooray"]:
positive += eval(irow["reactions"])[ii]
issues.loc[ix, 'positive'] = int(positive)
# Add the repository
url_repo = repos.loc[irow["repo"]]["html_url"]
url_repo_parts = url_repo.split("/")[-1]
issues.loc[ix, "repo"] = f"[{url_repo_parts}]({url_repo})"
# Add the URL of each issue
url = f"{url_repo}/issues/{irow['number']}"
issues.loc[ix, "mdtitle"] = f"[{irow['title']}]({url})"
# Add a short body
issues["bodyshort"] = issues["body"].map(lambda a: a.replace("#", "")[:400] if a else '')---------------------------------------------------------------------------
LossySetitemError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/pandas/core/internals/blocks.py:1115, in Block.setitem(self, indexer, value)
1114 try:
-> 1115 casted = np_can_hold_element(values.dtype, value)
1116 except LossySetitemError:
1117 # current dtype cannot store value, coerce to common dtype
File /opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/pandas/core/dtypes/cast.py:1750, in np_can_hold_element(dtype, element)
1748 return element
-> 1750 raise LossySetitemError
1752 if dtype.kind == "f":
LossySetitemError:
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
Cell In[5], line 16
12
13 # Add the repository
14 url_repo = repos.loc[irow["repo"]]["html_url"]
15 url_repo_parts = url_repo.split("/")[-1]
---> 16 issues.loc[ix, "repo"] = f"[{url_repo_parts}]({url_repo})"
17
18 # Add the URL of each issue
19 url = f"{url_repo}/issues/{irow['number']}"
File /opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/pandas/core/indexing.py:938, in _LocationIndexer.__setitem__(self, key, value)
933 self._has_valid_setitem_indexer(key)
935 iloc: _iLocIndexer = (
936 cast("_iLocIndexer", self) if self.name == "iloc" else self.obj.iloc
937 )
--> 938 iloc._setitem_with_indexer(indexer, value, self.name)
File /opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/pandas/core/indexing.py:1953, in _iLocIndexer._setitem_with_indexer(self, indexer, value, name)
1950 # align and set the values
1951 if take_split_path:
1952 # We have to operate column-wise
-> 1953 self._setitem_with_indexer_split_path(indexer, value, name)
1954 else:
1955 self._setitem_single_block(indexer, value, name)
File /opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/pandas/core/indexing.py:2044, in _iLocIndexer._setitem_with_indexer_split_path(self, indexer, value, name)
2041 else:
2042 # scalar value
2043 for loc in ilocs:
-> 2044 self._setitem_single_column(loc, value, pi)
File /opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/pandas/core/indexing.py:2181, in _iLocIndexer._setitem_single_column(self, loc, value, plane_indexer)
2171 if dtype == np.void:
2172 # This means we're expanding, with multiple columns, e.g.
2173 # df = pd.DataFrame({'A': [1,2,3], 'B': [4,5,6]})
(...) 2176 # Here, we replace those temporary `np.void` columns with
2177 # columns of the appropriate dtype, based on `value`.
2178 self.obj.iloc[:, loc] = construct_1d_array_from_inferred_fill_value(
2179 value, len(self.obj)
2180 )
-> 2181 self.obj._mgr.column_setitem(loc, plane_indexer, value)
File /opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/pandas/core/internals/managers.py:1541, in BlockManager.column_setitem(self, loc, idx, value, inplace_only)
1539 col_mgr.setitem_inplace(idx, value)
1540 else:
-> 1541 new_mgr = col_mgr.setitem((idx,), value)
1542 self.iset(loc, new_mgr._block.values, inplace=True)
File /opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/pandas/core/internals/managers.py:620, in BaseBlockManager.setitem(self, indexer, value)
616 # No need to split if we either set all columns or on a single block
617 # manager
618 self = self.copy(deep=True)
--> 620 return self.apply("setitem", indexer=indexer, value=value)
File /opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/pandas/core/internals/managers.py:445, in BaseBlockManager.apply(self, f, align_keys, **kwargs)
443 applied = b.apply(f, **kwargs)
444 else:
--> 445 applied = getattr(b, f)(**kwargs)
446 result_blocks = extend_blocks(applied, result_blocks)
448 out = type(self).from_blocks(result_blocks, [ax.view() for ax in self.axes])
File /opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/pandas/core/internals/blocks.py:1118, in Block.setitem(self, indexer, value)
1115 casted = np_can_hold_element(values.dtype, value)
1116 except LossySetitemError:
1117 # current dtype cannot store value, coerce to common dtype
-> 1118 nb = self.coerce_to_target_dtype(value, raise_on_upcast=True)
1119 return nb.setitem(indexer, value)
1120 else:
File /opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/pandas/core/internals/blocks.py:468, in Block.coerce_to_target_dtype(self, other, raise_on_upcast)
465 raise_on_upcast = False
467 if raise_on_upcast:
--> 468 raise TypeError(f"Invalid value '{other}' for dtype '{self.values.dtype}'")
469 if self.values.dtype == new_dtype:
470 raise AssertionError(
471 f"Did not expect new dtype {new_dtype} to equal self.dtype "
472 f"{self.values.dtype}. Please report a bug at "
473 "https://github.com/pandas-dev/pandas/issues."
474 )
TypeError: Invalid value '[voila](https://github.com/voila-dashboards/voila)' for dtype 'int64'A table of all the open issues in the voila-dashboards github organization, sorted by the number of ๐ and โค๏ธ reactions.
issues_sorted = issues.sort_values("positive", ascending=False).head(100)[["mdtitle", "repo", "bodyshort", "positive"]]
issues_sorted = issues_sorted.rename(columns={"bodyshort": "body", "mdtitle": "title", "positive": "๐"})
def render_markdown(text):
if isinstance(text, str): # Ensure the cell content is a string
return markdown(text)
return text
md_cols = ["title", "body", "repo"]
styledict = {ii: render_markdown for ii in md_cols}
df_style = issues_sorted
styled_df = issues_sorted.style.format(styledict | {"๐": int}).hide(axis="index")
styled_df