Skip to content

Commit

Permalink
doc:update link to hash commands
Browse files Browse the repository at this point in the history
  • Loading branch information
cunla committed Sep 21, 2024
1 parent 8a82b5c commit ace2b94
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 120 deletions.
79 changes: 49 additions & 30 deletions docs/redis-commands/Redis.md
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@ Stores the union of multiple sorted sets in a key.



## `generic` commands (20/33 implemented)
## `generic` commands (20/26 implemented)

### [DEL](https://redis.io/commands/del/)

Expand Down Expand Up @@ -977,30 +977,6 @@ Copies the value of a key to a new key.

Returns the expiration time of a key as a Unix timestamp.

#### [MIGRATE](https://redis.io/commands/migrate/) <small>(not implemented)</small>

Atomically transfers a key from one Redis instance to another.

#### [OBJECT](https://redis.io/commands/object/) <small>(not implemented)</small>

A container for object introspection commands.

#### [OBJECT ENCODING](https://redis.io/commands/object-encoding/) <small>(not implemented)</small>

Returns the internal encoding of a Redis object.

#### [OBJECT FREQ](https://redis.io/commands/object-freq/) <small>(not implemented)</small>

Returns the logarithmic access frequency counter of a Redis object.

#### [OBJECT IDLETIME](https://redis.io/commands/object-idletime/) <small>(not implemented)</small>

Returns the time since the last access to a Redis object.

#### [OBJECT REFCOUNT](https://redis.io/commands/object-refcount/) <small>(not implemented)</small>

Returns the reference count of a value of a key.

#### [PEXPIRETIME](https://redis.io/commands/pexpiretime/) <small>(not implemented)</small>

Returns the expiration time of a key as a Unix milliseconds timestamp.
Expand All @@ -1009,10 +985,6 @@ Returns the expiration time of a key as a Unix milliseconds timestamp.

Returns the sorted elements of a list, a set, or a sorted set.

#### [TOUCH](https://redis.io/commands/touch/) <small>(not implemented)</small>

Returns the number of existing keys out of those specified after updating the time they were last accessed.

#### [WAIT](https://redis.io/commands/wait/) <small>(not implemented)</small>

Blocks until the asynchronous replication of all preceding write commands sent by the connection is completed.
Expand Down Expand Up @@ -1185,7 +1157,7 @@ Queries a geospatial index for members inside an area of a box or a circle, opti



## `hash` commands (16/16 implemented)
## `hash` commands (16/27 implemented)

### [HDEL](https://redis.io/commands/hdel/)

Expand Down Expand Up @@ -1252,6 +1224,53 @@ Returns the length of the value of a field.
Returns all values in a hash.


### Unsupported hash commands
> To implement support for a command, see [here](../../guides/implement-command/)
#### [HEXPIRE](https://redis.io/commands/hexpire/) <small>(not implemented)</small>

Set expiry for hash field using relative time to expire (seconds)

#### [HEXPIREAT](https://redis.io/commands/hexpireat/) <small>(not implemented)</small>

Set expiry for hash field using an absolute Unix timestamp (seconds)

#### [HEXPIRETIME](https://redis.io/commands/hexpiretime/) <small>(not implemented)</small>

Returns the expiration time of a hash field as a Unix timestamp, in seconds.

#### [HGETF](https://redis.io/commands/hgetf/) <small>(not implemented)</small>

For each specified field, returns its value and optionally set the field's remaining expiration time in seconds / milliseconds

#### [HPERSIST](https://redis.io/commands/hpersist/) <small>(not implemented)</small>

Removes the expiration time for each specified field

#### [HPEXPIRE](https://redis.io/commands/hpexpire/) <small>(not implemented)</small>

Set expiry for hash field using relative time to expire (milliseconds)

#### [HPEXPIREAT](https://redis.io/commands/hpexpireat/) <small>(not implemented)</small>

Set expiry for hash field using an absolute Unix timestamp (milliseconds)

#### [HPEXPIRETIME](https://redis.io/commands/hpexpiretime/) <small>(not implemented)</small>

Returns the expiration time of a hash field as a Unix timestamp, in msec.

#### [HPTTL](https://redis.io/commands/hpttl/) <small>(not implemented)</small>

Returns the TTL in milliseconds of a hash field.

#### [HSETF](https://redis.io/commands/hsetf/) <small>(not implemented)</small>

For each specified field, returns its value and optionally set the field's remaining expiration time in seconds / milliseconds

#### [HTTL](https://redis.io/commands/httl/) <small>(not implemented)</small>

