<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Quansight Labs</title>
    <description>The latest articles on Forem by Quansight Labs (@quansightlabs).</description>
    <link>https://forem.com/quansightlabs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F3674%2F8a1f0537-cedf-48c3-9f01-1a90a0a6a689.jpg</url>
      <title>Forem: Quansight Labs</title>
      <link>https://forem.com/quansightlabs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/quansightlabs"/>
    <language>en</language>
    <item>
      <title>Is GitHub Actions suitable for running benchmarks?</title>
      <dc:creator>Jaime Rodríguez-Guerra</dc:creator>
      <pubDate>Wed, 18 Aug 2021 14:38:43 +0000</pubDate>
      <link>https://forem.com/quansightlabs/is-github-actions-suitable-for-running-benchmarks-111h</link>
      <guid>https://forem.com/quansightlabs/is-github-actions-suitable-for-running-benchmarks-111h</guid>
      <description>&lt;p&gt;Benchmarking software is a tricky business. For robust results, you need dedicated hardware that only runs the benchmarking suite under controlled conditions. No other processes! No OS updates! Nothing else! Even then, you might find out that CPU throttling, thermal regulation and other issues can introduce noise in your measurements.&lt;/p&gt;

&lt;p&gt;So, how are we even trying to do it on a CI provider like GitHub Actions? Every job runs in a separate VM instance with frequent updates and shared resources. It looks like it would just be a very expensive random number generator.&lt;/p&gt;

&lt;p&gt;Well, it turns out that there &lt;em&gt;is&lt;/em&gt; a sensible way to do it: &lt;strong&gt;relative benchmarking&lt;/strong&gt;. And we know it works because we have been collecting stability data points for several weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good benchmarking on shared resources?
&lt;/h2&gt;

&lt;p&gt;Speed-critical projects use benchmark suites to track performance over time and detect regressions from commit to commit. For these measurements to be useful, they need to be comparable and hence use the exact same conditions for each data point. Guaranteeing this in absolute manners can be a daunting task, but there are ways around it.&lt;/p&gt;

&lt;p&gt;Instead of going through all the complications involved in renting or acquiring dedicated hardware, setting up credentials and monitoring costs, we hoped we could use the same free cloud resources normally used for CI tests. Ideally, GitHub Actions.&lt;/p&gt;

&lt;p&gt;Let's compare the requirements for good benchmarks and the features provided by CI services. That way we can understand how to work around some of the apparent limitations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;A good benchmark suite...&lt;/th&gt;
&lt;th&gt;CI services...&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;runs on the same hardware every time&lt;/td&gt;
&lt;td&gt;provide a different (standardized) machine for each run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;runs on dedicated hardware&lt;/td&gt;
&lt;td&gt;run on shared resources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;runs on a frozen OS configuration&lt;/td&gt;
&lt;td&gt;update their VM images often&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;requires renting or acquiring such hardware&lt;/td&gt;
&lt;td&gt;are free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;requires authentication mechanisms&lt;/td&gt;
&lt;td&gt;implement authentication out of the box&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;requires hardware that can be abused through public PRs  &lt;/td&gt;
&lt;td&gt;are designed for public PRs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;p&gt;Looking at that table we see that CI services are attractive because of the cost and setup, but fail to provide some of the essential quality factors for reliable benchmarking. That is, if we want to track performance over time and compare absolute measurements directly.&lt;/p&gt;

&lt;p&gt;What if we only want to detect regressions introduced in a PR? Or in the current commit against the last release? We do not need absolute measurements, just a way to &lt;em&gt;compare&lt;/em&gt; two commits in a reliable way. This is exactly what we meant by &lt;em&gt;relative benchmarking&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The idea is to run the benchmarking suite in the same CI job for the two commits we are comparing. This way, we guarantee we are using the exact same machine and configuration for both. By doing this, we are essentially canceling out the background noise and can estimate the performance &lt;em&gt;ratio&lt;/em&gt; of the two commits.&lt;/p&gt;

&lt;p&gt;There are some gotchas, though. Benchmark suites can take long to run, and running them twice makes it even worse. This opens an even larger time window for other CI jobs to pollute our measurements with resource-intensive tasks that happen to be running at the same time. To minimize these effects, benchmarking tools run the tests several times in different schedules and apply some statistics to correct for the inevitable deviations. Or, at least, &lt;em&gt;try&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Relative performance measurements with Airspeed Velocity
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;scikit-image&lt;/code&gt;, the project that commissioned this task, uses &lt;a href="https://asv.readthedocs.io/"&gt;Airspeed Velocity&lt;/a&gt;, or &lt;code&gt;asv&lt;/code&gt;, for their benchmark tests.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;asv&lt;/code&gt;'s main feature is being able to track performance measurements over time in a JSON database and generate beautiful dashboards that can be published to a static site server like GitHub Pages. For an example, look at the reports for &lt;code&gt;pandas&lt;/code&gt; at their &lt;a href="https://pandas.pydata.org/speed/pandas/"&gt;speed.pydata.org&lt;/a&gt; website.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;asv&lt;/code&gt; &lt;em&gt;also&lt;/em&gt; has a special subcommand named &lt;code&gt;continuous&lt;/code&gt;, which might provide the functionally we needed. The help message says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Run a side-by-side comparison of two commits for continuous integration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This sounds like exactly what we are looking for! Let's break down how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When we run &lt;code&gt;asv continuous A B&lt;/code&gt;, &lt;code&gt;asv&lt;/code&gt; will create at least two&lt;sup&gt;†&lt;/sup&gt; virtual environments (one per commit) and install revisions A and B in those, respectively. If the project involves compiled libraries (as is the case with &lt;code&gt;scikit-image&lt;/code&gt;), this can be a lengthy process!&lt;/li&gt;
&lt;li&gt;The default configuration will run the benchmark in two interleaved passes, with several repeats each. In other words, &lt;code&gt;asv&lt;/code&gt; will run the suite four times (&lt;code&gt;A-&amp;gt;B-&amp;gt;A-&amp;gt;B&lt;/code&gt;)! This is done to account for the unavoidable deviations from ideality caused from co-running processes, as mentioned above.&lt;/li&gt;
&lt;li&gt;The statistics for each commit are gathered and a report table is presented. The ratio of each test is computed and, if it is greater than a certain threshold (&lt;code&gt;1.2&lt;/code&gt; by default) an error is emitted.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;sup&gt;†&lt;/sup&gt; &lt;code&gt;asv&lt;/code&gt; supports the notion of a configuration matrix, so you can test your code under different environments; e.g. NumPy versions, Python interpreters, etc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the benchmark suite of &lt;code&gt;scikit-image&lt;/code&gt; as of June/July 2021, this ends up taking up to two hours. This raises two questions we will answer in the following sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Although we are trying hard to reduce measurement errors, is that enough? Are these measurements reliable?&lt;/li&gt;
&lt;li&gt;Two hours might be too long. Are there any settings we can tune to reduce the runtime without reducing the accuracy of the measurements?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Are CI services reliable enough for benchmarking?
&lt;/h2&gt;

&lt;p&gt;We saw above that CI services are not designed for this kind of task, but with some workarounds they might be good enough. However, how can we be sure? As data-driven scientists, we say let's run an experiment!&lt;/p&gt;

&lt;h3&gt;
  
  
  The setup
&lt;/h3&gt;

&lt;p&gt;If our experiment is data-driven, we should generate some data first. This is our strategy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We will benchmark and compare two commits that are exactly the same in terms of tested code.&lt;/li&gt;
&lt;li&gt;Under ideal conditions, we should see that the performance ratio between the two commits is &lt;code&gt;1.0&lt;/code&gt;. In other words, performance should be the same. Of course, these are not ideal conditions, so some kind of error is expected. We just want it to stay reliably under an acceptable threshold.&lt;/li&gt;
&lt;li&gt;We will implement a GitHub Actions workflow that will run every six hours (four times a day) and collect results for a week or more. This will help us account for two things:

&lt;ul&gt;
&lt;li&gt;Accumulate sufficient data points to answer our question.&lt;/li&gt;
&lt;li&gt;Account for time factors like different days of the week (e.g. weekday vs weekend), or the time of the day (3am vs 3pm).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;The workflow will upload the benchmark results as artifacts we can download and process locally with a Jupyter Notebook.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Check the &lt;a href="https://github.com/jaimergp/scikit-image/blob/main/.github/workflows/benchmarks-cron.yml"&gt;GitHub Actions workflow in this fork&lt;/a&gt;!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The results
&lt;/h3&gt;

