diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a2f46b342..4705a5d45 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -23,26 +23,8 @@ jobs: bublik/data/migrations/** bublik/analytics/migrations/** - format-check: - name: Check Code Formatting - needs: detect-changes - runs-on: ubuntu-latest - if: ${{ needs.detect-changes.outputs.python_files != '' }} - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - - name: Install Black - run: pip install $(grep '^black==' requirements.txt) - - - name: Run Black in check mode - run: | - echo "${{ needs.detect-changes.outputs.python_files }}" | xargs black --check --diff - - lint-check: - name: Check Code Quality + ruff-check: + name: Check Python Quality needs: detect-changes runs-on: ubuntu-latest if: ${{ needs.detect-changes.outputs.python_files != '' }} @@ -53,26 +35,12 @@ jobs: python-version: '3.12' - name: Install Ruff - run: pip install ruff + run: pip install $(grep '^ruff' requirements.txt) - - name: Run Ruff + - name: Run Ruff formatter in check mode run: | - echo "${{ needs.detect-changes.outputs.python_files }}" | xargs ruff check - - f-string-check: - name: Check F-String Usage - needs: detect-changes - runs-on: ubuntu-latest - if: ${{ needs.detect-changes.outputs.python_files != '' }} - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - - name: Install Flynt - run: pip install flynt + echo "${{ needs.detect-changes.outputs.python_files }}" | xargs ruff format --check --diff - - name: Run Flynt in check mode + - name: Run Ruff linter run: | - echo "${{ needs.detect-changes.outputs.python_files }}" | xargs flynt -f + echo "${{ needs.detect-changes.outputs.python_files }}" | xargs ruff check diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 07f6e8ebe..7a2ec2eda 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,8 +1,8 @@ repos: - repo: local hooks: - - id: run-my-script - name: Run My Script + - id: ruff-python-quality + name: Ruff Python Quality entry: ./scripts/pyformat language: script types: [python] diff --git a/README.md b/README.md index e71b894b4..c3b9e5ce6 100644 --- a/README.md +++ b/README.md @@ -42,23 +42,44 @@ For now some documentation can be found in **doc/wiki** here. # Development -## Pre-commit checkings +## Pre-commit checks -After initial deploy please run the: +Pre-commit installs a local Git hook that runs before `git commit` creates a +commit. In this project, the hook runs Ruff on changed Python files via: +``` +./scripts/pyformat -c +``` + +Install the hook once after setting up the repository: ``` pre-commit install ``` -This will allow the pre-commit tool to run `./scripts/pyformat -c` before each -commit. -Please note that you can always disable the pre-commit validation by running: +After that, every `git commit` will automatically run: +``` +ruff format --check --diff +ruff check +``` + +If the hook fails, fix the reported issues and run `git commit` again. To apply +Ruff formatting and autofixes manually, run: +``` +./scripts/pyformat +``` + +You can run the hook manually for all files with: +``` +pre-commit run --all-files +``` + +You can disable the local hook with: ``` pre-commit uninstall ``` ## Checking your changes -You can use pyformat script to check your changes. +You can use pyformat script to run Ruff formatting and lint checks. For this you need to run: ``` diff --git a/bublik/core/auth.py b/bublik/core/auth.py index 12d721dcb..9a4469cc4 100644 --- a/bublik/core/auth.py +++ b/bublik/core/auth.py @@ -70,9 +70,9 @@ def wrapper(*args, **kwargs): def check_action_permission(action): - ''' + """ Check if the action requires permission. - ''' + """ def wrapper(func): @wraps(func) diff --git a/bublik/core/cache.py b/bublik/core/cache.py index 66f6fd805..87ca1f7cc 100644 --- a/bublik/core/cache.py +++ b/bublik/core/cache.py @@ -159,12 +159,12 @@ def tests(self): class _ProjectSectionCache: - ''' + """ Base class for project section caches. Each section cache stores data under keys like 'project:{project_id}:{SECTION}:{data_key}'. - ''' + """ SECTION: ClassVar[str] | None = None KEY_DATA_CHOICES: ClassVar[set[str]] | None = None @@ -220,7 +220,7 @@ class _TagsCache(_ProjectSectionCache): } def load(self): - ''' + """ Populate tags cache for the project. Each cache entry stores a mapping of meta tag IDs to their string @@ -235,7 +235,7 @@ def load(self): Value format: {meta_id: 'tag_name=tag_value'} - ''' + """ tags = models.Meta.objects.filter(type='tag') diff --git a/bublik/core/config/reformatting/dispatcher.py b/bublik/core/config/reformatting/dispatcher.py index 7929e8de2..61cde24b5 100644 --- a/bublik/core/config/reformatting/dispatcher.py +++ b/bublik/core/config/reformatting/dispatcher.py @@ -62,9 +62,9 @@ def update_config(reformatted_config): class ConfigReformatStatuses(str, Enum): - ''' + """ All available config reformatting statuses. - ''' + """ SUCCESS = 'success' SKIPPED = 'skipped' diff --git a/bublik/core/config/reformatting/steps.py b/bublik/core/config/reformatting/steps.py index ff7b08096..c5430314c 100644 --- a/bublik/core/config/reformatting/steps.py +++ b/bublik/core/config/reformatting/steps.py @@ -12,10 +12,10 @@ class BaseReformatStep: def apply(self, config, **kwargs): - ''' + """ Reformats the provided content if it has not been reformatted yet, and outputs the execution status. Returns the content. - ''' + """ try: if not self.applied(config, **kwargs): config = self.reformat(config, **kwargs) @@ -28,25 +28,25 @@ def apply(self, config, **kwargs): raise err def applied(self, config, **kwargs): - ''' + """ Checks whether the step has already been applied. - ''' + """ msg = 'Subclasses must implement `applied`.' raise NotImplementedError(msg) def reformat(self, config, **kwargs): - ''' + """ Reformats the provided content. - ''' + """ msg = 'Subclasses must implement `reformat`.' raise NotImplementedError(msg) class UpdateAxisXStructure(BaseReformatStep): - ''' + """ Reformat passed report config content: "axis_x": -> "axis_x": {"arg": } - ''' + """ def applied(self, config, **kwargs): content = config.content @@ -68,12 +68,12 @@ def reformat(self, config, **kwargs): class UpdateSeqSettingsStructure(BaseReformatStep): - ''' + """ Reformat passed report config content: Add the 'sequences' foreign key for all sequences settings (sequence_group_arg, percentage_base_value, sequence_name_conversion). Rename 'sequence_name_conversion' to 'arg_vals_labels'. - ''' + """ def applied(self, config, **kwargs): content = config.content @@ -109,11 +109,11 @@ def reformat(self, config, **kwargs): class UpdateDashboardHeaderStructure(BaseReformatStep): - ''' + """ Reformat passed global per_conf config content: DASHBOARD_HEADER: {: