diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..63d64f0 --- /dev/null +++ b/.flake8 @@ -0,0 +1,9 @@ +# Taken directly from https://github.com/ambv/black/blob/master/.flake8 +[flake8] +ignore = E203, E266, E501, W503, C901, D104, D100 +max-line-length = 88 +max-complexity = 18 +select = B,C,E,F,W,T4,B9 +per-file-ignores = + tests/**:D101,D102,D103 +docstring-convention = numpy diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..08f4e4f --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @betatim @xhochy diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..175844a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + groups: + dependencies: + patterns: + - "*" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..5e35133 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,30 @@ +name: Build and upload to PyPI +on: + push: + pull_request: + release: + types: [published] + +jobs: + build_artifacts: + name: Build artifacts + runs-on: ubuntu-latest + strategy: + fail-fast: true + steps: + - uses: actions/checkout@v4 + - name: Fetch full git history + run: git fetch --prune --unshallow + - name: Set up Conda env + uses: mamba-org/setup-micromamba@068f1ab4b37ed9b3d9f73da7db90a0cda0a48d29 + with: + environment-file: environment.yml + cache-environment: true + - shell: bash -el {0} + run: + python -m build + - uses: pypa/gh-action-pypi-publish@v1.12.3 + if: github.event_name == 'release' + with: + user: __token__ + password: ${{ secrets.PYPI_RELEASE_TOKEN }} diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..f77ebc2 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,32 @@ +name: CI +on: [push, pull_request] + +# Automatically stop old builds on the same branch/PR +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash -el {0} + +jobs: + pre-commit-checks: + name: "Linux - pre-commit checks - Python 3.10" + timeout-minutes: 30 + runs-on: ubuntu-latest + env: + PRE_COMMIT_USE_MICROMAMBA: 1 + steps: + - name: Checkout branch + uses: actions/checkout@v4 + - name: Set up micromamba + uses: mamba-org/setup-micromamba@068f1ab4b37ed9b3d9f73da7db90a0cda0a48d29 + - name: Add micromamba to GITHUB_PATH + run: echo "${HOME}/micromamba-bin" >> "$GITHUB_PATH" + - name: Install Python 3.10 + uses: actions/setup-python@v5 + with: + python-version: "3.10" + - name: Run pre-commit checks + uses: pre-commit/action@v3.0.1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..394e28d --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,35 @@ +repos: + - repo: https://github.com/Quantco/pre-commit-mirrors-black + rev: 23.7.0 + hooks: + - id: black-conda + args: + - --safe + - --target-version=py38 + - repo: https://github.com/Quantco/pre-commit-mirrors-flake8 + rev: 6.1.0 + hooks: + - id: flake8-conda + - repo: https://github.com/Quantco/pre-commit-mirrors-isort + rev: 5.12.0 + hooks: + - id: isort-conda + additional_dependencies: [-c, conda-forge, toml=0.10.2] + - repo: https://github.com/Quantco/pre-commit-mirrors-mypy + rev: "1.5.1" + hooks: + - id: mypy-conda + additional_dependencies: + - -c + - conda-forge + - types-mock + - types-setuptools + - types-redis + - types-boto + - boto3-stubs + - repo: https://github.com/Quantco/pre-commit-mirrors-pyupgrade + rev: 3.10.1 + hooks: + - id: pyupgrade-conda + args: + - --py38-plus diff --git a/README.md b/README.md index 554bfb0..c6a7641 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # VS Code on Binder [![PyPI](https://img.shields.io/pypi/v/jupyter-vscode-proxy)](https://pypi.org/project/jupyter-vscode-proxy/) -[![Install with conda](https://anaconda.org/conda-forge/jupyter-vscode-proxy/badges/installer/conda.svg)](https://github.com/conda-forge/jupyter-vscode-proxy-feedstock) +[![Install with conda](https://anaconda.org/conda-forge/jupyter-vscode-proxy/badges/version.svg)](https://github.com/conda-forge/jupyter-vscode-proxy-feedstock) VS Code on Binder, because sometimes you need a real editor. diff --git a/environment.yml b/environment.yml index bc2c718..7ea9cee 100644 --- a/environment.yml +++ b/environment.yml @@ -1,6 +1,8 @@ +name: vscode-binder channels: - conda-forge dependencies: - numpy + - python-build - jupyter-server-proxy - code-server >=3.2 diff --git a/jupyter_vscode_proxy/__init__.py b/jupyter_vscode_proxy/__init__.py index bc78f26..eb5ae43 100644 --- a/jupyter_vscode_proxy/__init__.py +++ b/jupyter_vscode_proxy/__init__.py @@ -1,46 +1,75 @@ import os import shutil +from typing import Any, Callable, Dict, List -def setup_vscode(): - def _get_vscode_cmd(port): - executable = "code-server" +def _get_inner_vscode_cmd() -> List[str]: + return [ + "code-server", + "--auth", + "none", + "--disable-telemetry", + ] + + +def _get_inner_openvscode_cmd() -> List[str]: + return [ + "openvscode-server", + "--without-connection-token", + "--telemetry-level", + "off", + ] + + +_CODE_EXECUTABLE_INNER_CMD_MAP: Dict[str, Callable] = { + "code-server": _get_inner_vscode_cmd, + "openvscode-server": _get_inner_openvscode_cmd, +} + + +def _get_cmd_factory(executable: str) -> Callable: + if executable not in _CODE_EXECUTABLE_INNER_CMD_MAP: + raise KeyError( + f"'{executable}' is not one of {_CODE_EXECUTABLE_INNER_CMD_MAP.keys()}." + ) + + get_inner_cmd = _CODE_EXECUTABLE_INNER_CMD_MAP[executable] + + def _get_cmd(port: int) -> List[str]: if not shutil.which(executable): - raise FileNotFoundError("Can not find code-server in PATH") - + raise FileNotFoundError(f"Can not find {executable} in PATH") + # Start vscode in CODE_WORKINGDIR env variable if set # If not, start in 'current directory', which is $REPO_DIR in mybinder # but /home/jovyan (or equivalent) in JupyterHubs working_dir = os.getenv("CODE_WORKINGDIR", ".") extensions_dir = os.getenv("CODE_EXTENSIONSDIR", None) - extra_extensions_dir = os.getenv("CODE_EXTRA_EXTENSIONSDIR", None) - cmd = [ - executable, - "--auth", - "none", - "--disable-telemetry", - "--port=" + str(port), - ] + cmd = get_inner_cmd() + + cmd.append("--port=" + str(port)) if extensions_dir: cmd += ["--extensions-dir", extensions_dir] - if extra_extensions_dir: - cmd += ["--extra-extensions-dir", extra_extensions_dir] - cmd.append(working_dir) return cmd + return _get_cmd + + +def setup_vscode() -> Dict[str, Any]: + executable = os.environ.get("CODE_EXECUTABLE", "code-server") + icon = "code-server.svg" if executable == "code-server" else "vscode.svg" return { - "command": _get_vscode_cmd, - "timeout": 20, + "command": _get_cmd_factory(executable), + "timeout": 300, "new_browser_tab": True, "launcher_entry": { "title": "VS Code", "icon_path": os.path.join( - os.path.dirname(os.path.abspath(__file__)), "icons", "vscode.svg" + os.path.dirname(os.path.abspath(__file__)), "icons", icon ), }, } diff --git a/jupyter_vscode_proxy/icons/code-server.svg b/jupyter_vscode_proxy/icons/code-server.svg new file mode 100644 index 0000000..85b701d --- /dev/null +++ b/jupyter_vscode_proxy/icons/code-server.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/postBuild b/postBuild index ff03503..542f613 100644 --- a/postBuild +++ b/postBuild @@ -1,10 +1,5 @@ #!/bin/bash -# Enable the proxy extension in notebook and lab -jupyter serverextension enable --py jupyter_server_proxy -jupyter labextension install @jupyterlab/server-proxy -jupyter lab build - code-server --install-extension ms-python.python # Install the VS code proxy diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..32f5676 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,53 @@ +[build-system] +requires = ["setuptools", "setuptools-scm", "wheel"] + +[tool.setuptools_scm] +version_scheme = "post-release" + +[project] +name = "jupyter_vscode_proxy" +description = "VS Code extension for Jupyter" +readme = "README.md" +dynamic = ["version"] +authors = [ + {name = "Tim Head", email = "noreply@example.com"}, +] +classifiers = [ + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", +] +requires-python = ">=3.8" +license = {text = "BSD-3-clause"} + +[project.urls] +repository = "https://github.com/betatim/vscode-binder" + +[project.entry-points.jupyter_serverproxy_servers] +vscode = "jupyter_vscode_proxy:setup_vscode" + +[tool.black] +exclude = ''' +/( + \.eggs + | \.git + | \.venv + | build + | dist +)/ +''' + +[tool.isort] +profile = "black" +line_length = 88 +known_first_party = "{{ project_slug }}" +skip_glob = '\.eggs/*,\.git/*,\.venv/*,build/*,dist/*' +default_section = 'THIRDPARTY' + +[tool.mypy] +python_version = '3.8' +ignore_missing_imports = true +no_implicit_optional = true +check_untyped_defs = true diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 8183238..0000000 --- a/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[metadata] -license_files = LICENSE diff --git a/setup.py b/setup.py deleted file mode 100644 index f51d1b7..0000000 --- a/setup.py +++ /dev/null @@ -1,31 +0,0 @@ -import setuptools - - -with open("README.md", encoding="utf8") as f: - readme = f.read() - - -setuptools.setup( - name="jupyter-vscode-proxy", - version="0.1", - url="https://github.com/betatim/vscode-binder", - author="Tim Head", - license="BSD", - description="VS Code extension for Jupyter", - long_description=readme, - long_description_content_type="text/markdown", - packages=setuptools.find_packages(), - keywords=["Jupyter", "vscode", "vs code", "editor"], - classifiers=["Framework :: Jupyter"], - install_requires=[ - 'jupyter-server-proxy' - ], - entry_points={ - "jupyter_serverproxy_servers": ["vscode = jupyter_vscode_proxy:setup_vscode",] - }, - package_data={"jupyter_vscode_proxy": ["icons/*"]}, - project_urls={ - "Source": "https://github.com/betatim/vscode-binder/", - "Tracker": "https://github.com/betatim/vscode-binder/issues", - }, -)