Disable box-sizing prop in grid if already globally set

It would be great if there was an option we could set to remove the box-sizing property from the grid in the case we have already defined it globally. If you'd like I could make a PR?

No, there is not a specific option for that.
But you can use @include grid-column($global: false) to avoid to generate
box-sizing. But with that you will loose also the rules: display: flex
and flex-direction: column. That rules are not needed in every case, but
have a try in your case.
On the repetition:
If you use gzip, css repetitions are not an issue at all. Every repetition
is compressed, so there is not bytes difference.
If you don't have gzip, give a try to the use-dry option. You can find it
in the README. It will avoid the repetitions for you
Il giorno lun 14 ago 2017 alle 18:00 Eric Fuhrmann<EMAIL_ADDRESS>ha scritto:

As title says, I already am defining box-sizing: border-box globally so
would like to save some repetition if possible.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/Objectway/super-gigi/issues/13, or mute the thread
https://github.com/notifications/unsubscribe-auth/ACQ3Mj4_uQlnJ2hr8agW2HgCIdXu-D0Xks5sYH1JgaJpZM4O2oku
.

Interesting, I didn't realize that about gzip. Well that definitely is a good solution for myself, so I will close this issue.
That said, I did create a PR for adding another setting that would disable this as well. Perhaps it's worth keeping in case someone does not wish to compile with gzip?
Regardless feel free to decline my PR if you feel that gzip is a suitable solution.

The PR is a good idea, I will leave that here, waiting if someone has
something to say. (And I'm in vacation, so I will open a real pc in weeks
:D)
Cheers
Il giorno lun 14 ago 2017 alle 19:05 Eric Fuhrmann<EMAIL_ADDRESS>ha scritto:

Closed #13 https://github.com/Objectway/super-gigi/issues/13.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/Objectway/super-gigi/issues/13#event-1205247265, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ACQ3MnJhv5UxodwDpwVr6VStLxzv2VMkks5sYIxUgaJpZM4O2oku
.


Argo CD is just CD; Added Argo Workflows for CI.

Argo CI/CD is mislabeled. Argo has multiple components. CD and CI are two separate ones. I've ensured they are both available and I've corrected the labeling.

Argo CD - this is delivery only, not CI. As such, I've renamed Argo CI/CD to Argo CD.
Argo Workflows - this is a jobs pipeline tool; and is the CI component for Argo. I've added this to the repo.

Tested deployment of argo-workflows:
$ kubectl apply -f app.yaml
namespace/argo created
customresourcedefinition.apiextensions.k8s.io/clusterworkflowtemplates.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/cronworkflows.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/workfloweventbindings.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/workflows.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/workflowtemplates.argoproj.io created
serviceaccount/argo created
serviceaccount/argo-server created
role.rbac.authorization.k8s.io/argo-role created
clusterrole.rbac.authorization.k8s.io/argo-aggregate-to-admin created
clusterrole.rbac.authorization.k8s.io/argo-aggregate-to-edit created
clusterrole.rbac.authorization.k8s.io/argo-aggregate-to-view created
clusterrole.rbac.authorization.k8s.io/argo-cluster-role created
clusterrole.rbac.authorization.k8s.io/argo-server-cluster-role created
rolebinding.rbac.authorization.k8s.io/argo-binding created
clusterrolebinding.rbac.authorization.k8s.io/argo-binding created
clusterrolebinding.rbac.authorization.k8s.io/argo-server-binding created
configmap/workflow-controller-configmap created
service/argo-server created
service/workflow-controller-metrics created
deployment.apps/argo-server created
deployment.apps/workflow-controller created

$ kubectl get pods -n argo
NAME                                   READY   STATUS    RESTARTS   AGE
argo-server-6cdfbbcfb5-mxzbk           0/1     Running   0          20s
workflow-controller-64c947c746-4hgm6   1/1     Running   0          20s

@saiyam1814, done.

@protosam version should be quoted string like "v0.1.0"

@saiyam1814 done.
It functionally doesn't matter though. Semantic versioning is always going to be a string to YAML. Semantic versioning being formatted like [0-9]+\.[0-9]+\.[0-9]+.
These three are just (default):
$ grep '^version: (default)' */manifest.yaml -l
chaos-mesh/manifest.yaml
metrics-server/manifest.yaml
traefik/manifest.yaml

If this is a concern though, every one of these existing manifests don't meet this requirement of being quoted for the version:
$ grep '^version: [^"]' */manifest.yaml -l
argo-workflows/manifest.yaml
bitwardenrs/manifest.yaml
cert-manager/manifest.yaml
chaos-mesh/manifest.yaml
docker-registry/manifest.yaml
dynamic-pv-scaler/manifest.yaml
flux/manifest.yaml
ghost/manifest.yaml
gitea/manifest.yaml
helm/manifest.yaml
jenkins/manifest.yaml
joomla/manifest.yaml
kube-hunter/manifest.yaml
kube-scan/manifest.yaml
kubei/manifest.yaml
kubeless/manifest.yaml
kubernetes-dashboard/manifest.yaml
kubevious/manifest.yaml
linkerd/manifest.yaml
litmuschaos/manifest.yaml
loki/manifest.yaml
longhorn/manifest.yaml
maesh/manifest.yaml
mariadb/manifest.yaml
metrics-server/manifest.yaml
mongodb/manifest.yaml
netdata/manifest.yaml
nextcloud/manifest.yaml
nginx/manifest.yaml
nodered/manifest.yaml
okteto/manifest.yaml
openfaas/manifest.yaml
permission-manager/manifest.yaml
polaris/manifest.yaml
portainer/manifest.yaml
rancher/manifest.yaml
sealed-secrets/manifest.yaml
selenium/manifest.yaml
system-upgrade-controller/manifest.yaml
tekton/manifest.yaml
traefik/manifest.yaml
wordpress/manifest.yaml

Yes We are slowly moving to standardize things and getting rid of default version and making sure all the new commits happen with quoted strings (I know this was fixed but just want to keep things same)
We will be reaching out to maintainers to get these fixed but for the new ones we want a specific version than default of latest.
There is an option for plans where people can define both stable and latest in manifest and give version as multiple.

PR lgtm


Make Map and Identifier Public

This is a great repo.
I needed to be able to compare with other devices and identifiers so I made the identifier and the mapIdentifierToDevice public.
No changes were made to your code, only increased the public api
I also added a unit test.
Thx.

Hi Kraig, thank you very much! Can you briefly explain why you need the identifier? I'm just curious ...  Thing is, I think that the identifier is kind of an implementation detail ... Can you shortly explain your situation (why you need it)? That'd be super nice :)
Do you think a nicer solution would be to provide another initializer that takes an identifier? You could then create a device from an identifier and compare / etc. those.

Sure @dennisweissmann
The reason I need access to the identifier is because the app I'm working on uses that identifier in the model to record what device the user was on when they performed a specific action.
We have logs in our model that have a device_type property.  That type's value is the identifier.
When we display that log later, we tell the user what action was performed and what device it was performed on.
Example of our log:
LOG

id = uuid ex("ijfoaiwej3o23jijdf")
proj_id = string ex("3iiji3imofw90m")
equip_id = string ex("fji3ijfi900a3jn")
action_type = int ex(10)
device_type = string ex("iPhone3,1")
updated_on = date ex(1472141086)
updater_id = string ex("ifj3ij0vn398bji")

and so forth...
Thank you for the consideration, I hope that answers your question.
-Kraig

Hi Kraig,
Thanks so much for your thorough explanation! I thought a little bit more about the approach I explained earlier but I figured yours is easier (because the other device created would have the same battery / etc. stats as the real one). Merged, thanks again! :)

Awesome.  Thx for the quick responses and for the awesome pod.


Tons of wakelocks

Another Widget seems to cause a lot of wakelocks, and that was even before I enabled weather.

Checked with Wakelock Detector Lite. Any ideas?
Edit: what I posted above is actually "wake-up triggers", which still seem abnormally high compared to other apps. Image below shows actual CPU wakelocks, which only sum up to 2 seconds but were executed 131 times.

Same problem here (OnePlus 3 running Android 8.0.0 and OxygenOS 5.0.3).
Here are some screen capture showing the issue:
1. Wakelock Detector Full - CPU Wakelock

2. Wakelock Detector Full - Wakeup Triggers

3. BetterBatteryStats - Partial Wakelocks

4. BetterBatteryStats - Alarms

Fixed in version 2.0.1.


python3.5 await support code

import tornadis
from redis import RedisError
from json import loads, dumps
import datetime

