Comments (7)
That's because the while
AST node has 8 instances of _ast.Pass
object inside the node.orelse
attribute. I don't know why that happens, but this is an edge case and I don't see why it should be supported. Do you have any use-case for such scenario?
from radon.
Thank you for the fast reply. I should probably have made a more sane example. Radon seems to add 1 to CC for any line in the else-block of a loop - thus the following more reasonable example would, too, produce an unexpected CC number (5 rather than the expected 3):
def func(a):
for i in range(a):
if a**2 > 30:
break
else:
b = a**2
print("The for-loop didn't break and terminated with the value {}.".format(b))
from radon.
Oh I get it now. Sorry for the misunderstanding!
Yes, the error stems from the fact that for every For/While
node radon adds len(node.orelse) + 1
to the complexity. That's incorrect, and it should be bool(node.orelse) + 1
. The complexity would then be 4:
- +1 for the function (base complexity);
- +1 for the
for
loop; - +1 for the
if
branch; - +1 for the
else
branch at loop level.
I'm thinking about adding 1
for the else
because it's syntactic sugar for if not interrupted: ...
. See for example this answer on StackOverflow:
http://stackoverflow.com/a/9980752/448496
Do you agree?
from radon.
I agree that adding 1
for the else
block would make sense considering the equivalent code.
from radon.
I am not sure that I fully understand why CC should be 4 and not 3. If we take the graph theoretic approach as used by McCabe I believe we have a situation as the one attached.
Normally, "else" does not contribute to CC and I would be quite reluctant to say that we have two types of "else" - one that contributes +1 to CC and another that does not contribute to CC. And based on the graph theoretic consideration I do not see that this is necessary.
from radon.
Well the problem is that else
really has two meanings that are not quite the same. When used in conjunction with if
/elif
instructions they don't add a new decision point. However, when used with for
/while
loops, it is arguable that they do.
Consider this piece of code:
for i in range(a):
print(i)
if i ** 2 > 30:
break
else:
print('Else executed')
Now if else
weren't available in Python, the equivalent code would be:
interrupted = False
for i in range(a):
print(i)
if i ** 2 > 30:
interrupted = True
break
if not interrupted:
print('Else executed')
You can't do simpler than that, and the if
branch obviously introduces a new decision point. If you make a graph of the latter, CC would be 4.
Now, I understand what you are saying and you have a point arguing that the else
shouldn't count, however I feel that the transformation of syntactic sugar into its equivalent code is somewhat clearer.
from radon.
Unless I have made an error above I still believe CC=3. In my opinion we should use the definition by McCabe which is a graph theoretical measure - this evaluates the code as it is and not by an equivalent mapping. I do see your point but my concern is that the CC presented is not the one defined by McCabe, which I find problematic.
from radon.
Related Issues (20)
- Nested classes issue HOT 3
- Can't get the actual complexity for block of code HOT 1
- Installing radon breaks flake8 HOT 8
- Support of pyproject.toml file HOT 1
- Radon struggles to collect statistics from large files HOT 2
- Is Randon able to run into Java files? HOT 2
- [feature] Add support for pre-commit HOT 5
- Python 3.10: match-case syntax not yet supported by radon? HOT 1
- summary not shown when using --json flag HOT 3
- 5.1.0: sphinx warnings HOT 2
- Misspelled 'clasification' in markdown exports HOT 1
- Documentation link outdated HOT 2
- wrong complexity for linear function HOT 1
- New release to drop future package HOT 7
- 5.1.0 - wrong import HOT 2
- Support mi/hal in flake8 plugin
- Radon crashes on unrelated config option in pyproject.toml HOT 3
- Add line numbers to Halstead results
- RFE: is it possible to start making github releases?🤔
- Radon can't run when use pytest log fornat: `$()d` HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from radon.