&lt;p&gt;To measure the stability of the different benchmark runs we will be looking at the performance ratio of the measurements between the two commits. Since they are identical in terms of tested code, ideally they should be all &lt;code&gt;1.0&lt;/code&gt;. We know this will not happen, but maybe the errors are not that big and stay like that regardless the time of the day or the day of the week.&lt;/p&gt;

&lt;p&gt;After collecting data points for 16 days, these are the results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZgnOXqKz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t3emvt00206nqxp42xyt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZgnOXqKz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t3emvt00206nqxp42xyt.png" alt="Reliability of benchmarks in GitHub Actions. This 2D plot shows a 16-day timeseries in the X axis. Each data point in the X axis corresponds to a cloud of 75 measurements (one per benchmark test). The y-axis spread of each cloud corresponds to the performance ratio. Ideal measurements would have a performance ratio of 1.0, since both runs returned the exact same performance. In practice this does not happen and we can observe ratios between 0.5 and 1.5. This plot shows that while there is an observable y-spread, it is small enough to be considered sensitive to performance regressions of more than 50%."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average time taken: 1h55min&lt;/li&gt;
&lt;li&gt;Minimum and maximum ratios observed: 0.51, 1.36&lt;/li&gt;
&lt;li&gt;Mean and standard deviation of ratios: 1.00, 0.05&lt;/li&gt;
&lt;li&gt;Proportion of false positives: 4/108 = 3.7%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the X axis you can see the different runs, sorted by date and time. Days of the week are grouped with colored patches for easier visual analysis. In the Y axis, we plot the performance ratio. Each of those vertical clouds include 75 points, one per benchmark test. Ideally, they should all fall at &lt;code&gt;y=1&lt;/code&gt;. Of course, not all of them are there, but a surprising amount of them do!&lt;/p&gt;

&lt;p&gt;But! We do see some bigger deviations at certain times! How is that possible? Well, that's the error we were talking about! These outliers are the ones that would concern us because they can be interpreted as &lt;strong&gt;false positives&lt;/strong&gt;. In other words: &lt;code&gt;asv&lt;/code&gt; would report a performance regression, when in fact there's none. However, in the observed measurements, the outliers were always within &lt;code&gt;y ∈ (0.5, 1.4)&lt;/code&gt;. That means we can affirm that the method is sensitive enough to detect performance regressions of 50% or more! This is good enough for our project and, in fact, some projects might even be happy with a threshold of &lt;code&gt;2.0&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are curious about how we automatically downloaded the artifacts, parsed the output, and plotted the performance ratios, check the Jupyter Notebook &lt;a href="https://gist.github.com/jaimergp/aa4f059c14e394c4089b320cb8b51b1a"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Can we make it run faster without losing accuracy?
&lt;/h2&gt;

&lt;p&gt;We just found out that this approach is sensitive enough &lt;em&gt;but&lt;/em&gt; it takes two hours to run. Is it possible to reduce that time without sacrificing sensitivity? We need to remember that &lt;code&gt;asv&lt;/code&gt; is running several passes and repeats to reduce the measurement error, but maybe some of those default counter-measures are not needed. Namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The benchmark runs with &lt;code&gt;--interleave-processes&lt;/code&gt;, but it can be disabled with &lt;code&gt;--no-interleave-processes&lt;/code&gt;. The help message for this flag says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Interleave benchmarks with multiple processes across commits. This can avoid measurement biases from commit ordering, can take longer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How much longer? Does it help keep error under control? We should measure that.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;By default, all tests are run several times, with different schedules. There are two &lt;a href="https://asv.readthedocs.io/en/stable/benchmarks.html#timing-benchmarks"&gt;benchmark attributes&lt;/a&gt; that govern these settings: &lt;code&gt;processes&lt;/code&gt; and &lt;code&gt;repeat&lt;/code&gt;. &lt;code&gt;processes&lt;/code&gt; defaults to &lt;code&gt;2&lt;/code&gt;, which means that the full suite will be run twice per commit. If we only do one pass (&lt;code&gt;processes=1&lt;/code&gt;), we will reduce the running time in half, but will we lose too much accuracy?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To answer both questions, we added more entries to the data collection workflow shown above by &lt;a href="https://github.com/jaimergp/scikit-image/blob/e561996/.github/workflows/benchmarks-cron.yml#L14-L23"&gt;parameterizing the &lt;code&gt;asv&lt;/code&gt; command-line options&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These are the results!&lt;/p&gt;

&lt;h3&gt;
  
  
  No process interleaving
&lt;/h3&gt;

&lt;p&gt;Disabling process interleaving should be faster and maybe the accuracy loss is not that bad. But... how bad? Here are the results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cqDgtK9c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2uurdca0w25koysu680.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cqDgtK9c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2uurdca0w25koysu680.png" alt="Reliability of benchmarks in GitHub Actions, no interleaving. With no interleaving, the vertical spread is more evident, with several clouds spreading beyond the desired interval. One particular outlier happened on the first Saturday, with half the cloud below 0.75. This 2D plot shows a 16-day timeseries in the X axis. Each data point in the X axis corresponds to a cloud of 75 measurements (one per benchmark test). The y-axis spread of each cloud corresponds to the performance ratio. Ideal measurements would have a performance ratio of 1.0, since both runs returned the exact same performance. In practice this does not happen."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average time taken: 1h39min&lt;/li&gt;
&lt;li&gt;Minimum and maximum ratios observed: 0.43, 1.5&lt;/li&gt;
&lt;li&gt;Mean and standard deviation of ratios: 0.99, 0.07&lt;/li&gt;
&lt;li&gt;Proportion of false positives: 6/66 = 9.99%&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Single-pass with &lt;code&gt;processes=1&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In this configuration, we expect a drastic 50% running time reduction, since we will only do one pass per commit, instead of two. However, the accuracy loss might be too dramatic... Let's see!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AJioAvtU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1h5fo00b2wbh8smozloy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AJioAvtU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1h5fo00b2wbh8smozloy.png" alt="Reliability of benchmarks in GitHub Actions, single pass. With a single process, the y-spread is significantly wider. Some data points can be observed even beyond a ratio of 2.5, and the overall visual spread is larger; i.e. the clouds are taller than in the ideal case of having a small, contained cloud at 1.0. This 2D plot shows a 16-day timeseries in the X axis. Each data point in the X axis corresponds to a cloud of 75 measurements (one per benchmark test). The y-axis spread of each cloud corresponds to the performance ratio. Ideal measurements would have a performance ratio of 1.0, since both runs returned the exact same performance. In practice this does not happen."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average time taken: 1h7min&lt;/li&gt;
&lt;li&gt;Minimum and maximum ratios observed: 0.51, 2.76&lt;/li&gt;
&lt;li&gt;Mean and standard deviation of ratios: 1.01, 0.07&lt;/li&gt;
&lt;li&gt;Proportion of false positives: 8/64 = 12.5%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first sight, those clouds look very spread! The number of false positives is also larger.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary of the strategies
&lt;/h3&gt;

&lt;p&gt;Let's take a look at the three strategies now. The main columns are &lt;strong&gt;runtime&lt;/strong&gt; and &lt;strong&gt;%FP&lt;/strong&gt; (percentage of false positives). We want the smallest %FP at the shortest runtime.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Runtime   &lt;/th&gt;
&lt;th&gt;%FP&lt;/th&gt;
&lt;th&gt;Min&lt;/th&gt;
&lt;th&gt;Max&lt;/th&gt;
&lt;th&gt;Mean  &lt;/th&gt;
&lt;th&gt;Std&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default&lt;/td&gt;
&lt;td&gt;1h55&lt;/td&gt;
&lt;td&gt;3.7&lt;/td&gt;
&lt;td&gt;0.51  &lt;/td&gt;
&lt;td&gt;1.36&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No interleaving  &lt;/td&gt;
&lt;td&gt;1h39&lt;/td&gt;
&lt;td&gt;9.99  &lt;/td&gt;
&lt;td&gt;0.43&lt;/td&gt;
&lt;td&gt;1.50&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;td&gt;0.07&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single pass&lt;/td&gt;
&lt;td&gt;1h07&lt;/td&gt;
&lt;td&gt;12.5&lt;/td&gt;
&lt;td&gt;0.51&lt;/td&gt;
&lt;td&gt;2.76  &lt;/td&gt;
&lt;td&gt;1.01&lt;/td&gt;
&lt;td&gt;0.07&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;p&gt;Unsurprisingly, the default strategy (two passes, interleaved) is the most accurate, but also the most time consuming. Disabling process interleaving helps reduce the average runtime 16min but the false positives increased to more than double! Using a single pass brought the runtime down to an hour, but multiplied the false positives by almost four.&lt;/p&gt;