class Redis:
    def __init__(self, *args, **kwds):
        self._client = tornadis.Client(*args, **kwds)

    # SERVER INFORMATION
    async def bgrewriteaof(self):
        "Tell the Redis server to rewrite the AOF file from data in memory."
        return await self._client.call('BGREWRITEAOF')

    async def bgsave(self):
        """
        Tell the Redis server to save its data to disk.  Unlike save(),
        this method is asynchronous and return awaits immediately.
        """
        return await self._client.call('BGSAVE')

    async def client_kill(self, address):
        "Disconnects the client at ``address`` (ip:port)"
        return await self._client.call('CLIENT KILL', address)

    async def client_list(self):
        "Returns a list of currently connected clients"
        return await self._client.call('CLIENT LIST')

    async def client_getname(self):
        "Returns the current connection name"
        return await self._client.call('CLIENT GETNAME')

    async def client_setname(self, name):
        "Sets the current connection name"
        return await self._client.call('CLIENT SETNAME', name)

    async def config_get(self, pattern="*"):
        "Return a dictionary of configuration based on the ``pattern``"
        return await self._client.call('CONFIG GET', pattern)

    async def config_set(self, name, value):
        "Set config item ``name`` with ``value``"
        return await self._client.call('CONFIG SET', name, value)

    async def config_resetstat(self):
        "Reset runtime statistics"
        return await self._client.call('CONFIG RESETSTAT')

    async def config_rewrite(self):
        "Rewrite config file with the minimal change to reflect running config"
        return await self._client.call('CONFIG REWRITE')

    async def dbsize(self):
        "Returns the number of keys in the current database"
        return await self._client.call('DBSIZE')

    async def debug_object(self, key):
        "Returns version specific meta information about a given key"
        return await self._client.call('DEBUG OBJECT', key)

    async def echo(self, value):
        "Echo the string back from the server"
        return await self._client.call('ECHO', value)

    async def flushall(self):
        "Delete all keys in all databases on the current host"
        return await self._client.call('FLUSHALL')

    async def flushdb(self):
        "Delete all keys in the current database"
        return await self._client.call('FLUSHDB')

    async def info(self, section=None):
        """
        Returns a dictionary containing information about the Redis server

        The ``section`` option can be used to select a specific section
        of information

        The section option is not supported by older versions of Redis Server,
        and will generate ResponseError
        """
        if section is None:
            return await self._client.call('INFO')
        else:
            return await self._client.call('INFO', section)

    async def lastsave(self):
        """
        Return a Python datetime object representing the last time the
        Redis database was saved to disk
        """
        return await self._client.call('LASTSAVE')

    async def object(self, infotype, key):
        "Return the encoding, idletime, or refcount about the key"
        return await self._client.call('OBJECT', infotype, key, infotype=infotype)

    async def ping(self):
        "Ping the Redis server"
        return await self._client.call('PING')

    async def save(self):
        """
        Tell the Redis server to save its data to disk,
        blocking until the save is complete
        """
        return await self._client.call('SAVE')

    async def sentinel(self, *args):
        "Redis Sentinel's SENTINEL command."
        warnings.warn(
            DeprecationWarning('Use the individual sentinel_* methods'))

    async def sentinel_get_master_addr_by_name(self, service_name):
        "Returns a (host, port) pair for the given ``service_name``"
        return await self._client.call('SENTINEL GET-MASTER-ADDR-BY-NAME',
                                    service_name)

    async def sentinel_master(self, service_name):
        "Returns a dictionary containing the specified masters state."
        return await self._client.call('SENTINEL MASTER', service_name)

    async def sentinel_masters(self):
        "Returns a list of dictionaries containing each master's state."
        return await self._client.call('SENTINEL MASTERS')

    async def sentinel_monitor(self, name, ip, port, quorum):
        "Add a new master to Sentinel to be monitored"
        return await self._client.call('SENTINEL MONITOR', name, ip, port, quorum)

    async def sentinel_remove(self, name):
        "Remove a master from Sentinel's monitoring"
        return await self._client.call('SENTINEL REMOVE', name)

    async def sentinel_sentinels(self, service_name):
        "Returns a list of sentinels for ``service_name``"
        return await self._client.call('SENTINEL SENTINELS', service_name)

    async def sentinel_set(self, name, option, value):
        "Set Sentinel monitoring parameters for a given master"
        return await self._client.call('SENTINEL SET', name, option, value)

    async def sentinel_slaves(self, service_name):
        "Returns a list of slaves for ``service_name``"
        return await self._client.call('SENTINEL SLAVES', service_name)

    async def shutdown(self):
        "Shutdown the server"
        try:
            self._client.call('SHUTDOWN')
        except ConnectionError:
            # a ConnectionError here is expected
            return
        raise RedisError("SHUTDOWN seems to have failed.")

    async def slaveof(self, host=None, port=None):
        """
        Set the server to be a replicated slave of the instance identified
        by the ``host`` and ``port``. If called without arguments, the
        instance is promoted to a master instead.
        """
        if host is None and port is None:
            return await self._client.call('SLAVEOF', Token('NO'), Token('ONE'))
        return await self._client.call('SLAVEOF', host, port)

    async def slowlog_get(self, num=None):
        """
        Get the entries from the slowlog. If ``num`` is specified, get the
        most recent ``num`` items.
        """
        args = ['SLOWLOG GET']
        if num is not None:
            args.append(num)
        return await self._client.call(*args)

    async def slowlog_len(self):
        "Get the number of items in the slowlog"
        return await self._client.call('SLOWLOG LEN')

    async def slowlog_reset(self):
        "Remove all items in the slowlog"
        return await self._client.call('SLOWLOG RESET')

    async def time(self):
        """
        Returns the server time as a 2-item tuple of ints:
        (seconds since epoch, microseconds into this second).
        """
        return await self._client.call('TIME')

    # BASIC KEY COMMANDS
    async def append(self, key, value):
        """
        Appends the string ``value`` to the value at ``key``. If ``key``
        doesn't already exist, create it with a value of ``value``.
        Returns the new length of the value at ``key``.
        """
        return await self._client.call('APPEND', key, value)

    async def bitcount(self, key, start=None, end=None):
        """
        Returns the count of set bits in the value of ``key``.  Optional
        ``start`` and ``end`` paramaters indicate which bytes to consider
        """
        params = [key]
        if start is not None and end is not None:
            params.append(start)
            params.append(end)
        elif (start is not None and end is None) or \
                (end is not None and start is None):
            raise RedisError("Both start and end must be specified")
        return await self._client.call('BITCOUNT', *params)

    async def bitop(self, operation, dest, *keys):
        """
        Perform a bitwise operation using ``operation`` between ``keys`` and
        store the result in ``dest``.
        """
        return await self._client.call('BITOP', operation, dest, *keys)

    async def bitpos(self, key, bit, start=None, end=None):
        """
        Return the position of the first bit set to 1 or 0 in a string.
        ``start`` and ``end`` difines search range. The range is interpreted
        as a range of bytes and not a range of bits, so start=0 and end=2
        means to look at the first three bytes.
        """
        if bit not in (0, 1):
            raise RedisError('bit must be 0 or 1')
        params = [key, bit]

        start is not None and params.append(start)

        if start is not None and end is not None:
            params.append(end)
        elif start is None and end is not None:
            raise RedisError("start argument is not set, "
                             "when end is specified")
        return await self._client.call('BITPOS', *params)

    async def decr(self, name, amount=1):
        """
        Decrements the value of ``key`` by ``amount``.  If no key exists,
        the value will be initialized as 0 - ``amount``
        """
        return await self._client.call('DECRBY', name, amount)

    async def delete(self, *names):
        "Delete one or more keys specified by ``names``"
        return await self._client.call('DEL', *names)

    async def __delitem__(self, name):
        self.delete(name)

    async def dump(self, name):
        """
        Return a serialized version of the value stored at the specified key.
        If key does not exist a nil bulk reply is return awaited.
        """
        return await self._client.call('DUMP', name)

    async def exists(self, name):
        "Returns a boolean indicating whether key ``name`` exists"
        return await self._client.call('EXISTS', name)
    __contains__ = exists

    async def expire(self, name, time):
        """
        Set an expire flag on key ``name`` for ``time`` seconds. ``time``
        can be represented by an integer or a Python timedelta object.
        """
        if isinstance(time, datetime.timedelta):
            time = time.seconds + time.days * 24 * 3600
        return await self._client.call('EXPIRE', name, time)

    async def expireat(self, name, when):
        """
        Set an expire flag on key ``name``. ``when`` can be represented
        as an integer indicating unix time or a Python datetime object.
        """
        if isinstance(when, datetime.datetime):
            when = int(mod_time.mktime(when.timetuple()))
        return await self._client.call('EXPIREAT', name, when)

    async def get_json(self, name):

        r = await self.get(name)
        if r:
            r = r.decode('utf-8')
            r = loads(r)
        return r

    async def get(self, name):
        """
        Return the value at key ``name``, or None if the key doesn't exist
        """
        return await self._client.call('GET', name)

    async def __getitem__(self, name):
        """
        Return the value at key ``name``, raises a KeyError if the key
        doesn't exist.
        """
        value = self.get(name)
        if value:
            return await value
        raise KeyError(name)

    async def getbit(self, name, offset):
        "Returns a boolean indicating the value of ``offset`` in ``name``"
        return await self._client.call('GETBIT', name, offset)

    async def getrange(self, key, start, end):
        """
        Returns the substring of the string value stored at ``key``,
        determined by the offsets ``start`` and ``end`` (both are inclusive)
        """
        return await self._client.call('GETRANGE', key, start, end)

    async def getset(self, name, value):
        """
        Sets the value at key ``name`` to ``value``
        and return awaits the old value at key ``name`` atomically.
        """
        return await self._client.call('GETSET', name, value)

    async def incr(self, name, amount=1):
        """
        Increments the value of ``key`` by ``amount``.  If no key exists,
        the value will be initialized as ``amount``
        """
        return await self._client.call('INCRBY', name, amount)

    async def incrby(self, name, amount=1):
        """
        Increments the value of ``key`` by ``amount``.  If no key exists,
        the value will be initialized as ``amount``
        """

        # An alias for ``incr()``, because it is already implemented
        # as INCRBY redis command.
        return await self.incr(name, amount)

    async def incrbyfloat(self, name, amount=1.0):
        """
        Increments the value at key ``name`` by floating ``amount``.
        If no key exists, the value will be initialized as ``amount``
        """
        return await self._client.call('INCRBYFLOAT', name, amount)

    async def keys(self, pattern='*'):
        "Returns a list of keys matching ``pattern``"
        return await self._client.call('KEYS', pattern)

    async def mget(self, keys, *args):
        """
        Returns a list of values ordered identically to ``keys``
        """
        args = list_or_args(keys, args)
        return await self._client.call('MGET', *args)

    async def mset(self, *args, **kwargs):
        """
        Sets key/values based on a mapping. Mapping can be supplied as a single
        dictionary argument or as kwargs.
        """
        if args:
            if len(args) != 1 or not isinstance(args[0], dict):
                raise RedisError('MSET requires **kwargs or a single dict arg')
            kwargs.update(args[0])
        items = []
        for pair in iteritems(kwargs):
            items.extend(pair)
        return await self._client.call('MSET', *items)

    async def msetnx(self, *args, **kwargs):
        """
        Sets key/values based on a mapping if none of the keys are already set.
        Mapping can be supplied as a single dictionary argument or as kwargs.
        Returns a boolean indicating if the operation was successful.
        """
        if args:
            if len(args) != 1 or not isinstance(args[0], dict):
                raise RedisError('MSETNX requires **kwargs or a single '
                                 'dict arg')
            kwargs.update(args[0])
        items = []
        for pair in iteritems(kwargs):
            items.extend(pair)
        return await self._client.call('MSETNX', *items)

    async def move(self, name, db):
        "Moves the key ``name`` to a different Redis database ``db``"
        return await self._client.call('MOVE', name, db)

    async def persist(self, name):
        "Removes an expiration on ``name``"
        return await self._client.call('PERSIST', name)

    async def pexpire(self, name, time):
        """
        Set an expire flag on key ``name`` for ``time`` milliseconds.
        ``time`` can be represented by an integer or a Python timedelta
        object.
        """
        if isinstance(time, datetime.timedelta):
            ms = int(time.microseconds / 1000)
            time = (time.seconds + time.days * 24 * 3600) * 1000 + ms
        return await self._client.call('PEXPIRE', name, time)

    async def pexpireat(self, name, when):
        """
        Set an expire flag on key ``name``. ``when`` can be represented
        as an integer representing unix time in milliseconds (unix time * 1000)
        or a Python datetime object.
        """
        if isinstance(when, datetime.datetime):
            ms = int(when.microsecond / 1000)
            when = int(mod_time.mktime(when.timetuple())) * 1000 + ms
        return await self._client.call('PEXPIREAT', name, when)

    async def psetex(self, name, time_ms, value):
        """
        Set the value of key ``name`` to ``value`` that expires in ``time_ms``
        milliseconds. ``time_ms`` can be represented by an integer or a Python
        timedelta object
        """
        if isinstance(time_ms, datetime.timedelta):
            ms = int(time_ms.microseconds / 1000)
            time_ms = (time_ms.seconds + time_ms.days * 24 * 3600) * 1000 + ms
        return await self._client.call('PSETEX', name, time_ms, value)

    async def pttl(self, name):
        "Returns the number of milliseconds until the key ``name`` will expire"
        return await self._client.call('PTTL', name)

    async def randomkey(self):
        "Returns the name of a random key"
        return await self._client.call('RANDOMKEY')

    async def rename(self, src, dst):
        """
        Rename key ``src`` to ``dst``
        """
        return await self._client.call('RENAME', src, dst)

    async def renamenx(self, src, dst):
        "Rename key ``src`` to ``dst`` if ``dst`` doesn't already exist"
        return await self._client.call('RENAMENX', src, dst)

    async def restore(self, name, ttl, value):
        """
        Create a key using the provided serialized value, previously obtained
        using DUMP.
        """
        return await self._client.call('RESTORE', name, ttl, value)

    async def set_json(self, name, value, ex=None, px=None, nx=False, xx=False):
        return await self.set(name,dumps(value,ensure_ascii=False),ex,px,nx,xx)

    async def set(self, name, value, ex=None, px=None, nx=False, xx=False):
        """
        Set the value at key ``name`` to ``value``

        ``ex`` sets an expire flag on key ``name`` for ``ex`` seconds.

        ``px`` sets an expire flag on key ``name`` for ``px`` milliseconds.

        ``nx`` if set to True, set the value at key ``name`` to ``value`` if it
            does not already exist.

        ``xx`` if set to True, set the value at key ``name`` to ``value`` if it
            already exists.
        """
        pieces = [name, value]
        if ex:
            pieces.append('EX')
            if isinstance(ex, datetime.timedelta):
                ex = ex.seconds + ex.days * 24 * 3600
            pieces.append(ex)
        if px:
            pieces.append('PX')
            if isinstance(px, datetime.timedelta):
                ms = int(px.microseconds / 1000)
                px = (px.seconds + px.days * 24 * 3600) * 1000 + ms
            pieces.append(px)

        if nx:
            pieces.append('NX')
        if xx:
            pieces.append('XX')
        return await self._client.call('SET', *pieces)

    async def __setitem__(self, name, value):
        self.set(name, value)

    async def setbit(self, name, offset, value):
        """
        Flag the ``offset`` in ``name`` as ``value``. Returns a boolean
        indicating the previous value of ``offset``.
        """
        value = value and 1 or 0
        return await self._client.call('SETBIT', name, offset, value)

    async def setex(self, name, time, value):
        """
        Set the value of key ``name`` to ``value`` that expires in ``time``
        seconds. ``time`` can be represented by an integer or a Python
        timedelta object.
        """
        if isinstance(time, datetime.timedelta):
            time = time.seconds + time.days * 24 * 3600
        return await self._client.call('SETEX', name, time, value)

    async def setnx(self, name, value):
        "Set the value of key ``name`` to ``value`` if key doesn't exist"
        return await self._client.call('SETNX', name, value)

    async def setrange(self, name, offset, value):
        """
        Overwrite bytes in the value of ``name`` starting at ``offset`` with
        ``value``. If ``offset`` plus the length of ``value`` exceeds the
        length of the original value, the new value will be larger than before.
        If ``offset`` exceeds the length of the original value, null bytes
        will be used to pad between the end of the previous value and the start
        of what's being injected.

        Returns the length of the new string.
        """
        return await self._client.call('SETRANGE', name, offset, value)

    async def strlen(self, name):
        "Return the number of bytes stored in the value of ``name``"
        return await self._client.call('STRLEN', name)

    async def substr(self, name, start, end=-1):
        """
        Return a substring of the string at key ``name``. ``start`` and ``end``
        are 0-based integers specifying the portion of the string to return await.
        """
        return await self._client.call('SUBSTR', name, start, end)

    async def ttl(self, name):
        "Returns the number of seconds until the key ``name`` will expire"
        return await self._client.call('TTL', name)

    async def type(self, name):
        "Returns the type of key ``name``"
        return await self._client.call('TYPE', name)

    async def watch(self, *names):
        """
        Watches the values at keys ``names``, or None if the key doesn't exist
        """
        warnings.warn(DeprecationWarning('Call WATCH from a Pipeline object'))

    async def unwatch(self):
        """
        Unwatches the value at key ``name``, or None of the key doesn't exist
        """
        warnings.warn(
            DeprecationWarning('Call UNWATCH from a Pipeline object'))

    # LIST COMMANDS
    async def blpop(self, keys, timeout=0):
        """
        LPOP a value off of the first non-empty list
        named in the ``keys`` list.

        If none of the lists in ``keys`` has a value to LPOP, then block
        for ``timeout`` seconds, or until a value gets pushed on to one
        of the lists.

        If timeout is 0, then block indefinitely.
        """
        if timeout is None:
            timeout = 0
        if isinstance(keys, basestring):
            keys = [keys]
        else:
            keys = list(keys)
        keys.append(timeout)
        return await self._client.call('BLPOP', *keys)

    async def brpop(self, keys, timeout=0):
        """
        RPOP a value off of the first non-empty list
        named in the ``keys`` list.

        If none of the lists in ``keys`` has a value to LPOP, then block
        for ``timeout`` seconds, or until a value gets pushed on to one
        of the lists.

        If timeout is 0, then block indefinitely.
        """
        if timeout is None:
            timeout = 0
        if isinstance(keys, basestring):
            keys = [keys]
        else:
            keys = list(keys)
        keys.append(timeout)
        return await self._client.call('BRPOP', *keys)

    async def brpoplpush(self, src, dst, timeout=0):
        """
        Pop a value off the tail of ``src``, push it on the head of ``dst``
        and then return await it.

        This command blocks until a value is in ``src`` or until ``timeout``
        seconds elapse, whichever is first. A ``timeout`` value of 0 blocks
        forever.
        """
        if timeout is None:
            timeout = 0
        return await self._client.call('BRPOPLPUSH', src, dst, timeout)

    async def lindex(self, name, index):
        """
        Return the item from list ``name`` at position ``index``

        Negative indexes are supported and will return await an item at the
        end of the list
        """
        return await self._client.call('LINDEX', name, index)

    async def linsert(self, name, where, refvalue, value):
        """
        Insert ``value`` in list ``name`` either immediately before or after
        [``where``] ``refvalue``

        Returns the new length of the list on success or -1 if ``refvalue``
        is not in the list.
        """
        return await self._client.call('LINSERT', name, where, refvalue, value)

    async def llen(self, name):
        "Return the length of the list ``name``"
        return await self._client.call('LLEN', name)

    async def lpop(self, name):
        "Remove and return await the first item of the list ``name``"
        return await self._client.call('LPOP', name)

    async def lpush(self, name, *values):
        "Push ``values`` onto the head of the list ``name``"
        return await self._client.call('LPUSH', name, *values)

    async def lpushx(self, name, value):
        "Push ``value`` onto the head of the list ``name`` if ``name`` exists"
        return await self._client.call('LPUSHX', name, value)

    async def lrange(self, name, start, end):
        """
        Return a slice of the list ``name`` between
        position ``start`` and ``end``

        ``start`` and ``end`` can be negative numbers just like
        Python slicing notation
        """
        return await self._client.call('LRANGE', name, start, end)

    async def lrem(self, name, count, value):
        """
        Remove the first ``count`` occurrences of elements equal to ``value``
        from the list stored at ``name``.

        The count argument influences the operation in the following ways:
            count > 0: Remove elements equal to value moving from head to tail.
            count < 0: Remove elements equal to value moving from tail to head.
            count = 0: Remove all elements equal to value.
        """
        return await self._client.call('LREM', name, count, value)

    async def lset(self, name, index, value):
        "Set ``position`` of list ``name`` to ``value``"
        return await self._client.call('LSET', name, index, value)

    async def ltrim(self, name, start, end):
        """
        Trim the list ``name``, removing all values not within the slice
        between ``start`` and ``end``

        ``start`` and ``end`` can be negative numbers just like
        Python slicing notation
        """
        return await self._client.call('LTRIM', name, start, end)

    async def rpop(self, name):
        "Remove and return await the last item of the list ``name``"
        return await self._client.call('RPOP', name)

    async def rpoplpush(self, src, dst):
        """
        RPOP a value off of the ``src`` list and atomically LPUSH it
        on to the ``dst`` list.  Returns the value.
        """
        return await self._client.call('RPOPLPUSH', src, dst)

    async def rpush(self, name, *values):
        "Push ``values`` onto the tail of the list ``name``"
        return await self._client.call('RPUSH', name, *values)

    async def rpushx(self, name, value):
        "Push ``value`` onto the tail of the list ``name`` if ``name`` exists"
        return await self._client.call('RPUSHX', name, value)

    async def sort(self, name, start=None, num=None, by=None, get=None,
             desc=False, alpha=False, store=None, groups=False):
        """
        Sort and return await the list, set or sorted set at ``name``.

        ``start`` and ``num`` allow for paging through the sorted data

        ``by`` allows using an external key to weight and sort the items.
            Use an "*" to indicate where in the key the item value is located

        ``get`` allows for return awaiting items from external keys rather than the
            sorted data itself.  Use an "*" to indicate where int he key
            the item value is located

        ``desc`` allows for reversing the sort

        ``alpha`` allows for sorting lexicographically rather than numerically

        ``store`` allows for storing the result of the sort into
            the key ``store``

        ``groups`` if set to True and if ``get`` contains at least two
            elements, sort will return await a list of tuples, each containing the
            values fetched from the arguments to ``get``.

        """
        if (start is not None and num is None) or \
                (num is not None and start is None):
            raise RedisError("``start`` and ``num`` must both be specified")

        pieces = [name]
        if by is not None:
            pieces.append(Token('BY'))
            pieces.append(by)
        if start is not None and num is not None:
            pieces.append(Token('LIMIT'))
            pieces.append(start)
            pieces.append(num)
        if get is not None:
            # If get is a string assume we want to get a single value.
            # Otherwise assume it's an interable and we want to get multiple
            # values. We can't just iterate blindly because strings are
            # iterable.
            if isinstance(get, basestring):
                pieces.append(Token('GET'))
                pieces.append(get)
            else:
                for g in get:
                    pieces.append(Token('GET'))
                    pieces.append(g)
        if desc:
            pieces.append(Token('DESC'))
        if alpha:
            pieces.append(Token('ALPHA'))
        if store is not None:
            pieces.append(Token('STORE'))
            pieces.append(store)

        if groups:
            if not get or isinstance(get, basestring) or len(get) < 2:
                raise DataError('when using "groups" the "get" argument '
                                'must be specified and contain at least '
                                'two keys')

        options = {'groups': len(get) if groups else None}
        return await self._client.call('SORT', *pieces, **options)

    # SCAN COMMANDS
    async def scan(self, cursor=0, match=None, count=None):
        """
        Incrementally return await lists of key names. Also return await a cursor
        indicating the scan position.

        ``match`` allows for filtering the keys by pattern

        ``count`` allows for hint the minimum number of return awaits
        """
        pieces = [cursor]
        if match is not None:
            pieces.extend([Token('MATCH'), match])
        if count is not None:
            pieces.extend([Token('COUNT'), count])
        return await self._client.call('SCAN', *pieces)

    #async def scan_iter(self, match=None, count=None):
    #    """
    #    Make an iterator using the SCAN command so that the client doesn't
    #    need to remember the cursor position.

    #    ``match`` allows for filtering the keys by pattern

    #    ``count`` allows for hint the minimum number of return awaits
    #    """
    #    cursor = '0'
    #    while cursor != 0:
    #        cursor, data = self.scan(cursor=cursor, match=match, count=count)
    #        for item in data:
    #            yield item

    async def sscan(self, name, cursor=0, match=None, count=None):
        """
        Incrementally return await lists of elements in a set. Also return await a cursor
        indicating the scan position.

        ``match`` allows for filtering the keys by pattern

        ``count`` allows for hint the minimum number of return awaits
        """
        pieces = [name, cursor]
        if match is not None:
            pieces.extend([Token('MATCH'), match])
        if count is not None:
            pieces.extend([Token('COUNT'), count])
        return await self._client.call('SSCAN', *pieces)

    # async def sscan_iter(self, name, match=None, count=None):
    #     """
    #     Make an iterator using the SSCAN command so that the client doesn't
    #     need to remember the cursor position.

    #     ``match`` allows for filtering the keys by pattern

    #     ``count`` allows for hint the minimum number of return awaits
    #     """
    #     cursor = '0'
    #     while cursor != 0:
    #         cursor, data = self.sscan(name, cursor=cursor,
    #                                   match=match, count=count)
    #         for item in data:
    #             yield item

    async def hscan(self, name, cursor=0, match=None, count=None):
        """
        Incrementally return await key/value slices in a hash. Also return await a cursor
        indicating the scan position.

        ``match`` allows for filtering the keys by pattern

        ``count`` allows for hint the minimum number of return awaits
        """
        pieces = [name, cursor]
        if match is not None:
            pieces.extend([Token('MATCH'), match])
        if count is not None:
            pieces.extend([Token('COUNT'), count])
        return await self._client.call('HSCAN', *pieces)

    # async def hscan_iter(self, name, match=None, count=None):
    #     """
    #     Make an iterator using the HSCAN command so that the client doesn't
    #     need to remember the cursor position.

    #     ``match`` allows for filtering the keys by pattern

    #     ``count`` allows for hint the minimum number of return awaits
    #     """
    #     cursor = '0'
    #     while cursor != 0:
    #         cursor, data = self.hscan(name, cursor=cursor,
    #                                   match=match, count=count)
    #         for item in data.items():
    #             yield item

    async def zscan(self, name, cursor=0, match=None, count=None,
              score_cast_func=float):
        """
        Incrementally return await lists of elements in a sorted set. Also return await a
        cursor indicating the scan position.

        ``match`` allows for filtering the keys by pattern

        ``count`` allows for hint the minimum number of return awaits

        ``score_cast_func`` a callable used to cast the score return await value
        """
        pieces = [name, cursor]
        if match is not None:
            pieces.extend([Token('MATCH'), match])
        if count is not None:
            pieces.extend([Token('COUNT'), count])
        options = {'score_cast_func': score_cast_func}
        return await self._client.call('ZSCAN', *pieces, **options)

    # async def zscan_iter(self, name, match=None, count=None,
    #                score_cast_func=float):
    #     """
    #     Make an iterator using the ZSCAN command so that the client doesn't
    #     need to remember the cursor position.

    #     ``match`` allows for filtering the keys by pattern

    #     ``count`` allows for hint the minimum number of return awaits

    #     ``score_cast_func`` a callable used to cast the score return await value
    #     """
    #     cursor = '0'
    #     while cursor != 0:
    #         cursor, data = self.zscan(name, cursor=cursor, match=match,
    #                                   count=count,
    #                                   score_cast_func=score_cast_func)
    #         for item in data:
    #             yield item

    # SET COMMANDS
    async def sadd(self, name, *values):
        "Add ``value(s)`` to set ``name``"
        return await self._client.call('SADD', name, *values)

    async def scard(self, name):
        "Return the number of elements in set ``name``"
        return await self._client.call('SCARD', name)

    async def sdiff(self, keys, *args):
        "Return the difference of sets specified by ``keys``"
        args = list_or_args(keys, args)
        return await self._client.call('SDIFF', *args)

    async def sdiffstore(self, dest, keys, *args):
        """
        Store the difference of sets specified by ``keys`` into a new
        set named ``dest``.  Returns the number of keys in the new set.
        """
        args = list_or_args(keys, args)
        return await self._client.call('SDIFFSTORE', dest, *args)

    async def sinter(self, keys, *args):
        "Return the intersection of sets specified by ``keys``"
        args = list_or_args(keys, args)
        return await self._client.call('SINTER', *args)

    async def sinterstore(self, dest, keys, *args):
        """
        Store the intersection of sets specified by ``keys`` into a new
        set named ``dest``.  Returns the number of keys in the new set.
        """
        args = list_or_args(keys, args)
        return await self._client.call('SINTERSTORE', dest, *args)

    async def sismember(self, name, value):
        "Return a boolean indicating if ``value`` is a member of set ``name``"
        return await self._client.call('SISMEMBER', name, value)

    async def smembers(self, name):
        "Return all members of the set ``name``"
        return await self._client.call('SMEMBERS', name)

    async def smove(self, src, dst, value):
        "Move ``value`` from set ``src`` to set ``dst`` atomically"
        return await self._client.call('SMOVE', src, dst, value)

    async def spop(self, name):
        "Remove and return await a random member of set ``name``"
        return await self._client.call('SPOP', name)

    async def srandmember(self, name, number=None):
        """
        If ``number`` is None, return awaits a random member of set ``name``.

        If ``number`` is supplied, return awaits a list of ``number`` random
        memebers of set ``name``. Note this is only available when running
        Redis 2.6+.
        """
        args = number and [number] or []
        return await self._client.call('SRANDMEMBER', name, *args)

    async def srem(self, name, *values):
        "Remove ``values`` from set ``name``"
        return await self._client.call('SREM', name, *values)

    async def sunion(self, keys, *args):
        "Return the union of sets specified by ``keys``"
        args = list_or_args(keys, args)
        return await self._client.call('SUNION', *args)

    async def sunionstore(self, dest, keys, *args):
        """
        Store the union of sets specified by ``keys`` into a new
        set named ``dest``.  Returns the number of keys in the new set.
        """
        args = list_or_args(keys, args)
        return await self._client.call('SUNIONSTORE', dest, *args)

    # SORTED SET COMMANDS
    async def zadd(self, name, *args, **kwargs):
        """
        Set any number of score, element-name pairs to the key ``name``. Pairs
        can be specified in two ways:

        As *args, in the form of: score1, name1, score2, name2, ...
        or as **kwargs, in the form of: name1=score1, name2=score2, ...

        The following example would add four values to the 'my-key' key:
        redis.zadd('my-key', 1.1, 'name1', 2.2, 'name2', name3=3.3, name4=4.4)
        """
        pieces = []
        if args:
            if len(args) % 2 != 0:
                raise RedisError("ZADD requires an equal number of "
                                 "values and scores")
            pieces.extend(args)
        for pair in iteritems(kwargs):
            pieces.append(pair[1])
            pieces.append(pair[0])
        return await self._client.call('ZADD', name, *pieces)

    async def zcard(self, name):
        "Return the number of elements in the sorted set ``name``"
        return await self._client.call('ZCARD', name)

    async def zcount(self, name, min, max):
        """
        Returns the number of elements in the sorted set at key ``name`` with
        a score between ``min`` and ``max``.
        """
        return await self._client.call('ZCOUNT', name, min, max)

    async def zincrby(self, name, value, amount=1):
        "Increment the score of ``value`` in sorted set ``name`` by ``amount``"
        return await self._client.call('ZINCRBY', name, amount, value)

    async def zinterstore(self, dest, keys, aggregate=None):
        """
        Intersect multiple sorted sets specified by ``keys`` into
        a new sorted set, ``dest``. Scores in the destination will be
        aggregated based on the ``aggregate``, or SUM if none is provided.
        """
        return await self._zaggregate('ZINTERSTORE', dest, keys, aggregate)

    async def zlexcount(self, name, min, max):
        """
        Return the number of items in the sorted set ``name`` between the
        lexicographical range ``min`` and ``max``.
        """
        return await self._client.call('ZLEXCOUNT', name, min, max)

    async def zrangebylex(self, name, min, max, start=None, num=None):
        """
        Return the lexicographical range of values from sorted set ``name``
        between ``min`` and ``max``.

        If ``start`` and ``num`` are specified, then return await a slice of the
        range.
        """
        if (start is not None and num is None) or \
                (num is not None and start is None):
            raise RedisError("``start`` and ``num`` must both be specified")
        pieces = ['ZRANGEBYLEX', name, min, max]
        if start is not None and num is not None:
            pieces.extend([Token('LIMIT'), start, num])
        return await self._client.call(*pieces)

    async def zrangebyscore(self, name, min, max, start=None, num=None,
                      withscores=False, score_cast_func=float):
        """
        Return a range of values from the sorted set ``name`` with scores
        between ``min`` and ``max``.

        If ``start`` and ``num`` are specified, then return await a slice
        of the range.

        ``withscores`` indicates to return await the scores along with the values.
        The return await type is a list of (value, score) pairs

        `score_cast_func`` a callable used to cast the score return await value
        """
        if (start is not None and num is None) or \
                (num is not None and start is None):
            raise RedisError("``start`` and ``num`` must both be specified")
        pieces = ['ZRANGEBYSCORE', name, min, max]
        if start is not None and num is not None:
            pieces.extend([Token('LIMIT'), start, num])
        if withscores:
            pieces.append(Token('WITHSCORES'))
        options = {
            'withscores': withscores,
            'score_cast_func': score_cast_func
        }
        return await self._client.call(*pieces, **options)

    async def zrank(self, name, value):
        """
        Returns a 0-based value indicating the rank of ``value`` in sorted set
        ``name``
        """
        return await self._client.call('ZRANK', name, value)

    async def zrem(self, name, *values):
        "Remove member ``values`` from sorted set ``name``"
        return await self._client.call('ZREM', name, *values)

    async def zremrangebylex(self, name, min, max):
        """
        Remove all elements in the sorted set ``name`` between the
        lexicographical range specified by ``min`` and ``max``.

        Returns the number of elements removed.
        """
        return await self._client.call('ZREMRANGEBYLEX', name, min, max)

    async def zremrangebyrank(self, name, min, max):
        """
        Remove all elements in the sorted set ``name`` with ranks between
        ``min`` and ``max``. Values are 0-based, ordered from smallest score
        to largest. Values can be negative indicating the highest scores.
        Returns the number of elements removed
        """
        return await self._client.call('ZREMRANGEBYRANK', name, min, max)

    async def zremrangebyscore(self, name, min, max):
        """
        Remove all elements in the sorted set ``name`` with scores
        between ``min`` and ``max``. Returns the number of elements removed.
        """
        return await self._client.call('ZREMRANGEBYSCORE', name, min, max)

    async def zrevrange(self, name, start, end, withscores=False,
                  score_cast_func=float):
        return await self._zrange( name, start, end, withscores, score_cast_func, "ZREVRANGE")

    async def zrange(self, name, start, end, withscores=False, score_cast_func=float):
        return await self._zrange( name, start, end, withscores, score_cast_func, "ZRANGE")

    async def _zrange(self, name, start, end, withscores=False,
                  score_cast_func=float, action="ZREVRANGE"):
        """
        Return a range of values from sorted set ``name`` between
        ``start`` and ``end`` sorted in descending order.

        ``start`` and ``end`` can be negative, indicating the end of the range.

        ``withscores`` indicates to return await the scores along with the values
        The return await type is a list of (value, score) pairs

        ``score_cast_func`` a callable used to cast the score return await value
        """
        pieces = [action, name, start, end]
        if withscores:
            pieces.append('WITHSCORES')
        r = await self._client.call(*pieces)
        if withscores:
            t = []
            result = []
            for pos,i in enumerate(r):
                if pos%2:
                    t.append(score_cast_func(i))
                    result.append(tuple(t))
                    t = []
                else:
                    t.append(i)
            r = result
        return r

    async def zrevrangebyscore(self, name, max, min, start=None, num=None,
                         withscores=False, score_cast_func=float):
        """
        Return a range of values from the sorted set ``name`` with scores
        between ``min`` and ``max`` in descending order.

        If ``start`` and ``num`` are specified, then return await a slice
        of the range.

        ``withscores`` indicates to return await the scores along with the values.
        The return await type is a list of (value, score) pairs

        ``score_cast_func`` a callable used to cast the score return await value
        """
        if (start is not None and num is None) or \
                (num is not None and start is None):
            raise RedisError("``start`` and ``num`` must both be specified")
        pieces = ['ZREVRANGEBYSCORE', name, max, min]
        if start is not None and num is not None:
            pieces.extend([Token('LIMIT'), start, num])
        if withscores:
            pieces.append(Token('WITHSCORES'))
        options = {
            'withscores': withscores,
            'score_cast_func': score_cast_func
        }
        return await self._client.call(*pieces, **options)

    async def zrevrank(self, name, value):
        """
        Returns a 0-based value indicating the descending rank of
        ``value`` in sorted set ``name``
        """
        return await self._client.call('ZREVRANK', name, value)

    async def zscore(self, name, value):
        "Return the score of element ``value`` in sorted set ``name``"
        return await self._client.call('ZSCORE', name, value)

    async def zunionstore(self, dest, keys, aggregate=None):
        """
        Union multiple sorted sets specified by ``keys`` into
        a new sorted set, ``dest``. Scores in the destination will be
        aggregated based on the ``aggregate``, or SUM if none is provided.
        """
        return await self._zaggregate('ZUNIONSTORE', dest, keys, aggregate)

    async def _zaggregate(self, command, dest, keys, aggregate=None):
        pieces = [command, dest, len(keys)]
        if isinstance(keys, dict):
            keys, weights = iterkeys(keys), itervalues(keys)
        else:
            weights = None
        pieces.extend(keys)
        if weights:
            pieces.append(Token('WEIGHTS'))
            pieces.extend(weights)
        if aggregate:
            pieces.append(Token('AGGREGATE'))
            pieces.append(aggregate)
        return await self._client.call(*pieces)

    # HYPERLOGLOG COMMANDS
    async def pfadd(self, name, *values):
        "Adds the specified elements to the specified HyperLogLog."
        return await self._client.call('PFADD', name, *values)

    async def pfcount(self, name):
        """
        Return the approximated cardinality of
        the set observed by the HyperLogLog at key.
        """
        return await self._client.call('PFCOUNT', name)

    async def pfmerge(self, dest, *sources):
        "Merge N different HyperLogLogs into a single one."
        return await self._client.call('PFMERGE', dest, *sources)

    # HASH COMMANDS
    async def hdel(self, name, *keys):
        "Delete ``keys`` from hash ``name``"
        return await self._client.call('HDEL', name, *keys)

    async def hexists(self, name, key):
        "Returns a boolean indicating if ``key`` exists within hash ``name``"
        return await self._client.call('HEXISTS', name, key)

    async def hget(self, name, key):
        "Return the value of ``key`` within the hash ``name``"
        return await self._client.call('HGET', name, key)

    async def hgetall(self, name):
        "Return a Python dict of the hash's name/value pairs"
        return await self._client.call('HGETALL', name)

    async def hincrby(self, name, key, amount=1):
        "Increment the value of ``key`` in hash ``name`` by ``amount``"
        return await self._client.call('HINCRBY', name, key, amount)

    async def hincrbyfloat(self, name, key, amount=1.0):
        """
        Increment the value of ``key`` in hash ``name`` by floating ``amount``
        """
        return await self._client.call('HINCRBYFLOAT', name, key, amount)

    async def hkeys(self, name):
        "Return the list of keys within hash ``name``"
        return await self._client.call('HKEYS', name)

    async def hlen(self, name):
        "Return the number of elements in hash ``name``"
        return await self._client.call('HLEN', name)

    async def hset(self, name, key, value):
        """
        Set ``key`` to ``value`` within hash ``name``
        Returns 1 if HSET created a new field, otherwise 0
        """
        return await self._client.call('HSET', name, key, value)

    async def hsetnx(self, name, key, value):
        """
        Set ``key`` to ``value`` within hash ``name`` if ``key`` does not
        exist.  Returns 1 if HSETNX created a field, otherwise 0.
        """
        return await self._client.call('HSETNX', name, key, value)

    async def hmset(self, name, mapping):
        """
        Set key to value within hash ``name`` for each corresponding
        key and value from the ``mapping`` dict.
        """
        if not mapping:
            raise DataError("'hmset' with 'mapping' of length 0")
        items = []
        for pair in iteritems(mapping):
            items.extend(pair)
        return await self._client.call('HMSET', name, *items)

    async def hmget(self, name, keys, *args):
        "Returns a list of values ordered identically to ``keys``"
        args = list_or_args(keys, args)
        return await self._client.call('HMGET', name, *args)

    async def hvals(self, name):
        "Return the list of values within hash ``name``"
        return await self._client.call('HVALS', name)

    async def publish(self, channel, message):
        """
        Publish ``message`` on ``channel``.
        Returns the number of subscribers the message was delivered to.
        """
        return await self._client.call('PUBLISH', channel, message)

    async def eval(self, script, numkeys, *keys_and_args):
        """
        Execute the Lua ``script``, specifying the ``numkeys`` the script
        will touch and the key names and argument values in ``keys_and_args``.
        Returns the result of the script.

        In practice, use the object return awaited by ``register_script``. This
        function exists purely for Redis API completion.
        """
        return await self._client.call('EVAL', script, numkeys, *keys_and_args)

    async def evalsha(self, sha, numkeys, *keys_and_args):
        """
        Use the ``sha`` to execute a Lua script already registered via EVAL
        or SCRIPT LOAD. Specify the ``numkeys`` the script will touch and the
        key names and argument values in ``keys_and_args``. Returns the result
        of the script.

        In practice, use the object return awaited by ``register_script``. This
        function exists purely for Redis API completion.
        """
        return await self._client.call('EVALSHA', sha, numkeys, *keys_and_args)

    async def script_exists(self, *args):
        """
        Check if a script exists in the script cache by specifying the SHAs of
        each script as ``args``. Returns a list of boolean values indicating if
        if each already script exists in the cache.
        """
        return await self._client.call('SCRIPT EXISTS', *args)

    async def script_flush(self):
        "Flush all scripts from the script cache"
        return await self._client.call('SCRIPT FLUSH')

    async def script_kill(self):
        "Kill the currently executing Lua script"
        return await self._client.call('SCRIPT KILL')

    async def script_load(self, script):
        "Load a Lua ``script`` into the script cache. Returns the SHA."
        return await self._client.call('SCRIPT LOAD', script)

    async def register_script(self, script):
        """
        Register a Lua ``script`` specifying the ``keys`` it will touch.
        Returns a Script object that is callable and hides the complexity of
        deal with scripts, keys, and shas. This is the preferred way to work
        with Lua scripts.
        """
        return await Script(self, script)

