Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[flake8]
max-line-length = 120
2 changes: 1 addition & 1 deletion .github/workflows/push-copr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:

- name: Submit the build
env:
COPR_PR_WEBHOOK: https://copr.fedorainfracloud.org/webhooks/custom/24190/c23f34c1-e02e-41a0-9435-6c7e4a6e56c0/resalloc/
COPR_PR_WEBHOOK: https://copr.fedorainfracloud.org/webhooks/custom-dir/praiskup/resalloc-ci:pr:${{github.event.number}}/c23f34c1-e02e-41a0-9435-6c7e4a6e56c0/resalloc/
COPR_PUSH_WEBHOOK: ${{ secrets.COPR_PUSH_WEBHOOK }}
run: |
curl https://raw.githubusercontent.com/praiskup/copr-ci-tooling/main/copr-gh-actions-submit > submit
Expand Down
128 changes: 128 additions & 0 deletions .pylintrc/pylintrc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
"""
pylint plugin doing resalloc-specific transformation to shut-down specific
errors which we can not easily ignore because the ignore mechanisms don't have
the needed granularity (copy-paste from Copr).
"""

import os
import subprocess
from astroid import MANAGER, scoped_nodes, nodes, extract_node


def register(_linter):
""" required pylint entrypoint """


class Cache:
"""
Some rather expensive checks cached (as a class to avoid using globals).
"""
_gitroot = None
_test_files = {
# Some modules have None in the file argument:
# ipdb> function
# <FunctionDef.cmp_to_key l.None at 0x7febf4adcb20>
# ipdb> function.parent
# <Module._functools l.0 at 0x7febf4adcbb0>
# ipdb> function.parent.file is None
# True
None: False,
}
test_paths = {
"tests/",
}

@classmethod
def gitroot(cls):
""" Obtain the git-root of the current directory, and cache """
if cls._gitroot:
return cls._gitroot
cls._gitroot = subprocess.check_output(["git", "rev-parse",
"--show-toplevel"]).decode("utf-8").strip()
return cls.gitroot()

@classmethod
def _slow_is_test_file(cls, test_file):
if not test_file.startswith(cls.gitroot() + os.sep):
return False
relpath = os.path.relpath(test_file, cls.gitroot())
for test_path in cls.test_paths:
if relpath.startswith(test_path):
return True
return False

@classmethod
def is_test_file(cls, file_path):
"""
Check if file_path (path relative to the gitroot) is a test-file (per
cls.test_paths configuration).
"""
cached = cls._test_files.get(file_path)
if cached is None:
cls._test_files[file_path] = cls._slow_is_test_file(file_path)
return cls._test_files[file_path]


def module_path(node):
"""
Filename where the node (e.g. method) is defined.
"""
while node:
if isinstance(node, scoped_nodes.Module):
return node.file
node = node.parent
return None


def add_fake_docs(the_object):
"""
Add fake docs to the specified object so PyLint later doesn't complain about
missing docs.
"""
the_object.doc_node = nodes.Const("fake docs")
the_object.doc = "fake docs"


def transform_functions(function):
"""
Transformate some function definitions so pylint doesn't object.
"""

filename = module_path(function)

if function.name == 'logger':
for prop in ['debug', 'info', 'warning', 'error', 'exception']:
function.instance_attrs[prop] = extract_node('def {name}(arg): return'.format(name=prop))

if function.name in ["upgrade", "downgrade"]:
# ignore missing-function-docstring in migrations
add_fake_docs(function)

if function.name == "step_impl":
# behave step definition
add_fake_docs(function)

if Cache.is_test_file(filename):
add_fake_docs(function)


def transform_classes(classdef):
"""
Transform Class definitions that don't need to have docstrings.
"""
filename = module_path(classdef)
if Cache.is_test_file(filename):
add_fake_docs(classdef)