&lt;p&gt;In short, we will stick to the default strategy for accuracy but need to investigate other ways to make it run in less time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We also considered running several single-pass replicas in parallel using different GitHub Actions jobs. In theory, a false positive could be spotted by comparing the values of the failing tests in the other replicas. Only true positives would reliably appear in all replicas. However, this consumes more CI resources (compilation happens several times) and is noisier from the maintainer perspective, who would need to check all replicas. Not to mention that more replicas increase the chances for more false positives!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Speeding up compilation times
&lt;/h2&gt;

&lt;p&gt;So far we have only looked at speeding up the benchmark suite itself, but we saw earlier that &lt;code&gt;asv&lt;/code&gt; will also spend some time setting up virtual environments and installing the project. Since installing &lt;code&gt;scikit-learn&lt;/code&gt; involves compiling some extensions, this can add up to a non-trivial amount of time.&lt;/p&gt;

&lt;p&gt;To accelerate the creation of the virtual environments, which in our case uses &lt;code&gt;conda&lt;/code&gt;, we replaced the &lt;code&gt;conda&lt;/code&gt; calls with a faster implementation called &lt;code&gt;mamba&lt;/code&gt;. We rely on an &lt;code&gt;asv&lt;/code&gt; implementation detail: to find &lt;code&gt;conda&lt;/code&gt;, &lt;code&gt;asv&lt;/code&gt; will first check the value of the &lt;code&gt;CONDA_EXE&lt;/code&gt; environment variable. This is normally set by &lt;code&gt;conda activate &amp;lt;env&amp;gt;&lt;/code&gt;, but we &lt;a href="https://github.com/scikit-image/scikit-image/blob/main/.github/workflows/benchmarks.yml#L77"&gt;overwrite it with the path to &lt;code&gt;mamba&lt;/code&gt;&lt;/a&gt; to have &lt;code&gt;asv&lt;/code&gt; use it instead.&lt;/p&gt;

&lt;p&gt;The second optimization is leveraging the use of a compiler cache. Since most of the modules will not change in a given PR, we can use &lt;code&gt;ccache&lt;/code&gt; to keep the unchanged libraries around. Check the &lt;a href="https://github.com/scikit-image/scikit-image/blob/main/.github/workflows/benchmarks.yml#L36-L56"&gt;workflow file&lt;/a&gt; to see how it can be implemented on GitHub Actions.&lt;/p&gt;

&lt;p&gt;These two changes together brought the average running time down to around 1h 20min. Not bad!&lt;/p&gt;

&lt;h2&gt;
  
  
  Run it on demand!
&lt;/h2&gt;

&lt;p&gt;Benchmarks do not need to run for every single commit pushed to a PR. In fact, that's probably a waste of resources. Instead, we'd like the maintainers to run the benchmarks on demand, whenever needed during the PR lifetime.&lt;/p&gt;

&lt;p&gt;GitHub Actions offers different kinds of events that will trigger a worklow. By default the &lt;code&gt;on.pull_request&lt;/code&gt; trigger is configured to act on three event types: &lt;code&gt;[opened, reopened, synchronize]&lt;/code&gt;. In practice, this means after every push or after closing+opening the PR. However, there are &lt;a href="https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request"&gt;more triggers&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Of all the choices, we settled for &lt;code&gt;labeled&lt;/code&gt;. This means that the workflow will be triggered whenever the PR is tagged with a label. To specify which label(s) are able to trigger the workflow, you can use an &lt;code&gt;if&lt;/code&gt; clause at the &lt;code&gt;job&lt;/code&gt; level, &lt;a href="https://github.com/scikit-image/scikit-image/blob/2fa66e5/.github/workflows/benchmarks.yml#L10"&gt;like this&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Benchmark&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;labeled&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;benchmark&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.label.name == 'run-benchmark' &amp;amp;&amp;amp; github.event_name == 'pull_request' }}&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Linux&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-20.04&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the PR will only get triggered if the label is named &lt;code&gt;run-benchmark&lt;/code&gt;. This works surprisingly well as a manual trigger! It is also restricted to authorized users (triaging permissions or above), so no need to fiddle with authentication tokens or similar complications.&lt;/p&gt;

&lt;p&gt;There is one gotcha, though: the checks UI will be appended to the last push event panel, which can be confusing if more commits have been added to the PR since the label was added. Ideally, the checks UI panel would be added next to the &lt;em&gt;@user added the run-benchmark label&lt;/em&gt; message. Maybe in a &lt;a href="https://twitter.com/jaime_rgp/status/1412419232340627467"&gt;future update&lt;/a&gt;?&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;We have seen that GitHub Actions is indeed good enough to perform relative benchmarking in a reliable way as long as several passes are averaged together (default behaviour in &lt;code&gt;asv continuous&lt;/code&gt;). This takes a bit more time but you can speed it up a bit with &lt;code&gt;mamba&lt;/code&gt; and &lt;code&gt;ccache&lt;/code&gt; for compiled libraries. Even in that case, it is probably overkill to run it for every push event, so we are using the &lt;code&gt;on.pull_request.labeled&lt;/code&gt; trigger to let the maintainers decide when to do it on demand.&lt;/p&gt;




&lt;h2&gt;
  
  
  Useful references
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/scikit-image/scikit-image/pull/5424"&gt;scikit-image/scikit-image #5424&lt;/a&gt;: The PR where
all this was implemented.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://gist.github.com/jaimergp/aa4f059c14e394c4089b320cb8b51b1a"&gt;Analysis notebook&lt;/a&gt;: The code used
to analyze the benchmarking data.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://asv.readthedocs.io"&gt;asv.readthedocs.io&lt;/a&gt;: The official documentation for &lt;code&gt;asv&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wolfv.medium.com/building-an-open-source-continuous-benchmark-system-717839093962"&gt;Building an Open Source, Continuous Benchmark System&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ursalabs.org/blog/announcing-conbench/"&gt;Conbench: Language-independent Continuous Benchmarking Tool, by Ursa Labs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://speed.pypy.org/"&gt;PyPy Speed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pandas.pydata.org/speed/pandas/"&gt;Pandas Speed&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Acknowledgements
&lt;/h2&gt;

&lt;p&gt;Thanks Gregory Lee, Stéfan van der Walt and Juan Nunez-Iglesias for their enthusiastic and useful feedback in the PR! The plots look that pretty thanks to comments provided by John Lee. Gregory Lee, Gonzalo Peña-Castellanos and Isabela Presedo-Floyd provided super valuable comments and suggestions for this post.&lt;/p&gt;

&lt;p&gt;This work was funded by the Chan-Zuckerberg Institute (CZI) as part of an &lt;a href="https://chanzuckerberg.com/eoss/proposals/gpu-acceleration-rapid-releases-and-biomedical-examples-for-scikit-image/"&gt;Essential Open Source Software for Science&lt;/a&gt; grant.&lt;/p&gt;

</description>
      <category>python</category>
      <category>benchmarking</category>
      <category>github</category>
      <category>ci</category>
    </item>
    <item>
      <title>Putting Out the Fire: Where Do We Start With Accessibility in JupyterLab?</title>
      <dc:creator>Isabela Presedo-Floyd</dc:creator>
      <pubDate>Thu, 27 May 2021 22:11:18 +0000</pubDate>
      <link>https://forem.com/quansightlabs/putting-out-the-fire-where-do-we-start-with-accessibility-in-jupyterlab-25od</link>
      <guid>https://forem.com/quansightlabs/putting-out-the-fire-where-do-we-start-with-accessibility-in-jupyterlab-25od</guid>
      <description>&lt;p&gt;I want to be honest with you, I started asking accessibility questions in JupyterLab spaces while filled with anxiety. Anxiety that I was shouting into the void and no one else would work on accessibility with me. Anxiety that I didn’t have the skills or energy or knowledge to back up what I wanted to do. Anxiety that I was going to do it wrong and make JupyterLab even more inaccessible. Sometimes I still feel that way.&lt;/p&gt;

&lt;p&gt;Here’s the thing. That anxiety, while real and worth acknowledging, doesn’t help the disabled people we constantly fail and exclude when we keep building things inaccessibly. So yes, I want you to know I felt that way and that you might too, but I also want you to remember who we are here for, especially if you are working to support a group you aren’t a part of (as is the case with me). Plus, many of these concerns didn’t end up happening. First, I didn’t end up being alone at all! Each of the people that have joined in have different skills that have helped us tackle issues that I don’t think any of us would’ve been able to on our own. Knowing we are working together also helps keep me accountable because I’d like to be able to show up to our meetings with something to share. As for worrying that I’m doing it all wrong, I suppose that’s still a possibility. Speaking for myself, I’d rather be making mistakes, learning, and iterating than continue to let JupyterLab stay inaccessible indefinitely.&lt;/p&gt;

&lt;p&gt;In a space where considering the needs of disabled people isn’t the standard, accessibility might feel like an insurmountable challenge. For example, when I showed up to our first devoted accessibility meeting, JupyterLab’s accessibility status was like a hazy shape in the distance. I was pretty sure it wasn’t good, but I didn’t know for sure how or why. A few meetings later and a closer look made me realize that haze was actually smoke and I'd walked myself and others directly into a (metaphorical) burning building. But just because it felt like everything was chaos without a good place to start didn't mean that was the truth. In fact, it wasn't. Building software is more about people more than any tool, so let’s consider what our regular team of people on the user-contributor-maintainer spectrum said are the basics of what they care about in JupyterLab.&lt;/p&gt;

&lt;p&gt;Users want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use JupyterLab to read or navigate documents.&lt;/li&gt;
&lt;li&gt;Use JupyterLab to edit and run documents. To edit a document, users need to be able to navigate where they want to edit, so the read-only experience is aprerequisite.&lt;/li&gt;
&lt;li&gt;Know what things they can do in JupyterLab and get help on how to do it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contributors want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gain enough understanding of a JupyterLab in order to work with it.&lt;/li&gt;
&lt;li&gt;Understand the expectations of their contributions and how to meet them. In this case, they would want to know that they need to think about accessibility and how to consider that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maintainers want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure that JupyterLab is both progressing and relatively stable.&lt;/li&gt;
&lt;li&gt;Promote sustainable growth for a project that doesn’t overwrite past efforts. Automation can be helpful because maintainers are usually strapped for time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the support of a team member with prior experience auditing for accessibility, we pinpointed &lt;a href="https://github.com/jupyterlab/jupyterlab/issues/9399"&gt;specific ways&lt;/a&gt; in which JupyterLab lacked support for accessibility broken up by &lt;a href="https://www.w3.org/TR/WCAG21/"&gt;WCAG 2.1&lt;/a&gt; standards.&lt;/p&gt;

&lt;p&gt;From conversations with these more experienced community members, we found that issues generally broke up into four categories of work needed (not necessarily in this order):&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Make JupyterLab accessible for a read-only type experience
&lt;/h2&gt;

&lt;p&gt;This is something users need. For our purposes, we’re using read-only to describe what you need to navigate and consume all the content in JupyterLab from the interface to the documents and processes that live in it. Most of this also falls under WCAG standards, and are the first things users need to start working with JupyterLab since it’s difficult to interact with a space if you can’t get where you want to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Make JupyterLab accessible for an interacting/editing experience
&lt;/h2&gt;

&lt;p&gt;This is something users need and is the other half of WCAG standards. Once you can navigate the space, people need to interact by writing, editing, running process, and so on. While WCAG standards do cover interactive web experiences and they are written generally enough to apply to many interface types, their roots in a more standard website experience means that we also have some grey areas to account for since JupyterLab can easily include complex and layered interactions than even other web apps. We are supporting this by looking into how other tools with similar uses (like coding) approach these types of accessibility and hope to test it in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Accessibility documentation
&lt;/h2&gt;

&lt;p&gt;This is something users and contributors need and has two parts. One part is making the documentation itself accessible through WCAG compliance in the docs theme, labeling relevant content, and providing content in different forms. Second is adding documentation specifically for accessibility such as how to use accessibility features and how accessibility fits in to our contribution process.&lt;/p&gt;

&lt;p&gt;Accessibility and documentation both have reputations for falling to the wayside, and we almost got so caught up in applying WCAG standards to the software itself that we continued the pattern. But making an accessible experience is, like any UX problem, not limited to the time spent within that product. Think of it this way, if there is no accessible documentation on how to get started with JupyterLab and use relevant accessibility support, then all the work we’ve done in the software itself won’t be able to serve the very people it is there for.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Adding relevant accessibility tests to the JupyterLab contributing workflow
&lt;/h2&gt;

&lt;p&gt;This is something contributors and maintainers need, though the results also benefit users. As grateful as I am to have a group of people who are taking action to make JupyterLab accessible, it isn’t enough on its own. We aren’t a group that can review every single PR and we may not all be able to devote time to this forever; tests ensure that accessibility remains a priority in the contributing workflow regardless of individual involvement. It also will help prevent current efforts from being overwritten by new contributions.&lt;/p&gt;

&lt;p&gt;Automated accessibility &lt;a href="https://www.w3.org/WAI/test-evaluate/tools/selecting/"&gt;testing has its limits&lt;/a&gt; because you are trying to quantify an experience without getting users involved, but I think a first pass and a reminder to the community—especially the contributing community—that accessibility is something we are all responsible for is critical. Since accessibility isn’t yet a regular standard for contributions in many projects, feedback from tests might also be an opportunity for people who haven’t worked with accessibility before to start learning more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where we are now
&lt;/h2&gt;

&lt;p&gt;As I’m writing this post, our team is mostly focused on JupyterLab accessibility for WCAG compliance starting with the read-only type experience. Among many things, JupyterLab is currently missing of &lt;a href="https://accessibility.18f.gov/landmarks/"&gt;landmarks&lt;/a&gt; and &lt;a href="https://webaim.org/articles/label-name/"&gt;labels&lt;/a&gt; that block manual accessibility testing to a degree since they prevent further navigation and interaction. Starting here means that we are a step closer to users being able to accessibly read content in the interface.&lt;/p&gt;

&lt;p&gt;If you are going to take away one thing from my journey so far, I’d tell you to be consistently brave. Feeling anxious in the face of challenges and accepting areas where you don’t yet have knowledge is normal, but it isn’t reason to back down. Find the people that will collaborate with you and dive in. And when I get lost and don’t know what to do, I find it most helpful to put people first and remember who I am doing this for. Breaking the work into pieces by what users need can help you strategically start putting out fires.&lt;/p&gt;

&lt;p&gt;Focusing on people just for strategy isn’t all though. Be on the look out for my next blog where I’ll talk about what the disconnect of what accessibility meant to different people in our community and how that impacted the time and way we’ve solved issues in JupyterLab so far.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Interested in getting involved? Join our community via the JupyterLab accessibility meetings listed every other week on the &lt;a href="https://jupyter.readthedocs.io/en/latest/community/content-community.html#jupyter-community-meetings"&gt;Jupyter community calendar&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>jupyter</category>
      <category>inclusion</category>
    </item>
    <item>
      <title>Rethinking Jupyter Interactive Documentation</title>
      <dc:creator>Matthias Bussonnier</dc:creator>
      <pubDate>Fri, 07 May 2021 19:45:38 +0000</pubDate>
      <link>https://forem.com/quansightlabs/rethinking-jupyter-interactive-documentation-4okm</link>
      <guid>https://forem.com/quansightlabs/rethinking-jupyter-interactive-documentation-4okm</guid>
      <description>&lt;p&gt;Jupyter Notebook first release was 8 years ago – under the IPython Notebook name at the time. Even if notebooks were not invented by Jupyter; they were definitely democratized by it. Being Web powered allowed development of many changes in the Datascience world. Objects now often expose rich representation; from Pandas dataframes with as html tables, to more recent &lt;a href="https://github.com/scikit-learn/scikit-learn/pull/14180" rel="noopener noreferrer"&gt;Scikit-learn model&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Today I want to look into a topic that has not evolved much since, and I believe&lt;br&gt;
could use an upgrade. Accessing interactive Documentation when in a Jupyter session, and what it could become. At the end I'll link to my current prototype if you are adventurous.&lt;/p&gt;
&lt;h1&gt;
  
  
  The current limitation for users
&lt;/h1&gt;

&lt;p&gt;The current documentation of IPython and Jupyter come in a few forms, but mostly have the same limitation. The typical way to reach for help is to use the &lt;code&gt;?&lt;/code&gt; operator. Depending on the frontend you are using it will bring a pager, or a panel that will display some information about the current object.&lt;/p&gt;