interesting but should be another project
don't fit with tornadis goals


fixing broken pathway

fixing broken pathways of endpoints

gmove doesn't seem like this is broken! this is linking currently to our network endpoints page!

gmove, my mentioned link is correct but the pathway in doc is directing to empty file , your sincerely


Static file upload with file renaming doesn't work anymore?

If I am not mistaken the "classic" use case of uploading a single file and renaming on the server side doesn't work anymore.
Looking at the source at ftp.ts:70 the culprit is somewhere here:
      const remoteFile = join(remoteDir, parsedFileSource.base)

If I am not mistaken I think the destination filename needs to be taken into consideration here in the non-dynamic case.

Just confirmed that the "classic" way work with the v1 tag.


Member card links to the same member after pressing the back button and trying to view another member's profile

To produce the bug: Go to the members' directory, click on any member's profile (Member X) and then go back to the directory. Now try to open another member's profile (Member Y), the website will lead you to Member X's profile instead.
Kudos to @mahasneh

@itsmohmans please follow up on this task


Unrecognized manifest key 'arc_metadata

So I have been reading through all the issue reports and heard that "Unrecognized manifest key 'arc_metadata" isn't an issue. I'm trying to get DJI GO to work. I have the file converted and everything is working but the app doesn't load after about 5-7mins of waiting. I was also wondering if it was an issue with GPS, I don't think the app using it but can it could cause an effect...
Can anyone explain why? Or help me?
Running chrome os 32/bit acer intel 5th gen