def transform_modules(moduledef):
"""
Testing modules don't nave to have the doc-strings either.
"""
if Cache.is_test_file(moduledef.file):
add_fake_docs(moduledef)


MANAGER.register_transform(scoped_nodes.FunctionDef, transform_functions)
MANAGER.register_transform(scoped_nodes.ClassDef, transform_classes)
MANAGER.register_transform(scoped_nodes.Module, transform_modules)
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ SHELLTEST_OPTIONS :=
SHELL_TESTS := \
basic.sh \
check.sh \
named_counters.sh \
ondemand.sh \
reuse.sh

Expand Down
7 changes: 7 additions & 0 deletions config/pools.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,10 @@
## # "reused". The time spent is measured since the resource was taken for the
## # first time (assigned to sandbox). Default is 3600s.
## reuse_max_time: 3600
##
## # Whenever a new machine is allocated within this pool, the smallest integer values
## # are taken from the following named counters, and exported for the
## # callback scripts as environment variables, for example
## # NAMED_COUNTER_VALUE_foo=10 (considering values 0->9 are already taken).
## #named_counters:
## # - foo
23 changes: 22 additions & 1 deletion pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,25 @@ init-hook=
import sys
import subprocess
gitrootdir = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip()
sys.path.insert(0, os.path.join(gitrootdir))
sys.path.insert(0, gitrootdir)
sys.path.insert(0, os.path.join(gitrootdir, ".pylintrc"))

# Our own pylint transformations.
load-plugins=pylintrc

# Reasoning for class ignore
# --------------------------
# RState, TState
# Pylint doesn't parse the meta-class to detect the attributes.
ignored-classes=RState,TState

# Reasoning for ignored modules
# -----------------------------
# alembic:
# Pylint entirely fails to parse the module.
# Example error: Module 'alembic.op' has no 'drop_index' member
ignored-modules=alembic,setproctitle

[MESSAGES CONTROL]
# Reasoning for wide warning ignore
# ---------------------------------
Expand All @@ -37,3 +48,13 @@ disable=useless-object-inheritance,import-error,too-few-public-methods,consider-

[DESIGN]
min-public-methods=1


# evision|down_revision|branch_labels|depends_on is for alembic
[BASIC]
const-rgx=^(([A-Z_][A-Z0-9_]*)|(__.*__)|revision|down_revision|branch_labels|depends_on)$


[FORMAT]
# Maximum number of characters on a single line.
max-line-length=120
39 changes: 39 additions & 0 deletions resallocserver/alembic/versions/d79239ae23a7_named_counters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
Named Counters added

Revision ID: d79239ae23a7
Revises: b50e3f64fc2d
Create Date: 2026-03-04 10:52:27.756502
"""

from alembic import op
import sqlalchemy as sa

revision = 'd79239ae23a7'
Comment thread Fixed
down_revision = 'b50e3f64fc2d'
Comment thread Fixed
branch_labels = None
Comment thread Fixed
depends_on = None
Comment thread Fixed


def upgrade():
Comment thread Fixed
op.create_table(
'named_counters',
sa.Column('resource_id', sa.Integer(), nullable=False),
sa.Column('value', sa.Integer(), nullable=True),
sa.Column('counter_name', sa.String(), nullable=True),
sa.ForeignKeyConstraint(['resource_id'], ['resources.id'], ),
sa.PrimaryKeyConstraint('counter_name', 'value'),
sa.UniqueConstraint('value', 'counter_name')
)
with op.batch_alter_table('named_counters', schema=None) as batch_op:
batch_op.create_index(batch_op.f('ix_named_counters_counter_name'),
['counter_name'], unique=False)
batch_op.create_index(batch_op.f('ix_named_counters_value'), ['value'],
unique=False)


def downgrade():
Comment thread Fixed
with op.batch_alter_table('named_counters', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_named_counters_value'))
batch_op.drop_index(batch_op.f('ix_named_counters_counter_name'))
op.drop_table('named_counters')
Loading
Loading