&lt;p&gt;It can show some information about the current object (signature, file, sub/super classes) and the raw DocString of the object.&lt;/p&gt;

&lt;p&gt;You can scroll around but that's about it whether in terminal or Notebooks.&lt;/p&gt;

&lt;p&gt;Compare it to the same documentation on the NumPy website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flabs.quansight.org%2Fimages%2F2021%2F05%2Fnumpy-linspace-compare.png" class="article-body-image-wrapper"&gt;&lt;img alt="numpy.linspace on numpy.org" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flabs.quansight.org%2Fimages%2F2021%2F05%2Fnumpy-linspace-compare.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the left is the documentation for NumPy when visiting &lt;a href="https://numpy.org" rel="noopener noreferrer"&gt;the NumPy website&lt;/a&gt;. Let's call that "rendered documentation". On the right what you get in Jupyter Lab or in the IPython or regular Python REPL, let's cal that "help documentation" since it is typically reached via &lt;code&gt;identifier?&lt;/code&gt; or &lt;code&gt;help(identifier)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Compared to rendered documentation, the help documentation is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hard to read,&lt;/li&gt;
&lt;li&gt;Has no navigation,&lt;/li&gt;
&lt;li&gt;RST Directives have not been interpreted,&lt;/li&gt;
&lt;li&gt;No inline graphs, no rendered math.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is also no access to non-docstring based documentation, &lt;strong&gt;no narrative&lt;/strong&gt;, &lt;strong&gt;no tutorials&lt;/strong&gt;, &lt;strong&gt;no image gallery or examples&lt;/strong&gt;, no search, no syntax highlighting, no way to interact or modify documentation to test effects of parameters.&lt;/p&gt;
&lt;h1&gt;
  
  
  Limitation for authors
&lt;/h1&gt;

&lt;p&gt;Due to Jupyter and IPython limitations to display documentation I believe authors are often contained to document functions.&lt;/p&gt;

&lt;p&gt;Syntax in docstrings is often kept simple for readability, this first version is&lt;br&gt;
often preferred:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You can use ``np.einsum('i-&amp;gt;', a)`` ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the longer form, which makes the reference into a link when viewing rendered&lt;br&gt;
documentation, it is difficult to read when shown as help documentation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You can use :py:func:`np.einsum('i-&amp;gt;', a) &amp;lt;numpy.einsum&amp;gt;` ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also leads to long discussions about which syntax to use in advanced areas, like formulas in &lt;a href="https://github.com/sympy/sympy/issues/14964" rel="noopener noreferrer"&gt;Sympy's docstrings&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Many projects have to implement dynamic docstrings; for example to include all the parameters a function or class would pass down using &lt;code&gt;**kwargs&lt;/code&gt; (search the matplotlib source code for &lt;code&gt;_kwdoc&lt;/code&gt; for example, or look at the &lt;code&gt;pandas.DataFrame&lt;/code&gt; implementation).&lt;/p&gt;

&lt;p&gt;This can make it relatively difficult for authors and contributors to properly maintain and provide comprehensive docs.&lt;/p&gt;

&lt;p&gt;I'm not sure I can completely predict all the side effects this has on how library maintainers write docs; but I believe there is also a strong opportunity for a tool to help there. See for example &lt;a href="https://github.com/Carreau/velin" rel="noopener noreferrer"&gt;vélin&lt;/a&gt; which attempts to auto reformat and fix common NumPyDoc's format mistakes and&lt;br&gt;
typos – but that's a subject of a future post.&lt;/p&gt;

&lt;h1&gt;
  
  
  Stuck between a Rock and a Hard place
&lt;/h1&gt;

&lt;p&gt;While Sphinx and related projects are great at offering hosted HTML documentation, extensive usage of those makes interactive documentation harder to consume.&lt;/p&gt;

&lt;p&gt;While it is possible to &lt;a href="https://github.com/spyder-ide/docrepr" rel="noopener noreferrer"&gt;run Sphinx on the fly when rendering docstrings&lt;/a&gt;, most Sphinx features only work when building a full project, with the proper configuration and extension, and can be computationally intensive. This makes running Sphinx locally impractical.&lt;/p&gt;

&lt;p&gt;Hosted websites often may not reflect the locally installed version of the libraries and require careful linking, deprecation and narrative around platform or version specific features.&lt;/p&gt;

&lt;h1&gt;
  
  
  This is fixable
&lt;/h1&gt;

&lt;p&gt;For the past few months I've been working on rewriting how IPython (and hence Jupyter) can display documentation. It works both in terminal (IPython) and browser context (notebook, JupyterLab, Spyder) with proper rendering, and currently understands most directives; it could be customized to understand any new ones:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flabs.quansight.org%2Fimages%2F2021%2F05%2Fpapyri-1.png" class="article-body-image-wrapper"&gt;&lt;img alt="papyri1" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flabs.quansight.org%2Fimages%2F2021%2F05%2Fpapyri-1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above is the (terminal) documentation of &lt;code&gt;scipy.polynomial.lagfit&lt;/code&gt;, see how the single backticks are properly understood and refer to known parameters, it detected that  &lt;code&gt;`n`&lt;/code&gt; is incorrect as it should have double backticks; notice the rendering of the math even in terminal.&lt;/p&gt;

&lt;p&gt;For that matter technically this does not care as to whether the DocString is written in RST or Markdown; though I need to implement the latter part. I believe though that some maintainers would be quite happy to use Markdown, the syntax of which more users are familiar with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flabs.quansight.org%2Fimages%2F2021%2F05%2Fpapyri-nav.gif" class="article-body-image-wrapper"&gt;&lt;img alt="papyri navigation" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flabs.quansight.org%2Fimages%2F2021%2F05%2Fpapyri-nav.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It supports navigation – here in a terminal – where clicking or pressing enter on a link would bring you to the target page. In the above gif you can see that many tokens of the code example are also automatically type-inferred (thanks &lt;a href="https://github.com/davidhalter/jedi" rel="noopener noreferrer"&gt;Jedi&lt;/a&gt;), and can also be clicked on to navigate to their corresponding page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flabs.quansight.org%2Fimages%2F2021%2F05%2Fpapyri-terminal-fig.png" class="article-body-image-wrapper"&gt;&lt;img alt="papyri terminal-fig" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flabs.quansight.org%2Fimages%2F2021%2F05%2Fpapyri-terminal-fig.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Images are included, even in the terminal when they are not inline but replaced by a button to open them in your preferred viewer (see the &lt;code&gt;Open with quicklook&lt;/code&gt; in the above screenshot).&lt;/p&gt;

&lt;h1&gt;
  
  
  The future
&lt;/h1&gt;

&lt;p&gt;I'm working on a number of other features, in particular:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rendering of narrative docs – for which I have a prototype,&lt;/li&gt;
&lt;li&gt;automatic indexing of all the figures and plots –  working but slow right now,&lt;/li&gt;
&lt;li&gt;proper cross-library referencing and indexing without the need for intersphinx.
For example, it is possible from the &lt;code&gt;numpy.linspace&lt;/code&gt; page to see all pages that
reference it, or use &lt;code&gt;numpy.linspace&lt;/code&gt; in their example section
(see previous image).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And many others, like showing a graph of the local references between functions, search, and preference configurability. I think this could also support many other desirable features, like user preferences (hide/show type annotation, deprecated directives, and custom color/syntax highlighting) - though I haven't started working on these. I do have some ideas on how this could be used to provide translations as well.&lt;/p&gt;

&lt;p&gt;Right now, is it not as fast and efficient as I would like to – though it's faster than running Sphinx on the fly – but requires some ahead of time processing. And it crashes in many places; it can render most of the documentation of SciPy, NumPy, xarray, IPython and scikit-image.&lt;/p&gt;

&lt;p&gt;I encourage you to think about what features you are missing when using documentation from within Jupyter and let me know. I hope this could become a nice addition to Sphinx when consulting documentation from within Jupyter.&lt;/p&gt;

&lt;p&gt;For now I've submitted a &lt;a href="https://docs.google.com/document/d/1hk-Ww7pUwnoHINNhDeP9UOPvNEemAFe-pohK5dCtZPs/edit?usp=sharing" rel="noopener noreferrer"&gt;Letter of intent to CZI EOSS 4&lt;/a&gt; in an attempt to get some of that work funded to land in IPython, and if you have any interest in contributing or want something like that for your library, feel free to reach out.&lt;/p&gt;