It seems like chrome doesn't recognize this metadata. The arc_metadata is for ARC not for chrome

I have the same problem for every app I install...
After starting even waiting for more than 30 minutes these don't works...
The warning is always the same:
Unrecognized manifest key 'arc_metadata'.
ARC Window Popup:<PHONE_NUMBER>625ms
ARC appWindow Init: 1.655029296875ms
ARC JS Init: 5.11083984375ms
Compositor is disabled
ARC HTML5 FS: Request FileSystem: 10.212890625ms
File system initialization 1/2
ARC HTML5 FS: prefetchFileMetadata_: 20.498046875ms
ChildPlugin backgroundpage:0:umareporter(so_executable) Run: 2003.126220703125ms
retry to spawn with timeout 4sec.
ChildPlugin backgroundpage:0:umareporter(so_executable) Run: 4005.087646484375ms
timeout to spawn ChildPlugin process: umareporter(so_executable), umareporter bool ArcRuntime.DexoptInterrupted false
retry to spawn with timeout 8sec.
ChildPlugin backgroundpage:0:umareporter(so_executable) Run: 8004.23193359375ms
retry to spawn with timeout 16sec.

The highlighted code lines are (instagram app in this case):
	"arc_metadata": {
		"enableAdb": true,
		"apkList": [
			"Instagram_10.25.1_apk-dl.com.apk"
		],
		"enableExternalDirectory": false,
		"formFactor": "tablet",
		"name": "Instagram_10.25.1_apk",
		"orientation": "landscape",
		"packageName": "Instagram_10.25.1_apk",
		"useGoogleContactsSyncAdapter": false,
		"usePlayServices": [
			"gcm",
			"plus"
		]
	},

