Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix the off by one issues #6

Merged
merged 1 commit into from Aug 7, 2014
Merged

Conversation

bukzor
Copy link
Contributor

@bukzor bukzor commented Apr 18, 2014

Resolves #5

@asottile
Copy link
Member

+1 code looks good too.

@sigmavirus24
Copy link
Member

Just noticed you sent this. I have #7 which resolves this and other issues. I changed the calculation but in a more obvious way. The issue is that the number of decisions is off by one, not the formula which you're changing.

@bukzor
Copy link
Contributor Author

bukzor commented Apr 18, 2014

@sigmavirus24 : I noticed that as well, and updated my branch as such.

The dot-graph of the trivial function is much more sensible now ( f1->stmt1 rather than f1->f1) as a bonus.

The --minimum-threshold option for dot graphing was also of by one as a consequence.
I've made the default to show all graphs, even when I've introduced a bug to make the complexity negative =X

@bukzor
Copy link
Contributor Author

bukzor commented Apr 18, 2014

updated the diff

@bukzor bukzor mentioned this pull request Apr 18, 2014
@@ -286,7 +286,7 @@ def main(argv):
help="output a graphviz dot file", action="store_true")
opar.add_option("-m", "--min", dest="threshold",
help="minimum complexity for output", type="int",
default=2)
default=0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should this be 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default, I want to see a graph of everything.
Previously it was 2 when the minimum was in fact 2 due to bugs.
I've made 0 mean "literally everything", so that I can still graph things out when I've introduced bugs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about not making the graph utility rely on the threshold?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only purpose of the minimum threshold is to limit the output for dot mode.
I believe you're confusing this with flake8's -m/--maximum-threshold, which is unrelated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bukzor I'm not confusing it with anything. There are multiple purposes to the minimum option. It determines when errors are printed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you like, but my perception of the original intent was to cull very large outputs, and you'd lose that ability.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then why not set the default to 1 and force your own use of this to always use 0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the intent was to show everything by default, and the original
author simply hadn't considered (with good reason) negative complexities.

A default of 1 would behave quite similarly, but hide bugs from the output,
which is not a good practice.

On Fri, Apr 18, 2014 at 2:43 PM, Ian Cordasco notifications@github.comwrote:

In mccabe.py:

@@ -286,7 +286,7 @@ def main(argv):
help="output a graphviz dot file", action="store_true")
opar.add_option("-m", "--min", dest="threshold",
help="minimum complexity for output", type="int",

  •                default=2)
    
  •                default=0)
    

Then why not set the default to 1 and force your own use of this to always
use 0.


Reply to this email directly or view it on GitHubhttps://github.com//pull/6/files#r11788170
.

Buck Golemon
Cell: (408) 202-3901

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with a default of 0 is that when used to actually determine the complexity of a file or piece of code (when not using the graph functionality) you will everything printed to the screen.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you like, this was meant to be a minor improvement.
The 2 was obviously a holdover from buggier days.

:)

@bukzor bukzor mentioned this pull request Apr 18, 2014
@sigmavirus24
Copy link
Member

FYI @bukzor I really want to merge this so if you can address that one concern and rebase it, I'd ❤︎ it. :)

@bukzor
Copy link
Contributor Author

bukzor commented Apr 22, 2014

The problem with a default of 0 is that when used to actually determine the complexity of a file or piece of code (when not using the graph functionality) you will everything printed to the screen.

This was the previous behavior as well; the smallest complexity a function could have was 2, and functions with a complexity of 2 were printed.

@bukzor
Copy link
Contributor Author

bukzor commented Apr 22, 2014

I've updated the diff as you want.

@@ -67,6 +67,8 @@ def __init__(self, name, entity, lineno):

def connect(self, n1, n2):
self.nodes[n1].append(n2)
# Ensure that the destination node is always counted.
self.nodes[n2]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a no-op?!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It causes an entry to be created in a defaultdict.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see :)

However, "explicit is better than implicit", so self.nodes[n2] = list() is IMO much better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bukzor it's perfectly obvious to those who understand what self.nodes is. Do not feel pressured to do more than is necessary

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change duplicates what was done by @sigmavirus24 on a previous commit in def complexity(self):.

I proposed in the comment https://github.com/flintwork/mccabe/pull/7/files#diff-c8e207640776e7218af4cd9951eb2fceL84 to adjust slightly the computation to highlight the fact that it is num_nodes which was wrong, not num_edges.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, "explicit is better than implicit", so self.nodes[n2] = list() is IMO much better.

@schlamar That has different behavior. We're not guaranteed that n2 has no successors.
The explicit version of this line would be:

if n2 not in self.nodes[n2]: self.nodes[n2] = self.nodes.default_factory()

Which is, of course, the behavior of defaultdict.__getitem__, except with worse performance.
If you still like this better than it is currently written, I will change it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bukzor what you wrote is fine. Anyone who has read the code will understand the expected behaviour.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a tree has more than one leaf node, #6 will be correct while #7 will not.

@bukzor it seems that the algorithm used by this mccabe script does not support more than one leaf. The proposal #16 does not change the behavior, it fixes num_nodes/num_edges internal computation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While that may be true (or may not; it's certainly not obvious), it doesn't change the truth of my assertion:

If a tree has more than one leaf node, #6 will be correct while #7 will not.

It's certainly not impossible that the tree will have more than one leaf after future changes.
This leads me to say that #6 is more correct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyone who has read the code will understand the expected behaviour.

It was not obvious for me (with years of Python experience) and I've never seen this before. So an additional comment like "ensure the key is in the defaultdict" wouldn't harm anyone, right? :)

@sigmavirus24
Copy link
Member

@bukzor this is still not in a mergable state. Were you planning on rebasing?

@bukzor
Copy link
Contributor Author

bukzor commented May 8, 2014

Rebased and passed CI.
I was very glad to see the new tests.

https://travis-ci.org/bukzor/mccabe/builds/24735372

@@ -3,3 +3,5 @@
*.py[cod]
.tox
dist
# silly vim.
.*.sw[a-z]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use your global gitignore for such files :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @schlamar about this. Please revert this addition.

@bukzor
Copy link
Contributor Author

bukzor commented Jul 16, 2014

Rebased again.
Removed the .gitignore change.
All issues resolved I think.

@bukzor
Copy link
Contributor Author

bukzor commented Jul 23, 2014

All issues resolved I think.

@sigmavirus24
Copy link
Member

Thanks for the reminder @bukzor. I'll take another look at this tonight.

@sigmavirus24 sigmavirus24 merged commit c306935 into PyCQA:master Aug 7, 2014
@sigmavirus24
Copy link
Member

Sorry that it took so long to merge this @bukzor

Thanks for the contribution

@bukzor
Copy link
Contributor Author

bukzor commented Aug 7, 2014

cool!

Let me know when we should see an improved behavior from flake8.

@sigmavirus24
Copy link
Member

@bukzor I don't have maintainer or owner permissions on the PyPI package so this will have to wait for @florentx to have the time to either grant me such permissions or release the package itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

off by two
5 participants