&lt;p&gt;You can find the repository &lt;a href="https://github.com/Carreau/papyri" rel="noopener noreferrer"&gt;on my GitHub account&lt;/a&gt;, it's still in pre-alpha stage. It is still quite unstable with too many hard coded values to my taste, and needs some polish to be considered usable for production. I've focused my effort for now mostly on terminal rendering – a Jupyter notebook or JupyterLab extension would be welcome. So if you are adventurous and like to work from the cutting (or even bleeding) edge, please feel free to try it out and open issues/pull request.&lt;/p&gt;

&lt;p&gt;It also needs to be better documented (pun intended), I'm hoping to use papyri itself to document papyri; but it needs to be a bit more mature for that.&lt;/p&gt;

&lt;p&gt;Stay tuned for more news, I'll try to explain how it works in more detail in a follow-up post, and discuss some of the advantages (and drawbacks) this project has.&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>datascience</category>
      <category>jupyter</category>
    </item>
    <item>
      <title>Spot the differences: what is new in Spyder 5?</title>
      <dc:creator>Isabela Presedo-Floyd</dc:creator>
      <pubDate>Sat, 17 Apr 2021 15:11:46 +0000</pubDate>
      <link>https://forem.com/quansightlabs/spot-the-differences-what-is-new-in-spyder-5-28cj</link>
      <guid>https://forem.com/quansightlabs/spot-the-differences-what-is-new-in-spyder-5-28cj</guid>
      <description>&lt;p&gt;In case you missed it, Spyder 5 was released at the beginning of April! This blog post is a conversation attempting to document the long and complex process of improving Spyder's UI with this release. Portions lead by Juanita Gomez (&lt;a class="mentioned-user" href="https://dev.to/juanis2112"&gt;@juanis2112&lt;/a&gt;
) are marked as &lt;strong&gt;Juanita&lt;/strong&gt;, and those lead by Isabela Presedo-Floyd are marked as &lt;strong&gt;Isabela&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What did we do?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;[Juanita]&lt;/strong&gt; &lt;a href="https://www.spyder-ide.org/"&gt;Spyder&lt;/a&gt; was created more than 10 years ago and it has had the contributions of a great number of developers who have written code, proposed ideas, opened issues and tested PRs in order to build a piece of Spyder on their own. We (the Spyder team) have been lucky to have such a great community of people contributing throughout the years,  but this is the first time that we decided to ask for help from an UX/UI expert! Why? You might wonder. Having the contributions of this great amount of people has resulted in inconsistencies around Spyder’s interface which we didn’t stop to analyze until now. &lt;/p&gt;

&lt;p&gt;When Isabela joined Quansight, we realized that we had an opportunity of improving Spyder’s interface with her help. We thought her skill set was everything we needed to make Spyder’s UI better.  So we started by reviewing the results of a community survey from a few months ago and realized that some of the most common feedback from users is related to its interface (very crowded, not consistent, many colors). This is why we decided to start  a joint project with Isabela, (who we consider now part of the Spyder team) called &lt;a href="https://github.com/spyder-ide/spyder/releases/tag/v5.0.0"&gt;Spyder 5&lt;/a&gt;!!!&lt;/p&gt;

&lt;p&gt;This version was in development for over a year and was finally released on April 2nd. It has some nice new features that we hope will benefit our users greatly. Most of these are focused on improving Spyder’s interface and usability, which we did thanks to Isabela’s help. The 3 main UX features implemented in this release were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A brand new color palette designed to bring greater consistency to the UI 
and to make it easier to use.&lt;/li&gt;
&lt;li&gt;The redesign of our toolbars by adjusting the margins and sizes of all the 
buttons to meet accessibility recommendations.&lt;/li&gt;
&lt;li&gt;A new set of icons to ensure a consistent style.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How did we do it?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. First impressions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;[Isabela]&lt;/strong&gt; I find collaboration usually starts with three things: discovering and stating a problem, asking why, and figuring out the best ways to communicate with each other. For me, this is a design problem on it’s own, especially when starting to work with a new team like I was with Spyder. For this project, I was asked to audit Spyder for any UX/UI issues and report back. Because I have a habit of pushing every button in an interface, I ended up having a lot (maybe too much) feedback to pass on. One of the things I remember most about opening Spyder for the first time was having three dialogs pop up immediately. That’s really not the first impression you want to give, and I remember talking to Juanita about that right away. Figuring out how to state problems as simply and clearly to a group of people I didn’t know yet  was intimidating and went through several phases.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. From the “nightmare document” to the issue tracker
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;[Juanita]&lt;/strong&gt; The first phase was discussing all the problems that Isabela found in weekly meetings with Carlos, the Spyder maintainer, and Stephanie, another Spyder core developer. I created a Google drive document (which we ended up calling “The Nightmare document”) in which I collected most of the feedback that Isabela gave us. Then, I grouped this information into categories depending on whether the comments were about the interface, in general, or if they were about a specific pane. Once we agreed on a relevant problem that we wanted to address, I opened an issue on a new repo that we  created in the Spyder’s organization called “&lt;a href="https://github.com/spyder-ide/ux-improvements/issues"&gt;ux-improvements&lt;/a&gt;.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Isabela]&lt;/strong&gt; In fact, that wasn’t even the first set of documents we were working with; I had a whole table, numbering system, and document I was trying to handle before. But it was Juanita that turned them into Github issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Sorting out the nightmare
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;[Juanita]&lt;/strong&gt; Since we ended up with more than 30 issues, we had to start a “triaging phase.” We had to label, triage, organize, and prioritize issues according to “urgency” and importance. This issue tracker became our main tool to keep up with all the plans for the future!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Isabela]&lt;/strong&gt; Juanita did wonderful work tracking our progress through issues and keeping us all accountable, but we were still left with a long list of issues to triage—long enough that it wasn’t all getting in Spyder 5. To have the greatest impact on Spyder, we started with the issues that had influence on Spyder as a whole. Toolbars, icons, and colors are something you will always encounter from the first impression to the most recent, so it made sense to start thinking about those big picture issues first.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Digging deeper into the dark hole
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;[Isabela]&lt;/strong&gt; When prioritizing the audit feedback for Spyder 5, each pass seemed to get to a deeper layer of the problem. For example, what started as issues to make &lt;a href="https://github.com/spyder-ide/ux-improvements/issues/2"&gt;tooltips more legible&lt;/a&gt; and improve the variable explorer’s &lt;a href="https://github.com/spyder-ide/ux-improvements/issues/7"&gt;color coding&lt;/a&gt; soon became the realization that we weren’t sure exactly what blue was already being used for much of Spyder’s interface. It got more complicated when we found out how many colors were hard coded across multiple files or defined by an external project. Eventually, the problem changed from the color contrast of tool tips to an &lt;a href="https://github.com/spyder-ide/ux-improvements/issues/13"&gt;unsustainable approach for managing color&lt;/a&gt; across the two default Spyder themes rooted in a non-Spyder repo. Work at each step did build up into a larger solution, but it’s worth noting that it isn’t what we set out to do in the first place. &lt;/p&gt;

&lt;h3&gt;
  
  
  5. What witchcraft does Isabela do in the background?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;[Juanita]&lt;/strong&gt; One of the most important parts of the process was designing the mock ups for the new ideas that we came up with for the interface which is definitely not our expertise. So... how did the designs magically appear &lt;br&gt;
on our Github issues?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Isabela]&lt;/strong&gt; First things first, it isn’t actually witchcraft even if it looks magical from the outside. How I work depends somewhat on what problem we are trying to solve, so let’s use the design of &lt;a href="https://github.com/spyder-ide/ux-improvements/issues/33#issuecomment-776376943"&gt;custom icons&lt;/a&gt; for Spyder 5 as an example. Once I had a defined list of icons to work on, I needed to spend time making progress on my own. Research on best practices for the relevant area of design is where I started; in this case, I knew we were going to be working with &lt;a href="https://materialdesignicons.com/"&gt;Material Design Icons’&lt;/a&gt; specifications. After that, I did a combination of pen-and-paper sketching and working digitally based on the existing icons in Spyder and Material Design Icons while I kept note of the pros and cons for different directions. I also collected design elements as I built them so that I could make more consistent, accurate designs faster as I worked. For the icons, this included things like letters, rounded corners, and templates for the size and spacing of elements. Finally, I compared options side by side and tried them out in the interface to evaluate what designs were strong enough to bring them to the rest of the team. Then we discussed the options together.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zGRM-xUx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yvtvt6071c96nbpofz50.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zGRM-xUx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yvtvt6071c96nbpofz50.png" alt="Spyder 5 icon mockups"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Mock ups Vs Reality
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;[Juanita]&lt;/strong&gt; After many discussions, mock ups, and meetings, decisions weremade and we were ready to move onto the implementation phase. A big part of the improvements were made in &lt;a href="https://github.com/ColinDuquesnoy/QDarkStyleSheet/"&gt;QDarkStyleSheet&lt;/a&gt; where we did the new palette and color system for both the dark and light themes of Spyder. In my opinion, this was the hardest part of the process since it involved getting familiar with the code first and then,  trying and trying again changing lines of code to change the color or style of buttons, tabs, toolbars, borders, etc… &lt;/p&gt;