I am on Debian testing with Chromium (Vers. 59.0.3071.86 64bit), Twerk (vers. 1.4.2) and ARChon Custom Runtime (vers. 1.2).
How can I solve this problem?

I'm running some apps with ARCWelder
Twerk didn't work for me (Tested on ArchLinux with Chrome 59.0.3071.109 (AUR))
@winnipeg23 @Brando-code


domain length validation and return early as possible

Thanks for your contribution @ppkgtmm

Thanks for your contribution @ppkgtmm


Dirty fix so the docs can build (hopefully)

For some weird reason, python setup.py install thinks aiohttp-xmlrp is
the same module as aiohttp. So instead of install aiohttp-xmlrp first,
we'll install aiohttp first. Hopefully this allows the docs to build.

th


Wgsl part 2

Writing as a separate PR to make review easier. In this PR I want to focus on ironing out some details wrt the new shaders.
After this I'll port the other shaders.

Ready for review (this PR merges into the wgsl branch).

LGTM!


Documentation missing from tarball

With the move to the documentation being pulled in as a submodule, tag tarballs from GitHub no longer includes documentation. If the submodule was some kind of dependency - another library or project - it would make sense to not be included but the project's own documentation is missing.
I recommend uploading a release tarball that includes a copy of the documentation from the appropriate submodule commit.

