Commit a5afdc21 authored by Peder Bergebakken Sundt's avatar Peder Bergebakken Sundt
Browse files
parent 7f76f6bd
Loading
Loading
Loading
Loading
+326 −55
Original line number Diff line number Diff line
@@ -2,34 +2,39 @@
  lib,
  buildPythonPackage,
  fetchFromGitHub,
  pythonAtLeast,

  # build-system
  hatchling,
  pre-commit,
  toml,
  uv-dynamic-versioning,

  # dependencies
  alembic,
  requests,
  click,
  granian,
  httpx,
  packaging,
  platformdirs,
  psutil,
  pydantic,
  python-multipart,
  python-socketio,
  redis,
  reflex-hosting-cli,
  rich,
  sqlmodel,
  starlette,
  typing-extensions,
  wrapt,

  # sub package dependencies
  pydantic,
  griffelib,
  mistletoe,
  pyyaml,
  typing-inspection,
  email-validator,
  ruff-format,

  # tests
  attrs,
  typer,
  numpy,
  pandas,
  pillow,
@@ -41,71 +46,126 @@
  python-dotenv,
  ruff,
  starlette-admin,
  unzip,
  uvicorn,
  versionCheckHook,
  writableTmpDirAsHomeHook,
}:

let

  metaCommon = {
    description = "Web apps in pure Python";
    homepage = "https://github.com/reflex-dev/reflex";
    license = lib.licenses.asl20;
    maintainers = with lib.maintainers; [ pbsds ];
  };

  buildSubPackage =
    {
      pname,
      version,
      src,
      workspace,
      workspaces,
      subPkgs,
    }:
    buildPythonPackage {
      inherit pname version src;
      pyproject = true;
      sourceRoot = "${src.name}/packages/${pname}";

      build-system = [
        hatchling
        uv-dynamic-versioning
        ruff
      ]
      ++ lib.optional (pname != "hatch-reflex-pyi") subPkgs.hatch-reflex-pyi;

      preBuild = ''
        # for .ruff_cache and whatnot, written by hatch-reflex-pyi
        chmod -R +w ../..
      '';

      inherit (workspace) dependencies;

      # the top-level package tests everything
      doCheck = false;

      meta = metaCommon;
    };

in

