FIX: DRAFT !  equate empty string to null for more intuitive results

Description
In the real world, there is often little difference between null and an empty string ('').  For a developer it is not easy to know if a field is saved as an empty string or null or how that works, especially if you are new to Silverstripe (or if you are focussing on the actual problem and do not really care about these sort of details).
In my case, I wrote:
MyDataObject::get()->filter(['MyField:not' => ['', null, 0]);

In my simple thinking, I was like, anything with a real entry (i.e. not NULL, EMPTY STRING, or ZERO).  What I noticed though is that LESS rows were included than expected.
Now, also consider this: For example, if you write:
foreach(MyDataObject::get() as $myObject) {
    $myObject->MyField = '';
    $myObject->write();
}
echo
    MyDataObject::get()->count() .
    '=' .
    MyDataObject::get()->filter(['MyField' => ''])->count()
;

You will see that the answer is foo=0,  where foo is obviously the number of records.  That is not intuitive.
I have investigated this a little and by taking two random DataObjects with a Varchar field and filtering for "falsy" vs non-falsy. With interesting results.  I will list the results below.
I tried to fix this by just poking around and what I got up to so far is a the attached pull requests.  This is just a trial pull request to see if it works!  Obviously this is a super risky "breaking" change so improvements are:

bury deeper into query model
consider other field types
consider more complex queries

An alternative would be too simply throw an error for any query where the value is an empty string to warn developers that the results may not be as expected.
Another alternative would be to keep the code as-is, but to make the NULL filter requirement a lot more obvious in the documentation.
Of course, one of the more "hidden" scenarios is, for example, when filtering using a variable that can be any string (including an empty one). In this scenario, as developer, you would simply forget to turn an empty string (one of many strings) into a NULL value.
Manual testing steps

<?php

use SilverStripe\Control\Director;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Environment;
use SilverStripe\Dev\BuildTask;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DB;

class Test extends BuildTask
{
    protected $title = 'Test';

    protected $description = 'Test';

    protected $tablesToTest = [
// ADD YOU OWN TABLES HERE!
    ];

    private static $segment = 'test';
    protected $api = null;

    public function run($request)
    {
        Environment::increaseTimeLimitTo(3600);
        Environment::increaseMemoryLimitTo('512M');
        $this->header("====================================");
        $this->header("====================================");
        $this->header("HAS VALUE");
        $this->header("====================================");
        $this->header("====================================");

        $this->runExcludeOrExclude('buildExcludeScenarioArray', 'not', 'HasValue');

        $this->header("====================================");
        $this->header("====================================");
        $this->header("DOES NOT HAVE VALUE");
        $this->header("====================================");
        $this->header("====================================");

        $this->runExcludeOrExclude('buildIncludeScenarioArray', '', 'DoesNotHaveValue');

    }

    /**
     * optional method to reset all to empty string
     */
    protected function resetToEmptyString(string $className, string $fieldName)
    {
        Config::modify()->set(DataObject::class, 'validation_enabled', false);
        foreach ($className::get() as $object) {
            $object->$fieldName = '';
            $object->write();
        }
        echo $className::get()->count() .'='. $className::get()->filter([$fieldName => ''])->count();
    }

    protected function runExcludeOrExclude(string $method, string $phrase, string $rightAnswer)
    {
        $testCount = 0;
        foreach ($this->tablesToTest as $tableName => $details) {
            $className = $details['ClassName'];
            $fieldName = $details['Field'];
            $answers = [
                'HasValue' => 0,
                'DoesNotHaveValue' => 0,
            ];
            foreach ($className::get() as $record) {
                if (trim((string) $record->$fieldName)) {
                    $answers['HasValue']++;

                } else {
                    $answers['DoesNotHaveValue']++;
                }
            }
            $answer = $answers[$rightAnswer];
            $tableSafe = $this->replaceTableAndFieldName($tableName, $tableName, $fieldName);
            $fieldSafe = $this->replaceTableAndFieldName($fieldName, $tableName, $fieldName);
            $this->header(
                'testing '.$tableSafe . '.'.$fieldSafe.'
                ('.$className::get()->count().' records)
                for not falsy values.
                Expected answer: '.$answer.'
                (derived by looping through dataobjects)'
            );
            $scenarios = $this->$method($tableName, $fieldName, $className);
            foreach ($scenarios as $i => $results) {
                $testCount++;
                $count = $results['v'];
                $isCorrect = ($count === $answer);
                $isCorrectPhrase = $isCorrect ? 'CORRECT' : 'WRONG ANSWER';
                foreach ($results as $key => $sql) {
                    if ($key !== 'v' && $key !== 'sql') {
                        $sql = $this->recursiveReplaceValues($sql, $tableName, $fieldName);
                        $sql = $this->normalizeWhitespace(print_r($sql, 1));
                        $this->outcome('===== TEST '.$testCount.'====='.PHP_EOL.$isCorrectPhrase. '('. $count.  '), PRODUCED BY: ');
                        $this->outcome($key.' = '.$sql);
                    }
                }
                if (!$isCorrect) {
                    $whereOnlySQL = $cleanSQL = $this->whereOnlyPhrase($results['sql']);
                    $this->outcome('SQL: '.$this->replaceTableAndFieldName($whereOnlySQL, $tableName, $fieldName));
                }
            }
        }
    }

    protected function buildExcludeScenarioArray(string $tableName, string $fieldName, string $className): array
    {
        $scenario = [];

        // SQL based scenarios
        $sqlQueries = [
            'SELECT COUNT(*) FROM "' . $tableName . '" WHERE "' . $fieldName . '" IS NOT NULL',
            'SELECT COUNT(*) FROM "' . $tableName . '" WHERE "' . $fieldName . '" <> \'\'',
            'SELECT COUNT(*) FROM "' . $tableName . '" WHERE "' . $fieldName . '" IS NOT NULL AND "' . $fieldName . '" <> \'\'',
            // 'SELECT COUNT(*) FROM "' . $tableName . '" WHERE "' . $fieldName . '" <> 0',
            // 'SELECT COUNT(*) FROM "' . $tableName . '" WHERE "' . $fieldName . '" NOT IN (\'\', NULL, 0)',
            // 'SELECT COUNT(*) FROM "' . $tableName . '" WHERE "' . $fieldName . '" IS NOT NULL AND "' . $fieldName . '" <> \'\' AND "' . $fieldName . '" <> 0'
        ];

        foreach ($sqlQueries as $key => $sql) {
            $scenario[] = [
                'DB::query' => $sql,
                'v' => (int) DB::query($sql)->value(),
                'sql' => $sql,
            ];
        }

        // ORM based scenarios
        $filters = [
            [$fieldName . ':not' => ['']],
            [$fieldName . ':not' => [null]],
            [$fieldName . ':not' => ['', null]],
            [$fieldName . ':not' => ''],
            [$fieldName . ':not' => null],
            // [$fieldName . ':not' => [0]],
            // [$fieldName . ':not' => [0, null]],
            // [$fieldName . ':not' => 0],
            // [$fieldName . ':not' => ['', 0]],
            // [$fieldName . ':not' => ['', null, 0]],
        ];

        foreach ($filters as $key => $filter) {
            $scenario[] = [
                'filter' => $filter,
                'v' => (int) $className::get()->filter($filter)->count(),
                'sql' => $className::get()->filter($filter)->sql(),
            ];
        }

        // Exclude based scenarios
        $excludes = [
            [$fieldName  => ['']],
            [$fieldName  => [null]],
            [$fieldName  => ['', null]],
            [$fieldName  => ''],
            [$fieldName  => null],
            // [$fieldName  => [0]],
            // [$fieldName  => [0, null]],
            // [$fieldName  => ['', 0]],
            // [$fieldName  => ['', null, 0]],
            // [$fieldName  => 0],
        ];

        foreach ($excludes as $key => $exclude) {
            $scenario[] = [
                'exclude' => $exclude,
                'v' => (int) $className::get()->exclude($exclude)->count(),
                'sql' => $className::get()->exclude($exclude)->sql(),
            ];
        }

        return $scenario;
    }

    protected function buildIncludeScenarioArray(string $tableName, string $fieldName, string $className): array
    {
        $scenario = [];

        // SQL based scenarios
        $sqlQueries = [
            'SELECT COUNT(*) FROM "' . $tableName . '" WHERE "' . $fieldName . '" IS NULL',
            'SELECT COUNT(*) FROM "' . $tableName . '" WHERE "' . $fieldName . '" <> \'\'',
            'SELECT COUNT(*) FROM "' . $tableName . '" WHERE "' . $fieldName . '" IS NULL OR "' . $fieldName . '" = \'\'',
            // 'SELECT COUNT(*) FROM "' . $tableName . '" WHERE "' . $fieldName . '" <> 0',
            // 'SELECT COUNT(*) FROM "' . $tableName . '" WHERE "' . $fieldName . '" NOT IN (\'\', NULL, 0)',
            // 'SELECT COUNT(*) FROM "' . $tableName . '" WHERE "' . $fieldName . '" IS NOT NULL AND "' . $fieldName . '" <> \'\' AND "' . $fieldName . '" <> 0'
        ];

        foreach ($sqlQueries as $key => $sql) {
            $scenario[] = [
                'DB::query' => $sql,
                'v' => (int) DB::query($sql)->value(),
                'sql' => $sql,
            ];
        }

        // ORM based scenarios
        $filters = [
            [$fieldName  => ['']],
            [$fieldName  => [null]],
            [$fieldName  => ['', null]],
            [$fieldName  => ''],
            [$fieldName  => null],
            // [$fieldName  => [0]],
            // [$fieldName  => [0, null]],
            // [$fieldName  => ['', 0]],
            // [$fieldName  => ['', null, 0]],
            // [$fieldName  => 0],
        ];

        foreach ($filters as $key => $filter) {
            $scenario[] = [
                'filter' => $filter,
                'v' => (int) $className::get()->filter($filter)->count(),
                'sql' => $className::get()->filter($filter)->sql(),
            ];
        }

        // Exclude based scenarios
        $excludes = [
            [$fieldName . ':not' => ['']],
            [$fieldName . ':not' => [null]],
            [$fieldName . ':not' => ['', null]],
            [$fieldName . ':not' => ''],
            [$fieldName . ':not' => null],
            // [$fieldName . ':not' => [0]],
            // [$fieldName . ':not' => [0, null]],
            // [$fieldName . ':not' => 0],
            // [$fieldName . ':not' => ['', 0]],
            // [$fieldName . ':not' => ['', null, 0]],
        ];

        foreach ($excludes as $key => $exclude) {
            $scenario[] = [
                'exclude' => $exclude,
                'v' => (int) $className::get()->exclude($exclude)->count(),
                'sql' => $className::get()->exclude($exclude)->sql(),
            ];
        }

        return $scenario;
    }

    protected function recursiveReplaceValues($input, $tableName, $fieldName): array|string
    {
        if (is_null($input)) {
            return '[NULL]';
        }
        if ($input === '') {
            return '[EMPTY STRING]';
        }
        if (!is_array($input)) {
            return $this->replaceTableAndFieldName($input, $tableName, $fieldName);
        }
        foreach ($input as $key => $value) {
            if (is_array($value)) {
                // Recursively apply the function to nested arrays
                $input[$key] = $this->recursiveReplaceValues($value, $tableName, $fieldName);
            } elseif (is_null($value)) {
                // Replace null with [NULL]
                $input[$key] = '[NULL]';
            } elseif ($value === '') {
                // Replace empty string with [EMPTY STRING]
                $input[$key] = '[EMPTY STRING]';
            } elseif ($value === 0) {
                // Replace 0 with [ZERO]
                $input[$key] = '[ZERO]';
            } else {
                $input = $this->replaceTableAndFieldName($input, $tableName, $fieldName);
            }
            $newKey = $this->replaceTableAndFieldName($key, $tableName, $fieldName);
            $newVal = $input[$key];
            unset($input[$key]);
            $input[$newKey] = $newVal;
        }

        return $input;
    }

    protected function replaceTableAndFieldName($input, $tableName, $fieldName): string
    {
        $tableKeys = array_keys($this->tablesToTest);
        $tablePos = (array_search($tableName, $tableKeys, true)) + 1;
        $replaceTable = 'TABLE'.$tablePos;
        $input = str_replace($tableName, $replaceTable, $input);
        $input = str_replace($fieldName, 'MYFIELD', $input);
        return $input;
    }

    protected function normalizeWhitespace(string $input): string
    {
        // Replace multiple spaces, tabs, newlines with a single space
        return preg_replace('/\s+/', ' ', $input);
    }
    protected function header($message)
    {
        if (Director::is_cli()) {
            echo PHP_EOL;
            echo PHP_EOL;
            echo PHP_EOL;
            echo PHP_EOL;
            echo '========================='.PHP_EOL;
            echo $message . PHP_EOL;
            echo '========================='.PHP_EOL;
            ;
        } else {
            echo '
' . $message . '
';
        }
    }

    protected function outcome($mixed)
    {
        if (Director::is_cli()) {
            echo PHP_EOL;
            print_r($mixed);
            echo PHP_EOL;
        } else {
            echo '
';
            print_r($mixed);
            echo '
';
        }
    }

    protected function whereOnlyPhrase(string $sql): string
    {
        // Remove everything before WHERE
        $pos = stripos($sql, ' WHERE ');
        if ($pos !== false) {
            // Return the part of the string starting from WHERE
            $sql = substr($sql, $pos);
        }

        // Remove everything from ORDER BY onward
        $sql = preg_replace('/\sORDER\sBY.*/i', '', $sql);

        return $sql;
    }

}

Issues
These may be related:
https://github.com/silverstripe/silverstripe-framework/issues/10930
https://github.com/silverstripe/silverstripe-framework/issues/8135
From Nightjarnz:
https://github.com/silverstripe/silverstripe-framework/blob/5/src/ORM/Filters/ExactMatchFilter.php#L118
https://github.com/silverstripe/silverstripe-framework/blob/5/src/ORM/Filters/ExactMatchFilter.php#L221-L223
Pull request checklist

[N ] The target branch is correct

See picking the right version

[Y] All commits are relevant to the purpose of the PR (e.g. no debug statements, unrelated refactoring, or arbitrary linting)

Small amounts of additional linting are usually okay, but if it makes it hard to concentrate on the relevant changes, ask for the unrelated changes to be reverted, and submitted as a separate PR.

[Y ] The commit messages follow our commit message guidelines
[ ?] The PR follows our contribution guidelines
[ ?] Code changes follow our coding conventions
[ N] This change is covered with tests (or tests aren't necessary for this change)
[ N] Any relevant User Help/Developer documentation is updated; for impactful changes, information is added to the changelog for the intended release
[ ?] CI is green

results from test before changing code (search for WRONG to see 18 unexpected results):
Running Task Test
====================================
====================================
HAS VALUE
====================================
====================================
testing MYTABLE.MYFIELD (20 records) for not falsy values.  OR "MYTABLE"."MYFIELD" IS NULL)
===== TEST 5=====
CORRECT(12), PRODUCED BY:
filter = Array ( [MYFIELD:not] => Array ( [0] => [NULL] ) )
===== TEST 6=====
CORRECT(12), PRODUCED BY:
filter = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 7=====
WRONG ANSWER(20), PRODUCED BY:
filter = Array ( [MYFIELD:not] => [EMPTY STRING] )
SQL:  WHERE ("MYTABLE"."MYFIELD" != ? OR "MYTABLE"."MYFIELD" IS NULL)
===== TEST 8=====
CORRECT(12), PRODUCED BY:
filter = Array ( [MYFIELD:not] => [NULL] )
===== TEST 9=====
WRONG ANSWER(20), PRODUCED BY:
exclude = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] ) )
SQL:  WHERE (("MYTABLE"."MYFIELD" NOT IN (?) OR "MYTABLE"."MYFIELD" IS NULL))
===== TEST 10=====
CORRECT(12), PRODUCED BY:
exclude = Array ( [MYFIELD] => Array ( [0] => [NULL] ) )
===== TEST 11=====
CORRECT(12), PRODUCED BY:
exclude = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 12=====
WRONG ANSWER(20), PRODUCED BY:
exclude = Array ( [MYFIELD] => [EMPTY STRING] )
SQL:  WHERE (("MYTABLE"."MYFIELD" != ? OR "MYTABLE"."MYFIELD" IS NULL))
===== TEST 13=====
CORRECT(12), PRODUCED BY:
exclude = Array ( [MYFIELD] => [NULL] )
testing MYOTHERTABLE.MYFIELD (58 records) for not falsy values.  OR "MYOTHERTABLE"."MYFIELD" IS NULL)
===== TEST 18=====
CORRECT(43), PRODUCED BY:
filter = Array ( [MYFIELD:not] => Array ( [0] => [NULL] ) )
===== TEST 19=====
CORRECT(43), PRODUCED BY:
filter = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 20=====
WRONG ANSWER(58), PRODUCED BY:
filter = Array ( [MYFIELD:not] => [EMPTY STRING] )
SQL:  WHERE ("MYOTHERTABLE"."MYFIELD" != ? OR "MYOTHERTABLE"."MYFIELD" IS NULL)
===== TEST 21=====
CORRECT(43), PRODUCED BY:
filter = Array ( [MYFIELD:not] => [NULL] )
===== TEST 22=====
WRONG ANSWER(58), PRODUCED BY:
exclude = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] ) )
SQL:  WHERE (("MYOTHERTABLE"."MYFIELD" NOT IN (?) OR "MYOTHERTABLE"."MYFIELD" IS NULL))
===== TEST 23=====
CORRECT(43), PRODUCED BY:
exclude = Array ( [MYFIELD] => Array ( [0] => [NULL] ) )
===== TEST 24=====
CORRECT(43), PRODUCED BY:
exclude = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 25=====
WRONG ANSWER(58), PRODUCED BY:
exclude = Array ( [MYFIELD] => [EMPTY STRING] )
SQL:  WHERE (("MYOTHERTABLE"."MYFIELD" != ? OR "MYOTHERTABLE"."MYFIELD" IS NULL))
===== TEST 26=====
CORRECT(43), PRODUCED BY:
exclude = Array ( [MYFIELD] => [NULL] )
====================================
====================================
DOES NOT HAVE VALUE
====================================
====================================
testing MYTABLE.MYFIELD (20 records) for not falsy values. Expected answer: 8 (derived by looping through dataobjects)
===== TEST 1=====
CORRECT(8), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYTABLE" WHERE "MYFIELD" IS NULL
===== TEST 2=====
WRONG ANSWER(12), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYTABLE" WHERE "MYFIELD" <> ''
SQL:  WHERE "MYFIELD" <> ''
===== TEST 3=====
CORRECT(8), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYTABLE" WHERE "MYFIELD" IS NULL OR "MYFIELD" = ''
===== TEST 4=====
WRONG ANSWER(0), PRODUCED BY:
filter = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] ) )
SQL:  WHERE ("MYTABLE"."MYFIELD" IN (?))
===== TEST 5=====
CORRECT(8), PRODUCED BY:
filter = Array ( [MYFIELD] => Array ( [0] => [NULL] ) )
===== TEST 6=====
CORRECT(8), PRODUCED BY:
filter = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 7=====
WRONG ANSWER(0), PRODUCED BY:
filter = Array ( [MYFIELD] => [EMPTY STRING] )
SQL:  WHERE ("MYTABLE"."MYFIELD" = ?)
===== TEST 8=====
CORRECT(8), PRODUCED BY:
filter = Array ( [MYFIELD] => [NULL] )
===== TEST 9=====
WRONG ANSWER(0), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] ) )
SQL:  WHERE (("MYTABLE"."MYFIELD" IN (?)))
===== TEST 10=====
CORRECT(8), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => Array ( [0] => [NULL] ) )
===== TEST 11=====
CORRECT(8), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 12=====
WRONG ANSWER(0), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => [EMPTY STRING] )
SQL:  WHERE (("MYTABLE"."MYFIELD" = ?))
===== TEST 13=====
CORRECT(8), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => [NULL] )
testing MYOTHERTABLE.MYFIELD (58 records) for not falsy values. Expected answer: 15 (derived by looping through dataobjects)
===== TEST 14=====
CORRECT(15), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYOTHERTABLE" WHERE "MYFIELD" IS NULL
===== TEST 15=====
WRONG ANSWER(43), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYOTHERTABLE" WHERE "MYFIELD" <> ''
SQL:  WHERE "MYFIELD" <> ''
===== TEST 16=====
CORRECT(15), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYOTHERTABLE" WHERE "MYFIELD" IS NULL OR "MYFIELD" = ''
===== TEST 17=====
WRONG ANSWER(0), PRODUCED BY:
filter = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] ) )
SQL:  WHERE ("MYOTHERTABLE"."MYFIELD" IN (?))
===== TEST 18=====
CORRECT(15), PRODUCED BY:
filter = Array ( [MYFIELD] => Array ( [0] => [NULL] ) )
===== TEST 19=====
CORRECT(15), PRODUCED BY:
filter = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 20=====
WRONG ANSWER(0), PRODUCED BY:
filter = Array ( [MYFIELD] => [EMPTY STRING] )
SQL:  WHERE ("MYOTHERTABLE"."MYFIELD" = ?)
===== TEST 21=====
CORRECT(15), PRODUCED BY:
filter = Array ( [MYFIELD] => [NULL] )
===== TEST 22=====
WRONG ANSWER(0), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] ) )
SQL:  WHERE (("MYOTHERTABLE"."MYFIELD" IN (?)))
===== TEST 23=====
CORRECT(15), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => Array ( [0] => [NULL] ) )
===== TEST 24=====
CORRECT(15), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 25=====
WRONG ANSWER(0), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => [EMPTY STRING] )
SQL:  WHERE (("MYOTHERTABLE"."MYFIELD" = ?))
===== TEST 26=====
CORRECT(15), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => [NULL] )

