Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
/python_memcached.egg-info
.tox
.coverage
.idea
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please revert these changes.

Copy link
Copy Markdown
Contributor Author

@matteius matteius Nov 2, 2017

Choose a reason for hiding this comment

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

No way. If you don't want that in the .gitignore then you don't need my time wasted on your pet project.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In my experiencing maintaining Django, we've recommended to use git config core.excludesfile for excluding IDE-specific files. That way if a new IDE comes along, its users can update their configuration own rather than requiring many projects to update .gitingore. I was also suggesting to exclude unrelated changes like this in a bug fix as that can be confusing when looking at git blame.

As an aside, this isn't my pet project, I just asked Sean this week if I could help him maintain it as it seems inactive.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well thats great that you have a Collaborator tag and I have nothing even though I've pointed you at several other issues in the past week that you have been actively helping clean up. I guess if thats the standard way to do it ... I wouldn't mind if the .gitignore got long because it would at least be a way to ignore things we know are common for the community. I personally use mercurial way more than git, so I don't know all the bells and whistles. It saddens me that the desired approach is that everyone does a one-off and pretends like the world is IDE agnostic.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm fine smashing it down to a single commit -- I mean personally I would never do it, because I am against re-writing history, but whatever. I really just want this bug fixed. I put 3 hours into this last night just trying to get it this far. So you figure I have 8 hours into trying to improve this library.

Copy link
Copy Markdown
Owner

@linsomniac linsomniac Nov 2, 2017

Choose a reason for hiding this comment

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

I really appreciate both of you collaborating on this and the effort both of you have put into this. It saddens me that this has devolved into anger. It would sadden me if you chose to not participate, especially after all your work, because ".idea" is not added to the project .gitignore. If that is the choice you want to make, I'll support your choice though.

Thank you @timgraham for the pointer about core.excludesfile, I was not aware of that. I agree that that is the right place for this exclude, after reading the git docs describing it as the preferred solution for files generated by a users editor. Quoting:

Patterns which a user wants git to ignore in all situations (e.g., backup or temporary files
generated by the user’s editor of choice) generally go into a file specified by
core.excludesfile in the user’s ~/.gitconfig

Quoted from: https://git-scm.com/docs/gitignore/1.7.12

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is because you are way more unreasonable than working with the DRF creator. I assume its because he is from Europe and you are not. The .idea directory will always be the PyCharm/IntelliJ local IDE config for all users, but I assume its because you want no reference to commercial software in your OSS. You would rather enforce these kind of standards than to actually realize that so many people are running into this problem with python 3 in their production code. Its not really acceptable when memcached error crashes the page for the end-user, but I guess we can argue about what should live in which .gitconfig. Either way, you'd have to be stupid to ever want users to add a .idea directory to the root of your project.

lastfailed
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
language: python
python:
- 2.7
- 3.3
- 3.4
- 3.5
- 3.6
- pypy
services:
- memcached
Expand All @@ -12,3 +12,4 @@ before_script: pip install -r test-requirements.txt
script:
- flake8
- nosetests
- python -c 'import memcache; memcache._doctest()'
4 changes: 2 additions & 2 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
* Added testing for Python 3.5 (PR from Tim Graham) #110
* Added testing for Python 3.5 and 3.6 (PR from Tim Graham) #110, #131

* Fixed typos in docstrings (PR from Romuald Brunet, reviewed by Tim
Graham) #105

* Removing Python 2.6 and 3.2 testing (PR from Tim Graham) #115
* Removing Python 2.6, 3.2, and 3.3 testing (PR from Tim Graham) #115, #116

