Git Product home page Git Product logo

fakeredis-py's Introduction

Daniel Moran

Subscribe on Polar

Hi, Iā€™m Daniel! Iā€™m a software engineer who loves simplifying things and creating tools that help developers.

Services Offered

  • Tailored Software Solutions: Seamlessly implement even the most intricate software requirements tailored to your specific needs.
  • JetBrains IDE Plugin Development: Craft custom JetBrains IDE plugins to elevate productivity, enhance developer experience, and streamline workflow within your organization.
  • CI/CD Optimization: Refine and optimize your development team's Continuous Integration/Continuous Deployment (CI/CD) processes to ensure efficient and reliable software delivery. e.g., implement mechanisms within your CI/CD pipeline to uphold stringent code quality standards.
  • Architectural Design: Strategically design architectures for new services, whether building upon existing legacy systems or developing from scratch, to meet evolving business demands and technological advancements.

Feel free to reach out to discuss how I can contribute to your project's success or inquire about my past endeavours. My clientele spans from industry giants to budding startups, and I'm adept at catering to diverse business landscapes. Connect with me on LinkedIn to explore collaboration opportunities and delve deeper into your requirements.

Technologies I work with

Kotlin

fakeredis-py's People

Contributors

adamantike avatar alejom99 avatar alexeshoo avatar allanino avatar amertz08 avatar anentropic avatar aviddiviner avatar blfoster avatar bluemoo avatar bmerry avatar cunla avatar dependabot[bot] avatar dwilliams-kenzan avatar emorozov avatar fferrara avatar jamesls avatar jdufresne avatar matt-snider avatar mgetka avatar msabramo avatar nfvs avatar nimrod-otonomo avatar pdc avatar pindia avatar raab70 avatar rotten avatar saabeilin avatar thomasleveil avatar upcfrost avatar viljoviitanen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

fakeredis-py's Issues

Lack of support for EXPIRE Redis-7 options [NX|XX|GT|LT]

Describe the bug
In version 1.9.0, this project has added support for Redis-7.
But when I try to use the new expire command feature. It raises the following error:

>>> import fakeredis
>>> r = fakeredis.FakeRedis()
>>> r.expire("KEY", 10, nx=True)

redis.exceptions.ResponseError: wrong number of arguments for 'expire' command

To Reproduce
Steps to reproduce the behavior:

  1. Install fakeredis 1.9.0
  2. exec python
  3. exec following instructions:
>>> import fakeredis
>>> r = fakeredis.FakeRedis()
>>> r.expire("KEY", 10, nx=True)
  1. See error
redis.exceptions.ResponseError: wrong number of arguments for 'expire' command

Expected behavior
A clear and concise description of what you expected to happen.
Set expiry (10) only when the key ("KEY") has no expiry

Screenshots
If applicable, add screenshots to help explain your problem.
No Screenshots

Desktop (please complete the following information):

  • OS: [e.g. iOS] Window
  • python version 3.8
  • redis-py version 1.9.0
  • full requirements.txt?
    fakeredis~=1.9.0

Additional context
Add any other context about the problem here.

@command((Key(), Int))
def expire(self, key, seconds):
return self._expireat(key, self._db.time + seconds)

ModuleNotFoundError: No module named 'sortedcontainers'

Describe the bug
Using fakeredis 1.7.6 on unit tests automated by tox gives a ModuleNotFoundError: No module named 'sortedcontainers'. This error does not happen on 1.7.5. Maybe sortedcontainers should be added as a dependency?

To Reproduce
Steps to reproduce the behavior:

  1. Create a unit test that uses fakeredis 1.7.6
  2. Run unit test on a clean virtualenv created by tox
  3. See error

Expected behavior
sortedcontainers should be installed together with fakeredis as a dependency

Screenshots
N/A

Desktop (please complete the following information):

  • OS: Ubuntu
  • python 3.8.10

Additional context
N/A

Fakeredis 1.7.4 not compatible with Python 3.10

Describe the bug
Unable to install fakeredis 1.74 with Python 3.10