results from test after changing code (note only two, "expected" errors):
Running Task Test
====================================
====================================
HAS VALUE
====================================
====================================
testing MYTABLE.MYFIELD (20 records) for not falsy values. Expected answer: 12 (derived by looping through dataobjects)
===== TEST 1=====
CORRECT(12), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYTABLE" WHERE "MYFIELD" IS NOT NULL
===== TEST 2=====
CORRECT(12), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYTABLE" WHERE "MYFIELD" <> ''
===== TEST 3=====
CORRECT(12), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYTABLE" WHERE "MYFIELD" IS NOT NULL AND "MYFIELD" <> ''
===== TEST 4=====
CORRECT(12), PRODUCED BY:
filter = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] ) )
===== TEST 5=====
CORRECT(12), PRODUCED BY:
filter = Array ( [MYFIELD:not] => Array ( [0] => [NULL] ) )
===== TEST 6=====
CORRECT(12), PRODUCED BY:
filter = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 7=====
CORRECT(12), PRODUCED BY:
filter = Array ( [MYFIELD:not] => [EMPTY STRING] )
===== TEST 8=====
CORRECT(12), PRODUCED BY:
filter = Array ( [MYFIELD:not] => [NULL] )
===== TEST 9=====
CORRECT(12), PRODUCED BY:
exclude = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] ) )
===== TEST 10=====
CORRECT(12), PRODUCED BY:
exclude = Array ( [MYFIELD] => Array ( [0] => [NULL] ) )
===== TEST 11=====
CORRECT(12), PRODUCED BY:
exclude = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 12=====
CORRECT(12), PRODUCED BY:
exclude = Array ( [MYFIELD] => [EMPTY STRING] )
===== TEST 13=====
CORRECT(12), PRODUCED BY:
exclude = Array ( [MYFIELD] => [NULL] )
testing MYOTHERTABLE.MYFIELD (58 records) for not falsy values. Expected answer: 43 (derived by looping through dataobjects)
===== TEST 14=====
CORRECT(43), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYOTHERTABLE" WHERE "MYFIELD" IS NOT NULL
===== TEST 15=====
CORRECT(43), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYOTHERTABLE" WHERE "MYFIELD" <> ''
===== TEST 16=====
CORRECT(43), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYOTHERTABLE" WHERE "MYFIELD" IS NOT NULL AND "MYFIELD" <> ''
===== TEST 17=====
CORRECT(43), PRODUCED BY:
filter = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] ) )
===== TEST 18=====
CORRECT(43), PRODUCED BY:
filter = Array ( [MYFIELD:not] => Array ( [0] => [NULL] ) )
===== TEST 19=====
CORRECT(43), PRODUCED BY:
filter = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 20=====
CORRECT(43), PRODUCED BY:
filter = Array ( [MYFIELD:not] => [EMPTY STRING] )
===== TEST 21=====
CORRECT(43), PRODUCED BY:
filter = Array ( [MYFIELD:not] => [NULL] )
===== TEST 22=====
CORRECT(43), PRODUCED BY:
exclude = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] ) )
===== TEST 23=====
CORRECT(43), PRODUCED BY:
exclude = Array ( [MYFIELD] => Array ( [0] => [NULL] ) )
===== TEST 24=====
CORRECT(43), PRODUCED BY:
exclude = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 25=====
CORRECT(43), PRODUCED BY:
exclude = Array ( [MYFIELD] => [EMPTY STRING] )
===== TEST 26=====
CORRECT(43), PRODUCED BY:
exclude = Array ( [MYFIELD] => [NULL] )
====================================
====================================
DOES NOT HAVE VALUE
====================================
====================================
testing MYTABLE.MYFIELD (20 records) for not falsy values. Expected answer: 8 (derived by looping through dataobjects)
===== TEST 1=====
CORRECT(8), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYTABLE" WHERE "MYFIELD" IS NULL
===== TEST 2=====
WRONG ANSWER(12), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYTABLE" WHERE "MYFIELD" <> ''
SQL:  WHERE "MYFIELD" <> ''
===== TEST 3=====
CORRECT(8), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYTABLE" WHERE "MYFIELD" IS NULL OR "MYFIELD" = ''
===== TEST 4=====
CORRECT(8), PRODUCED BY:
filter = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] ) )
===== TEST 5=====
CORRECT(8), PRODUCED BY:
filter = Array ( [MYFIELD] => Array ( [0] => [NULL] ) )
===== TEST 6=====
CORRECT(8), PRODUCED BY:
filter = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 7=====
CORRECT(8), PRODUCED BY:
filter = Array ( [MYFIELD] => [EMPTY STRING] )
===== TEST 8=====
CORRECT(8), PRODUCED BY:
filter = Array ( [MYFIELD] => [NULL] )
===== TEST 9=====
CORRECT(8), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] ) )
===== TEST 10=====
CORRECT(8), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => Array ( [0] => [NULL] ) )
===== TEST 11=====
CORRECT(8), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 12=====
CORRECT(8), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => [EMPTY STRING] )
===== TEST 13=====
CORRECT(8), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => [NULL] )
testing MYOTHERTABLE.MYFIELD (58 records) for not falsy values. Expected answer: 15 (derived by looping through dataobjects)
===== TEST 14=====
CORRECT(15), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYOTHERTABLE" WHERE "MYFIELD" IS NULL
===== TEST 15=====
WRONG ANSWER(43), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYOTHERTABLE" WHERE "MYFIELD" <> ''
SQL:  WHERE "MYFIELD" <> ''
===== TEST 16=====
CORRECT(15), PRODUCED BY:
DB::query = SELECT COUNT(*) FROM "MYOTHERTABLE" WHERE "MYFIELD" IS NULL OR "MYFIELD" = ''
===== TEST 17=====
CORRECT(15), PRODUCED BY:
filter = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] ) )
===== TEST 18=====
CORRECT(15), PRODUCED BY:
filter = Array ( [MYFIELD] => Array ( [0] => [NULL] ) )
===== TEST 19=====
CORRECT(15), PRODUCED BY:
filter = Array ( [MYFIELD] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 20=====
CORRECT(15), PRODUCED BY:
filter = Array ( [MYFIELD] => [EMPTY STRING] )
===== TEST 21=====
CORRECT(15), PRODUCED BY:
filter = Array ( [MYFIELD] => [NULL] )
===== TEST 22=====
CORRECT(15), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] ) )
===== TEST 23=====
CORRECT(15), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => Array ( [0] => [NULL] ) )
===== TEST 24=====
CORRECT(15), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => Array ( [0] => [EMPTY STRING] [1] => [NULL] ) )
===== TEST 25=====
CORRECT(15), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => [EMPTY STRING] )
===== TEST 26=====
CORRECT(15), PRODUCED BY:
exclude = Array ( [MYFIELD:not] => [NULL] )