&lt;p&gt;The other problem that I ran into, was trying to meet the designs’ specifications. Specially, when working with the &lt;a href="https://github.com/spyder-ide/ux-improvements/issues/28"&gt;toolbars&lt;/a&gt;, figuring the right number for the pixels of margins and sizes was a challenge. I tried several values before finding one that closely matched the proposed mock up only to realize later that “pixels” was not the best unit for the specifications. I ended up using “em” since it was more consistent across operating systems. Isabela, Stephanie and Carlos were part of this process as well. Between the four of us we managed to implement all the changes that we had planned for Spyder 5, the new color palette, the complete redesign of toolbars and the new set of icons. It was an arduous task, more than we all expected, but at the end we were all very happy with the results and thankful to Isabela for helping us to give a new face to Spyder. &lt;/p&gt;

&lt;h2&gt;
  
  
  What's the final result?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;[Isabela]&lt;/strong&gt; Individually, the colors, toolbars, and icons may feel like small adjustments, but those are some of the elements that make up most of Spyder. When they are together, those small adjustments set the mood in the interface; they are more noticeable, and rooted in the Spyder UI many people are already familiar with. While the changes may feel obvious when they are new, they are also chosen to create consistent patterns across interactions that can become more comfortable over time. Spyder’s default dark and light modes, for example, used to use a different set of UI elements between modes. Now they both use the same elements and it is only the colors that change. This makes it easier for users to jump into a familiar interface and take what they know from working in one space to another. For contributors, it gives a more clear UI pattern for them to follow in their own work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before and after (Dark theme)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0n8nll8E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gg8lmbh7p3mqw1y1pd4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0n8nll8E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gg8lmbh7p3mqw1y1pd4l.png" alt="Spyder 5 vs Spyder 4 dark theme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Before and after (Light theme)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mfo-sPeF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/emv88xwj3m5hbt13xm8z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mfo-sPeF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/emv88xwj3m5hbt13xm8z.png" alt="Spyder 5 vs Spyder 4 light theme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What did we learn :)?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;[Isabela]&lt;/strong&gt; From developing new skills to working as a team for the first time, I think we both took a lot from this process. Here are some lessons that stood out to us.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Juanita]&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sometimes it is better to try some of the ideas during the process, than having long discussions about an idea and implementing at the end. In some cases you end up realizing that things don’t look as good as you thought they would, or that some are not even possible.&lt;/li&gt;
&lt;li&gt;One of the most important parts of the design process is to get yourself in the users’ shoes. At the end, they are the reason why we work to improve things constantly.&lt;/li&gt;
&lt;li&gt;Occasionally, less is more. Simple and consistent is better than crowded and complicated. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;[Isabela]&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don’t be afraid of asking questions even when you think you understand the problem because every bit of information can be useful to better grasping what hurts or helps users.&lt;/li&gt;
&lt;li&gt;Always take the time to review what you might think is obvious with the rest of the team. It’s easy to forget about what you know when you are working with people who have different skills than you.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>spyder</category>
      <category>ux</category>
      <category>ui</category>
      <category>release</category>
    </item>
    <item>
      <title>A step towards educating with Spyder</title>
      <dc:creator>Juanita Gomez</dc:creator>
      <pubDate>Fri, 16 Apr 2021 16:10:56 +0000</pubDate>
      <link>https://forem.com/quansightlabs/a-step-towards-educating-with-spyder-4jmf</link>
      <guid>https://forem.com/quansightlabs/a-step-towards-educating-with-spyder-4jmf</guid>
      <description>&lt;p&gt;As a community manager in the Spyder team, I have been looking for ways of involving more users in the community and making Spyder useful for a larger number of people. With this, a new idea came: Education.&lt;/p&gt;

&lt;p&gt;For the past months, we have been wondering with the team whether Spyder could also serve as a teaching-learning platform, especially in this era where remote instruction has become necessary. We submitted a proposal to the Essential Open Source Software for Science (EOSS) program of the Chan&lt;br&gt;
Zuckerberg Initiative, during its third cycle, with the idea of providing a simple way inside Spyder to create and share interactive tutorials on topics relevant to scientific research. Unfortunately, we didn’t get this funding,&lt;br&gt;
but we didn’t let this great idea die.&lt;/p&gt;

&lt;p&gt;We submitted a second proposal to the &lt;a href="https://www.python.org/psf/"&gt;Python Software Foundation&lt;/a&gt; from which we were awarded $4000. For me, this is the perfect opportunity for&lt;br&gt;
us to take the first step towards using Spyder for education.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the project is about
&lt;/h2&gt;

&lt;p&gt;The goal of this project is to create specialized Python online training content that uses Spyder as the main platform to deliver it. The grant will cover the development of three practical workshops:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Python for Financial Data Analysis with Spyder&lt;/li&gt;
&lt;li&gt;Python for Scientific Computing and Visualization with Spyder&lt;/li&gt;
&lt;li&gt;Spyder 5 Plugin Development&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;They will be included as part of &lt;a href="https://docs.spyder-ide.org/current/index.html"&gt;Spyder’s documentation&lt;/a&gt; for remote learning, but they will also be used as hands-on materials for talks and workshops.&lt;/p&gt;

&lt;p&gt;These materials are meant for users to learn how Spyder can accelerate their workflow when working with Python in scientific research and data analysis. The idea is for us to provide a way in which we can help people get the most&lt;br&gt;
out of Spyder by applying it in their day-to-day jobs.&lt;/p&gt;

&lt;p&gt;The first two workshops will cover aspects such as data exploration and visualization with Spyder’s variable explorer and plots panes, getting documentation through Spyder’s help pane, writing good quality and efficient code using Spyder’s code analysis and profiler, etc.&lt;/p&gt;

&lt;p&gt;Our last workshop will demonstrate how to create a plugin for Spyder, which, thanks to our new API in &lt;a href="https://github.com/spyder-ide/spyder/releases/tag/v5.0.0"&gt;Spyder 5&lt;/a&gt;, released in April 2021, will allow users to easily customize and extend Spyder’s interface with new menus, toolbars, widgets or panes in order to adapt it to their own needs...&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it is important
&lt;/h2&gt;

&lt;p&gt;This project will benefit the international community of Spyder users (around 500,000, we estimate) to discover new capabilities of Spyder in order to take advantage of all its resources. It will also provide testing materials for potential users who will be able to adopt Spyder as a tool for&lt;br&gt;
their work in Financial Data Analysis, Scientific research and Spyder plugin development.&lt;/p&gt;

&lt;p&gt;For the past months, our &lt;a href="https://youtube.com/playlist?list=PLPonohdiDqg9epClEcXoAPUiK0pN5eRoc"&gt;documentation tutorials&lt;/a&gt; have had a great impact in our community, with more than 20,000 views in our YouTube channel. We expect these workshops to be a great input to our documentation and help us continue building a community around Spyder.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is next?
&lt;/h2&gt;

&lt;p&gt;This project is just the first step towards making Spyder an educational tool. In the future, we hope that we can develop the infrastructure necessary to support in-IDE tutorials, by improving the tools like &lt;a href="https://github.com/executablebooks/jupyter-book"&gt;Jupyter Book&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://github.com/executablebooks/sphinx-thebe"&gt;sphinx-thebe&lt;/a&gt;, &lt;a href="https://github.com/executablebooks/MyST-Parser"&gt;MyST-Parser&lt;/a&gt; which will provide better integration to write educational tutorials.&lt;/p&gt;

&lt;p&gt;The final goal is to enable researchers, educators and experts that don’t necessarily have a software engineering background to build scientific programming tutorials easily and provide them as online learning materials&lt;br&gt;
in Spyder. Once the infrastructure is built, we can develop several examples to demonstrate Spyder capabilities and teach basic scientific programming concepts applicable to a variety of fields.&lt;/p&gt;

