From 1c02939680a9b80244894668a64333b9e5444639 Mon Sep 17 00:00:00 2001 From: Dominik Breksa Date: Sun, 14 Dec 2025 20:07:43 +0100 Subject: [PATCH] feat: Added .clang-tidy .clang-format --- .clang-format | 280 +++++++++++++++++++++++++++ .clang-tidy | 24 +++ .github/workflows/cpp_linter.yaml | 8 +- .github/workflows/python_linter.yaml | 12 +- Makefile | 3 + setup.py | 16 +- src/cpp/fast/fast.cpp | 79 ++++++++ src/cpp/fast/foo.cpp | 93 --------- 8 files changed, 401 insertions(+), 114 deletions(-) create mode 100644 .clang-format create mode 100644 .clang-tidy create mode 100644 src/cpp/fast/fast.cpp delete mode 100644 src/cpp/fast/foo.cpp diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..9d8f49e --- /dev/null +++ b/.clang-format @@ -0,0 +1,280 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: Left +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseColons: false +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowBreakBeforeNoexceptSpecifier: Never +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: true +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterExternBlock: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: true + BeforeWhile: true + IndentBraces: true + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAdjacentStringLiterals: true +BreakAfterAttributes: Leave +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Attach +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: true +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 3 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +KeepEmptyLinesAtEOF: false +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: NextLine +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakScopeResolution: 500 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +PPIndentWidth: -1 +QualifierAlignment: Leave +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + - ParseTestProto + - ParsePartialTestProto + CanonicalDelimiter: pb + BasedOnStyle: google +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SkipMacroDefinitionBody: false +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterPlacementOperator: true + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: Auto +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +... + diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..75b1bf3 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,24 @@ +Checks: > + -*, + bugprone-*, + google-*, + misc-*, + modernize-*, + performance-*, + portability-*, + readability-*, + -google-readability-namespace-comments, + -google-runtime-int, + -google-runtime-references, + -misc-non-private-member-variables-in-classes, + -readability-named-parameter, + -readability-braces-around-statements, + -readability-magic-numbers, + -misc-include-cleaner, + -modernize-use-trailing-return-type, + -misc-use-anonymous-namespace, + -bugprone-easily-swappable-parameters, + -modernize-avoid-c-arrays + + +WarningsAsErrors: "*" \ No newline at end of file diff --git a/.github/workflows/cpp_linter.yaml b/.github/workflows/cpp_linter.yaml index 3286734..72329a7 100644 --- a/.github/workflows/cpp_linter.yaml +++ b/.github/workflows/cpp_linter.yaml @@ -13,14 +13,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v6 - name: Python Setup - uses: actions/setup-python@v3 + uses: actions/setup-python@v6 with: python-version: 3.13 + cache: 'pip' + cache-dependency-path: ./setup.cfg - name: Install libraries run: make python-install-development - - name: clang-tidy + - name: Run clang-tidy run: make clang-tidy diff --git a/.github/workflows/python_linter.yaml b/.github/workflows/python_linter.yaml index ecc7912..291339e 100644 --- a/.github/workflows/python_linter.yaml +++ b/.github/workflows/python_linter.yaml @@ -13,20 +13,22 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v6 - name: Python Setup - uses: actions/setup-python@v3 + uses: actions/setup-python@v6 with: python-version: 3.13 + cache: 'pip' + cache-dependency-path: ./setup.cfg - name: Install libraries run: make python-install-development - - name: mypy + - name: Run mypy run: make mypy - - name: ruff + - name: Run ruff run: make ruff - - name: flake8 + - name: Run flake8 run: make flake8 diff --git a/Makefile b/Makefile index 1618561..290f0ca 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,9 @@ python-install-development: python-install-editable: pip3 install -e .[development] +clang-format: + clang-format -i $(shell find ./src/cpp/ -name '*.hpp' -o -name '*.cpp') + clang-tidy: clang-tidy $(shell find ./src/cpp/ -name '*.hpp' -o -name '*.cpp') -- -I$(shell python3 -c "import sysconfig; print(sysconfig.get_path('include'))") -I$(shell python3 -c "import numpy; print(numpy.get_include())") diff --git a/setup.py b/setup.py index 0005f18..401400f 100644 --- a/setup.py +++ b/setup.py @@ -1,23 +1,13 @@ from setuptools import setup, Extension -import numpy +import numpy as np def main() -> None: setup(ext_modules=[ Extension(name='app.fast', - sources=['src/cpp/fast/foo.cpp'], - include_dirs=[numpy.get_include()], + sources=['src/cpp/fast/fast.cpp'], + include_dirs=[np.get_include()], language='c++'), ]) if __name__ == '__main__': main() - - -# {'stdlib': '/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13', -# 'platstdlib': '/Users/bodzio/Desktop/APP/advanced-python-programming-project/.venv/lib/python3.13', -# 'purelib': '/Users/bodzio/Desktop/APP/advanced-python-programming-project/.venv/lib/python3.13/site-packages', -# 'platlib': '/Users/bodzio/Desktop/APP/advanced-python-programming-project/.venv/lib/python3.13/site-packages', -# 'include': '/Library/Frameworks/Python.framework/Versions/3.13/include/python3.13', -# 'platinclude': '/Library/Frameworks/Python.framework/Versions/3.13/include/python3.13', -# 'scripts': '/Users/bodzio/Desktop/APP/advanced-python-programming-project/.venv/bin', -# 'data': '/Users/bodzio/Desktop/APP/advanced-python-programming-project/.venv'} \ No newline at end of file diff --git a/src/cpp/fast/fast.cpp b/src/cpp/fast/fast.cpp new file mode 100644 index 0000000..2842e55 --- /dev/null +++ b/src/cpp/fast/fast.cpp @@ -0,0 +1,79 @@ +#define PY_SSIZE_T_CLEAN +#include +#include + +static PyObject *numpy_system(PyObject */*self*/, PyObject *args) { + const char *command = nullptr; + int sts = 0; + + if (PyArg_ParseTuple(args, "s", &command) == 0) { + return nullptr; + } + + sts = system(command); + return PyLong_FromLong(sts); +} + +static PyObject *numpy_add(PyObject */*self*/, PyObject *args) { + PyArrayObject *arr = nullptr; + PyArg_ParseTuple(args, "O", &arr); + + if (PyErr_Occurred() != nullptr) { + return nullptr; + } + if (!PyArray_Check(arr) || PyArray_TYPE(arr) != NPY_DOUBLE) { + PyErr_SetString(PyExc_TypeError, "Argument must be a numpy array of type double!"); + return nullptr; + } + + auto* data = reinterpret_cast(PyArray_DATA(arr)); + const int64_t size = PyArray_SIZE(arr); + + double total = 0.; + for (std::size_t i = 0; i < size; i++) { + total += data[i]; + } + + return PyFloat_FromDouble(total); +} + +static PyObject *NumpyError = nullptr; + +static int numpy_module_exec(PyObject *module) { + if (NumpyError != nullptr) { + PyErr_SetString(PyExc_ImportError, "cannot initialize numpy module more than once"); + return -1; + } + + NumpyError = PyErr_NewException("numpy.error", nullptr, nullptr); + if (PyModule_AddObjectRef(module, "NumpyError", NumpyError) < 0) { + return -1; + } + + return 0; +} + +static PyMethodDef numpy_methods[] = { + {"system", numpy_system, METH_VARARGS, "Execute a shell command." }, + {"numpy_add", numpy_add, METH_VARARGS, "Perform adding operation."}, + {nullptr, nullptr, 0, nullptr } /* Sentinel */ +}; + +static PyModuleDef_Slot numpy_module_slots[] = { + {Py_mod_exec, reinterpret_cast(numpy_module_exec)}, + {0, nullptr } +}; + +static struct PyModuleDef numpy_module = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "numpy", + .m_size = 0, // non-negative + .m_methods = numpy_methods, + .m_slots = numpy_module_slots, +}; + +PyMODINIT_FUNC PyInit_fast(void) { + PyObject *module_obj = PyModuleDef_Init(&numpy_module); + import_array(); + return module_obj; +} \ No newline at end of file diff --git a/src/cpp/fast/foo.cpp b/src/cpp/fast/foo.cpp deleted file mode 100644 index 0d7b485..0000000 --- a/src/cpp/fast/foo.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#define PY_SSIZE_T_CLEAN -#include -#include - -static PyObject * -numpy_system(PyObject *self, PyObject *args) -{ - const char *command; - int sts; - - if (!PyArg_ParseTuple(args, "s", &command)) - { - return NULL; - } - - sts = system(command); - return PyLong_FromLong(sts); -} - -static PyObject * -numpy_add(PyObject *self, PyObject *args) -{ - PyArrayObject *arr; - PyArg_ParseTuple(args, "O", &arr); - if(PyErr_Occurred()) - { - return NULL; - } - if(!PyArray_Check(arr) || PyArray_TYPE(arr) != NPY_DOUBLE) - { - PyErr_SetString(PyExc_TypeError, "Argument must be a numpy array of type double!"); - return NULL; - } - - - double *data = reinterpret_cast(PyArray_DATA(arr)); - int64_t size = PyArray_SIZE(arr); - - double total = 0; - for (int i = 0; i < size; i++) - { - total += data[i]; - } - - return PyFloat_FromDouble(total); -} - -static PyObject *SpamError = NULL; - -static int -numpy_module_exec(PyObject *m) -{ - if (SpamError != NULL) - { - PyErr_SetString(PyExc_ImportError, - "cannot initialize numpy module more than once"); - return -1; - } - SpamError = PyErr_NewException("numpy.error", NULL, NULL); - if (PyModule_AddObjectRef(m, "SpamError", SpamError) < 0) - { - return -1; - } - - return 0; -} - -static PyMethodDef numpy_methods[] = { - {"system", numpy_system, METH_VARARGS, "Execute a shell command."}, - {"numpy_add", numpy_add, METH_VARARGS, "Perform adding operation."}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - -static PyModuleDef_Slot numpy_module_slots[] = { - {Py_mod_exec, reinterpret_cast(numpy_module_exec)}, - {0, NULL} -}; - -static struct PyModuleDef numpy_module = { - .m_base = PyModuleDef_HEAD_INIT, - .m_name = "numpy", - .m_size = 0, // non-negative - .m_methods = numpy_methods, - .m_slots = numpy_module_slots, -}; - -PyMODINIT_FUNC -PyInit_fast(void) -{ - PyObject* module_obj = PyModuleDef_Init(&numpy_module); - import_array(); - return module_obj; -} \ No newline at end of file