Is the "DRAFT" in the pr title part of the context, or do you mean the pr is a draft and shouldn't be reviewed yet?
If the latter, please click "Convert to draft"

DRAFT is in, I would like for someone to have a look at it for some feedback. I know it can not be merged like this, but I can't progress, because I need it to be reviewed.

Now, also consider this: For example, if you write:
foreach(MyDataObject::get() as $myObject) {
    $myObject->MyField = '';
    $myObject->write();
}
echo
    MyDataObject::get()->count() .
    '=' .
    MyDataObject::get()->filter(['MyField' => ''])->count()
;

You will see that the answer is foo=0, where foo is obviously the number of records. That is not intuitive.

That seems like exactly what you'd expect, isn't it?
The value for MyField is explicitly set to an empty string. So when you filter your query to only include records where MyField is set to an empty string... naturally that returns all records.

Now, also consider this: For example, if you write:
foreach(MyDataObject::get() as $myObject) {
    $myObject->MyField = '';
    $myObject->write();
}
echo
    MyDataObject::get()->count() .
    '=' .
    MyDataObject::get()->filter(['MyField' => ''])->count()
;

You will see that the answer is foo=0, where foo is obviously the number of records. That is not intuitive.

That seems like an outright bug. What's actually stored in the database? Is it set to null or is it actually an empty string?

It is stored as a NULL value. I will run it again on a different project, just to be sure it is correct.

My general feeling on this is that is dangerous to assume your opening statement:

there is often little difference between null and an empty string ('').

While I appreciate that you are trying to make things more "intuitive", there's a balance to be had here between things that feel right, and things that are objectively correct.
I think an approach to take would be to be able to pass a specific token into the filter that means "empty" - to your specific example, something like:
foreach(MyDataObject::get() as $myObject) {
    $myObject->MyField = '';
    $myObject->write();
}
echo
    MyDataObject::get()->count() .
    '=' .
    MyDataObject::get()->filter(['MyField' => DB::EMPTY_TOKEN])->count()
;

where DB:EMPTY_TOKEN is some sort of special combination of characters that is transposed into null || '' || 0, or something sensible that matches the "intuitive" matching you are after, while still preserving the "technically accurate" behaviour in place. Do you think that would work for your use-case?

It is stored as a NULL value

Ahh okay that makes sense then. So yeah filtering by empty string and treating it as null would (usually) make sense.
We do have to consider however that people can decide they don't want empty strings to be stored as null and implement a custom DBField for that - in which case changing the filter logic would break their custom DBField.
I think at best this would have to be configurable.
It should either target CMS 6 and be on by default, or if it targets CMS 5 as this PR currently is it should be off by default.

My general feeling on this is that is dangerous to assume your opening statement:

there is often little difference between null and an empty string ('').

No, that is not dangerous, that is a fact. Just ask 100 content editors - do you care about the difference between null and an empty string.  In real life, they are usually the same thing. I appreciate that NULL basically means: "no set" and an empty string a particular value that is set. That is not lost on me, but Silverstripe is for the real world.

I think an approach to take would be to be able to pass a specific token into the filter that means "empty" - to your specific example, something like:

The problem with this is that we do not always control what we filter for, if you filter for a variable (e.g. from a form input), then you need to consider this every time. I guess what I am saying is that the NULL vs EMPTY STRING is an edge case, not the other way around.

I like @andrewandante's suggestion of having a const that people can use - that helps to remove the ambiguity. Though it does depend on developers knowing that's there to use which I think will be the hard part.

Just ask 100 content editors - do you care about the difference between null and an empty string

Content editors aren't the ones setting up the data model and using the ORM :p

I like @andrewandante's suggestion of having a const that people can use - that helps to remove the ambiguity. Though it does depend on developers knowing that's there to use which I think will be the hard part.

I think it should be the other way around. If you filter for NULL or EMPTY STRING it should yield the same result, unless you set some "strict" setting, in which case it would go for NULL or EMPTY STRING only.

