Skip to content

Sym two #814

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

Merged
merged 24 commits into from
Jul 22, 2020
Merged

Sym two #814

merged 24 commits into from
Jul 22, 2020

Conversation

etiennerichart
Copy link
Contributor

@etiennerichart etiennerichart commented Jun 26, 2020

Use os.path.realpath to see the source of symbolic links and makes sure that we are not in a loop. Also include importtest.py and importtestfolder to test if program gets stuck in a loop.

Resolves #806

Copy link
Member

@thomasballinger thomasballinger left a comment

Choose a reason for hiding this comment

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

Thanks for exploring a few options here, I think I like this last one best.

for subname in find_modules(pathname):
if subname != "__init__":
yield "%s.%s" % (name, subname)
pathReal = os.path.realpath(pathname)
Copy link
Member

Choose a reason for hiding this comment

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

small nit, but in this project (and most Python projects) we use snake_case instead of camelCase

if subname != "__init__":
yield "%s.%s" % (name, subname)
pathReal = os.path.realpath(pathname)
if not pathReal in paths:
Copy link
Member

Choose a reason for hiding this comment

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

in Python not needle in haystack is parsed as (not needle) in haystack, so

>>> not "/some/path"
False
>>> not "/some/path" in ["/some/path"]
False
>>> False in [False]
True
>>> not "/some/path" in [False]
True

so instead, this should be
if pathReal not in paths:

@@ -134,6 +137,7 @@ def complete(cursor_offset, line):

def find_modules(path):
"""Find all modules (and packages) for a given directory."""

Copy link
Member

Choose a reason for hiding this comment

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

extra blank line

yield name


Copy link
Member

Choose a reason for hiding this comment

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

the convention being followed here is two lines between top-level statements. You should pip install black and run black on this file; that will autoformat it, dealing with these details. Or better you can set up VSCode to run black automatically.

@etiennerichart
Copy link
Contributor Author

@thomasballinger I am trying to write the test file but am having an issue with the try: on line 12. Also, I was wondering if the files made in the temp directory will be erased after the temp directory is closed or if they will keep taking up space.

Copy link
Member

@thomasballinger thomasballinger left a comment

Choose a reason for hiding this comment

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

See the docs for tempfile.TemporaryDirectory - the files in the temp directory will be erased along with the directory after exiting the context manager.

@etiennerichart
Copy link
Contributor Author

I have almost finished turning the test class into a test file but for some reason the test is passing when it should not. In the temp directory setup I have it print out what should appear and in what order and the 'Left' file is first. In the actual test 'Left' is last and yet the test still passes.

@etiennerichart
Copy link
Contributor Author

etiennerichart commented Jul 8, 2020

I have made the changes so that importtest now works. While I was debugging I used the nosetests -s command and it seems that the temp directory is showing up in (I bolded what I think is the temp dir), '..SS.S...........S..S.......................S...SSSSS......................................................tmpfaxxkuhx
.tmptz3ajosr

.....S..............S.....SSS..........................S.....SS.SSSSSS.....................................................................SS....................SSSS...SS..............................S.S..........' Is there anything else I should do to integrate the test with the rest of the test files? Also, should I get rid of the print statements in the except, and is there something better than sys.exit to use since I am worried that it may interrupt the temp dir's auto cleanup. Would a break (out of the with) work?

@sebastinas
Copy link
Contributor

Please move the test file to bpython/test.

@etiennerichart etiennerichart marked this pull request as ready for review July 8, 2020 20:08
Copy link
Contributor

@sebastinas sebastinas left a comment

Choose a reason for hiding this comment

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

Sorry, I've some more comments that I missed earlier.

@sebastinas sebastinas added this to the release-0.20 milestone Jul 11, 2020
@@ -71,7 +71,7 @@ def test_simple_symbolic_link_loop(self):
self.filepaths.remove(thing)

else:
@unittest.skip()
@unittest.skip("test doesn't work in python 2")
Copy link
Member

Choose a reason for hiding this comment

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

This should be something like skipIf with a condition that is true for Python 2.

@thomasballinger
Copy link
Member

Now when I run this test after commenting out your fix, it still passes; so I'm worried this isn't testing what we think it is.

One problem I see is that sometimes you're using the string 'import_test_folder' when there's no folder that exists with that name. When I run your setup function (and then pause in it so I have time to examine the files) I see that the temporary directory is named /var/folders/ty/d8c6t0c176db_ll_xh2jqn_80000gn/T/tmp5kxo1jhg (this will be different every time) and it looks like this:

tomb ~$ tree /var/folders/ty/d8c6t0c176db_ll_xh2jqn_80000gn/T/tmp5kxo1jhg
/var/folders/ty/d8c6t0c176db_ll_xh2jqn_80000gn/T/tmp5kxo1jhg
├── Left
│   ├── __init__.py
│   └── toRight -> import_test_folder/Right
├── Level0
│   ├── Level1
│   │   ├── Level2
│   │   │   ├── Level3 -> import_test_folder/Level0/Level1
│   │   │   └── __init__.py
│   │   └── __init__.py
│   └── __init__.py
└── Right
    ├── __init__.py
    └── toLeft -> import_test_folder/Left

5 directories, 8 files
```

One this to fix would be these symlink target filenames, and then check that the test fails without your fix, but passes with it.

@thomasballinger
Copy link
Member

This fails for me locally now, but it looks close. If I sort both lists and print them, I get

actual: ['Left', 'Level0', 'Level0.Level1', 'Level0.Level1.Level2', 'Level0.Level1.Level2.Level3', 'Right', 'Right.toLeft', 'Right.toLeft.toRight']
expected: ['Left', 'Left.toRight', 'Left.toRight.toLeft', 'Level0', 'Level0.Level1', 'Level0.Level1.Level2', 'Level0.Level1.Level2.Level3', 'Right']

Is this passing for you?

It occurs to me that this could be nondeterministic since a given module can be referred to mulitple ways based on which filepath got our import discoverer there first, say if os.listdir() returned files in a different order we could end up with different names for the same modules. If this isn't passing for you yet either then we may not need to do this, but if it is and this is something nondeterministic we want to control we could sort the results of os.listdir() in the import completion code to ensure the same results each time.

@etiennerichart
Copy link
Contributor Author

I think that the problem is that when going between left and right it went right first whereas on my computer it went left first
your computer : ['Right.toLeft', 'Right.toLeft.toRight']
mine: [ 'Left.toRight', 'Left.toRight.toLeft']

@thomasballinger
Copy link
Member

Got it, I think we want to change the implementation then to sort. I think wrapping the os.listdir() call with sorted() like sorted(os.listdir()) would do it.

@thomasballinger
Copy link
Member

This alternative approach works for me, import completion will traverse the filesystem in the nondeterministic order determined by os.listdir() but both orders work in the test. @sebastinas thoughts?

Copy link
Contributor

@sebastinas sebastinas left a comment

Choose a reason for hiding this comment

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

Looks good to me, but please squash the commits when merging the changes.

@thomasballinger thomasballinger merged commit b2111bd into bpython:master Jul 22, 2020
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.

High CPU load when bpython is in use
3 participants