* Removing unnecessary parens in return statements (PR from Tim Graham)
#113
Expand Down
17 changes: 8 additions & 9 deletions memcache.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ def _deletetouch(self, expected, cmd, key, time=0, noreply=False):
if line and line.strip() in expected:
return 1
self.debuglog('%s expected %s, got: %r'
% (cmd, ' or '.join(expected), line))
% (cmd, b' or '.join(expected), line))
except socket.error as msg:
if isinstance(msg, tuple):
msg = msg[1]
Expand Down Expand Up @@ -834,9 +834,9 @@ def set_multi(self, mapping, time=0, key_prefix='', min_compress_len=0,
'''Sets multiple keys in the memcache doing just one query.

>>> notset_keys = mc.set_multi({'key1' : 'val1', 'key2' : 'val2'})
>>> mc.get_multi(['key1', 'key2']) == {'key1' : 'val1',
... 'key2' : 'val2'}
1
>>> keys = mc.get_multi(['key1', 'key2'])
>>> keys == {'key1': 'val1', 'key2': 'val2'}
True


This method is recommended over regular L{set} as it lowers
Expand All @@ -856,14 +856,13 @@ def set_multi(self, mapping, time=0, key_prefix='', min_compress_len=0,
sending to memcache. Allows you to efficiently stuff these
keys into a pseudo-namespace in memcache:

>> notset_keys = mc.set_multi(
>>> notset_keys = mc.set_multi(
... {'key1' : 'val1', 'key2' : 'val2'},
... key_prefix='subspace_')
>>> len(notset_keys) == 0
True
>>> mc.get_multi(['subspace_key1',
... 'subspace_key2']) == {'subspace_key1': 'val1',
... 'subspace_key2' : 'val2'}
>>> keys = mc.get_multi(['subspace_key1', 'subspace_key2'])
>>> keys == {'subspace_key1': 'val1', 'subspace_key2': 'val2'}
True

Causes key 'subspace_key1' and 'subspace_key2' to be
Expand Down Expand Up @@ -1141,7 +1140,7 @@ def get_multi(self, keys, key_prefix=''):
... key_prefix='pfx_') == {'k1' : 1, 'k2' : 2}
1

get_mult [ and L{set_multi} ] can take str()-ables like ints /
get_multi [ and L{set_multi} ] can take str()-ables like ints /
longs as keys too. Such as your db pri key fields. They're
rotored through str() before being passed off to memcache,
with or without the use of a key_prefix. In this mode, the
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
])
1 change: 1 addition & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
nose
coverage
hacking
mock
13 changes: 10 additions & 3 deletions tests/test_memcache.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from __future__ import print_function

import unittest

import mock
import six
import unittest
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This import shouldn't be resorted. Standard library imports are separated from third-party imports.

Copy link
Copy Markdown
Contributor Author

@matteius matteius Nov 2, 2017

Choose a reason for hiding this comment

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

That's not true, locally it failed flake8 due to the imports needing to be alphabetical for lsort. Maybe you don't realize that mock is a part of the standard library in Py3?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry, I didn't know that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I only included it in the test-requirements.txt for users of python 2.7


from memcache import Client, SERVER_MAX_KEY_LENGTH, SERVER_MAX_VALUE_LENGTH # noqa: H301
from memcache import Client, _Host, SERVER_MAX_KEY_LENGTH, SERVER_MAX_VALUE_LENGTH # noqa: H301


class FooStruct(object):
Expand Down Expand Up @@ -166,6 +166,13 @@ def test_disconnect_all_delete_multi(self):
ret = self.mc.delete_multi({'keyhere': 'a', 'keythere': 'b'})
self.assertEqual(ret, 1)

@mock.patch.object(_Host, 'readline')
def test_memcached_error_unexpected_reply(self, mock_readline):
"""Test that the debug log executes properly in error response."""
mock_readline.return_value = 'SET'
cache_key = ':cache:key:1'
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there a special significance to this cache key name? Also, it looks like it doesn't need to be an intermediate variable.

Can you add an assertion for the debug output?

Copy link
Copy Markdown
Contributor Author

@matteius matteius Nov 2, 2017

Choose a reason for hiding this comment

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

These are stylistic decisions in writing the test. The test passes because the debug log doesn't blow up, and fails if you take out the change because of the python 3 TypeError. I'm done making your changes -- if you want to fix this library then just take my work and do it yourself because you are too damn picky. I've already converted our apps away from using this library, and was trying to make it better for people that still use it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm simply trying to improve the quality of the tests. Please don't assume malicious intent. I'll see if I can address my suggestions if you're not interested.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well I personally like when there are intermediate variables in tests because it both names the value, and allows a debugger to introspect things. It also makes it easier later on if you want to then assert things about the key, because most likely if its not a named variable, another dev extending the test will copy the magic value all over the place. I've seen this time and time again.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I guess the problem with your suggestions is that its nit-picking a test that I choose to add. At least my test mocks out communication with Memcahed server to a certain extent. How about spending the time on the existing tests, mocking them, and adding more test coverage rather than be upset about an intermediate variable and a lack of assertion in the test case. The test runner still fails a test if something raises exception, so I feel like these are subjective stylistic preferences and not something enforced by flake8 or that actually improve the test. I wasn't willing to assert anything about the logging because I think its ridiculous it doesn't even use the logging module, but I think I've stated that already.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I just saw the passive aggressive thumbs up about adding an assertion of the awful logging methodology in your code base @linsomniac , but I am not going to do that.

self.mc.touch(cache_key)


if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tox]
minversion = 1.6
envlist = py27,py33,py34,py35,pypy,pep8
envlist = py27,py34,py35,p36,pypy,pep8
skipsdist = True

[testenv]
Expand Down