To sum up what's being discussed in the Silverstripe User's Slack at the moment:

it appears the SS is doing some "magic" to set an empty string (in this case) as null to represent an "empty" value. There's some debate as to whether this is desired, but it is currently the case
the problem that is occurring at the moment is a disconnect between the filtering behaviour and the storage behaviour - if I can set '' and get null, I should be able to filter for '' and return null results. It is this inconsistency that is the core of the issue
so any proposed changes should either:

lean into the magic, and have the filter understand it
lean away from the magic, and have things stored as they are put in

For more of my own opinions 😅

Content editors aren't the ones setting up the data model and using the ORM

^ I agree with this sentiment entirely. Yes, content authors aren't expect to know the difference between null and '' in the case of the filter, but equally they aren't writing the code. Devs are expected to know the difference.

I think it should be the other way around. If you filter for NULL or EMPTY STRING it should yield the same result, unless you set some "strict" setting, in which case it would go for NULL or EMPTY STRING only.

I think the preference here comes down to which way we lean. If we go for the magic route, we want to lean towards a loose match, with strict as an option. Otherwise, the other way around.


Jade4J does not support unbuffered code blocks

As stated here, Jade supports the following syntax:
-
  var tmp = 12
h1= tmp

This syntax works on http://jade-lang.com/demo/ but not on http://naltatis.github.io/jade-syntax-docs/, and not in my project (Using SparkJava with Jade templating implemented with Jade4J).

Fixed in 1.2.4


error loading sound from file psych engine

Describe your problem here.
I CANT FIX THISSSS

Are you modding a build from source or with Lua?
Lua
What is your build target?
Windows x64
Did you edit anything in this build? If so, mention or summarize your changes.
No response

Are you sure you put the song in the correct position and the song is exactly ogg and not from mp3 and renamed to ogg?

And if that song doesn't work, just delete that song and download another link of the song and remember that the song must be ogg, and if it is mp3, go to the web to convert mp3 to ogg.


Add RequestHandling.AllowLegacyCookies custom setting documentation

Can you wait for my team's approval?

publish with 9.24.3

Ah - that one is already published. Shall I merge immediately then if you are happy.
Thanks @jveldhuizen

@jveldhuizen Thanks for the PR. I've proofread it to match our style for links and versioning. My changes are in this commit: c60e52f
I note that there isn't a change for Mendix 10 - is that deliberate?
Let me know if you are happy with my changes. I'll assume that all these versions will be released close to each other and publish with 9.24.3 unless I hear otherwise.

Mendix 10 doesn't contain this custom setting. We did only introduce this in the 7, 8 and 9 versions. In Mendix 10, we don't want that people enable vulnerable behavior.
I really don't know if 7.23.36, 8.18.25, 9.6.18, 9.12.15 and 9.18.8 will be released close to each other. I only know that this setting is included in these next releases of these MTS/LTS versions.


HELP

I Need someone to hack a facebook for me

Paid available
DM for paid only not free
On Thu, 27 Oct 2022 at 4:36 AM, Lazy6666666 @.***>
wrote:

I Need someone to hack a facebook for me
—
Reply to this email directly, view it on GitHub
https://github.com/chinoogawa/fbht/issues/54, or unsubscribe
https://github.com/notifications/unsubscribe-auth/AHRZQ4X2I3SX7HUGZRR7HYDWFG2PDANCNFSM6AAAAAARPPFA6Q
.
You are receiving this because you are subscribed to this thread.Message
ID: @.***>

ok i will do this , but you have to payment me for this job
On Thu, Oct 27, 2022 at 5:06 AM Lazy6666666 @.***>
wrote:

I Need someone to hack a facebook for me
—
Reply to this email directly, view it on GitHub
https://github.com/chinoogawa/fbht/issues/54, or unsubscribe
https://github.com/notifications/unsubscribe-auth/APMPWJHKXFBDHXA4PH3X7VTWFG2PPANCNFSM6AAAAAARPPFA6Q
.
You are receiving this because you are subscribed to this thread.Message
ID: @.***>

ok i will do this , but you have to payment me for this job
…
Do it for me! And i will send you money after proof. If ok then its my email<EMAIL_ADDRESS>

Paid available DM for paid only not free
…

proff first then payment?

ok i will do this , but you have to payment me for this job
On Thu, Oct 27, 2022 at 5:06 AM Lazy6666666 @.***>
wrote:

I Need someone to hack a facebook for me
—
Reply to this email directly, view it on GitHub
https://github.com/chinoogawa/fbht/issues/54, or unsubscribe
https://github.com/notifications/unsubscribe-auth/APMPWJHKXFBDHXA4PH3X7VTWFG2PPANCNFSM6AAAAAARPPFA6Q
.
You are receiving this because you are subscribed to this thread.Message
ID: @.***>

Yo i need u to do something

I Need someone to hack a facebook for me

Hello, This is Shohag. I am a professional Ethical Hacker,
Security Specialist as well as Penetration Tester. I can test the following vulnerability and I will provide you with a perfect assessment of your website security
which makes your website safe and sound.
My Experience:
💗. Recovering Hacked WordPress Website
💗. Full Vulnerability Scan and WordPress website malware removal
💗. Vulnerability Assessment
💗. Antispam protection
💗. Analysis of database servers
💗. Restore a hacked website
💗. Ethical Hacking(White Hat Hacker)
💗. Hacked account recovery
💗. Password recovery
💗. Decode encrypted files
💗. Vulnerability Testing
💗....my  WhatsApp number +8801314956025

ok i will do this , but you have to payment me for this job
…
On Thu, Oct 27, 2022 at 5:06 AM Lazy6666666 @.> wrote: I Need someone to hack a facebook for me — Reply to this email directly, view it on GitHub <#54>, or unsubscribe https://github.com/notifications/unsubscribe-auth/APMPWJHKXFBDHXA4PH3X7VTWFG2PPANCNFSM6AAAAAARPPFA6Q . You are receiving this because you are subscribed to this thread.Message ID: @.>

Hello, This is Shohag. I am a professional Ethical Hacker,
Security Specialist as well as Penetration Tester. I can test the following vulnerability and I will provide you with a perfect assessment of your website security
which makes your website safe and sound.
My Experience:
💗. Recovering Hacked WordPress Website
💗. Full Vulnerability Scan and WordPress website malware removal
💗. Vulnerability Assessment
💗. Antispam protection
💗. Analysis of database servers
💗. Restore a hacked website
💗. Ethical Hacking(White Hat Hacker)
💗. Hacked account recovery
💗. Password recovery
💗. Decode encrypted files
💗. Vulnerability Testing
💗....my  WhatsApp number +8801314956025

I Need someone to hack a facebook for me

My Experience:
💗. Recovering Hacked WordPress Website
💗. Full Vulnerability Scan and WordPress website malware removal
💗. Vulnerability Assessment
💗. Antispam protection
💗. Analysis of database servers
💗. Restore a hacked website
💗. Ethical Hacking(White Hat Hacker)
💗. Hacked account recovery
💗. Password recovery
💗. Decode encrypted files
💗. Vulnerability Testing
💗....my WhatsApp number +8801314956025

ok i will do this , but you have to payment me for this job
…
On Thu, Oct 27, 2022 at 5:06 AM Lazy6666666 @.> wrote: I Need someone to hack a facebook for me — Reply to this email directly, view it on GitHub <#54>, or unsubscribe https://github.com/notifications/unsubscribe-auth/APMPWJHKXFBDHXA4PH3X7VTWFG2PPANCNFSM6AAAAAARPPFA6Q . You are receiving this because you are subscribed to this thread.Message ID: @.>

My Experience:
💗. Recovering Hacked WordPress Website
💗. Full Vulnerability Scan and WordPress website malware removal
💗. Vulnerability Assessment
💗. Antispam protection
💗. Analysis of database servers
💗. Restore a hacked website
💗. Ethical Hacking(White Hat Hacker)
💗. Hacked account recovery
💗. Password recovery
💗. Decode encrypted files
💗. Vulnerability Testing
💗....my WhatsApp number +8801314956025

Paid available DM for paid only not free
…

proff first then payment?

My Experience:
💗. Recovering Hacked WordPress Website
💗. Full Vulnerability Scan and WordPress website malware removal
💗. Vulnerability Assessment
💗. Antispam protection
💗. Analysis of database servers
💗. Restore a hacked website
💗. Ethical Hacking(White Hat Hacker)
💗. Hacked account recovery
💗. Password recovery
💗. Decode encrypted files
💗. Vulnerability Testing
💗....my WhatsApp number +8801314956025

How much
On Sun, 30 Oct 2022 at 8:04 AM Jordan Smith @.***>
wrote:

My Facebook account got recovered back after it was hacked for some
months. So happy I was recommended to contact Agent_huncho on Instagram he
was the one that helped me and recover my account
@Agent_huncho on instagram
https://instagram.com/agent_huncho?utm_medium=copy_link
Sent with GitHawk http://githawk.com
—
Reply to this email directly, view it on GitHub
https://github.com/chinoogawa/fbht/issues/54#issuecomment-1296095956,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/A3236ZQGW23BL5USBRZHQUDWFXXVXANCNFSM6AAAAAARPPFA6Q
.
You are receiving this because you authored the thread.Message ID:
@.***>

I Need someone to hack a facebook for me

HI!! I am Virtual CISO, Cyber Security, Cyber defense, Ethical Hacker, expert I am prompt engineer working to create and maintain AI-generated content in Spanish.  I do have a Msc in computer engineering I am working for severals Internationals Enterprises where I do intensive researches in Penetration Testing, Vulnerability managements, Technological Risk, Security Architecture
My WhatsApp number+8801314956025


Tweak to remove weird _sortOrder dependency

Hoist P/R Checklist
Pull request authors: Review and check off the below. Items that do not apply can also be
checked off to indicate they have been considered. If unclear if a step is relevant, please leave
unchecked and note in comments.

[X] Caught up with develop branch as of last change.
[X] Added CHANGELOG entry, or determined not required.
[X] Reviewed for breaking changes, added breaking-change label + CHANGELOG if so.
[X] Updated doc comments / prop-types, or determined not required.
[X] Reviewed and tested on Mobile, or determined not required.
[X] Created Toolbox branch / PR, or determined not required.

If your change is still a WIP, please use the "Create draft pull request" option in the split
button below to indicate it is not ready yet for a final review.

Pull request reviewers: when merging this P/R, please consider using a squash commit to
collapse multiple intermediate commits into a single commit representing the overall feature
change. This helps keep the commit log clean and easy to scan across releases. PRs containing a
single commit should be rebased when possible.

we are only dealing with leaf columns here -- I don't think our exporter has ever dealt column groups


Tweaked the library to support inheritance

Updated FixedLength.java
Updated ParserTest.java
Updated FormatterTest.java
Created InheritedEmployee.java
Created AbstractPerson.java

My pleasure. When's the next planned release?

@shotishu , it is already released as 0.10, it will appear in maven central shortly when its caches will be refreshed.


