diff --git a/flake.nix b/flake.nix index 4d92e60..13df2f6 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,5 @@ { - description = "Reusable Python development environment"; + description = "Customizable Python development environment"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; @@ -9,66 +9,120 @@ outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: let - pkgs = import nixpkgs { inherit system; }; - - # Python version configuration - easy to change in one place - pythonVersion = pkgs.python311; - - # Define Python packages in a separate variable for clarity - pythonPackages = ps: with ps; [ - # Data science - numpy - pandas - matplotlib - scipy + # Function to create a Python environment with a given version + mkPython = { + pythonVersion ? "python313", # Default Python version + extraPackages ? [], # Additional packages to include + extraSystemPackages ? [] # Additional system packages + }: + let + pkgs = import nixpkgs { inherit system; }; - # Web and networking - requests - httpx - beautifulsoup4 + # Select Python version based on the parameter + python = pkgs.${pythonVersion}; - # Development tools - black - pylint - pytest - ipython - - # Add more packages as needed - ]; - - # Create the Python environment with the specified packages - pythonEnv = pythonVersion.withPackages pythonPackages; - in - { - # Development shell for interactive use - devShells.default = pkgs.mkShell { - buildInputs = [ - pythonEnv - pkgs.poetry - pkgs.git + # Base Python packages that are always included + basePackages = ps: with ps; [ + # Data science + numpy + pandas + matplotlib + + # Development tools + black + pytest + ipython + + # Add more default packages as needed ]; - shellHook = '' - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - echo "🐍 Python $(${pythonVersion}/bin/python --version)" - echo "📦 Poetry $(${pkgs.poetry}/bin/poetry --version)" - echo "📂 Working directory: $(pwd)" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - ''; + # Combine base packages with extra packages + allPackages = ps: (basePackages ps) ++ (extraPackages ps); + + # Create the Python environment + pythonEnv = python.withPackages allPackages; + in + { + # The Python environment + package = pythonEnv; + + # Make the chosen Python version accessible + inherit python pythonVersion; + + # Development shell with the Python environment + devShell = pkgs.mkShell { + buildInputs = [ + pythonEnv + ] ++ extraSystemPackages; + + shellHook = '' + echo "Python $(${python}/bin/python --version)" + echo "Custom Python environment activated!" + ''; + }; + }; + + # Default Python configuration + defaultPython = mkPython {}; + in + { + # Expose the function to create custom Python environments + lib = { + inherit mkPython; }; - # Make the Python environment available as a package - packages.default = pythonEnv; - - # Add an app that runs Python directly - apps.default = flake-utils.lib.mkApp { - drv = pythonEnv; - name = "python"; - exePath = "/bin/python"; + # Default packages using default Python version + packages = { + default = defaultPython.package; }; - # Add formatter for consistent Nix code formatting - formatter = pkgs.nixpkgs-fmt; + # Default development shell + devShells.default = defaultPython.devShell; + + # NixOS module for system-wide integration + nixosModules.default = { config, lib, pkgs, ... }: + with lib; + let + cfg = config.services.customPython; + in { + options.services.customPython = { + enable = mkEnableOption "Enable the custom Python environment"; + + pythonVersion = mkOption { + type = types.str; + default = "python311"; + description = "Python version to use (e.g., python39, python310, python311)"; + }; + + extraPackages = mkOption { + type = types.functionTo (types.listOf types.anything); + default = _: []; + description = "Extra Python packages to include"; + }; + + extraSystemPackages = mkOption { + type = types.listOf types.package; + default = []; + description = "Extra system packages to include"; + }; + + includeInSystemPackages = mkOption { + type = types.bool; + default = true; + description = "Whether to include the Python environment in system packages"; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = mkIf cfg.includeInSystemPackages [ + (mkPython { + pythonVersion = cfg.pythonVersion; + extraPackages = cfg.extraPackages; + extraSystemPackages = cfg.extraSystemPackages; + }).package + ]; + }; + }; } ); }