Представьте: вы потягиваете кофе, а Jupyter Notebook послушно превращает ваши переменные Python в сонеты Шекспира. В этом сила расширений — и сегодня мы создадим такое, которое будет действительно полезным (хотя поддержка ямбического пентаметра может появиться в версии 2). Приготовьтесь к насыщенному кодингом путешествию по системе расширений Jupyter!

Подготовка основы

Прежде чем мы начнём творить чудеса, давайте подготовим мастерскую нашего волшебника:

# Создаём каркас расширения
npx create-jupyterlab-extension jupyterlab_stonks
cd jupyterlab_stonks
jlpm install

Это создаёт проект TypeScript (двоюродный брат JavaScript, знающий о типах). Не паникуйте — мы будем писать обычный JS с аннотациями типов в качестве дополнительных спасательных жилетов. Наши файлы для работы:

  1. src/index.ts — точка входа расширения;
  2. schema/plugin.json — метаданные расширения;
  3. style/base.css — CSS для элементов пользовательского интерфейса.

Жизненный цикл расширения

Давайте наглядно покажем, как расширения взаимодействуют с Jupyter:

graph TD A[Код расширения] --> B[Упаковщик Webpack] B --> C[Оболочка JupyterLab] C --> D[Реестр плагинов] D --> E{Триггер активации} E -->|Действие пользователя| F[Выполнение команд] F --> G[Обновления DOM]

Совет от профессионала: архитектура JupyterLab похожа на луковицу — слой за слоем, но понять её гораздо проще, чем заставить плакать.

Создание виджета отслеживания рынка

Давайте создадим биржевой тикер, рядом с которым «Волк с Уолл-стрит» покажется распродажей. Сначала зарегистрируем плагин:

// src/index.ts
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
const plugin: JupyterFrontEndPlugin<void> = {
  id: 'jupyterlab-stonks',
  autoStart: true,
  activate: (app) => {
    console.log('JupyterLab Stonks активировано! 🚀');
    // Здесь будет жить наш виджет
    addTickerWidget(app);
  }
};
export default plugin;

Теперь самое интересное — класс нашего виджета:

class StonksWidget {
  constructor() {
    this.node = document.createElement('div');
    this.node.id = 'stonks-ticker';
    this._tickers = ['TSLA', 'NVDA', 'AMD'];
  }
  updatePrices() {
    // Сделаем вид, что мы делаем реальные вызовы API
    const prices = this._tickers.map(t => 
      `${t}: $${(Math.random() * 1000).toFixed(2)} 📈`
    );
    this.node.innerHTML = prices.join(' | ');
  }
}

Подключение к пользовательскому интерфейсу Jupyter

Пора сделать так, чтобы наш виджет хорошо сочетался с существующим интерфейсом Jupyter:

function addTickerWidget(app) {
  const widget = new StonksWidget();
  widget.updatePrices();
  // Добавляем в верхнюю панель
  app.shell.add(widget, 'top', { rank: 1000 });
  // Обновляем каждые 30 секунд
  setInterval(() => widget.updatePrices(), 30000);
}

Хотите добавить пункт контекстного меню? Проще простого:

app.contextMenu.addItem({
  command: 'stonks:refresh',
  selector: '.jp-Notebook',
  rank: 900
});

Профессиональная отладка

Когда что-то ломается (а это случится), используйте эти мощные инструменты:

  1. jlpm run build:watch — автоматическая перестройка при изменениях;
  2. jupyter lab --watch — автоперезагрузка JupyterLab;
  3. Инструменты разработчика браузера — ваш новый лучший друг;
  4. console.log(Осторожно помещённые ${diagnostic} операторы). Помните: отладка — это как быть детективом в криминальной истории, где вы также являетесь убийцей.

Подводные камни развёртывания

Когда вы будете готовы выпустить своё творение:

jupyter labextension install .

Следите за этими распространёнными ошибками:

  1. Несоответствие версий (JupyterLab 4.x против 3.x);
  2. Совпадение имён классов CSS;
  3. Чрезмерно усердные блокировщики рекламы, поглощающие ваши вызовы API;
  4. Пользователи, которые действительно хотят получать советы по акциям от вашего расширения.

Что делать дальше

Теперь, когда вы освоили основы, попробуйте:

  • Добавить компоненты React;
  • Интегрироваться с системой ядра Jupyter;
  • Создать собственные типы ячеек ноутбука;
  • Построить интерактивные инструменты визуализации данных. Экосистема расширений Jupyter похожа на набор LEGO для взрослых — бесконечные возможности, и вы определённо наступите на несколько острых кусочков по пути. Помните: с большой силой расширений приходит большая ответственность. Используйте его для создания потрясающих инструментов, а не только для вставки GIF с котиками (если только это не ваше хобби — я не буду осуждать). Удачного кодирования! 🛠️