Adding LICENSE headers to gcloud.streaming.

@tseaver The failure is lint:
C:  1, 0: Too many lines in module (1213/1200) (too-many-lines)

I can temporarily disable for the file or temporarily raise the limit and deal with after this PR? I'm expecting to lean out this code a bit as I pass through to factor out httplib2 dependencies.

I think that's fine. It's barely 1% over.
If you're worried about remembering this later, you could make an issue.

@daspecster I was asking @tseaver because he dislikes the churn (as do I) in the settings

Gotcha,
Couldn't you just add something like this to this particular module?
# pylint: disable=C0321
until the refactoring happens?

Yup that was

I can temporarily disable for the file

but I wouldn't use the obfuscated C0321 I'd use too-many-lines to make it clear

@tseaver PTAL

Grrr, arbirtray limits bite us again.  Go ahead with a per-file override, I think.

LGTM once pylint is appeased.


Give preference to PreprovisioningNetworkDataName

metal3 passes PreprovisioningNetworkDataName to the Config Drive during provisioning if not overridden by specifying NetworkData. Let's honor that and not overwrite with our own generated network data.

/cherry-pick 18.0.0-proposed


plot-from-file passes faulty args to uiop:launch-program because of back-quote comma-splice (,@)

This is on CentOS 7,
LS> (lisp-implementation-type)
"SBCL"
LS> (lisp-implementation-version)
"2.0.7"