buildPythonPackage (finalAttrs: {
  pname = "reflex";
  version = "0.8.28";
  version = "0.9.1";
  pyproject = true;

  src = fetchFromGitHub {
    owner = "reflex-dev";
    repo = "reflex";
    tag = "v${finalAttrs.version}";
    hash = "sha256-sohID83qFnXV8vsaRy+t4cKxkki97U7sFxHIEYIEWeY=";
    hash = "sha256-YYy/K4AXeh9wS4Vodg3NOqwolPYHTgpP5/yWkutMsxo=";
  };

  # For some reason, pre_commit is supposedly missing when python>=3.14
  postPatch = lib.optionalString (pythonAtLeast "3.14") ''
    substituteInPlace pyproject.toml \
      --replace-fail '"pre_commit", ' ""
  '';

  build-system = [
    hatchling
    pre-commit
    toml
    uv-dynamic-versioning
  ];

  nativeBuildInputs = [
    ruff
  ];

  dependencies = [
    alembic
  dependencies =
    let
      inherit (finalAttrs.passthru) subPkgs;
    in
    [
      click
      requests
      granian
      httpx
      packaging
    platformdirs
      psutil
    pydantic
      python-multipart
      python-socketio
      redis
    reflex-hosting-cli
      rich
    sqlmodel
      starlette
      typing-extensions
      wrapt
      plotly

      subPkgs.reflex-base
      subPkgs.reflex-components-code
      subPkgs.reflex-components-core
      subPkgs.reflex-components-dataeditor
      subPkgs.reflex-components-gridjs
      subPkgs.reflex-components-lucide
      subPkgs.reflex-components-markdown
      subPkgs.reflex-components-moment
      subPkgs.reflex-components-plotly
      subPkgs.reflex-components-radix
      subPkgs.reflex-components-react-player
      subPkgs.reflex-components-recharts
      subPkgs.reflex-components-sonner
      subPkgs.reflex-hosting-cli
    ]
    ++ granian.optional-dependencies.reload;

  nativeCheckInputs = [
    attrs
    typer
    numpy
    pandas
    pillow
    playwright
    plotly
    pytest-asyncio
    pytest-mock
    pytestCheckHook
    python-dotenv
    ruff
    starlette-admin
    unzip
    uvicorn
    versionCheckHook
    writableTmpDirAsHomeHook
@@ -113,43 +173,254 @@ buildPythonPackage (finalAttrs: {
  versionCheckProgramArg = "--version";

  disabledTests = [
    # Tests touch network
    "test_find_and_check_urls"
    "test_event_actions"
    "test_upload_file"
    # Touches network
    "test_node_version"

    # /proc is too funky in nix sandbox
    "test_get_cpu_info"

    # flaky
    "test_preprocess" # KeyError: 'reflex___state____state'
    "test_send" # AssertionError: Expected 'post' to have been called once. Called 0 times.
    "test_state_manager_lock" # Lock expired for token 87164611-f...
    # tries to pin the string of a traceback, doesn't account for ansi colors
    "test_state_with_invalid_yield"

    # tries to run bun or npm
    "test_output_system_info"
    # Comparison with magic string
    "test_background_task_no_block"

    # reflex.utils.exceptions.StateSerializationError: Failed to serialize state
    # reflex___istate___dynamic____dill_state due to unpicklable object.
    "test_fallback_pickle"

    # AssertionError (mocked_open.call_count == 2)
    "test_delete_token_from_config"
  ];

  disabledTestPaths = [
    "tests/benchmarks/"
    "tests/integration/"

    # circular imports (reflex-docgen)
    "tests/units/docgen/test_class_and_component.py"
    "tests/units/docgen/test_markdown.py"
    "docs/app/tests/test_docgen_double_eval.py"

    # circular imports (reflex_site_shared)
    "docs/app/tests/test_routes.py"
  ];

  __darwinAllowLocalNetworking = true;

  pythonImportsCheck = [ "reflex" ];
  pythonImportsCheck = [
    "reflex"
    "reflex.admin"
    "reflex.app"
    "reflex.app_mixins.lifespan"
    "reflex.app_mixins.middleware"
    "reflex.app_mixins.mixin"
    "reflex.assets"
    "reflex.compiler"
    "reflex.components"
    "reflex.config"
    "reflex.constants"
    "reflex.custom_components"
    "reflex.environment"
    "reflex.event"
    "reflex.experimental"
    "reflex.experimental.client_state"
    "reflex.experimental.hooks"
    "reflex.experimental.memo"
    "reflex.istate"
    "reflex.middleware"
    "reflex.model"
    "reflex.page"
    "reflex.plugins"
    "reflex.plugins.sitemap"
    "reflex.plugins.tailwind_v3"
    "reflex.plugins.tailwind_v4"
    "reflex.reflex"
    "reflex.route"
    "reflex.state"
    "reflex.style"
    "reflex.utils"
    "reflex.vars"
  ];

  meta = {
    description = "Web apps in pure Python";
    homepage = "https://github.com/reflex-dev/reflex";
  passthru = {
    # all [tool.uv.sources] workspaces in pyproject.toml
    workspaces =
      let
        inherit (finalAttrs.passthru) subPkgs;
      in
      # this is generated with:
      # ./pkgs/development/python-modules/reflex/mk_workspaces.sh
      {
        hatch-reflex-pyi.dependencies = [
          hatchling
        ];
        integrations-docs.dependencies = [
        ];
        reflex-base.dependencies = [
          packaging
          platformdirs
          pydantic
          rich
          typing-extensions
        ];
        reflex-components-code.dependencies = [
          subPkgs.reflex-base
          subPkgs.reflex-components-core
          subPkgs.reflex-components-lucide
          subPkgs.reflex-components-radix
          subPkgs.reflex-components-sonner
          ruff
        ];
        reflex-components-core.dependencies = [
          python-multipart
          subPkgs.reflex-base
          subPkgs.reflex-components-lucide
          subPkgs.reflex-components-sonner
          ruff
          starlette
          typing-extensions
        ];
        reflex-components-dataeditor.dependencies = [
          subPkgs.reflex-base
          subPkgs.reflex-components-core
          subPkgs.reflex-components-lucide
          subPkgs.reflex-components-sonner
          ruff
        ];
        reflex-components-gridjs.dependencies = [
          subPkgs.reflex-base
          ruff
        ];
        reflex-components-internal.dependencies = [
          finalAttrs.finalPackage # reflex
          subPkgs.reflex-base
          subPkgs.reflex-components-code
          subPkgs.reflex-components-core
          subPkgs.reflex-components-dataeditor
          subPkgs.reflex-components-gridjs
          subPkgs.reflex-components-lucide
          subPkgs.reflex-components-markdown
          subPkgs.reflex-components-moment
          subPkgs.reflex-components-plotly
          subPkgs.reflex-components-radix
          subPkgs.reflex-components-react-player
          subPkgs.reflex-components-recharts
          subPkgs.reflex-components-sonner
          subPkgs.reflex-hosting-cli
          ruff
        ];
        reflex-components-lucide.dependencies = [
          subPkgs.reflex-base
          ruff
        ];
        reflex-components-markdown.dependencies = [
          subPkgs.reflex-base
          subPkgs.reflex-components-code
          subPkgs.reflex-components-core
          subPkgs.reflex-components-lucide
          subPkgs.reflex-components-radix
          subPkgs.reflex-components-sonner
          ruff
        ];
        reflex-components-moment.dependencies = [
          subPkgs.reflex-base
          ruff
        ];
        reflex-components-plotly.dependencies = [
          subPkgs.reflex-base
          subPkgs.reflex-components-core
          subPkgs.reflex-components-lucide
          subPkgs.reflex-components-sonner
          ruff
        ];
        reflex-components-radix.dependencies = [
          subPkgs.reflex-base
          subPkgs.reflex-components-core
          subPkgs.reflex-components-lucide
          subPkgs.reflex-components-sonner
          ruff
        ];
        reflex-components-react-player.dependencies = [
          subPkgs.reflex-base
          subPkgs.reflex-components-core
          subPkgs.reflex-components-lucide
          subPkgs.reflex-components-sonner
          ruff
        ];
        reflex-components-recharts.dependencies = [
          subPkgs.reflex-base
          ruff
        ];
        reflex-components-sonner.dependencies = [
          subPkgs.reflex-base
          subPkgs.reflex-components-lucide
          ruff
        ];
        reflex-docgen.dependencies = [
          griffelib
          mistletoe
          pyyaml
          finalAttrs.finalPackage # reflex
          typing-extensions
          typing-inspection
        ];
        reflex-hosting-cli.dependencies = [
          click
          httpx
          packaging
          platformdirs
          rich
        ];
        reflex-site-shared.dependencies = [
          email-validator
          httpx
          pyyaml
          finalAttrs.finalPackage # reflex
          subPkgs.reflex-base
          subPkgs.reflex-components-code
          subPkgs.reflex-components-core
          subPkgs.reflex-components-dataeditor
          subPkgs.reflex-components-gridjs
          subPkgs.reflex-components-internal
          subPkgs.reflex-components-lucide
          subPkgs.reflex-components-markdown
          subPkgs.reflex-components-moment
          subPkgs.reflex-components-plotly
          subPkgs.reflex-components-radix
          subPkgs.reflex-components-react-player
          subPkgs.reflex-components-recharts
          subPkgs.reflex-components-sonner
          subPkgs.reflex-hosting-cli
          ruff
          ruff-format
        ];
      };

    inherit buildSubPackage;
    subPkgs = lib.flip lib.mapAttrs finalAttrs.passthru.workspaces (
      pname: workspace:
      (finalAttrs.passthru.buildSubPackage {
        inherit pname workspace;
        inherit (finalAttrs) version src;
        inherit (finalAttrs.passthru) workspaces subPkgs;
      })
    );

    tests = {
      reflex-no-checks = finalAttrs.finalPackage.overrideAttrs (old: {
        pname = "${old.pname}-sans-checks-phase";
        doCheck = false;
        nativeCheckInputs = [ ];
      });
    }
    // finalAttrs.passthru.subPkgs;
  };

  meta = metaCommon // {
    changelog = "https://github.com/reflex-dev/reflex/releases/tag/${finalAttrs.src.tag}";
    license = lib.licenses.asl20;
    maintainers = with lib.maintainers; [ pbsds ];
    mainProgram = "reflex";
  };
})
+33 −0
Original line number Diff line number Diff line
#!/usr/bin/env nix-shell
#!nix-shell --pure -i bash -p nix jq yq
set -euo pipefail

src=$(nix-build . -A python3Packages.reflex.src --no-out-link)
# echo >&2 "src=$src"; exit 0 # DEBUG

declare -a workspace_paths=( "$src"/packages/* )
# printf >&2 "%s\n" "${workspace_paths[@]}"; exit 0 # DEBUG

declare -a workspaces=( "${workspace_paths[@]##*/}" )
# printf >&2 "%s\n" "${workspaces[@]}"; exit 0 # DEBUG

workspaces_json=$( printf '"%s"\n' "${workspaces[@]}" | jq -s '.' -c )

for workspace in "${workspaces[@]}"; do
  echo "$workspace.dependencies = ["
  tomlq <"$src/packages/$workspace/pyproject.toml" \
    --argjson "workspaces" "$workspaces_json" \
    '.project.dependencies + (.tool.hatch.build.hooks."reflex-pyi".dependencies // [])
      | map( split("[ !><=]"; null)[0] ) # remove ">= 1.2.3"
      | map( gsub("_"; "-") )            # normalize attrpath/pname
      | unique[]
      | if (. as $dep | $workspaces|index($dep) != null) then
          "  subPkgs.\(.)"
        elif . == "reflex" then
          "  finalAttrs.finalPackage # reflex"
        else
          "  \(.)"
        end
    ' -r
  echo '];'
done