Returns the TTL in seconds of a hash field.


## `hyperloglog` commands (3/3 implemented)

Expand Down
53 changes: 0 additions & 53 deletions docs/redis-commands/RedisGraph.md

This file was deleted.

75 changes: 47 additions & 28 deletions fakeredis/_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,25 @@ class Hash(dict): # type:ignore
DECODE_ERROR = msgs.INVALID_HASH_MSG
redis_type = b"hash"

def __init__(self):
super().__init__()
self.expirations: Dict[bytes, int] = {}

def _check_expire(self, key: bytes) -> None:
if key in self.expirations and self.expirations[key] < int(time.time()):
del self[key]
del self.expirations[key]

def __get__(self, key: bytes) -> Any:
self._check_expire(key)
if key in self:
return self[key]
return self.__get__(key)

def __contains__(self, item):
self._check_expire(item)
return super().__contains__(item)


class RedisType:
@classmethod
Expand All @@ -123,8 +142,8 @@ class Int(RedisType):

DECODE_ERROR = msgs.INVALID_INT_MSG
ENCODE_ERROR = msgs.OVERFLOW_MSG
MIN_VALUE = -(2**63)
MAX_VALUE = 2**63 - 1
MIN_VALUE = -(2 ** 63)
MAX_VALUE = 2 ** 63 - 1

@classmethod
def valid(cls, value: int) -> bool:
Expand Down Expand Up @@ -182,13 +201,13 @@ class Float(RedisType):

@classmethod
def decode(
cls,
value: bytes,
allow_leading_whitespace: bool = False,
allow_erange: bool = False,
allow_empty: bool = False,
crop_null: bool = False,
decode_error: Optional[str] = None,
cls,
value: bytes,
allow_leading_whitespace: bool = False,
allow_erange: bool = False,
allow_empty: bool = False,
crop_null: bool = False,
decode_error: Optional[str] = None,
) -> float:
# Redis has some quirks in float parsing, with several variants.
# See https://github.com/antirez/redis/issues/5706
Expand Down Expand Up @@ -239,13 +258,13 @@ class SortFloat(Float):

@classmethod
def decode(
cls,
value: bytes,
allow_leading_whitespace: bool = True,
allow_erange: bool = False,
allow_empty: bool = True,
crop_null: bool = True,
decode_error: Optional[str] = None,
cls,
value: bytes,
allow_leading_whitespace: bool = True,
allow_erange: bool = False,
allow_empty: bool = True,
crop_null: bool = True,
decode_error: Optional[str] = None,
) -> float:
return super().decode(value, allow_leading_whitespace=True, allow_empty=True, crop_null=True)

Expand Down Expand Up @@ -347,13 +366,13 @@ def decode(cls, value: bytes) -> "StringTest":

class Signature:
def __init__(
self,
name: str,
func_name: str,
fixed: Tuple[Type[Union[RedisType, bytes]]],
repeat: Tuple[Type[Union[RedisType, bytes]]] = (), # type:ignore
args: Tuple[str] = (), # type:ignore
flags: str = "",
self,
name: str,
func_name: str,
fixed: Tuple[Type[Union[RedisType, bytes]]],
repeat: Tuple[Type[Union[RedisType, bytes]]] = (), # type:ignore
args: Tuple[str] = (), # type:ignore
flags: str = "",
):
self.name = name
self.func_name = func_name
Expand All @@ -374,7 +393,7 @@ def check_arity(self, args: Sequence[Any], version: Tuple[int]) -> None:
raise SimpleError(msg)