</description>
      <category>spyder</category>
      <category>community</category>
      <category>grant</category>
    </item>
    <item>
      <title>Accessibility: Who's Responsible?</title>
      <dc:creator>Isabela Presedo-Floyd</dc:creator>
      <pubDate>Sat, 27 Mar 2021 02:56:37 +0000</pubDate>
      <link>https://forem.com/quansightlabs/accessibility-who-s-responsible-13ki</link>
      <guid>https://forem.com/quansightlabs/accessibility-who-s-responsible-13ki</guid>
      <description>&lt;p&gt;For the past few months, I've been part of a group of people in the JupyterLab community who've committed to start chipping away at the many accessibility failings of JupyterLab. I find this work is critical, fascinating, and a learning experience for everyone involved. So I'm going to document my personal experience and lessons I've learned in a series of blog posts. Welcome!&lt;/p&gt;

&lt;p&gt;Because this is the first of a series, I want to make sure we start with a good foundation. Let me answer some questions you might be having.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; Who are you? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A:&lt;/strong&gt; I'm Isabela, a UX/UI designer at &lt;a href="https://labs.quansight.org/"&gt;Quansight Labs&lt;/a&gt;, who cares about accessibility and is fortunate to work somewhere where that is a respected concern. I also spend time in the Jupyter ecosystem—especially around JupyterLab —though that is not the only open-source community you can find me in. I like to collect gargoyles, my hair is pink, and I love the sunflower emoji 🌻. It's nice to meet you!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; What is the Jupyter ecosystem and JupyterLab? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A:&lt;/strong&gt; &lt;a href="https://jupyter.org/"&gt;Project Jupyter&lt;/a&gt; is an organization that produces open-source software and open standards. The Jupyter ecosystem is a term used to describe projects that are directly a part of or support Project Jupyter. JupyterLab is one of its primary projects and a staple for the day-to-day work of many students, professionals, researchers, and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; What is accessibility? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A:&lt;/strong&gt; Accessibility is a term used to describe the practice of creating things in a way that makes them usable for people with disabilities. I’m going to be talking mostly about web accessibility since JupyterLab is a web app. If you're asking why you should care about accessibility, please take a moment to read &lt;a href="https://www.w3.org/WAI/fundamentals/accessibility-intro/#context"&gt;why it matters&lt;/a&gt; (hint: there are ethical, legal, and business reasons to care). Inaccessible experiences can have consequences, from people not being able to get information they need to being unable to pursue whole careers that rigidly require the use of inaccessible software (such as JupyterLab).&lt;/p&gt;

&lt;h2&gt;
  
  
  How did we get here?
&lt;/h2&gt;

&lt;p&gt;The Jupyter ecosystem is full of people who care about accessibility. I know this because I've heard people ask about accessibility in community meetings. I know this because I've read discussions about accessibility on Github issues and PRs. I know this because the project has a &lt;a href="https://github.com/jupyter/accessibility/"&gt;repository&lt;/a&gt; devoted to organizing community accessibility efforts. If this is the case, then why hasn't JupyterLab already been made more accessible in the past three years it's been deemed "&lt;a href="https://blog.jupyter.org/jupyterlab-is-ready-for-users-5a6f039b8906"&gt;ready for users&lt;/a&gt;?" (I'm intentionally not mentioning other Jupyter projects to limit this post's scope.)&lt;/p&gt;

&lt;p&gt;Because for every time accessibility is brought up, I've also experienced a hesitance around taking action. Even though I’ve never heard it explicitly said, the way I’ve seen these efforts get lost time and time again has come to mean this in my head: “accessibility is someone else’s problem.” But it can’t always be someone else’s problem; at some point there is a person taking ownership of the work.&lt;/p&gt;

&lt;p&gt;So who is responsible for making something accessible? Probably not the users, though feedback can be a helpful step in making change. Certainly not the people that already can’t use the tool because it isn’t accessible. But I, personally, think anyone who is part of making that tool is responsible for building and maintaining its accessibility. Just as any user experience encompasses the whole of a product, an accessible experience does the same. This should be a consideration from within the product, to its support/documentation, to any other interaction. A comprehensive team who thinks to ask questions like, “how would I use this if I could only use my keyboard?” or “would I be able to get the same information if I were colorblind?” are starting to hold themselves and their team accountable. Taking responsibility is key to starting and sustaining change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Misconceptions
&lt;/h2&gt;

&lt;p&gt;Here are a few common concerns I’ve heard when people tell me why they can’t or haven’t worked on accessibility. I’m going to paraphrase some replies I've heard when asking about accessibility in many different environments (not only JupyterLab) over the years.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I don’t know anything!&lt;/strong&gt; And that’s fine. You don’t have to be an expert! Fortunately, there are already a lot of resources out on the wide open internet, some even focused on beginners (some of my personal favorites are at &lt;a href="https://www.a11yproject.com/resources"&gt;The A11y Project&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/What_is_accessibility"&gt;MDN&lt;/a&gt;). Of course, it’s important to remember that learning will mean that you are likely to make mistakes and need to keep iterating. This isn’t a one-and-done deal. If you do have access to an expert, spending time to build a foundation means they can help you tackle greater obstacles instead of just giving you the basics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I don’t have time for another project!&lt;/strong&gt; Accessibility doesn’t have to be your only focus. JupyterLab sure isn’t the only project I am working on, and it won’t be in the near future. Any progress is better than no progress, and several people doing even a little work can add up faster than you might think. Besides, there’s a good chance you won’t even have to go out of your way to start improving accessibility. Start by asking questions about a project you are already working on. Is there a recommended way to design and build a component? Is information represented in more than one way? Is everything labeled? It’s good practice and more sustainable to consider accessibility as a regular part of your process instead of a special side project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It’s not a good use of my energy to work on something that only affects a few people!&lt;/strong&gt; It’s not just a few people. Read what &lt;a href="https://www.who.int/en/news-room/fact-sheets/detail/disability-and-health"&gt;WHO&lt;/a&gt; and the &lt;a href="https://www.cdc.gov/ncbddd/disabilityandhealth/infographic-disability-impacts-all.html"&gt;CDC&lt;/a&gt; have to say about the number of people with disabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I don’t want to make abled people’s experience different than it already is!&lt;/strong&gt; Depending on what you are doing, the changes might not be active or noticeable unless assistive technologies or accessibility features are being actively used. And in many cases, accessibility features improve the experience for all users and not just those they were designed for (sometimes called the &lt;a href="https://uxdesign.cc/the-curb-cut-effect-universal-design-b4e3d7da73f5"&gt;curb cut effect&lt;/a&gt;). Even if you aren’t convinced, I’d encourage you to ask yourself why creating the user experience you want and making that experience accessible are mutually exclusive. What are people missing out on if they can’t use your product? What are you missing out on if they can’t use your product?&lt;/p&gt;

&lt;h2&gt;
  
  
  What could responsibility be like?
&lt;/h2&gt;

&lt;p&gt;With JupyterLab, it was just a matter of a few people who were willing to say they were tired of waiting and able to spend time both learning what needed to be done as well as doing it. Speaking for myself, I did not come in as an expert or with undivided obligations or even someone with all the skills to make changes that are needed. I think this is important to note because it seems to me that it could have just as easily been other members of the community in my position given similar circumstances.&lt;/p&gt;

&lt;p&gt;Our first step in taking responsibility was setting up a regular time to meet so we could check-in and help one another. Then we set reasonable goals and scoped the work: we decided to focus on JupyterLab rather than multiple projects at once, address &lt;a href="https://www.w3.org/TR/WCAG21/"&gt;WCAG 2.1 standards&lt;/a&gt; in parts of JupyterLab we were already working on, and follow up on past work that other community members began. This is just the beginning, but I hope it was a helpful peek into the process we are trying out.&lt;/p&gt;

&lt;h2&gt;
  
  
  But wait, there's more!
&lt;/h2&gt;

&lt;p&gt;Deciding to make accessibility a priority in Jupyter spaces isn't where this work ends. Join me for the next post in this series where I'll talk about my not-so-subtle panic at the amount of problems to be solved, how to move forwards in spite of panic, and the four experience types in JupyterLab that we must address to be truly accessible.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Interested in getting involved? Join our community via the JupyterLab accessibility meetings listed every other week on the &lt;a href="https://jupyter.readthedocs.io/en/latest/community/content-community.html#jupyter-community-meetings"&gt;Jupyter community calendar&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>jupyter</category>
      <category>inclusion</category>
    </item>
  </channel>
</rss>