It is related to a previously submitted Issue.
Running:
LS> (plot:plot-from-file #P"/tmp/plot/cars-scatter-plot.html" :browser :default)
ends up in the debugger:
The value
  "/tmp/plot/cars-scatter-plot.html"
is not of type
  LIST
   [Condition of type TYPE-ERROR]

I can fix that if, in plot/plot.lisp by removing the @ from the back-quote. Here is the offending code:
(defun plot-from-file (filespec &key (browser *default-browser-command*) (browser-options *default-browser-options*))
  "Open plot specification FILESPEC"
  (let ((plot-file (namestring (truename filespec))))
    #+windows (setf plot-file (concatenate 'string "file:///" plot-file))
    (uiop:launch-program
     `(,(alexandria:assoc-value plot:*browser-commands* browser)
                         ;; Remove the `@' for uiop:launch-program & sp-ext:run-program to execute property
			 ,@(case browser
			     (:chrome (if (assoc "app" browser-options :test 'string=)
					              (setf (cdr (assoc "app" browser-options :test 'string=)) plot-file))
			      (encode-chrome-options browser-options))
			     (:default plot-file)))
		 :ignore-error-status t)))

I created a minimal example to illustrate the effects of the ,@:
LS> (let ((browser :default))
      `(abc ,@(case browser (:chrome nil) (:default t))))
(ABC . T)

OP here - let me debug this a bit more ... On Windows, I am getting a plot window as expected ... So please wait for an update from me

This is not an issue - I will close it.
On my CentOS, quicklisp downloaded an old version of the library, 20211020. On windows, it downloaded version 20220331.
The problem was on my side.


Add service for acknowledging subscriptions (#48)

Tasks for this PR:

[x] Implement Subscription Acknowledgements
[x] Write tests for subscription acknowledgements

Coverage increased (+0.1%) to 98.741% when pulling 9b18f4ab0af74d36c0ec5e13aebc834b1fda9199 on use-pupy:feature/subscription_acknowledgement into ffc2415a6b236ccf3061ca35e47a0f27517f5152 on jnbt:master.

Coverage increased (+0.1%) to 98.741% when pulling 9b18f4ab0af74d36c0ec5e13aebc834b1fda9199 on use-pupy:feature/subscription_acknowledgement into ffc2415a6b236ccf3061ca35e47a0f27517f5152 on jnbt:master.

Thank you @iDuuck and candy_check team for your great work. Do you plan to merge this PR anytime soon?

@ToTenMilan I am currently using this PR myself in a production application/API. You can use the PR instead of the current candy_check gem using the following line(s) in your Gemfile:
gem 'candy_check', git: 'https://github.com/use-pupy/candy_check.git',
                   branch: 'feature/subscription_acknowledgement'

Disclaimer: While I am in no will of spoofing anything, it is a general disclaimer, that you should always be sure, to check the software you are installing on your system/software. So be sure to check the branch out and what was edited and only then install it into your software.

@jnbt any chance this is worthy of being pulled in? I would love it in the primary gem instead of using a forked version.

I hope it will be merged at some point. For now using my branched version in a production-ready application.

@iDuuck Since the official candy_check gem already does acknowledgments and you can pass in a subscription id, like
result = acknowledger.acknowledge_product_purchase(
  package_name: "my-package-name",
  product_id: "my-subscription-id",
  token: "my-token"
)

(according to the readme),... then what does this PR provide that's different?  I'm naive and currently implementing IAP for iOS, and about to dive into google/android land so I'm just curious.

@courtsimas So, actually while it might work out (Spoiler: It didn't for me.) for some time, there could be a place in time, where the subscription will not be acknowledged anymore, because Google might cancel the ability to use the product acknowledgement endpoint for the subscriptions.
Looking at the Google Play API's and the Ruby Library this library is using, you are seeing, that there are actually two different methods for acknowledgment (Product ack. & Subscription ack.).
TLDR: This being said, I think, the endpoint (and the methods) might work for you, however, I would not rely my production code on those.

Fair enough. Makes sense. Like I mentioned, I haven’t done this yet - just now diggin in and planning my route. This is good to know.

@jnbt this would be a great addition to this gem, could you please take a look at it?
Thanks.

Very sad to still see this open...

Hey @christophweegen, would be awesome to get the opinion of @jnbt first, before putting more effort into the PR.

@iDuuck I agree. Everything looks fine. Just some instructions how to use it, would be really useful.

@iDuuck @jnbt Any update on this merge, it would be really useful to have this on the main gem

@jnbt Are there any obstacles to merge this PR? I would love to have to as acknowledging subscriptions is crucial part and it's missing now.

I am not using the library anymore actively, so I am not very eager to write a doc on this one. Would be awesome to get the docs written by someone after digging into the code here.


Add to arb files is changing the apps arbs, and a separate subprojects arbs

It should only add to arbs on the first location that it finds, not all locations found.
I have a folder called "extension" at the root level of my app.
I decided to give it it's own l10n.yaml and arb/l10n folders since it's only like 20 strings.
But adding to arb files in main app, also modifies the arbs in the 'extension' folder.
Your extension must be scanning for all arb files.  I thought I could temporarily rename 'extension/l10n.yaml' to some nonsense hoping it would not modify those arb files, but it modifies them anyway.

Hi @sgehrman,
The extension supports multi-project.
Perhaps the location you're trying to extract doesn't have a parent with l10n?
To reproduce the bug, I'd need the structure of your project (folders are enough)


Please include dark theme.

While I absolutely LOVE your extension I find the white WAY too bright and actually much prefer the dark theme option that was on regular Youtube.  Is there any way that you can bring that to this addon please?

That's definitely doable, but I don't think I have time for that now. However, Enhancer for YouTube can already do that, both extensions can work together.

Thank you!  That addon is simply fantastic!!!  I used the Ubuntu theme as
it is perfect for me.
Thanks again and keep up the excellent work!
On Fri, Jul 27, 2018 at 12:37 PM, Mirza Brunjadze<EMAIL_ADDRESS>wrote:

That's definitely doable, but I don't think I have time for that now.
However, Enhancer for YouTube
https://addons.mozilla.org/en-US/firefox/addon/enhancer-for-youtube/
can already do that, both extensions can work together.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/thisdotvoid/youtube-classic-extension/issues/4#issuecomment-408473055,
or mute the thread
https://github.com/notifications/unsubscribe-auth/An3FLH-cDwMaCaVQeQ8AQp6L9hPtVnPwks5uK0HMgaJpZM4Vjqzo
.


adding checks for pinning and private registry secrets

Function secretExists simply checks if a secret has been created.
resource.go uses this function to determine if secret for private container registry (registry-dockerconfig-secret) and digest pinning exist (github-ssh-credentials) are present and logs the result.
Fixes #6
Fixes #7

For github-ssh-credentials we need to insure that id_rsa exists and is populated as well. Im not sure if we need/have to do this for each key for the docker registry, since it seems that cmd the cluster already validates for empties on creation.

Am I missing something? What in this has to do with pinning?

updated with make generate, manifests, bundle run. waiting for review

updated to two commits


Pairs

Problem Link
https://www.hackerrank.com/challenges/pairs/problem
Coding platform
Hackerrank
Programming language

[ ] C
[ ] C++
[ ] Java
[ ] Python

Additional context (OPTIONAL)
Add any other context or screenshots about the feature request here.

Please review this problem and assign me in Java.

I would like to solve this in C++.

I can do it in c

I would like to do this one in python

Sure @pri1311 Go for it :)


Make bags-list generic over node value and instantiable

polkadot companion: https://github.com/paritytech/polkadot/pull/5065
This is a breaking change to some public APIs, but contains zero logic changes.
While this doesn't change any logic, it technically is a breaking change for the SortedListProvider, pallet-bags_list::Config, and VoteWeightProvider which gets renamed too ScoreProvider. All through of the aforementioned get a new associated type, Score, which replaces the concrete type VoteWeight. For those who need to migrate to the new APIs, simply set Score = VoteWeight. Check out the polkadot companion for examples

bot merge


DLL not found

DllNotFoundException: taichi_unity assembly:<unknown assembly> type:<unknown type> member:(null)
Taichi.Generated.Ffi.TixImportNativeRuntimeUnity () (at Assets/Taichi/Generated/taichi_unity.cs:26)
Taichi.Runtime.get_Singleton () (at Assets/Taichi/Runtime.cs:20)
Taichi.AotModule..ctor (System.String module_path) (at Assets/Taichi/AotModule.cs:10)
Taichi.AotModuleAsset.Load () (at Assets/Taichi/AotModuleAsset.cs:24)
Taichi.AotModuleAsset.GetAllKernels () (at Assets/Taichi/AotModuleAsset.cs:47)
ImplicitFem.Start () (at Assets/Scripts/ImplicitFem.cs:81)

Hi team, I'm trying to run this example on Ubuntu 20.04, with Unity 2023.1.0a21. It is complaining about the error above. Any suggestions for resolving this?

Sorry that we don't have prebuilt binary for Linux platform, but the examples should work out of the box on either Windows/macOS. You can follow the instruction here (https://github.com/taichi-dev/taichi-unity2) and see if you can build libtaichi_c_api.so and libtaichi_unity2.so and put them to Assets/Plugins.

I am getting the same issue on both Windows/macOS... Is there anything I can look into for this issue on Windows/macOS?

That's funny. Could you provide more information like unity logs etc about that? The repo is continuously covered by our CI so it shouldn't break.

It is the same DLLNotFoundException as above.
DllNotFoundException: taichi_unity assembly: type: member:(null)
Taichi.Generated.Ffi.TixImportNativeRuntimeUnity () (at Assets/Taichi/Generated/taichi_unity.cs:26)
Taichi.Runtime.get_Singleton () (at Assets/Taichi/Runtime.cs:20)
Taichi.AotModule..ctor (System.String module_path) (at Assets/Taichi/AotModule.cs:10)
Taichi.AotModuleAsset.Load () (at Assets/Taichi/AotModuleAsset.cs:24)
Taichi.AotModuleAsset.GetAllKernels () (at Assets/Taichi/AotModuleAsset.cs:47)
Mpm88.Start () (at Assets/Scripts/Mpm88.cs:33)
There is also a NullReferenceException which I believe is caused by the DLL not being found.
NullReferenceException: Object reference not set to an instance of an object
Mpm88.Update () (at Assets/Scripts/Mpm88.cs:102)

Well I just upgraded the prebuilts in https://github.com/taichi-dev/Taichi-UnityExample/pull/27. Please check if the latest master still have the problem. At least I tried a bit and it simply works. Otherwise I would recommend you to double check if you have installed the MSVC redistributables https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170 but it should come with any Windows 10 or higher. If it again crashes I can hardly help.

@PENGUINLIONG Thank you for upgrading the prebuilt. I have ended up fixing this issue by getting a fresh build and following the developer installation here https://docs.taichi-lang.org/docs/dev_install.


RUSTSEC-2024-0336: DoS in rustls: Infinite loop based on network input

The current release of rust-s3 uses rustls 0.20 via attohttpc. Unfortunately, the fixes for RUSTSEC-2024-0336 start in the 0.21 series. This means that users of the stable version of rust-s3 are unable to update rustls to address this issue.
It looks like the release candidates for rust-s3 allow newer versions of rust-s3 to be used. Is it possible to make a release to address this?

0.34 brings in rustls 0.21


Log level should be changed for etoolbox-link-inspector.log

The log level for should be changed for the etoolbox-link-inspector.log in ui.config/src/main/content/jcr_root/apps/etoolbox-link-inspector/osgiconfig/config/org.apache.sling.commons.log.LogManager.factory.config-etoolbox-link-inspector.xml from debug to info

Can I work on this issue?

Hi @siddhantdixit,
Thanks for you interest in EToolbox Link Inspector.
Sure, any contribution is welcome.
Best Regards


Clarification on softDelete2

Hi,
I'm using feathers with mongoose as a databae adapter. I figured out by testing and reading the code that softDelete2 only works by defining the deletedAt field as a number type instead of as a date like I tried at first time. Maybe it would be a good idea to update the documentation in order to clarify that.
Also, I've found that it uses {deletedAt: { $eq: -1 }}, thats works ok with mongoose, but I don't know if also works well with another connector as $eq doesn't seem to be supported in the common query api (https://docs.feathersjs.com/api/databases/querying.html)

We decided to use the Linux date to be consistent with createdAt and updatedAt.
Thanks for the $eq comment.
@marshallswain  ^^^

It’s also compatible with sequelize: https://sequelize.readthedocs.io/en/latest/docs/querying/

Knex requires a utility: https://github.com/bhoriuchi/knex-doc-filter/blob/master/README.md

I guess we'll change that to { deletedAt: -1 }

I also had to spend some time trying to figure out why softdelete2 was not working with the mongoose adapter. I agree with @germanp. Would be nice if the documentation mentioned this somehow.

A PR to the docs would be appreciated. That's how open source is supposed to work.


Bumping to 1.0.4

Fix #801 bumped the version number in bower.json and package.json to 1.0.3 - however this version number had already been released by @sks (without updating either of those files).
This bumps the version to 1.0.4 which will now be used to release the fix in #801.

Thanks @evanbruhn-ge


refactor: Vendor oasis-core v22.2, Use mostly vendored oasis-core

This PR is in preparation for supporting the E version (v23.x) of consensus. It is functionally a no-op, a refactor that will make v23 support easier/smoother.
Before this PR, the indexer-internal types were a mix of vendored v21.x (=Cobalt) oasis-core types, and unvendored oasis-core types.
Changes at a high level:
After this PR, nexus mostly only depends on vendored oasis-core; the remaining uses of  "live" oasis-core are limited to a handful of very common and stable types like staking.Address, and to modules /go/common/{cbor,quantity,crypto/address,entity}

NOTE: We used to also depend on the /go/common/node module of oasis-core, but the module types changed with v23, so in preparation for that, this PR also vendors /go/common/node and starts using it in Cobalt and Damask compatibility layers.

Changes at a low level:
The largest diffs are due to the vendored copy of oasis-core. Therefore, it's probably better to review commit by commit. Notable commits:

vendor-oasis-core: Support v22.2.11 (Damask) - Tweaks in the vendoring script. The script was previously only used for vendoring v21.x, and v22.x required some small changes. Notably, it required the inclusion of a few more enum constants because we (ab)use the v22.x types for two purposes:
1) For serde of gRPC requests/responses (as we also do for Cobalt, and later E)
2) As nexus's internal data representation (this needs a few more enums to interpret/manipulate; in an ideal world, we'd create our own types here)
Add vendored oasis-core v22.2.11 (Damask) - Huge diff, but it's just the result of running vendor_oasis_core.sh. Not worth reviewing IMO.
Replace usage of oasis-core with vendored 22.2.11; BREAKS THE BUILD and nodeapi/damask: Use raw gRPC instead of oasis-core wrappers - What the first commit message says. The first commit is just a mechanic find-replace, the second fixes the build by removing the use of oasis-core's convenience gRPC client wrappers. (The vendored oasis-core doesn't have those, it only has types.)
vendor-oasis-core: Support to vendor "node" module too and Re-vendor oasis-core v22.2.11 (incl node module); BREAKS THE BUILD and Use the damask vendored node module for cobalt too: As described above, this PR adds the go/common/node module from oasis-core into the vendored copy. These commits achieve that. I could interleave them with the above commits (which vendor all the other parts of oasis-core), but since it affects both Damask and Cobalt, I left it separate.

Testing:

To double-check compatibility with old types: Indexed blocks 8_048_956 (Damask genesis) to 8_049_964 using a cache that predates this migration.
To test e2e: Indexed blocks 8_048_956 (Damask genesis) to 8_065_753, verified there were no errors/warnings.

oh one other thing: is there any extra setup and logic in the oasis-core grpc client?

oh one other thing: is there any extra setup and logic in the oasis-core grpc client?

Shouldn't be, our connection setup is basically copy-pasted from oasis-core: https://github.com/oasisprotocol/nexus/blob/9e33faed3fc86d90edd16892b51826a38cc569fc/storage/oasis/connections/raw_grpc.go#L19-L19

aw nice now I can hack this to use no TLS for a TCP connection


The transfer activity log is always in progress when deleting the destination cloned blob container

Storage Explorer Version: 1.29.0
Build Number: 20230427.5
Branch: rel/1.29.0
Platform/OS: Windows 10/Linux Ubuntu 22.04/MacOS Ventura 13.3.1 (Apple M1 Pro)
Architecture: ia32/x64/arm64
How Found: exploratory testing
Regression From: Not a regression
Steps to Reproduce

Expand one storage account -> Blob Containers.
Open one blob container that contains several large blobs.
Try to clone the blob container.
Delete the clone blob container during transfer.
Check whether there is a failed activity log.

Expected Experience
There is a failed activity log.
Actual Experience
There is an in-progress activity log.
Additional Context
This issue doesn't reproduce for ADLS Gen2 blobs/file shares.

AzCopy breaks down the big file into many trunks for separate upload. It doesn't realize that the destination container has been deleted so it keeps trying to upload the remaining trunks which takes a while before it quits. The user can still cancel the job to avoid blocking future transfers.

Opened an issue for AzCopy to consider enhancing this experience. https://github.com/Azure/azure-storage-azcopy/issues/2196


Saving/Loading net representation by reference

Currently loading only requires 'net', except for synMechs which also require 'netParams'.
Add option so can choose between exhaustive representation (everything stored in 'net'), vs by reference (cell, synMech params etc stored in 'netParams' and accessed by label reference -- requires less storage, but slower)

Modified so synParams now also exhaustive representation.

[ ]Still remaining to add option so net stored by reference (cellParams, synMechsParams, stimParams,...)

added option to avoid saving cell 'secs' or 'conns'


Fixed issue 192

Fixed issue 192 (https://github.com/BoltsFramework/Bolts-iOS/issues/192), allowing projects that include frameworks which themselves include Bolts to work without running into “Include of non-modular header inside framework module” compilation errors.
The problem here was that there were dependencies included directly in the .h file instead of in the .m files (see here: http://stackoverflow.com/questions/28552500/xcode6-receiving-error-include-of-non-modular-header-inside-framework-module).
Instead these were moved to use the proper @class and @protocol definitions in the headers and only including the actual file in the .m file. This removes the circular dependency issues so that the Objective-C compiler can properly make everything work in projects that include sub-dependencies (ie: include a framework which it itself includes the Bolts library)

Let's have a broader discussion in #192.
The inclusion of dependencies in the framework header files is supported use case and used everywhere, say in Foundation/UIKit frameworks.

The fix above solves the issues. This was only problematic in 3 files so it's a fairly small change. Summary of changes:

Changed from use of imports to class forwarding
Moved the two protocols that were defined in the headers into their own respective files (BFAppLinkNavigationType.h and BFAppLinkReturnToRefererViewDelegate.h)

This does solve the issue and is either way a best-practice in general, improving compilation speed if nothing else. Please have a look and accept the pull request if this works. Clearly the issue is happening for some people and it's much better to solve these issues rather than depend on workarounds such as CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES to get around them (http://stackoverflow.com/questions/24103169/swift-compiler-error-non-modular-header-inside-framework-module)

Few nits here and there... I am sorry, but this still seems not necessary per discussion outlined in #192.
Class forwarding is a good approach, I absolutely agree though, but we are not using it in a lot of places, so I am somewhat sceptical about actual compilation impact.

Hey @marchy, I am going to close out this pull request as it looks abandoned.
Feel free to comment or rebase & reopen it.


Fix dynamic schema scan

What if we had schema scans actually build a schema instead of returning a single column of name?
This allows us to do things like schema scans with dynamic projections since our query behavior is based on column names. Otherwise to support something like this we'd need to have each expr know if it's apart of a schema scan to behave differently.

Very much agree.
The schema and schema iterator are currently in a weird state. We still have the SchemaIterator but use the ArrowSchema a lot more. Maybe we should more broadly speaking look at these again and combine the interfaces?

I was pretty sparse on the initial implementation but the idea was that the rows in the results are the columns of the schema, so an additional column of this result could for example be the type of the column. The whole point was that we could do things such as what you can do in postgres with select * from information_schema.columns where table_name = 'stud1';. The problem is though that we don't actually have a global schema so we will always need a layer that aggregates the potentially different sets of schemas, which is exactly what the distinct query plan does.
The idea was that the interface is that everything produces an arrow.Record, and schema scans are like accessing a different (meta-)table, therefore the expressions should not need to know anything special in regards to wether it's a tablescan or a schemascan.

I was pretty sparse on the initial implementation but the idea was that the rows in the results are the columns of the schema, so an additional column of this result could for example be the type of the column. The whole point was that we could do things such as what you can do in postgres with select * from information_schema.columns where table_name = 'stud1';. The problem is though that we don't actually have a global schema so we will always need a layer that aggregates the potentially different sets of schemas, which is exactly what the distinct query plan does.
The idea was that the interface is that everything produces an arrow.Record, and schema scans are like accessing a different (meta-)table, therefore the expressions should not need to know anything special in regards to whether it's a table-scan or a schema-scan.

Yea I understood the intent, it just made more sense to me to actually return a schema, the types can be added to the actual schema (I just skipped that for now). Otherwise you need to know that there is a magic column returned called name.


Grid and pane scaling and clipping

Grid now fills entire screen when resized, up to minimum size after which scroll pane kicks in. Blocks in grid happily follow suit. Displayable content can now (very basically) be added to blocks, and said content will be clipped off at the edges of blocks when it grows too large, for now.

There are a lot of imports, are they all needed or can they still be optimized? Other than that, solid changes. It is a nice feature to add!

Nice work, good start for the styling we will do next sprint


Add indexedDbKeyValueStore to @effect/platform-browser

What is the problem this feature would solve?
Right now the platform-browser packages exposes session storage and local storage.
Unfortunately those seems not to be an option while running inside a webworker or a sharedworker.
What is the feature you are proposing to solve the problem?
We could support indexeddb which is available both in a UI tab, and in a webworker context.
What alternatives have you considered?
No response

I have an implementation of this here https://github.com/jessekelly881/effect-idb. I could probably create a PR to add this.

Would be super useful. Maybe @myobie could take a look at the eventual PR as well, as he knows all the nuances and pitfalls related to IDB so we make sure to not wrap it in a leaky way.

+1 my wrapper is basically just duct tape and hope lol.


The header is jumping when switching pages

Current Behavior
When a navigation causes a scrollbar to appear/disappear, the page width changes. This causes the header logo to jump.
This can be reproduced on the compare view:

Go to an AAS Detail Page
Click on the "Compare" Button
While the Submodels are loading, the header logo is changing its location twice.

Expected Behaviour
The Header should always keep full width and be sticky. Only the area below the header should be scrollable and only this area should have the scrollbar.

solved!


Add EthGasStation to ecosystem readiness

Replaces #285.

Codecov Report

Merging #301 (4deffa4) into master (691d57c) will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff           @@
##           master     #301   +/-   ##
=======================================
  Coverage   93.55%   93.55%
=======================================
  Files          28       28
  Lines        1676     1676
=======================================
  Hits         1568     1568
  Misses        108      108

Flag
Coverage Δ

unittests
93.55% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 691d57c...4deffa4. Read the comment docs.


Update README.md account for new cuDNN version - installation instruction only works with Archive version

The Link now leads to cuDNN 9.0.0 which does not work:
link leads to cuDNN 9.0.0 which throws error ("FileNotFoundError: Could not find: cudnn64_8.dll. Is it on your PATH?")
Works with archive version zip file: cuDNN v8.9.7 (December 5th, 2023), for CUDA 12.x

@ewandel Thanks for your contribution to TRT-LLM.
We've updated the doc internally,please refer to https://nvidia.github.io/TensorRT-LLM/installation/windows.html
Sorry for the late response.


Codespace stretchyboy opulent guide vg7w7q5vqfxvq

Oops. Fixes styling problem

I've been testing with
Billie Jean is not my lover
She's just a girl who claims that I am the one
(But )the kid is not my son
She says I am the one, but the kid is not my son
Whisper it


Update the icloud device_tracker

Description:
This PR updates the icloud device_tracker with the following changes:

Each device has it's own dynamic interval instead of a fixed interval for all devices linked to one account. This interval is based on the location of the device, the distance towards home and the current battery level.
A service is added to call for an update once.
A service is added to change the interval to a new interval.
A service is added to play the Lost iPhone sound on any device.
A service is added to reset an account, it will restart the API. This is useful when not all devices are found at startup or when you have added a new device to your account.
2 Factor Authentication has been added to the iCloud tracker. It will ask which trusted device you'll want to use, send the verification code to that device and you'll be able to enter that code in the UI of HASS. Your account would be verified for 2 months (even after restarting HASS).

I closed my old PR https://github.com/home-assistant/home-assistant/pull/3946 to start anew with this PR.
Example entry for configuration.yaml (if applicable):
device_tracker:
  - platform: icloud
    account_name: person1
    username: <username of person1>
    password: <password of person1>
    ignored_devices:
      - iphonevanbvb
    google_maps_travel_time:
      iphonebart: sensor.bart_to_home
  - platform: icloud
    username: <username of person2>
    password: <password of person2>

Checklist:
If user exposed functionality or configuration variables are added/changed:

[ ] Documentation added/updated in home-assistant.github.io

I'll add the documentation tomorrow.

I have tested the latest version and it works on the latest dev version. I will be trying it on my production machine running 0.31.1 shortly.

@dale3h I don't think it will work, there is a mistake in the see service of the device_tracker entity. I fixed it in https://github.com/home-assistant/home-assistant/pull/4023 but this isn't in the release version yet.

Seems to work on 0.31.1 also!!!

@dale3h great news, thanks for testing! :-)

Working for me with 2fa on 0.31.1.

#4023 was only for the see service, which was used by the component icloud version

@kellerza yeah I forgot it wasn't needed anymore for this version ?
Anyway, these users have been using my latest version, so it's not untested ?

I'm not sure if it has already been mentioned, but this platform throws an error if I try to use Dale as the account_name instead of dale. I was confused by the error at first.
Can you make it load the account_name, and then automatically slugify it? I feel like this might lead to a bit of confusion and frustration for some users if they are not sure about it.
Also, what are your ideas on using just the account name portion of the email address (i.e. johnsmith3509) as the default account name instead of the entire thing (johnsmith3509@gmail.com)? This portion would still need to be slugified to remove common characters such as . and +.

@dale3h in the latest version, you need to use a slug, not a string.
I don't know enough Python to write some code to only use the account name from the email address

cv.slugify will Coerce it to be a slug

@dale3h & @kellerza I added the slug of the account part of the username as default for account name

@kellerza thanks for approving :-) now it's just a matter of having this merged? :-)

@balloob I didn't change the docs yet because I didn't want to have to change them multiple times.
The component gives each device it's own dynamic interval based on it's current zone, the distance towards home and the battery level.
The overridestates are used to override the default dynamic interval with a new fixed interval until the device changes zone.
The self.devices links the identifier from the API to the actual devicename, in the original tracker this isn't used so it would query the devices  you don't want to track, draining their battery unnecessary, because it doesn't know the identifiers from the API it doesn't want to track. The self.seendevices is used together with line 351 to determine if the device is a device you don't want to track, this is also done in the original tracker.
The Google Maps Travel Time integration is optional and it would determine the dynamic interval better for higher distances.

@balloob The integration of the Google Maps Travel Time sensor is removed. A lot of your other remarks are handled as well. Could you check this please?

The docs are being updated in this PR: https://github.com/home-assistant/home-assistant.github.io/pull/1388

@kellerza I re-added the original comment

@balloob FYI, with my latest change (removing the GMTT integration), the current config will always be valid after the update, the only thing that they can add is the account_name in the config (for example, in my config I use account_name: bart because otherwise my account_name would be de_van_bos

@balloob thanks for merging my tracker! :)

account_name is not being assigned correctly. I have 3 icloud platforms setup, and devices from one account are showing the account_name of another account. And it is random. One one reboot of hass, my iPhone and iPad are showing the account_name of one of the other 2 accounts, and on the next reboot of hass, my iPhone shows under the account_name of 1 account and my iPad shows the account_name from the 3rd account. And on a 3rd reboot, all but 1 of the 6 devices (1 iPhone and 1 Pad under each of the 3 accounst) showed up under the account_name of 1 account and the 6th device showed up under another account.
So there is something definitely wrong with the account_name reference, as it is random and rarely correct.

@jbardi it's better you make an issue instead of commenting on a closed PR.
I guess you have family sharing enabled? If so, you would only need to add one account in your config in HASS as each account will see all the devices of it's family. So if you enter 3 accounts, it will update each device 3 times, which will cause even more battery drainage. The account_name would be the account that has been used last to update the device.
About the device_name: it's the part after the dot in the entity id. It's the name of your device you find in Settings > General > Info > Name on your device itself. That name has all it's spaces removed and is then slugified.

still not clear to me, how 2 factor authentication is working. For me it doesn't ask for a device.


haskellPackages.sydtest: Unbreak by disabling test suite.

Second attempt at #236079

Do you maybe additionally want to enter yourself as a maintainer so you get notified in case the package breaks again?

@NorfairKing That's reasonable, thanks for sending the fix.
Could you resolve the merge conflict?  Then we can merge in.  (If you add new overrides somewhere in the middle of the file, instead of at the end, you're much more likely to advoid merge conflicts.)

Thx!


Suggestion to add "crop" option to thumbnail

I would like to suggest to add "crop" option to thumbnail.
I had a client who wants to set both width and height and make the $thumbnailMode to ImageInterface::THUMBNAIL_INSET.
It's like old 5.6 era of
$ih = Loader::helper('image');
$f = File::getByID(1);
$image = $ih->getThumbnail($thumbnail, 640, 640, false);

They wanted to set both max width and max height, and set the crop mode to false.
This was used in the news article page showing thumbnail image of the article.
So they sometime want to add portrait image in addition to landscape image.
In the future, I can see more of the cases like this would happen.
It would be like this

What do you think?

@katzueno
I have seen this feature requested before on the forums.
Example:
https://www.concrete5.org/community/forums/usage/image-thumbnails-with-height-but-no-width/

@MrKarlDilkington
Thanks. If people like it, I can make some code over the holiday.

+1 to this. I'm new to C5 and thumbnails is a thing that confused me the most. I just suggest same thing here + bunch of other suggestions on thumbnails subject.

@katzueno
There was another forum feature request for creating thumbnails with height and width auto and optional cropping when setting both height and width.
https://www.concrete5.org/community/forums/5-7-discussion/reasons-why-thumbnails-system-must-be-redone-in-c5/

I think this sounds like a good addition.

Opps, sorry. I haven't worked on the importer side.
I am fixing now.

There is a pending reorganization of the repository that is going to make this difficult to merge. We'd really like to have it; please consider reopening it against the develop branch at some point in the next few days.

OK I will organize it.


Remove circular deps

Remove all circular dependencies and add a lint check.
Circular dependencies prohibit us to properly sync the library internally at Google. This PR has no changes in functionality. Just moving code around.
An overview of the changes:

tensor.ts becomes a lightweight module with almost no dependencies. It doesn't depend on any environment/engine/ops anymore. Instead the environment registers an op handler and a tensor tracker, and the Tensor class delegates chain ops and registration to those handlers (see tensor.ts)
Combined environment.ts and engine.ts in one file as they were already deeply coupled
Split types.ts into types.ts and tensor_types.ts (the latter depends on tensor)
Split util.ts into util.ts and tensor_util.ts (the latter depends on tensor)
Split array_ops.ts into array_ops.ts and tensor_ops.ts (the latter doesn't call into ENV.engine, the former calls ENV.engine.runKernel)
Other minor splits (e.g. relu_ops.ts separated from unary_ops.ts because of circular dep, etc...)

DEV

This change is

Reviewed 1 of 31 files at r1, 1 of 48 files at r3.
Review status: :shipit: complete! 1 of 1 LGTMs obtained

src/environment.ts, line 660 at r4 (raw file):

const TEST_EPSILON_FLOAT32_DISABLED = 1e-1;

function hasExtension(gl: WebGLRenderingContext, extensionName: string) {

this file is enormous now, it was already growing out of hand.
There are a bunch of functions in this file that are leaves that do feature testing (all of the WebGL functions from here down), can you move them to a new file, maybe environment_util.ts?

src/tensor.ts, line 1261 at r4 (raw file):

}

// Maximum number of values before we decide to show ellipsis.

this file is also huge, could you move these functions out to tensor_util.ts (to remove dependency on Tensor just pass vals, shape, and strides directly)

src/tensor_types.ts, line 50 at r4 (raw file):

}

export interface ModelPredictConfig {

how about a model_types.ts file for these two interfaces (predict and inference model)?

Comments from Reviewable

Reviewed 31 of 31 files at r1, 3 of 3 files at r2, 48 of 48 files at r3, 27 of 27 files at r4, 5 of 7 files at r5.
Review status: :shipit: complete! 1 of 1 LGTMs obtained

src/environment.ts, line 660 at r4 (raw file):
Previously, nsthorat (Nikhil Thorat) wrote…
this file is enormous now, it was already growing out of hand.

Done! I split environment.ts into 3 files:

environment.ts 406 LOC
engine.ts 474 LOC
environment_util.ts 284 LOC

src/tensor.ts, line 1261 at r4 (raw file):
Previously, nsthorat (Nikhil Thorat) wrote…
this file is also huge, could you move these functions out to tensor_util.ts (to remove dependency on Tensor just pass vals, shape, and strides directly)

Done. Moved to tensor_format.ts since tensor_util.ts depends on Tensor since it has a bunch of utils that work with Tensors

src/tensor_types.ts, line 50 at r4 (raw file):
Previously, nsthorat (Nikhil Thorat) wrote…
how about a model_types.ts file for these two interfaces (predict and inference model)?

Done.

Comments from Reviewable


Error on profile and wallet name re-use

Issue description
Users are unable to delete a profile and create a new one with the same profile name so long as they haven't closed Firefly from the time of deletion to the time of creation. Specifically, Firefly throws an error of type AccountAliasAlreadyExists with a message can't create account: account alias already exists.
It's worth noting that changing the wallet name before deleting the profile will allow a user to create a profile of the same name, however the renamed wallet shows up in addition to the initial "Wallet 1" despite it being empty. This PR's changes make it so that upon deleting a profile, its wallet accounts are also deleted making it so re-creating the same profile would only show a newly initialized "Wallet 1".
Wallet version

1.1.0
develop

System specification

Ubuntu (20.04)
MacOS (Catalina 10.15.7)
Windows 10

Is it a repeatable issue?
Yes
Steps To reproduce the issue

Create a new profile of some specific name (e.g. TheProfile)
Delete TheProfile
Without closing the application, create another profile with the same name, TheProfile

Expected behaviour
Firefly should create the profile despite having the same name since it should've been deleted beforehand.
Actual behaviour
Firefly doesn't delete all instance of the profile thus resulting in the inability to create a profile of the same name. It deletes even the profile folder within ~/.config/Firefly/__storage__ (Ubuntu), but there is some other data not being accounted for. It's worth noting that closing the app is a workaround.
Errors
The following error is thrown once from the asyncCreateAccount method in wallet.ts:
{
    type: "AccountAliasAlreadyExists",
    message: "can't create account: account alias already exists",
    time:<PHONE_NUMBER>138 (or some other number)
}

Every error after is this error below, thrown from the asyncStoreMnemonic method also in wallet.ts:
{
    type: "StrongholdError",
    message: "the mnemonic was already stored`",
    time:<PHONE_NUMBER>578 (or some other number)
}

Fixed in: https://github.com/iotaledger/firefly/pull/1209


How to enforce Resource2 is created when I have Resource1 defined?

** Question : **
<A clear describe of your question. Ex, how can I do [...] for [...] with terraform-compliance ?>
How to check if Resource2 is also defined when Resource1 is defined?
I have an use case where in I need to check VPC Flow logs are enabled when a VPC is created
main.tf:
resource "aws_vpc" "main" {
  cidr_block = "<IP_ADDRESS>/16"
}
resource "aws_flow_log" "example" {
  log_destination      = aws_s3_bucket.example.arn
  log_destination_type = "s3"
  traffic_type         = "ALL"
  vpc_id               = aws_vpc.main.id
}

resource "aws_s3_bucket" "example" {
  bucket = "example"
}

so, I need my test be something like this
Given I have aws_vpc defined
Then aws_flow_log must be defined
And it must contain aws_vpc

currently we don't have a step def for the step2 mentioned above.
I wrote the below Scenario:
Given I have aws_vpc defined
Given I have aws_flow_log defined
Then it must contain aws_vpc

The above test worked fine when I have both aws_vpc and aws_flow_log resources defined, however when I don't have aws_flow_log resource defined, the step2 is been SKIPPED, however ideally I would want step2 to be FAILED when aws_flow_log resource is not defined( because in my case its mandatory for aws_vpc to have aws_flog_log enabled
Any ideas on how to finish my test described above? thanks in advance!

I glossed over the documentation, and couldn't find a way to do that.
I believe you are looking for something like
Given I have aws_vpc
Given I have aws_flow_log not defined
Then it must fail

Since When directives only work within a "given" resource.
Maybe those tests could be supported if we had one of the two:

Given I have resource not defined
@noskip tag that fails the scenario if it tries to skip

@eerkunt any thoughts?

I think with the use of
Given I have any resource defined

following a filtering step like ;
When its type is <resource_type>

and use of @precondition might solve this case.
E.g. (haven't tried) ;
Scenario: VPC is there
  Given I have any resource defined
  When its type is not aws_vpc
  Then it must fail

@precondition(filename.feature: VPC is there)
Scenario: VPC Flow Logs are defined
  Given I have any resource defined
  When its type is not aws_vpc_flow_log
  Then it must fail

Where the 2nd Scenario will first ensure the the first scenario passes and then runs.
Sounds like we need documentation with examples about @precondition tag - which doesn't exist right now.

Wouldn't this fail on any resource that is not an "aws_vpc?"
If we use preconditions, on execution we still end up with the two scenarios stacked on top of each other.
e.g.
Given I have any resource defined
When its type is not aws_vpc
Then it must fail
Given I have any resource defined
When its type is not aws_vpc_flow_log
Then it must fail

So we still need to be able capture

Given I have aws_vpc
Given I have aws_flow_log not defined
Then it must fail

in one scenario
I tested this to be working
Scenario: VPC implies flowlogs
	Given I have aws_vpc defined
	Given I have any resource defined
	Then its type must be aws_vpc_flowlog

@vrbcntrl could you give it a try?

I was thinking about simulating "Given I have "resource A" not defined" with the current possible directives.
The scenario given above simulates
Given I have "resource A" not defined
Then it must fail

If we come up with a way to represent the other case
Given I have "resource A" not defined
Then it passes

We would end up supporting the functionality of the directive.
However, I haven't been able to do so.

Hi @vrbcntrl,
With release 1.2.7, my previous response became outdated.
Scenario: VPC implies flowlogs
	Given I have aws_vpc defined
	Given I have any resource defined
	Then its type must be aws_vpc_flowlog

Should not filter the aws_vpc_flow resource. All then directives drill down. Then its type must be aws_vpc_flowlog should drill down to the value property of type.
We could use the newly added @noskip tag, which will fail on skip.
	@noskip_at_line_8
	Scenario: VPC implies flowlogs
		Given I have aws_vpc defined
		Given I have any resource defined
		When its type is aws_flow_log

Will fail if you have aws_vpc defined but not aws_flow_log. (Line 8 corresponds to When its type is aws_flow_log on my file.
However, I couldn't come up with a step that checks for your last step. I've looked into the plan file, there isn't anything resembling aws_vpc within the aws_flow_log resource.

Hi @Kudbettin ,
Thanks for your response. Its good to have the @noskip tag, I think it would be very helpful.
so, I have tested your Scenario with @noskip tag, and it works fine, its funny that even though my tf and plan has the aws_vpc referrence inside aws_flo_log resource, it still could not find it.
However, later I have tested this reference the other way round and it worked :)
Scenario: VPC with flow logs
        Given I have aws_vpc defined
	Then it must contain aws_flow_log

please see the attached main.tf and plan json I used for testing
main.tf.txt
plan.json.txt
I think this works fine as long as both aws_vpc and aws_flow_log resources are being created during the same plan, but if some one tries to create them separatetly, then the test fails.

@vrbcntrl,
Wow! It haven't occurred to me at all to try checking that, or looking into the contents of aws_vpc in general.
Just a heads up: the contents of aws_flow_log resource and the aws_vpc/aws_flow_log are slightly different.
I'm sorry I hadn't noticed your response. The notification got buried in my inbox :)

np @Kudbettin
Thank you for taking time to review our issues and fixing them :)
much appreciated.


Select Interface for QR code

Hi there,
how can i change the interface/ip-adress in the web frontend?
Neither mdns nor bridge seem to work:
{
    "mdns": {
        "interface": "<IP_ADDRESS>"
    },
    "bridge": {
        "host": "<IP_ADDRESS>",
    },

The System information panel is showing your default interface. If you fix your systems default interface, it will be reflected here.
You can see your default route by running this (inside the conainer if Docker):
 route | grep default

If you are running Docker, make sure you have started the container with --net=host.


Simple Feature request: don't create empty file if download fails.

Hi there,
Currently, if I run pivnet  download-product-files ... and I haven't accepted the EULA for this release, the pivnet cli creates this file but leaves it as zero length.
For scripting, it would be better for this file not to be created instead of exist but be invalid. (so we can do an if it exists skip the download step).
Thanks in advance.

@haydonryan Hey! Changes were made to ensure the zero length file does not exist after the cli fails to download. This includes the error that results from a EULA that has not previously been accepted.