def apply(
self, args: Sequence[Any], db: Database, version: Tuple[int]
self, args: Sequence[Any], db: Database, version: Tuple[int]
) -> Union[Tuple[Any], Tuple[List[Any], List[CommandItem]]]:
"""Returns a tuple, which is either:
- transformed args and a dict of CommandItems; or
Expand Down Expand Up @@ -406,10 +425,10 @@ def apply(
if type_.type_ is not None and item is not None and type(item.value) is not type_.type_:
raise SimpleError(msgs.WRONGTYPE_MSG)
if (
msgs.FLAG_DO_NOT_CREATE not in self.flags
and type_.type_ is not None
and item is None
and type_.type_ is not bytes
msgs.FLAG_DO_NOT_CREATE not in self.flags
and type_.type_ is not None
and item is None
and type_.type_ is not bytes
):
default = type_.type_()
args_list[i] = CommandItem(arg, db, item, default=default)
Expand Down
1 change: 0 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ nav:
- Redis commands: redis-commands/Redis.md
- RedisJSON commands: redis-commands/RedisJson.md
- Search commands: redis-commands/RedisSearch.md
- Graph commands: redis-commands/RedisGraph.md
- Time Series commands: redis-commands/RedisTimeSeries.md
- Probabilistic commands: redis-commands/RedisBloom.md
- Guides:
Expand Down
12 changes: 8 additions & 4 deletions scripts/create_issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import json
import os

import click
import requests
from dotenv import load_dotenv
from github import Github
Expand All @@ -21,7 +22,7 @@
IGNORE_GROUPS = {
'suggestion', 'tdigest', 'scripting', 'cf',
'graph', 'timeseries', 'connection',
'server', 'generic', 'cms', 'cluster', 'search',
'server', 'cms', 'cluster', 'search', 'hash'
}


Expand Down Expand Up @@ -60,8 +61,11 @@ def get_unimplemented_and_implemented_commands() -> tuple[dict[str, list[str]],
groups = sorted(implemented_dict.keys(), key=lambda x: len(unimplemented_dict[x]))
for group in groups:
unimplemented_count = len(unimplemented_dict[group])
if unimplemented_count == 0:
click.secho(f'{group} has all commands implemented', fg='green')
continue
total_count = len(implemented_dict.get(group)) + unimplemented_count
print(f'{group} has {unimplemented_count}/{total_count} unimplemented commands')
click.secho(f'{group} has {unimplemented_count}/{total_count} unimplemented commands')
return unimplemented_dict, implemented_dict


Expand All @@ -78,7 +82,7 @@ def __init__(self, dry=False):

def create_label(self, name):
if self.dry:
print(f'Creating label "{name}"')
click.secho(f'Creating label "{name}"', fg='cyan')
else:
self.gh_repo.create_label(name, "f29513")
self.labels.add(name)
Expand Down Expand Up @@ -111,7 +115,7 @@ def _handle_commands(gh: GithubData):
continue
if len(unimplemented[group]) == 0:
continue
print(f'### Creating issues for {group} commands')
click.secho(f'### Creating issues for {group} commands', fg='green')
for cmd in unimplemented[group]:
if cmd.upper() in IGNORE_COMMANDS:
continue
Expand Down
8 changes: 4 additions & 4 deletions scripts/generate_supported_commands_doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
from fakeredis._commands import SUPPORTED_COMMANDS

IGNORE_COMMANDS = {
'PUBSUB HELP', 'OBJECT HELP', 'FUNCTION HELP', 'SCRIPT HELP',
'PUBSUB HELP', 'FUNCTION HELP', 'SCRIPT HELP',
'JSON.DEBUG', 'JSON.DEBUG HELP', 'JSON.DEBUG MEMORY', 'JSON.RESP',
'XINFO', 'XINFO HELP', 'XGROUP', 'XGROUP HELP', 'XSETID',
'ACL HELP', 'COMMAND HELP', 'CONFIG HELP', 'DEBUG',
'MEMORY HELP', 'MODULE HELP', 'CLIENT HELP',
'PFDEBUG', 'PFSELFTEST', 'BITFIELD_RO',
'OBJECT', 'OBJECT HELP', 'OBJECT IDLETIME', 'OBJECT REFCOUNT', 'OBJECT FREQ', 'OBJECT ENCODING',
'MIGRATE', 'TOUCH',
}

THIS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)))
Expand All @@ -32,11 +34,9 @@ class CommandsMeta:

METADATA = [
CommandsMeta('.commands.json', 'Redis', 'Redis',
'https://raw.githubusercontent.com/redis/redis-doc/master/commands.json', ),
'https://raw.githubusercontent.com/redis/docs/refs/heads/main/data/commands.json', ),
CommandsMeta('.json.commands.json', 'RedisJson', 'JSON',
'https://raw.githubusercontent.com/RedisJSON/RedisJSON/master/commands.json', ),
CommandsMeta('.graph.commands.json', 'RedisGraph', 'Graph',
'https://raw.githubusercontent.com/RedisGraph/RedisGraph/master/commands.json', ),
CommandsMeta('.ts.commands.json', 'RedisTimeSeries', 'Time Series',
'https://raw.githubusercontent.com/RedisTimeSeries/RedisTimeSeries/master/commands.json', ),
CommandsMeta('.ft.commands.json', 'RedisSearch', 'Search',
Expand Down

0 comments on commit ace2b94

Please sign in to comment.