Thanks for reporting. I would however argue that the documentation is merely for online viewing on GitHub pages at http://gflags.github.io/gflags/. It's only "linked" as submodule

to not have to switch branches
to have a reference to the orphan gh-pages branch
to not have copies in master and gh-pages that need to be kept in sync
to have a reference to the revision of the docs at a certain release
for those browsing the repository files online

I see no actual need to include these files in a source release archive, i.e., to have it available offline. There is also no installation rule for these files. They are used for creating a binary release with CPack, however, but I assume the person who wants to run CPack to clone the Git repository (possibly with --depth=1) instead of downloading a tar ball.

I've just added the link to the online documentation to the README file.

There are many environments that do not have unfettered Internet access which make referencing a web page or running git pull challenging or sometimes impossible. Including documentation for offline use is significant in my opinion. It would be good for distribution (since the projects' Github page is the canonical source) to include it in the tarball rather than relying on 3rd parties to essentially repack it.

Your submodule breaks other projects that use gflags as a submodule. For example, if I try to clone gflags recursively it hangs:

git clone --recursive git@github.com:gflags/gflags.git
Cloning into 'gflags'...
remote: Counting objects: 2143, done.
remote: Total 2143 (delta 0), reused 0 (delta 0), pack-reused 2143
Receiving objects: 100% (2143/2143), 1.43 MiB | 540.00 KiB/s, done.
Resolving deltas: 100% (1236/1236), done.
Checking connectivity... done.
Submodule 'doc' (https://github.com/gflags/gflags.git) registered for path 'doc'
Cloning into 'doc'... (hang)

This is a problem because I would like to include gflags as a submodule of one of my projects, which means that a recursive clone hangs at your documentation. It seems like your submodule introduces a circular dependency by trying to checkout the same repo with the gh-pages branch. It seems kind of hosed...

@tuxfan Not "hosed" at all it seems...
as12312@cotopaxi:/Users/as12312/Desktop
> git clone --recursive git@github.com:gflags/gflags.git
Cloning into 'gflags'...
remote: Counting objects: 2143, done.
remote: Total 2143 (delta 0), reused 0 (delta 0), pack-reused 2143
Receiving objects: 100% (2143/2143), 1.43 MiB | 968.00 KiB/s, done.
Resolving deltas: 100% (1236/1236), done.
Checking connectivity... done.
Submodule 'doc' (https://github.com/gflags/gflags.git) registered for path 'doc'
Cloning into '/Users/as12312/Desktop/gflags/doc'...
Submodule path 'doc': checked out '971dd2a4fadac9cdab174c523c22df79efd63aa5'

as12312@cotopaxi:/Users/as12312/Desktop
> git --version
git version 2.9.3 (Apple Git-75)

There are many environments that do not have unfettered Internet access which make referencing a web page or running git pull challenging or sometimes impossible. Including documentation for offline use is significant in my opinion. It would be good for distribution (since the projects' Github page is the canonical source) to include it in the tarball rather than relying on 3rd parties to essentially repack it.

It's been a while, but IMHO gflags is a low-level software library. I cannot imagine any software developer to write code using this library in an environment where they could not have downloaded the index.html of the documentation beforehand if they needed it offline (which git clone and git submodule update --init do). There is no "manual" that comes with this library. The real documentation is the source code as the main stakeholders are C++ developers which should be pretty comfortable reading source code (i.e., the comments in gflags.h).


Filter empty geometries in STRtree to avoid segfaults. Fixes #345.

This PR fixes the issue with empty geometries and STRtree in #345.
I think I've done the right thing aiming this at the maint-1.5 branch but correct me if I've done it wrong?

Perfect. Thanks, @snorfalorpagus!


laravel5.4,php7,centos7

i got a problem, when i try to connect. it has this error:
 Pheanstalk\Exception\ConnectionException: Socket error 0:  (connecting to <IP_ADDRESS>:11300) in /www/xxx/vendor/pda/pheanstalk/src/Socket/NativeSocket.php:45
But i run command telnet  <IP_ADDRESS> 11300  is ok.please help me

i already used in php 7 centos 7 and laravel 5.2 5.5 and 5.6 ant its ok with all of them.
perhaps you have problem with server package not this package

This is not a bug report.


Is auto-editor able to strip silence without recompressing the video?

I'm brand new to auto-editor ... trying version 21w11a on M1 Mac, using this command-line:
auto-editor src.mp4 exportMediaOps -vcodec copy -acodec copy motionOps -mcut 200
I would expect auto-editor to be able to strip silence from src.mp4 without recompression. I understand that ffmpeg won't allow splits on non-keyframes, so I would expect a few seconds of slippage with each cut. But nevertheless there should still be a valid output file that is not recompressed.
Instead, src_ALTERED.mp4 is written with 0 bytes after about 12 minutes of processing (for a 3.5 GB input file), which I assume is an attempt at recompressing the video. I'm not sure if this is a bug or expected behaviour ... is auto-editor able to work in this way or am I barking up the wrong tree?
Thanks!

In case auto-editor can't do this directly I've created a ruby script which uses auto-editor's --export-as-json option to identify chunks of silence, then takes over and uses ffmpeg directly to losslessly cut out and reassemble the non-silent segments.
Source here: https://gist.github.com/genegoykhman/05f3d83acf72b79d86d93bace4e65c8e

This makes video processing so much faster! the only bug that I can see is the wrong video length on the video player.
I think this should be implemented in the auto editor

There are a lot of tradeoffs for lossless editing. Firstly, you can't speed up or slow down video or audio anymore. Clips must either be at normal speed or cut off completely. Secondly, it makes the cuts inaccurate, since they need to be tied to keyframes, which is not ideal for professional creators.
These reasons are why I have not implemented this feature. However, it could be implemented as its own subcommand, since it can add only options that support lossless editing's limitations.
This issue will be closed since the question has been answered and this issue is very old.


Patch/feature/gen system design document

Merged latest PR changes
Corrected plugin structure for proper package installation
Incorporated new template_engine functionality

All tests work pass and aac gen-design-doc system-design-doc.md.jinja2 model/flow/System.yaml test generates content as expected.

I scanned through the updates and things look good, but I'm a bit confused how this and PR #74 are related.  It also looks like content from the PR I merged last night is showing here as new.  I'm going to approve my review but leave it up to you guys to merge these into main.


No URL Scheme for Sileo & Zebra

Sileo & Zebra have no URL scheme, not sure if this is on purpose or not.

iPhone 13 Pro, 16.4, latest bootstrap (as of writing this)

This is known and mentioned in #2


Binary size

I've found that the binary generated by pyjac through cython is quite large for bigger mechanisms (pushing towards 1000s of species). See data below, from 11 to 654 species. The plot shows quadratic scaling with species count and somewhere between linear and quadratic with reaction count, and that pyjac's binary will cross 1 GB somewhere around ~1000 species or ~10000 reactions.
Are there any plans to work on reducing binary size, notably for really, really big mechanisms above 1000 species? My bet is that the only way through this could be fine-tuning the auto-generated code more or reducing what gets auto-generated (a 'middle ground' that uses loops and conditionals for some types of calculations while auto-generating unrolled code for others).

Mechanism
No. species
No. reactions
Binary size (MB)

Hydrogen, Burke et al.
11
27
0.2

Biodiesel, Luo et al.
115
659
10

Heptane, Mehl et al.
654
4846
271

FYI, it definitely looks like the dependency is stronger on reaction count than species count, which makes sense. Below are two similar mechanisms, with nearly identical species counts, but a factor of 1.7 between the reaction counts, which happens to match the factor of 1.7 between the binary sizes.

Mechanism
No. species
No. reactions
Binary size (MB)

Biodiesel, Luo et al. low-T
115
659
10

Biodiesel, Luo et al. high-T
118
1148
17

I compiled a 1034-species mechanism (PRF, Curran et al. from the Livermore website, with 7558 reactions) and the binary is 656 MB. Fun fact: the generated Jacobian was 30.6 million lines of code, which were split into 807 files for compilation!
I wonder how compiler-dependent this might be. These binaries are from gcc on my mac (latest OS, clang, etc.).

@michael-a-hansen you are absolutely correct that the size of the generated Jacobian library is massive --
to the point where we had to include code that would split the Jacobian evaluation into separate files so the compilers wouldn't break during compilation (gcc 4.4.7 used to segfault for big enough mechanisms).
The new version of pyJac will:
a) be sparse, and won't have to update (nearly) every single species for every reaction
b) won't be hard coded (and therefore will be much smaller)
As you've noticed the generated Jacobians get huge for large mechanisms as a result of these two reasons.  Is the size of the binary an issue other than the sheer ridiculousness of it?
Sidenote, I'm just about to begin validation testing so I should be able to give you a ballpark binary size for similar mechanisms in a day or two

Also, you might look into the -Os flag which tells GCC to try and minimize the size of the developed object, it would need to be added to libgen.py in a from source build

I eagerly await the new version! Let me know if I can help out in testing.
What do you mean by "won't be hard coded"?

@michael-a-hansen it will look much more like a loop / conditional based code (with options to unroll).  This direction was chosen to avoid the huge filesizes, as well as to enable opencl vectorization

Terrific! I'm very interested to see how various degrees of unrolling impact performance and memory across mechanism size. Thanks for the good work.


Feature/add portuguese

i am unable to see the language drop down in the menu

@Ran73Cohen
once #1514 is ready, please merge this language which enable english and portuguese options.

Continue in #1551


fix for API changes (FSharpDaemonBehaviour, namespaces)

@DedSec256 Could you move the namespaces change to another PR, please? The initial commit contained some logic changes, it'd be good to not hide it in tens of opens changes.


Abort 'port test' early if test.run is set to no

This will avoid installing dependencies if tests is not enabled.
Closes: https://trac.macports.org/ticket/45010

Hm, it seems that this actually breaks a couple of tests. Please take a look.

Yea I missed that.... strange a lot of tests under tests/test fail even though they don't set test.run.

When running those tests, the target is "test" and they don't have test.run in the Portfiles so it fails.  I wonder since the tests Portfiles all have 'test {}' in them, that this is why these fail.

I'm not sure this is the best or even correct way to fix this.

Before I work on this again, does anything object or have suggesting for a better way to handle the test portion? It does work as-is, just seems hackish.

Shouldn't be needed any more after ddc2655.


Node_modules not caching when deploying on dokku

Describe the bug
Hey, I'm using dokku to deploy my nestjs app. It seems that my node modules are never cached, can anyone help me figure out why?
I see that it says pnpm (nothing to cache) and dont understand why isnt there anything to cache?
Here's the log:
https://gist.github.com/rohanrajpal/bc7cc3b14b3f7f3866826b0aea84f004
To Reproduce
Steps to reproduce the behavior:

Setup dokku.com on any ec2 instance
Deploy a nestjs app setup with pnpm
Node modules are never cached

Versions (please complete the following information):

Heroku Stack: gliderlabs/herokuish:latest-22
Node Version: 18.12.1
NPM or Yarn Version: pnpm - 7.16.1

Additional context
The build log shared above has a lot more details
My best guess is that the path of caching is set incorrectly? Happy to make a PR if someone can point me in the right direction to fix this

On a little bit of investigation, I see that we are skipping the caching part after the build?
https://github.com/unfold/heroku-buildpack-pnpm/blob/main/bin/compile#L346

Alright, so the cache is indeed set. So am I right in assuming that caching is happening properly in this buildpack.
Node modules are installedin 38 seconds anyway, I guess that's good enough?
https://github.com/unfold/heroku-buildpack-pnpm/blob/main/bin/compile#L227

Yea, the text is wrong. Should be nothing extra to cache. It is handled by the default cache.


Multiplayer + 3rd Person Controller

Working:

Many players can connect together
Functional 3rd person controller (camera + player input)
Prototype Scene
Prototype Player Model + Animations
UI to Host a session or connect as a Client

Multiplayer TODO:

Sometimes the client/server get out of sync because movement if animation-based (Ex: If the player controller collides with an obstacle on the client but the server deems it's able to walk, it will just keep moving on the server). We need a way to resync (Send position from server to client)
Connexion looks a little laggy (small teleportations everywhere). More interpolation would be nice.

3rd Person TODO:

Add more controls (jump, crouch, etc.)
Polish the animations to make the movement feel smooth
Make camera lead the player movement slightly to improve controller feel

Probably worth exploring this library to sync Animations and positions as it seems more robust than the built-in one:
https://github.com/emotitron/Simple-Network-Sync
Example:
https://www.youtube.com/watch?v=5yslaRRaE8M


Path to mspdbcmf.exe could not be found

Describe the bug
When I run dotnet publish to build a Maui-Application, I get the following warning:
C:\Users\runneradmin\.nuget\packages\microsoft.windowsappsdk\1.1.3\buildTransitive\Microsoft.Build.Msix.Packaging.targets(341,5): warning : Path to `mspdbcmf.exe` could not be found. A symbols package will not be generated. Review https://aka.ms/windowsappsdkdocs and ensure that all prerequisites for Windows App SDK development have been installed. [D:\a\Maui-Issue-9879\Maui-Issue-9879\TestIssue9879\MauiApplication\MauiApplication.csproj]

This happens locally in my PowerShell and on GitHub Actions. The second option can be seen here:
x86 run
x64 run
Steps to reproduce the bug

Create a Maui Application from the template
Run dotnet publish in your shell (happens with any Windows-RID-Options)
You shall see the warning

Expected behavior
No warning. I don't know if the mspdbcmf.exe is important or not here.
Screenshots
No response
NuGet package version
No response
Packaging type
Packaged (MSIX)
Windows version
Windows 10 version 21H2 (19044, November 2021 Update)
IDE
Visual Studio 2022-preview
Additional context
No response

I'm having this issue as well. Will update if I figure it out

It also happens on Azure DevOps Pipelines.
Where is this exe? How do I get it?

This issue means that MAUI apps can't publish debug symbols in their package, even those the publish UI suggests so.

Not sure how, but this is working locally, but the same thing doesn't work on our build agents. ;(

same issue for WinUI 3

It started to occur for me when I changed NuGet packages destination (by overwriting NUGET_PACKAGES environment variable) to another partition (C:\Users\user.nuget\packages to B:\NuGet\packages). I needed to roll back to the user folder (default) in order to have the packages building working. I haven't checked if it would work on the same partition in another folder.

I have simple MAUI Blazor project and publishing with CLI per the instructions below causes this issue with -c Debug.
https://learn.microsoft.com/en-us/dotnet/maui/windows/deployment/publish-cli

I think a workaround is to install the C++ workload in VS. I think it was the C++ workload, but may have been another.

Can confirm that this made the warning disappear

@mattleibow @tipa Could you tell me what exact individual components you have selected? I have the below ones and the warning keeps appearing:

C++ core desktop features
MSVC v143 - VS 2022 C++ x64/x86 build tools (Latest)
C++ CMake tools for Windows
Windows 11 SDK (10.0.22621.0)
Windows 10 SDK (10.0.19041.0)

Closing, as problem appears to have been a missing workload (not a WinAppSDK issue)

@MichalMucek  I think you need MSVC v143 - VS 2022 C++ x64/x86 build tools (Latest) & also  MSVC v143 - VS 2022 C++ ARM64/ARM64EC build tools (Latest) - at least that's what's fixed it when I just had this issue reappear when setting up a new dev environment

@Scottj1s is there any hope/plans for a world in which the CLI is used with say VSCode and no full VS? VS is great and all, but if we are doing dotnet dev, we should not need vs installed.
Is there maybe some standalone tool to install? Would it be possible for the required parts to be in a nuget like the BuildTools one? It does not have to be in that one, but maybe there can be a "C++ build tools" nuget that we could optionally install?

This issue still happens for me.
With .NET 8/9 (8.0.400, 9.0.100), creating new MAUI app and then publishing with dotnet publish.
C:\Users\<user>\.nuget\packages\microsoft.windowsappsdk\1.5.240802000\buildTransitive\Microsoft.Build.Msix.Packaging.targets(354,5): warning : Path to `mspdbcmf.exe` could not be found. A symbols package will not be generated. Review https://aka.ms/windowsappsdkdocs and ensure that all prerequisites for Windows App SDK development have been installed. [pathToProject.csproj::TargetFramework=net8.0-windows10.0.22621.0]


HTML

HTML
User Story
As a bootcamp student
I want the prework notes to be structured on a webpage
so that I can easily find and read information
Acceptance Criteria
GIVEN a Prework Study Guide website
WHEN I visit the website in my browser
THEN I see four boxes titled HTML, CSS, Git, and JavasScript with associated notes listed

done


Some things are broken?

Vanilla: 2.1.8p2.
Bootstrap:  2.4.0
Did the full install with nodejs, bower, npm etc.  Worked without errors.
When I install I use the default Bootstrap theme and these problems are apparent:

Sign In button freezes the page.  Requires refresh.
Delete a post does not work (same as above, freezes page)

Anyone else seeing these problems?

Sounds like you have an JS conflict with another plugin. First step in debugging the issue would be checking your browser console for errors.

Hi!
Same to me... maybe a problem with jQuery 1.7.2? That's what my Vanilla uses!
Thank you!

My comment above still applies; you'll need to check your browser console for errors.

I can confirm that things are broken with 2.4.0 and vanilla 2.1.8p2. My width on the front page is now 10.000px . Investigating that right now.
I also got jquery error about version mismatch (vanilla wants 1.9.2) so i replaced custom.js with 2014 version (from july?). And no more jquery error in browser console.

I can confirm there is 10000px width in every .css.
:~/Desktop/vanilla-bootstrap-2.4.0$ grep -roP ".{0,30}width:10000" .
./design/custom_darkly.css:Meta,.BlockColumn .BlockTitle{width:10000
./design/custom_yeti.css:Meta,.BlockColumn .BlockTitle{width:10000
./design/custom_flatly.css:Meta,.BlockColumn .BlockTitle{width:10000
and so on. Hope this is useful info and that i'm not spamming :)

I'm investigating. Could you open up a new issue? The width bug is not JS related.

I´ve got the same problem, when I click on the sign button, the page freezes. Nice work btw!
Vanilla: 2.1.8p2.
Bootstrap: 2.4.0

Found the cause of the JS issue: A check was added in Bootstrap 3.3 to ensure that jQuery 1.9.1 and above is used (twbs/bootstrap#14852). Since Vanilla 2.1 still uses jQuery 1.7.2 this check will fail and JS execution will choke.
Since none of the Bootstrap JS components are used I'll simply remove them which should solve the issue.

Let me know if it works now!

Thanks allot, now it works! You´re awesome :)


[WIP] Remove support for node 16, add support for node 22

WHY are these changes introduced?
Fixes #0000

WHAT is this pull request doing?

Type of change

[ ] Patch: Bug (non-breaking change which fixes an issue)
[ ] Minor: New feature (non-breaking change which adds functionality)
[ ] Major: Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist

[ ] I have used yarn changeset to create a draft changelog entry (do NOT update the CHANGELOG.md files manually)
[ ] I have added/updated tests for this change
[ ] I have documented new APIs/updated the documentation for modified APIs (for public APIs)

Looks like this is the issue causing our tests to fail.
https://github.com/microsoft/TypeScript/issues/52331


Update some tutorials to use new PyTorch semantics

As per #930, updates the following examples:

vae/vae_comparison
bayesian_regression

@neerajprad Related to this pull request, I observed that there are still some type_as statements in distributions module. They are minor so we can incorporate the change in any new pull request. :D


LCD Display overlaps

I am trying to set up raspiblitz, but when I insert the flashed SD card and power the pi on, the display seems to be overlapping and is unreadable and unusable. I have tried to rotate the display using "display_rotate=3", but it remains unreadable.

I can't seem to find a solution, so any help would be appreciated.

Never used this or seen else with this display, but try rotating with 90 degrees, ie. set display_rotate=2
Also check if this helps: https://github.com/rootzoll/raspiblitz/issues/2908

I tried both suggestions and unfortunately neither one of them worked.

I haven't got this display to test, but could help if you share the exact model if someone else tries it.
How does your display look now after rotating 90 degrees?


IPFS submarining

IPFS Submarining
Sequential token minting has vulnerabilities.
One way to counteract the side effects of vulnerabilities is obfuscation of token and metadata information through obscurity. This can be done through IPFS Submarining. The general idea behind IPFS is uploading a folder of content, determining the hash of the content that becomes the key to access that data. If the content is generated ahead of time, the content hash can be predetermined. Then individual metadata files can be revealed at a later point.
From a user's perspective, it's best to reveal that information immediately after minting. From the creator's standpoint, the information is inaccessible until after minting.
image folder cid created with:

ipfs add -Qr --only-hash {folder-name}
ipfs add -Qr --only-hash {folder-name} | ipfs cid base32

individual files:

ipfs add -q --only-hash {file-name}
ipfs add -q --only-hash {file-name} | ipfs cid base32

Concerns:

high once files are uploaded to ipfs, they are visible from their CID. Ex: if creator checks files on testnet, those files can no longer be submarined and are also accessible and visible on mainnet.
high tools and number of steps increases
high Greater complexity can make the process harder to test, debug, and potentially cause immutable errors in production
medium - token minting is still sequential, which is still vulnerable
low Creator could launch a collection and never reveal the nft's
should it be a service stargaze creates, provides, and maintains?
should we use a paid submarine service?

References:
https://www.pinata.cloud/blog/introducing-submarining-what-it-is-why-you-need-it
https://www.submarine.me
https://github.com/kf106/ipfs-submarine

closing in favor of update and lock


Fix small typo for WriteToStorage example

Replaced name by key

Also please rebase with HAv2.

Fixed here: eada29eea32aa407862d067aa814bc95cb34d660


New cards to test

Would like to see:

Traverse the Ulvenwald

A bit expensive for Cheapo Supremo ($30 budget vintage), but still might be nice to see how well it does.

Elvish Spirit Guide

Now with the new reprints in Dominaria Remastered, it's finally Cheapo-viable!

Sol Ring

Implemented, but not tested

Anything else...?

ESG and Sol Ring are both added, along with a NUMBER of additional cards.
We don't have a lot of self-mill, and not many ways to get lands / artifacts into the graveyard, so unfortunately Traverse the Ulvenwald is unlikely to be a worthwhile inclusion. Lots of other new cards are implemented now though!


[Event Request change] table 37 "Sales Line" - OnCalcVATAmountLinesOnBeforeAssignAmtToHandle

In a previous request we asked for event OnCalcVATAmountLinesOnBeforeAssignAmtToHandle in procedure CalcVATAmountLines but the call was not placed in the three places requested. We are missing it in the QtyType::General case statement. QtyType::Shipping and QtyType::Invoicing are perfect:
                    case QtyType of
                        QtyType::General:
                            begin
                                VATAmountLine.Quantity += "Quantity (Base)";
                                OnCalcVATAmountLinesOnBeforeAssignAmtToHandle(SalesHeader, SalesLine, VATAmountLine, IncludePrepayments, QtyType, QtyToHandle, AmtToHandle); //A108F0084.Event18.05.n
                                VATAmountLine.SumLine(
                                  "Line Amount", "Inv. Discount Amount", "VAT Difference", "Allow Invoice Disc.", "Prepayment Line");
                            end;

Thanks for reporting this. We agree, and we’ll publish a fix asap, either in an update for the current version or in the next major release. Please do not reply to this, as we do not monitor closed issues. If you have follow-up questions or requests, please create a new issue where you reference this one.


merge develop into master

What type of PR is this?
/kind feature
What this PR does / why we need it:
Special notes for your reviewer:
Reivewers List:
@liuhaoyang
Does this PR introduce a user-facing change?

Additional documentation usage docs, etc.:

/approve


Accessibility settings page

References

Requires REST PR: Accessibility settings metadata field 9964
8_x backport: #3614
7_x backport: #3615

Fixes point 3 of #1191: "Content visually appears and disappears with no ability to adjust timing."
Description
This PR adds the 'Accessibility settings' page where a user can configure accessibility settings.  This page can be found either through the 'Accessibility settings' link in the footer, or through the link on the profile page. The settings are stored in a cookie when the user is not authorized and are stored in a metadata field (see backend PR) when the user is authenticated.
Instructions for Reviewers
Access the page through one of the mentioned links, or directly at /info/accessibility. Currently only two settings are available: notification time-out and live region time-out. Functionality of the notification time-out is the easiest to verify. Set a new value and click the 'Save accessibility settings` button. A notification will appear mentioning whether the changes are saved locally (cookie) or on the user profile (metadata) and this notification will stay as long as configured.
Live region time-out can be verified by making the live region visible. (see #3337)
List of changes in this PR:

Adds the accessibility-settings component and service
Adds links to the 'Accessibility settings' page to the footer and profile page.
Notifications added to the notifications-board will have the user-configured time-out (if set by the user).
Messages added to the live-region will have the user-configured time-out (if set by the user).

Checklist

[x] My PR is created against the main branch of code (unless it is a backport or is fixing an issue specific to an older branch).
[x] My PR is small in size (e.g. less than 1,000 lines of code, not including comments & specs/tests), or I have provided reasons as to why that's not possible.
[x] My PR passes ESLint validation using npm run lint
[x] My PR doesn't introduce circular dependencies (verified via npm run check-circ-deps)
[x] My PR includes TypeDoc comments for all new (or modified) public methods and classes. It also includes TypeDoc for large or complex private methods.
[x] My PR passes all specs/tests and includes new/updated specs or tests based on the Code Testing Guide.
[x] My PR aligns with Accessibility guidelines if it makes changes to the user interface.
[x] My PR uses i18n (internationalization) keys instead of hardcoded English text, to allow for translations.
[x] My PR includes details on how to test it. I've provided clear instructions to reviewers on how to successfully test this fix or feature.
[x] If my PR includes new libraries/dependencies (in package.json), I've made sure their licenses align with the DSpace BSD License based on the Licensing of Contributions documentation.
[x] If my PR includes new features or configurations, I've provided basic technical documentation in the PR itself.
[x] If my PR fixes an issue ticket, I've linked them together.

Hi @AAwouters. Thank you for this PR. Overall, it looks really good. I tested it locally, and I'm having a problem with the Accessibility Settings form, both as an anonymous user and when I'm logged in. It happens on Firefox and Chrome.
When I change the "Hide notifications automatically" setting to off and click "Save accessibility settings" the green "Successfully saved settings..." notification doesn't go away until I click on the 'X'. That isn't a big problem, but once I change that setting then I can never change it back to on. Every time I do the setting returns to off, even though the green "Successfully saved settings" notification appears.
However, I am able to change the Notification and Live region timeouts successfully. The green "Successfully saved settings..." notification appears and disappears on its own. Also, clicking on "Reset accessibility settings" works well. And the green "Successfully reset settings" notification goes away after a few seconds. So I think the problem is only with the option to hide notifications automatically.


Allow a customized 'default' status/presence for a proxy

Current behavior: All bots, upon a boot or a reboot, default to either sync or online, and any custom status they had set is wiped.
Proposed behavior: A config setting for setting a bot's default presence and status on startup for the bot. This would be especially nice to be easily configurable via systemd unit. This is useful for systems with large amounts of proxies, to prevent needing to manually run high amounts of !presence commands every time there's a reboot or network disconnection.

implemented in 6f98829002ebbac0e47a4771b36181596bf9a23b


Token Expiration

Using this awesome library and ember-simple-auth-auth0, I've got my ember apps talking to Auth0 and talking securely to my backend API. However, when the token expires, my backend API detects that and replies with a 401. ember-simple-auth should invalidate the session and then I would need to re-login or renew the session. Instead, I get two errors from Ember: Error while processing route (model failed) and The adapter operation was aborted.
Any suggestions on what I am doing wrong?
I'm using the ApplicationRouteMixin and DataAdapterMixin and using Ember Data to query the server.
Relevant versions:

ember-cli: 2.13.2
ember-simple-auth: 1.2.2
ember-simple-auth-auth0: 3.0.1
auth0.js: 8.6.0
auth0-lock: 10.15.1

Can you provide a stack trace? Is the 401 response the only response you're seeing or are there other responses as well?

Thanks for responding @marcoow. I lost track of this because I was working on other projects. I was able to return to this problem late last week and today. Fortunately, I finally figured it out. Turns out that my Web API backend wasn't sending the proper CORS headers back with the 401 response. Thus ember-simple-auth couldn't process it because the browser errored out underneath it.


ConnectivityScope capability and configuration networks

It specifies whether the network driver can
provide containers connectivity across hosts.
As of now, the data scope of the driver was
being overloaded with this notion.
The driver scope information is still valid
and it defines whether the data allocation
of the network resources can be done globally
or only locally.
With the scope network option, user can now
force a network as swarm scoped
regardless of the driver data scope.
In case the network is configured as swarm scoped,
and the network driver is multihost capable,
a network DB instance will be launched for it.

Support configuration networks:

They are configuration-only networks which
can be used to supply the configuration
when creating regular networks.
They do not get allocated and do net get plumbed.
Drivers do not get to know about them.
They can be removed, once no other network is
using them.
When user creates a network specifying a
configuration network for the config, no
other network specific configuration field
is are accepted. User can only specify
network operator fields (attachable, internal,...)
They do not need to have a driver field, that
field gets actually reset upon creation.

@aboch multihost should be a driver capability and not a per network option.

Thanks @aboch .
LGTM