DisplayCAL is huge... Sometimes, unnecessarily huge. There are modules with over 10s of thousands of lines of code in them, single functions or methods spaning over a couple thousand lines.
With the maximum McCabe complexity number set to 10 ruff check --statistics returns:
381 C901 [ ] complex-structure
max complexity set to 12 returns:
304 C901 [ ] complex-structure
This is too much. Having 1 or 2 very complex functions/methods might be okay, but we have 380 complex functions/methods and 304 them are execively complex.
So we need a good refactoring, splitting those functions to more manageable parts. It is also going make it easier to write tests. Along the way we also should address as many linting errors as possible.
It might be a good idea to do this in parts. So that we don't make it unnecessarily complicated to rebase any of the fixes done on the other branches.
Currently on develop branch, running ruff check --statistics DisplayCAL results:
6401 ANN001 [ ] missing-type-function-argument
3034 ANN201 [ ] missing-return-type-undocumented-public-function
2904 N806 [ ] non-lowercase-variable-in-function
1575 D102 [ ] undocumented-public-method
1425 N802 [ ] invalid-function-name
823 PLR2004 [ ] magic-value-comparison
710 N803 [ ] invalid-argument-name
683 UP031 [ ] printf-string-formatting
631 D415 [ ] missing-terminal-punctuation
516 ANN202 [ ] missing-return-type-private-function
486 ANN204 [ ] missing-return-type-special-method
444 S101 [ ] assert
341 E501 [ ] line-too-long
335 PLR0912 [ ] too-many-branches
305 C901 [ ] complex-structure
296 D103 [ ] undocumented-public-function
283 SIM108 [ ] if-else-block-instead-of-if-exp
254 D107 [ ] undocumented-public-init
242 D205 [ ] missing-blank-line-after-summary
241 PLR0915 [ ] too-many-statements
226 D101 [ ] undocumented-public-class
212 RUF046 [ ] unnecessary-cast-to-int
209 UP032 [*] f-string
205 UP024 [*] os-error-alias
200 PLR0913 [ ] too-many-arguments
192 RET505 [*] superfluous-else-return
182 D202 [*] blank-line-after-function
164 I001 [*] unsorted-imports
162 D105 [ ] undocumented-magic-method
155 UP009 [*] utf8-encoding-declaration
136 F401 [ ] unused-import
132 D100 [ ] undocumented-public-module
118 RET503 [ ] implicit-return
116 A002 [ ] builtin-argument-shadowing
111 RUF005 [ ] collection-literal-concatenation
106 ANN002 [ ] missing-type-args
104 UP006 [ ] non-pep585-annotation
99 ANN003 [ ] missing-type-kwargs
99 RET502 [*] implicit-return-value
95 PERF401 [ ] manual-list-comprehension
92 PLR5501 [*] collapsible-else-if
87 SIM102 [ ] collapsible-if
82 D209 [*] new-line-after-last-paragraph
81 B007 [ ] unused-loop-control-variable
79 FA100 [ ] future-rewritable-type-annotation
77 A001 [ ] builtin-variable-shadowing
74 PLR1730 [*] if-stmt-min-max
70 SIM105 [ ] suppressible-exception
64 SIM115 [ ] open-file-with-context-handler
61 F841 [*] unused-variable
61 RUF021 [*] parenthesize-chained-operators
58 S110 [ ] try-except-pass
58 B904 [ ] raise-without-from-inside-except
56 S603 [ ] subprocess-without-shell-equals-true
46 C408 [ ] unnecessary-collection-call
46 PIE808 [*] unnecessary-range-start
45 D403 [*] first-word-uncapitalized
44 F405 [ ] undefined-local-with-import-star-usage
40 UP035 [ ] deprecated-import
39 RET504 [ ] unnecessary-assign
38 PERF203 [ ] try-except-in-loop
34 D212 [*] multi-line-summary-first-line
32 RUF012 [ ] mutable-class-default
30 S607 [ ] start-process-with-partial-path
30 LOG015 [ ] root-logger-call
30 N801 [ ] invalid-class-name
28 PLR0911 [ ] too-many-return-statements
27 RET506 [*] superfluous-else-raise
25 SIM300 [*] yoda-conditions
25 FLY002 [ ] static-join-to-f-string
24 RUF010 [*] explicit-f-string-type-conversion
22 PIE790 [*] unnecessary-placeholder
21 N999 [ ] invalid-module-name
21 UP008 [ ] super-call-with-parameters
20 B028 [ ] no-explicit-stacklevel
20 RET508 [*] superfluous-else-break
18 ANN205 [ ] missing-return-type-static-method
18 N816 [ ] mixed-case-variable-in-global-scope
17 COM819 [*] prohibited-trailing-comma
17 RET507 [*] superfluous-else-continue
17 RUF001 [ ] ambiguous-unicode-character-string
15 N815 [ ] mixed-case-variable-in-class-scope
14 PIE810 [ ] multiple-starts-ends-with
14 RSE102 [*] unnecessary-paren-on-raise-exception
14 E731 [ ] lambda-assignment
12 F821 [ ] undefined-name
12 PLR1714 [ ] repeated-equality-comparison
11 Q000 [*] bad-quotes-inline-string
11 N813 [ ] camelcase-imported-as-lowercase
11 E713 [*] not-in-test
10 S324 [ ] hashlib-insecure-hash-function
10 SIM103 [ ] needless-bool
10 SIM117 [ ] multiple-with-statements
10 N817 [ ] camelcase-imported-as-acronym
10 F811 [ ] redefined-while-unused
10 PLR0402 [*] manual-from-import
10 UP015 [*] redundant-open-modes
9 ANN401 [ ] any-type
9 PIE804 [*] unnecessary-dict-kwargs
9 D200 [ ] unnecessary-multiline-docstring
9 UP034 [*] extraneous-parentheses
8 S108 [ ] hardcoded-temp-file
8 B023 [ ] function-uses-loop-variable
8 C404 [ ] unnecessary-list-comprehension-dict
8 SIM223 [ ] expr-and-false
7 ANN206 [ ] missing-return-type-class-method
7 S311 [ ] suspicious-non-cryptographic-random-usage
7 B018 [ ] useless-expression
7 C401 [ ] unnecessary-generator-set
7 PLR1704 [ ] redefined-argument-from-local
7 UP012 [*] unnecessary-encode-utf8
6 S103 [ ] bad-file-permissions
6 C406 [ ] unnecessary-literal-dict
6 SIM118 [ ] in-dict-keys
6 D417 [ ] undocumented-param
6 RUF003 [ ] ambiguous-unicode-character-comment
6 RUF015 [ ] unnecessary-iterable-allocation-for-first-element
5 S314 [ ] suspicious-xml-element-tree-usage
5 ISC001 [ ] single-line-implicit-string-concatenation
5 E722 [ ] bare-except
5 D412 [*] blank-lines-between-header-and-content
4 S306 [ ] suspicious-mktemp-usage
4 S310 [ ] suspicious-url-open-usage
4 C417 [ ] unnecessary-map
4 C418 [ ] unnecessary-literal-within-dict-call
4 SIM110 [ ] reimplemented-builtin
4 SIM113 [ ] enumerate-for-loop
4 SIM201 [ ] negate-equal-op
4 N811 [ ] constant-imported-as-non-constant
4 N818 [ ] error-suffix-on-exception-name
4 D211 [*] blank-line-before-class
4 D301 [ ] escape-sequence-in-docstring
4 F524 [ ] string-dot-format-missing-arguments
4 RUF051 [*] if-key-in-dict-del
3 YTT101 [ ] sys-version-slice3
3 S102 [ ] exec-builtin
3 S104 [ ] hardcoded-bind-all-interfaces
3 S318 [ ] suspicious-xml-mini-dom-usage
3 B009 [*] get-attr-with-constant
3 B020 [ ] loop-variable-overrides-iterator
3 C402 [ ] unnecessary-generator-dict
3 C419 [ ] unnecessary-comprehension-in-call
3 SIM114 [*] if-with-same-arms
3 E712 [ ] true-false-comparison
3 D104 [ ] undocumented-public-package
3 D201 [*] blank-line-before-function
3 F523 [*] string-dot-format-extra-positional-arguments
3 RUF017 [ ] quadratic-list-summation
2 S105 [ ] hardcoded-password-string
2 S202 [ ] tarfile-unsafe-members
2 S606 [ ] start-process-with-no-shell
2 B025 [ ] duplicate-try-block-exception
2 C416 [ ] unnecessary-comprehension
2 PYI036 [ ] bad-exit-annotation
2 RET501 [*] unnecessary-return-none
2 SIM109 [ ] compare-with-tuple
2 SIM112 [ ] uncapitalized-environment-variables
2 TC002 [ ] typing-only-third-party-import
2 PERF403 [ ] manual-dict-comprehension
2 D402 [ ] signature-in-docstring
2 D416 [*] missing-section-name-colon
2 PLR2044 [*] empty-comment
2 UP036 [ ] outdated-version-block
2 RUF100 [*] unused-noqa
1 S112 [ ] try-except-continue
1 S307 [ ] suspicious-eval-usage
1 S602 [ ] subprocess-popen-with-shell-equals-true
1 B008 [ ] function-call-in-default-argument
1 B034 [ ] re-sub-positional-args
1 A006 [ ] builtin-lambda-argument-shadowing
1 C403 [ ] unnecessary-list-comprehension-set
1 C410 [ ] unnecessary-literal-within-list-call
1 C414 [ ] unnecessary-double-cast-or-process
1 SIM101 [ ] duplicate-isinstance-call
1 SIM212 [ ] if-expr-with-twisted-arms
1 SIM905 [*] split-static-string
1 SLOT001 [ ] no-slots-in-tuple-subclass
1 TC003 [ ] typing-only-standard-library-import
1 N804 [ ] invalid-first-argument-name-for-class-method
1 PERF102 [ ] incorrect-dict-iterator
1 PERF402 [ ] manual-list-copy
1 E401 [*] multiple-imports-on-one-line
1 E714 [*] not-is-test
1 E743 [ ] ambiguous-function-name
1 D210 [ ] surrounding-whitespace
1 D411 [*] no-blank-line-before-section
1 D419 [ ] empty-docstring
1 F403 [ ] undefined-local-with-import-star
1 PLR1711 [*] useless-return
1 PLR1736 [*] unnecessary-list-index-lookup
1 UP004 [*] useless-object-inheritance
1 RUF013 [ ] implicit-optional
1 RUF022 [*] unsorted-dunder-all
1 RUF034 [ ] useless-if-else
Found 27232 errors.
[*] 2065 fixable with the `--fix` option (4994 hidden fixes can be enabled with the `--unsafe-fixes` option).
ToDo (some of the followings items are handled in their own tickets):
DisplayCAL is huge... Sometimes, unnecessarily huge. There are modules with over 10s of thousands of lines of code in them, single functions or methods spaning over a couple thousand lines.
With the maximum McCabe complexity number set to 10
ruff check --statisticsreturns:max complexity set to 12 returns:
This is too much. Having 1 or 2 very complex functions/methods might be okay, but we have 380 complex functions/methods and 304 them are execively complex.
So we need a good refactoring, splitting those functions to more manageable parts. It is also going make it easier to write tests. Along the way we also should address as many linting errors as possible.
It might be a good idea to do this in parts. So that we don't make it unnecessarily complicated to rebase any of the fixes done on the other branches.
Currently on
developbranch, runningruff check --statistics DisplayCALresults:ToDo (some of the followings items are handled in their own tickets):
DisplayCAL.meta:buildto BUILD and better use theBUILD_DATE.DisplayCAL.metashould be UPPERCASE.DisplayCAL.icc_profile:ICCProfile.__new__()asICCProfile.__init__()(Remove __new__ usage in ICCProfile, move initialization logic to __init__ #934).DisplayCAL.cgats:CGATSclass as a normal class instead of hackingdicttype and relying on those hacks (Refactor CGATS to derive from collections.abc.MutableMapping instead of dict #938).E402and address it too.DisplayCAL.edid.get_edid_from_xrandr()to use theDisplayCAL.xrandrmodule instead of re-implementing similar logic.flake8-use-pathlib (PTH)andrefurb (FURB)totool.ruff.lint.selectinpyproject.tomland slowly migrate toPathlib.DisplayCAL.wxversionmodule, as we never intent to have more than version ofwxPython(Remove DisplayCAL.wx_version module #940).