To Reproduce
Steps to reproduce the behavior:

  1. Install Python 3.10 with openssl-1.1.1o
  2. Pip install fakeredis
  3. Error received as below
  Running setup.py install for hiredis: started
  Running setup.py install for hiredis: finished with status 'error'
  error: subprocess-exited-with-error
  
  Ɨ Running setup.py install for hiredis did not run successfully.
  ā”‚ exit code: 1
  ā•°ā”€> [32 lines of output]
      /tmp/pip-install-_d6d1y9g/hiredis_a71de6dff6b144529f910eb349fefc27/setup.py:7: DeprecationWarning: the imp module is deprecated in favour of importlib and slated for removal in Python 3.12; see the module's documentation for alternative uses
        import sys, imp, os, glob, io
      /usr/local/lib/python3.10/site-packages/setuptools/dist.py:717: UserWarning: Usage of dash-separated 'description-file' will not be supported in future versions. Please use the underscore name 'description_file' instead
        warnings.warn(
      running install
      running build
      running build_py
      creating build
      creating build/lib.linux-x86_64-3.10
      creating build/lib.linux-x86_64-3.10/hiredis
      copying hiredis/__init__.py -> build/lib.linux-x86_64-3.10/hiredis
      copying hiredis/version.py -> build/lib.linux-x86_64-3.10/hiredis
      copying hiredis/hiredis.pyi -> build/lib.linux-x86_64-3.10/hiredis
      copying hiredis/py.typed -> build/lib.linux-x86_64-3.10/hiredis
      warning: build_py: byte-compiling is disabled, skipping.
      
      running build_ext
      building 'hiredis.hiredis' extension
      creating build/temp.linux-x86_64-3.10
      creating build/temp.linux-x86_64-3.10/src
      creating build/temp.linux-x86_64-3.10/vendor
      creating build/temp.linux-x86_64-3.10/vendor/hiredis
      gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -Ivendor -I/usr/local/include/python3.10 -c src/hiredis.c -o build/temp.linux-x86_64-3.10/src/hiredis.o
      gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -Ivendor -I/usr/local/include/python3.10 -c src/reader.c -o build/temp.linux-x86_64-3.10/src/reader.o
      gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -Ivendor -I/usr/local/include/python3.10 -c vendor/hiredis/alloc.c -o build/temp.linux-x86_64-3.10/vendor/hiredis/alloc.o
      gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -Ivendor -I/usr/local/include/python3.10 -c vendor/hiredis/read.c -o build/temp.linux-x86_64-3.10/vendor/hiredis/read.o
      vendor/hiredis/read.c: In function 'redisReaderFree':
      vendor/hiredis/read.c:646:9: error: 'for' loop initial declarations are only allowed in C99 mode
               for (int i = 0; i < r->tasks; i++) {
               ^
      vendor/hiredis/read.c:646:9: note: use option -std=c99 or -std=gnu99 to compile your code
      error: command '/usr/bin/gcc' failed with exit code 1
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: legacy-install-failure

Ɨ Encountered error while trying to install package.
ā•°ā”€> hiredis

note: This is an issue with the package mentioned above, not pip.
hint: See above for output from the failure.

Expected behavior
Clean install

Desktop (please complete the following information):

  • OS: CentOS Linux release 7.9.2009 (Core)
  • python version: 3.10.4
  • redis-py version: 4.2.2

zrange byscore kwarg not handled

zrangebyscore is deprecated in redis and replace by zrange with a byscore=True argument. This isn't handled in fakeredis, and I needed to change _zrange in _fakesocket to the following to handle this case:

    def _zrange(self, key, start, stop, reverse, *args):
        zset = key.value
        withscores = False
        byscore = False
        for arg in args:
            if casematch(arg, b'withscores'):
                withscores = True
            elif casematch(arg, b'byscore'):
                byscore = True
            else:
                raise SimpleError(msgs.SYNTAX_ERROR_MSG)
        if byscore:
            items = zset.irange_score(ScoreTest(start).lower_bound, ScoreTest(stop).upper_bound, reverse=reverse)
        else:
            start, stop = self._fix_range(start, stop, len(zset))
            if reverse:
                start, stop = len(zset) - stop, len(zset) - start
            items = zset.islice_score(start, stop, reverse)

        items = self._apply_withscores(items, withscores)
        return items

redis.exceptions.ResponseError: unknown command 'AUTH'

Describe the bug
When the REDIS_URL environment variable is set and it contains username and password this exception is raised:

  File "/usr/local/lib/python3.8/site-packages/flask_rq2/functions.py", line 127, in queue
    return self.rq.get_queue(queue_name).enqueue_call(
  File "/usr/local/lib/python3.8/site-packages/rq/queue.py", line 400, in enqueue_call
    return self.enqueue_job(job, pipeline=pipeline, at_front=at_front)
  File "/usr/local/lib/python3.8/site-packages/rq/queue.py", line 567, in enqueue_job
    pipe.execute()
  File "/usr/local/lib/python3.8/site-packages/redis/client.py", line 4012, in execute
    conn = self.connection_pool.get_connection('MULTI',
  File "/usr/local/lib/python3.8/site-packages/redis/connection.py", line 1192, in get_connection
    connection.connect()
  File "/usr/local/lib/python3.8/site-packages/fakeredis/_server.py", line 2690, in connect
    super().connect()
  File "/usr/local/lib/python3.8/site-packages/redis/connection.py", line 567, in connect
    self.on_connect()
  File "/usr/local/lib/python3.8/site-packages/redis/connection.py", line 643, in on_connect
    auth_response = self.read_response()
  File "/usr/local/lib/python3.8/site-packages/fakeredis/_server.py", line 2728, in read_response
    raise response
redis.exceptions.ResponseError: unknown command 'AUTH'

To Reproduce

  1. set REDIS_URL environment variable with a such value which includes username and password e.g. redis://user:password@host:11234
  2. queue any action/function, e.g. queue a function decorated with @rq.job()
  3. See error mentioned above

Expected behavior
The function should be run without any failure as it works with using REDIS_URL connection string without username or password.

Desktop:

  • OS: Docker container
  • python version 3.8
  • redis-py version 4.3.1
  • fakeredis version 1.7.5

Additional context

fakeredis/_server.py:

def on_connect(self):
        "Initialize the connection, authenticate and select a database"
        self._parser.on_connect(self)

        # if username and/or password are set, authenticate
        if self.username or self.password:                                      <---- this condition
            if self.username:
                auth_args = (self.username, self.password or '')
            else:
                auth_args = (self.password,)
            # avoid checking health here -- PING will fail if we try
            # to check the health prior to the AUTH
            self.send_command('AUTH', *auth_args, check_health=False)          <---- this line

            try:
                auth_response = self.read_response()
            except AuthenticationWrongNumberOfArgsError:
                # a username and password were specified but the Redis
                # server seems to be < 6.0.0 which expects a single password
                # arg. retry auth with just the password.
                # https://github.com/andymccurdy/redis-py/issues/1274
                self.send_command('AUTH', self.password, check_health=False)
                auth_response = self.read_response()

            if nativestr(auth_response) != 'OK':
                raise AuthenticationError('Invalid Username or Password')

Cannot create FakeRedis with positional host & port arguments

Describe the bug

In 1.8.1, if you try to create an instance of FakeRedis and pass in the the host & port args positionally, rather than by keyword - which is a perfectly valid and functional way of instantiating Redis - it will fail:

  • FakeRedisMixin.__init__() sets any keyword argument which you don't give it to the default value extracted from the signature of Redis.__init__() in **kwds
  • However, it doesn't check if any of those arguments have been passed positionally in *args
  • Thus, when it calls the Redis constructor as super().__init__(*args, **kwds), the host argument is set twice - once positionally and once by keyword - which is not legal in Python

To Reproduce

This is the code under test:

connection: redis.Redis = redis.Redis(redis_host, redis_port)

Patch it to this:

connection: redis.Redis = fakeredis.FakeRedis(redis_host, redis_port)

Expected behavior

FakeRedis should be a drop-in replacement for Redis

Actual behaviour

/usr/local/lib/python3.7/site-packages/fakeredis/_server.py:145: TypeError: __init__() got multiple values for argument 'host'

Desktop (please complete the following information):

  • OS: Alpine Linux v3.13
  • Python version: 3.7.10
  • redis-py version: 3.2.1
  • fakeredis version: 1.8.1

1.8 does not work as a monkey patch

I was using version 1.7.1 and this code worked

import redis
import arrow
import fakeredis

from datetime import date


def test_state(monkeypatch):
    monkeypatch.setattr(redis,'Redis',fakeredis.FakeRedis )

    from ..src.status import SystemState
    state = SystemState()

    print(state.serial)
    assert state.version == '2.0'
    assert state.timezone == 'America/New_York'
    state.lights = 'off'
    value, when = state.lights
    assert value == 'off'
 

However in 1.8 I get a connection pool error

fakeredis 1.8.1 missing in pypi

I cannot find the most recent fakeredis version 1.8.1 in pypi. Is there anything holding the release back?

venv āÆ pip_search fakeredis
                                                   šŸ https://pypi.org/search/?q=fakeredis šŸ                                                    
ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”³ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”³ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”³ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”“
ā”ƒ Package                     ā”ƒ Version       ā”ƒ Released   ā”ƒ Description                                                                        ā”ƒ
ā””ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā•‡ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā•‡ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā•‡ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”©
ā”‚ šŸ“‚ fakeredis                ā”‚ 1.8 > 1.7.6.1 ā”‚ 27-05-2022 ā”‚ Fake implementation of redis API for testing purposes.                             ā”‚

Change the way supported commands are registered

Is your feature request related to a problem? Please describe.
Currently, supported commands are triggered based on _fakeredis_sig (which @command decorator creates).

Describe the solution you'd like
A dictionary of command name to singature, to ensure module commands are supported easily.

Cleanup tests

Is your feature request related to a problem? Please describe.
At the moment, there is a lot of duplicate code on the test files (for skipping tests, etc.)

Describe the solution you'd like
Move all common methods (e.g., lupa_required_for_test, redis_below_v3) to conftest.py and use them appropriately.

Dependency 'sortedcontainers', 'six' gets dropped in 1.7.6

Describe the bug
Suddenly started encountering ModuleNotFoundError: No module named 'sortedcontainers' on import fakeredis in previously stable builds. Also seems like six is missing (though that's almost always in the env)

  ā€¢ Installing fakeredis (1.7.6)
  ā€¢ Installing imageio (2.19.2)
  ā€¢ Installing moto (3.1.10)
  ā€¢ Installing opencv-python-headless (4.5.5.64)
  ā€¢ Installing pydub (0.25.1)
  ā€¢ Installing pytest-mock (3.7.0)

...

    @pytest.fixture()
    def fake_redis():
>       import fakeredis

tests/conftest.py:17: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/fakeredis/__init__.py:1: in <module>
    from ._server import FakeServer, FakeRedis, FakeStrictRedis, FakeConnection   # noqa: F401
/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/fakeredis/_server.py:21: in <module>
    from ._zset import ZSet
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   import sortedcontainers
E   ModuleNotFoundError: No module named 'sortedcontainers'

/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/site-packages/fakeredis/_zset.py:1: ModuleNotFoundError

To Reproduce
Steps to reproduce the behavior:

  1. Fresh environment (eg docker run --rm -it python:3.8.10 bash)
  2. pip install fakeredis==1.7.6
  3. python -c "import fakeredis"

Oops, looks like six is also missing:

root@a6be9ecaf7f8:/# python -c "import fakeredis"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.8/site-packages/fakeredis/__init__.py", line 1, in <module>
    from ._server import FakeServer, FakeRedis, FakeStrictRedis, FakeConnection   # noqa: F401
  File "/usr/local/lib/python3.8/site-packages/fakeredis/_server.py", line 19, in <module>
    import six
ModuleNotFoundError: No module named 'six'

no prob, let's install that

root@a6be9ecaf7f8:/# pip install six
Collecting six
  Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: six
Successfully installed six-1.16.0

root@a6be9ecaf7f8:/# python -c "import fakeredis"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.8/site-packages/fakeredis/__init__.py", line 1, in <module>
    from ._server import FakeServer, FakeRedis, FakeStrictRedis, FakeConnection   # noqa: F401
  File "/usr/local/lib/python3.8/site-packages/fakeredis/_server.py", line 21, in <module>
    from ._zset import ZSet
  File "/usr/local/lib/python3.8/site-packages/fakeredis/_zset.py", line 1, in <module>
    import sortedcontainers
ModuleNotFoundError: No module named 'sortedcontainers'

Resolved by installing sortedcontainers:

root@a6be9ecaf7f8:/# pip install sortedcontainers
Collecting sortedcontainers
  Downloading sortedcontainers-2.4.0-py2.py3-none-any.whl (29 kB)
Installing collected packages: sortedcontainers
Successfully installed sortedcontainers-2.4.0

root@a6be9ecaf7f8:/# python -c "import fakeredis"

Expected behavior
successful import

Desktop (please complete the following information):

  • OS: macOS
  • python version : 3.8
  • redis-py version

Additional context
Add any other context about the problem here.

Make lupa and aioredis optional dependencies

See discussion on #13. lupa and aioredis should be optional dependencies.

  • Make lupa and aioredis optional in pyproject.toml
  • Create a test scheme where lupa is not installed.

I see that in #12 you migrated to poetry, where before you did have lupa and aioredis as optional in your setup.cfg:

[options.extras_require]
lua =
    lupa
aioredis =
    aioredis

but it doesn't seem to be the case in the pyproject.toml today with Poetry, unless there is some different way that I'm not aware of to mark them as optional. As per the poetry documentation that's how extras are 'expected' to be defined at least - if there's a different way it's specified in this project then I'd love to learn about that.

Separate commands to mixins

Separate all commands to mixin classes:

  • string_mixin.py
  • server_mixin.py
  • bitmap_mixin.py
  • list_mixin.py
  • sortedset_mixin.py
  • generic_mixin.py
  • transactions_mixin.py
  • connection_mixin.py
  • scripting_mixin.py
  • hash_mixin.py
  • pubsub_mixin.py
  • set_mixin.py

Pottery RedisDict compatibility

Describe the bug
pottery.RedisDict requires host as part of connection_pool.connection_kwargs.
https://github.com/brainix/pottery/blob/c7be6f1f25c5404a460b676cc60d4e6a931f8ee7/pottery/base.py#L90

To Reproduce
Create a pottery.RedisDict using an instance of fakeredis.

Solution
The solution already tested is to add host to this list

conn_pool_args = [

I could make the change and create the PR if that helps in any way

Thanks!

Redis dependency constraint should be updated to include security vulnerability check

Describe the bug
Current version of fakeredis constrains redis version to be <4.4, however a security vulnerability was identified and fixed in versions 6.2.7 and 7.0.0.

To Reproduce
N/A

Expected behavior
fakeredis should upgrade its dependency on redis to include vulnerability fix.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • python version
  • redis-py version
  • full requirements.txt?

Additional context
Add any other context about the problem here.

commands to modify sets have different signature then official redis client.

Describe the bug
Signature in fakeredis dont match normal redis client for set commands, srem in particular.

from fakeredis import FakeRedis
r = FakeRedis()
r.srem(name='somekey', values='one')

This crash with values does not exist, and I check the signature and members is there instead for fakeredis that is.

Workaround is to use r.srem('somekey', 'one') which I really dont like.

To Reproduce
Steps to reproduce the behavior:
just run the codesample above

In fakeredis the values field is called members, this needs to be updated.

Expected behavior
I expect the codesample above to work.

Screenshots
N/A

Desktop (please complete the following information):

  • OS: Ubuntu
  • python version 3.10.8
  • redis-py version 4.3.5
  • full requirements.txt (were using pypi but its about the same)
    geojson = {version="", index="pypi"}
    aiohttp = {version="
    ", index="pypi"}
    StrEnum = {version="", index="pypi"}
    python-json-logger = {version="
    ", index="pypi"}
    google-cloud-datastore = {version="", index="pypi"}
    google-cloud-bigquery = {version="
    ", index="pypi"}
    redis = {version="", index="pypi"}
    sanic = {version="
    ", index="pypi"}
    sanic-gzip = {version="*", index="pypi"}

Additional context
Add any other context about the problem here.

Fix aioredis section on readme

At the moment readme contains info about aioredis. It should mention that starting redis4.2 aioredis is not required.

fakeredis does not work out-of-the-box with redis-py versions earlier than 4.1.0

Describe the bug
fakeredis does not work out-of-the-box with redis-py versions earlier than 4.1.0 since 62133d2 as importlib-metadata was not a redis-py dependency before this point.

redis-py introduced importlib-metadata in 4.1.0. You can see this here redis/redis-py@v4.0.2...v4.1.0 (click "Files changes" and scroll to setup.py)

To Reproduce
Using Python 3.7

pip install redis==3.5.3
pip install fakeredis
python -c "import fakeredis"

Expected behavior
fakeredis should require importlib-metadata itself as it is required as a direct dependency of the fakeredis code.

Screenshots

root@64fd5842abed:/# python -V
Python 3.7.13
root@64fd5842abed:/# pip install redis==3.5.3
Collecting redis==3.5.3
  Downloading redis-3.5.3-py2.py3-none-any.whl (72 kB)
     ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā” 72.1/72.1 KB 1.6 MB/s eta 0:00:00
Installing collected packages: redis
Successfully installed redis-3.5.3
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 22.0.4; however, version 22.1.2 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.
root@64fd5842abed:/# pip install fakeredis
Collecting fakeredis
  Downloading fakeredis-1.8.1-py3-none-any.whl (35 kB)
Collecting sortedcontainers<3.0.0,>=2.4.0
  Downloading sortedcontainers-2.4.0-py2.py3-none-any.whl (29 kB)
Requirement already satisfied: redis<4.4 in /usr/local/lib/python3.7/site-packages (from fakeredis) (3.5.3)
Collecting six<2.0.0,>=1.16.0
  Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: sortedcontainers, six, fakeredis
Successfully installed fakeredis-1.8.1 six-1.16.0 sortedcontainers-2.4.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 22.0.4; however, version 22.1.2 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.
root@64fd5842abed:/# python -c "import fakeredis"
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/fakeredis/__init__.py", line 4, in <module>
    from importlib import metadata
ImportError: cannot import name 'metadata' from 'importlib' (/usr/local/lib/python3.7/importlib/__init__.py)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/fakeredis/__init__.py", line 6, in <module>
    import importlib_metadata as metadata
ModuleNotFoundError: No module named 'importlib_metadata'
root@64fd5842abed:/# 

Desktop (please complete the following information):

  • OS: Linux
  • Python 3.7.13
  • redis-py 3.5.3

Difference in `get` compared to real Redis

Describe the bug
When using Django cache with a Redis backend, the get() call returns an int if the value stored is an integer. FakeRedis returns a byte string for the same get() call.

Expected behavior
If the value stored is an integer (as can be confirmed with .incr()) the returned value should be an int rather than a byte string.

Screenshots

Screenshot 2022-10-19 at 9 20 29 AM

Desktop (please complete the following information):

  • OS: macOS Monterey 12.6
  • Python version: 3.10.8
  • Packages:
    • django-redis==5.2.0
    • fakeredis==1.9.3
    • redis==4.3.4

Implementing A Currently Unimplemented Command

@cunla First, huge thanks for maintaining the repo to begin with.

Second, can I ask for a little guidance on the "correct" way to add an implementation for a currently unimplemented command? The application whose test suite we're using fakeredis-py in uses zmscore in a few critical places, so I've had to implement a functional standin for it and sort of monkey-patch it into fakeredis-py as part of the test setup. It's not a huge deal at all, but it seems silly to not contribute the implementation to the fakeredis-py repo.

I did take a look at the repo itself, but very quickly got confused as to where exactly a given COMMAND is "fulfilled" by a given callable / function. I'd be more than happy to make a PR if you'd give me the quick and dirty how-to on adding a new command.

For reference, this is the implementation of zmscore I worked out:

from __functools__ import annotations
from typing import Any, Iterable
import fakeredis


def zmscore(self: fakeredis.FakeRedis, key: str | bytes, members: Iterable[Any]) -> tuple[float, ...]:
    """A functional stand-in for Redis's `zmscore` function."""
    pipe = self.pipeline()

    for member in members:
        member = member if isinstance(member, bytes) else str(member).encode()
        pipe.zscore(name=str(key), key=member)

    return tuple(pipe.execute())

Extract optional parameter handling to common method

Currently handling of optional redis command arguments is implemented on each command separately.
(examples: sort, restore, _zrangebyscore, zadd, set_)

The logic should be extracted to a common method handling these:

def _handle_optional_args(args:list[bytes], allowed_args:set[bytes]) -> set[bytes], list[bytes]:
"""Returning a set of allowed arguments in args and a list of the remaining args
"""

GETDEL support

Hi, any estimates when we'll get support for the GETDEL command? Thanks!

redis > 4.2.2 & fakeredis 1.7.4 & python3.8 - KeyError: 'connection_pool'

Describe the bug
A recent upgrade of our libraries upgraded the redis library from 3.5.3 to 4.2.2 - All tests that were using fakeredis now fail with a KeyError: 'connection_pool' error.

Upon producing the reproduction steps I noticed that there is a compatibility issue between fakeredis 1.7.4 and the current latest version of redis which is redis 4.3.1 so reverted to redis 4.2.2 for the purposes of this replication to avoid this incompatibility where the issue still occurs.

I've tried to look back through fakeredis.FakeStrictRedis -> FakeRedisMixin which references this key in this bit of code: https://github.com/dsoftwareinc/fakeredis-py/blob/master/fakeredis/_server.py#L2804 which is where the test traceback also references.

To Reproduce
I am working in pipenv, so as follows:
Install environment and required packages

pipenv --python 3.8.12 install "fakeredis[lua]~=1.7.4" "redis~=4.2.2" "pytest"

I am using the lua extra to be closer to the application

Create a sample test file with the following contents:

import fakeredis
import pytest


def test_example():

    redis = fakeredis.FakeStrictRedis(decode_responses=True)

    expected = True
    output = True
    assert expected == output

Run the test:

pipenv run pytest test_example.py

Review the output:

========================== test session starts ==========================
platform darwin -- Python 3.8.12, pytest-7.1.2, pluggy-1.0.0
rootdir: /Users/danstreeter/temp/fakeredis-bug
collected 1 item

fakeredis_test.py F                                               [100%]

=============================== FAILURES ================================
_____________________________ test_example ______________________________

    def test_example():

>       redis = fakeredis.FakeStrictRedis(decode_responses=True)

fakeredis_test.py:6:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <[AttributeError("'FakeStrictRedis' object has no attribute 'connection_pool'") raised in repr()] FakeStrictRedis object at 0x10d442d90>
server = None, connected = True, args = ()
kwargs = {'decode_responses': True}
bound = <BoundArguments (args=(), kwds={'decode_responses': True})>

    def __init__(self, *args, server=None, connected=True, **kwargs):
        # Interpret the positional and keyword arguments according to the
        # version of redis in use.
        bound = _ORIG_SIG.bind(*args, **kwargs)
        bound.apply_defaults()
>       if not bound.arguments['connection_pool']:
E       KeyError: 'connection_pool'

.venv/lib/python3.8/site-packages/fakeredis/_server.py:2804: KeyError
======================== short test summary info ========================
FAILED fakeredis_test.py::test_example - KeyError: 'connection_pool'
=========================== 1 failed in 0.18s ===========================

Expected behavior
I guess, for it to not fail - or some advice on how to provide a connection_pool parameter to the required FakeRedis instance.

Desktop (please complete the following information):

  • OS: OSX Monterey 12.3
  • python version - 3.8
  • redis-py version - 4.3.1
  • full requirements.txt?
pipenv lock -r

Warning: The lock flag -r/--requirements will be deprecated in a future version
of pipenv in favor of the new requirements command. For more info see
https://pipenv.pypa.io/en/latest/advanced/#generating-a-requirements-txt
NOTE: the requirements command parses Pipfile.lock directly without performing any
locking operations. Updating packages should be done by running pipenv lock.
#
# These requirements were autogenerated by pipenv
# To regenerate from the project's Pipfile, run:
#
#    pipenv lock --requirements
#

-i https://pypi.org/simple
async-timeout==4.0.2; python_version >= '3.6'
attrs==21.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
deprecated==1.2.13; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
fakeredis[lua]==1.7.4
iniconfig==1.1.1
lupa==1.13
packaging==21.3; python_version >= '3.6'
pluggy==1.0.0; python_version >= '3.6'
py==1.11.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
pyparsing==3.0.9; python_full_version >= '3.6.8'
pytest==7.1.2
redis==4.2.2
six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
sortedcontainers==2.4.0
tomli==2.0.1; python_version >= '3.7'
wrapt==1.14.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'

Additional context
Happy to assist in debugging if I can. =)

ensure_str is missing a parameter

I didn't check why your CI does not fail, but trying to package fakeredis 1.9.3 and running pytest to check package integrity fails with this error:

[ 49s] E TypeError: ensure_str() takes 2 positional arguments but 4 were given
[   49s] __________________ test_eval_global_variable[FakeStrictRedis] __________________
[   49s] 
[   49s] r = FakeStrictRedis<ConnectionPool<FakeConnection<server=<fakeredis._server.FakeServer object at 0x7f3a26ace250>,db=0>>>
[   49s] 
[   49s]     def test_eval_global_variable(r):
[   49s]         # Redis doesn't allow script to define global variables
[   49s]         with pytest.raises(ResponseError):
[   49s] >           r.eval('a=10', 0)
[   49s] 
[   49s] test/test_lua.py:214: 
[   49s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
[   49s] /usr/lib/python3.8/site-packages/redis/commands/core.py:5054: in eval
[   49s]     return self._eval("EVAL", script, numkeys, *keys_and_args)
[   49s] /usr/lib/python3.8/site-packages/redis/commands/core.py:5039: in _eval
[   49s]     return self.execute_command(command, script, numkeys, *keys_and_args)
[   49s] /usr/lib/python3.8/site-packages/redis/client.py:1235: in execute_command
[   49s]     return conn.retry.call_with_retry(
[   49s] /usr/lib/python3.8/site-packages/redis/retry.py:46: in call_with_retry
[   49s]     return do()
[   49s] /usr/lib/python3.8/site-packages/redis/client.py:1236: in <lambda>
[   49s]     lambda: self._send_command_parse_response(
[   49s] /usr/lib/python3.8/site-packages/redis/client.py:1211: in _send_command_parse_response
[   49s]     conn.send_command(*args)
[   49s] /usr/lib/python3.8/site-packages/redis/connection.py:797: in send_command
[   49s]     self.send_packed_command(
[   49s] /usr/lib/python3.8/site-packages/redis/connection.py:779: in send_packed_command
[   49s]     self._sock.sendall(item)
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_basefakesocket.py:208: in sendall
[   49s]     self._parser.send(data)
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_basefakesocket.py:118: in _parse_commands
[   49s]     self._process_command(fields)
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_basefakesocket.py:238: in _process_command
[   49s]     result = self._run_command(func, sig, fields[1:], False)
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_basefakesocket.py:139: in _run_command
[   49s]     result = func(*args)
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_fakesocket.py:1606: in eval
[   49s]     self._check_for_lua_globals(lua_runtime, expected_globals)
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_fakesocket.py:1528: in _check_for_lua_globals
[   49s]     unexpected = [self.ensure_str(var, 'utf-8', 'replace')
[   49s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
[   49s] 
[   49s] .0 = <set_iterator object at 0x7f3a2715c0c0>
[   49s] 
[   49s] >   unexpected = [self.ensure_str(var, 'utf-8', 'replace')
[   49s]                   for var in actual_globals - expected_globals]
[   49s] E   TypeError: ensure_str() takes 2 positional arguments but 4 were given
[   49s] 
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_fakesocket.py:1528: TypeError
[   49s] _______________ test_eval_global_and_return_ok[FakeStrictRedis] ________________
[   49s] 
[   49s] r = FakeStrictRedis<ConnectionPool<FakeConnection<server=<fakeredis._server.FakeServer object at 0x7f3a26b20580>,db=0>>>
[   49s] 
[   49s]     def test_eval_global_and_return_ok(r):
[   49s]         # Redis doesn't allow script to define global variables
[   49s]         with pytest.raises(ResponseError):
[   49s] >           r.eval(
[   49s]                 '''
[   49s]                 a=10
[   49s]                 return redis.status_reply("Everything is awesome")
[   49s]                 ''',
[   49s]                 0
[   49s]             )
[   49s] 
[   49s] test/test_lua.py:220: 
[   49s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
[   49s] /usr/lib/python3.8/site-packages/redis/commands/core.py:5054: in eval
[   49s]     return self._eval("EVAL", script, numkeys, *keys_and_args)
[   49s] /usr/lib/python3.8/site-packages/redis/commands/core.py:5039: in _eval
[   49s]     return self.execute_command(command, script, numkeys, *keys_and_args)
[   49s] /usr/lib/python3.8/site-packages/redis/client.py:1235: in execute_command
[   49s]     return conn.retry.call_with_retry(
[   49s] /usr/lib/python3.8/site-packages/redis/retry.py:46: in call_with_retry
[   49s]     return do()
[   49s] /usr/lib/python3.8/site-packages/redis/client.py:1236: in <lambda>
[   49s]     lambda: self._send_command_parse_response(
[   49s] /usr/lib/python3.8/site-packages/redis/client.py:1211: in _send_command_parse_response
[   49s]     conn.send_command(*args)
[   49s] /usr/lib/python3.8/site-packages/redis/connection.py:797: in send_command
[   49s]     self.send_packed_command(
[   49s] /usr/lib/python3.8/site-packages/redis/connection.py:779: in send_packed_command
[   49s]     self._sock.sendall(item)
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_basefakesocket.py:208: in sendall
[   49s]     self._parser.send(data)
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_basefakesocket.py:118: in _parse_commands
[   49s]     self._process_command(fields)
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_basefakesocket.py:238: in _process_command
[   49s]     result = self._run_command(func, sig, fields[1:], False)
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_basefakesocket.py:139: in _run_command
[   49s]     result = func(*args)
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_fakesocket.py:1606: in eval
[   49s]     self._check_for_lua_globals(lua_runtime, expected_globals)
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_fakesocket.py:1528: in _check_for_lua_globals
[   49s]     unexpected = [self.ensure_str(var, 'utf-8', 'replace')
[   49s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
[   49s] 
[   49s] .0 = <set_iterator object at 0x7f3a26cbc480>
[   49s] 
[   49s] >   unexpected = [self.ensure_str(var, 'utf-8', 'replace')
[   49s]                   for var in actual_globals - expected_globals]
[   49s] E   TypeError: ensure_str() takes 2 positional arguments but 4 were given
[   49s] 
[   49s] ../../BUILDROOT/python-fakeredis-1.9.3-0.x86_64/usr/lib/python3.8/site-packages/fakeredis/_fakesocket.py:1528: TypeError
[   49s] =============================== warnings summary ===============================
[   49s] test/test_connection.py::TestFakeStrictRedisConnectionErrors::test_hmset[FakeStrictRedis]
[   49s]   /home/abuild/rpmbuild/BUILD/fakeredis-py-1.9.3/test/test_connection.py:258: DeprecationWarning: FakeStrictRedis.hmset() is deprecated. Use FakeStrictRedis.hset() instead.
[   49s]     r.hmset('name', {'key': 1})
[   49s] 
[   49s] test/test_fakeredis6.py::test_hmset_empty_raises_error[FakeStrictRedis]
[   49s]   /home/abuild/rpmbuild/BUILD/fakeredis-py-1.9.3/test/test_fakeredis6.py:1543: DeprecationWarning: FakeStrictRedis.hmset() is deprecated. Use FakeStrictRedis.hset() instead.
[   49s]     r.hmset('foo', {})
[   49s] 
[   49s] test/test_fakeredis6.py::test_hmset[FakeStrictRedis]
[   49s]   /home/abuild/rpmbuild/BUILD/fakeredis-py-1.9.3/test/test_fakeredis6.py:1548: DeprecationWarning: FakeStrictRedis.hmset() is deprecated. Use FakeStrictRedis.hset() instead.
[   49s]     assert r.hmset('foo', {'k2': 'v2', 'k3': 'v3'}) is True
[   49s] 
[   49s] test/test_fakeredis6.py::test_hmset_wrong_type[FakeStrictRedis]
[   49s]   /home/abuild/rpmbuild/BUILD/fakeredis-py-1.9.3/test/test_fakeredis6.py:1554: DeprecationWarning: FakeStrictRedis.hmset() is deprecated. Use FakeStrictRedis.hset() instead.
[   49s]     r.hmset('foo', {'key': 'value'})
[   49s] 
[   49s] -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
[   49s] =========================== short test summary info ============================
[   49s] FAILED test/test_lua.py::test_eval_global_variable[FakeStrictRedis] - TypeErr...
[   49s] FAILED test/test_lua.py::test_eval_global_and_return_ok[FakeStrictRedis] - Ty...
[   49s] =========== 2 failed, 652 passed, 632 skipped, 4 warnings in 44.62s ============

Clearly there is somethring wrong in the last commit:

def ensure_str(self, s):
return (s.decode(encoding='utf-8', errors='replace')
if isinstance(s, bytes)
else str(s).encode(encoding='utf-8', errors='replace'))
def _check_for_lua_globals(self, lua_runtime, expected_globals):
actual_globals = set(lua_runtime.globals().keys())
if actual_globals != expected_globals:
unexpected = [self.ensure_str(var, 'utf-8', 'replace')
for var in actual_globals - expected_globals]
raise SimpleError(msgs.GLOBAL_VARIABLE_MSG.format(", ".join(unexpected)))

Support for Redis7

Is your feature request related to a problem? Please describe.
Support for changes in Redis v7

clarify license

Is your feature request related to a problem? Please describe.

Going by https://github.com/cunla/fakeredis-py/blob/master/pyproject.toml#L23 the project seems to be BSD-3-Clause but https://github.com/cunla/fakeredis-py/blob/master/LICENSE creates some confusion.

Describe the solution you'd like
Could the references to individuals be moved to a file COPYRIGHT and the LICENSE file just include the BSD-3-Clause?

Additional context
I am trying to automate an overview of the licenses included in my projects and currently I cannot detect the license using dependabots database.

Scan in lua script doesn't iterate all keys

I'm running the following lua script and it seems the scan command doesn't iterate on all the keys. I've run it with redis-py and it worked as expected

import fakeredis

r = fakeredis.FakeStrictRedis()
for i in range(100):
    r.set(f'key-{i}', i)

script = """
    local cursor = 0
    local seen = {}
    repeat
        local result = redis.call('SCAN', cursor)
        for _,key in ipairs(result[2]) do
            seen[#seen+1] = key
            redis.call('DEL', key)
        end
        cursor = tonumber(result[1])
    until cursor == 0
    return seen
"""

print(len(r.register_script(script)()))  # Expecting here 100, getting 50
print(len(r.keys()))  # Expecting here 0, getting 50

Desktop (please complete the following information):

  • OS: Mac
  • python version: 3.8
  • redis-py version: 4.3.4

lmove operation is missing

lmove operation is a new feature in redis version 6.2.0
It is similar to RPOPLPUSH, but instead it always poping and pushing from both side of the list independently
I am happy to implement it myself, I already have started a branch for this if you give me permission to do so

Critical: broken on CPython 3.8 & redis 4.2+

Describe the bug
The latest (at the time of this writing) release fakeredis-1.7.4 is completely broken on CPython 3.8.

To Reproduce
Assuming docker is available, simply run

docker run --rm -it python:3.8 /bin/bash -c "pip install fakeredis; python -c 'import fakeredis; fakeredis.FakeRedis()'"

<...>
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.8/site-packages/fakeredis/_server.py", line 2804, in __init__
    if not bound.arguments['connection_pool']:
KeyError: 'connection_pool'

Interestingly, CPython 3.9 works fine.

Expected behavior
Expected to be able to initialize an instance of fakeredis.FakeRedis.

Missing py.typed

Hiya and thanks for this library.

The issue is that it doesn't play nice with type checkers - because its missing a py.typed file. The fx is simple - add a py.typed file (its an empty file) into the source folder of the lib, and bundle it as part of the wheel. You can find instructions in the mypy docs.

Cheers.

Missing dependencies on latest pypi version: 1.7.6

Describe the bug

It looks like fakeredis still depends on six and sortedcontainers, but the dependencies were removed in this PR #12 while migrating to poetry.

Before #12 :

install_requires =
    packaging
    redis<=4.3.1
    six>=1.12
    sortedcontainers

After #12 :

python = "^3.8"
lupa = "1.13"
redis = "4.3.1"
aioredis = "^2.0.1"

Current master:

[tool.poetry.dependencies]
python = "^3.8"
lupa = { version = "^1.13", optional = true }
redis = "<=4.3.1"
aioredis = { version = "^2.0.1", optional = true }

[tool.poetry.extras]
lua = ["lupa"]
aioredis = ["aioredis"]

I'm getting an error when I try to import using the latest version:

ImportError while loading conftest '/home/lyst/code/tests/conftest.py'.
tests/conftest.py:8: in <module>
    from fakeredis import FakeRedis
../venv/lib/python3.9/site-packages/fakeredis/__init__.py:1: in <module>
    from ._server import FakeServer, FakeRedis, FakeStrictRedis, FakeConnection   # noqa: F401
../venv/lib/python3.9/site-packages/fakeredis/_server.py:21: in <module>
    from ._zset import ZSet
../venv/lib/python3.9/site-packages/fakeredis/_zset.py:1: in <module>
    import sortedcontainers
E   ModuleNotFoundError: No module named 'sortedcontainers'

To Reproduce
Steps to reproduce the behavior:

  1. Install version 1.7.6 on a clean environment
  2. Open a python shell
  3. import fakeredis
  4. See error:
(.venv) AA> python
Python 3.10.4 (main, Apr  9 2022, 21:27:52) [GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import fakeredis
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jose/workspace/lyst/braze-api/AA/.venv/lib/python3.10/site-packages/fakeredis/__init__.py", line 1, in <module>
    from ._server import FakeServer, FakeRedis, FakeStrictRedis, FakeConnection   # noqa: F401
  File "/home/jose/workspace/lyst/braze-api/AA/.venv/lib/python3.10/site-packages/fakeredis/_server.py", line 19, in <module>
    import six
ModuleNotFoundError: No module named 'six'

Expected behavior
No import errors.

Screenshots
N/A

Desktop (please complete the following information):

  • OS: Linux
  • python version: 3.10.4
  • redis-py version: pip install fakeredis==1.7.6
  • full requirements.txt?: N/A

Additional context
Add any other context about the problem here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    šŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ā¤ļø Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.