Unexpected order of operations when combining flip and offset

I noticed that when using the flip options, offsets are applied before the flip.  In my opinion this is unintuitive and I would propose either changing it (since the feature is relatively new, this hopefully wouldn't break too many workflows) or documenting the behavior in the readme.
Relevant code: https://github.com/plottertools/vpype-gcode/blob/1a74deca7bcf792297cb3a44119625f6d74e7ed3/vpype_gcode/gwrite.py#L133-L145
Example of current behavior (gcode)
SVG 175mm tall, with a line segment in the top left: ((10, 10), (30, 10))
profile toml:
offset_x = 45
offset_y = 45

When vertical_flip = false, I get this gcode, as expected:
G0 X55 Y55
G0 X75 Y55

When vertical_flip = true, I would expect:
G0 X55 Y210
G0 X75 Y210

but instead I get:
G0 X55 Y120
G0 X75 Y120

(The expected result can be achieved with offset_y = -45.)

@tyehle Any opinion on this?

@jwlarocque Thanks for the feedback. IIRC, we had some discussion on ordering already. Moving offset after invert_x/y would definitely break existing workflow. I'm not sure what would be the consequences of moving flips before the offset.

This seems accurate. I would expect the translate to have an absolute rather than a flipped effect. If we apply it the way we do it's x+offset and then x*-1 which actually gives us -x - offset.
Though really we might need a better arranged solution altogether since you might want some other things. And frankly this might be better off as part of vpype more properly. Something like CSS matrix parsing would make sense with a couple extra operations. translate(1in, 0) flip_x could be parsed and executed just as flip_x translate(1in, 0) could but the difference is a bit more obvious.
Changing the order of the static operations would always change how it works. Unless for some reason it multiplied by 0 or something, or otherwise couldn't matter. But flips, inverts, and offsets are equal to scale(-1, 1, cx, cy), scale(-1,1) and translate(ox, oy).

I like this idea of explicitly listing transforms in order!
This is how it could look like in the toml config file:
[gwrite.demo]
# ...
# scale_x = 10    # dont use, depreciated, still works as before
# offset_x = ...  # same
# flip_x = true   # same
transforms = [
    { type = "scale_x", value = 10 },
    { type = "flip_y", value = true },
    { type = "offset_x", value = "3cm" },
]

The operations would of course be applied in the listed order. The old parameters would remain and keep their effect, but be deprecated (non 0 value yield warning, removed altogether after a while).

Seems like flip_y wouldn't really need a value. And that formatting feels a bit hamstrung.
[gwrite.demo]
# ...
# scale_x = 10    # dont use, depreciated, still works as before
# offset_x = ...  # same
# flip_x = true   # same
transforms = [
    "scale_x(10)",
    "flip_y",
    "offset_x(3cm)",
]

or, more straightforward:
[gwrite.demo]
# ...
# scale_x = 10    # dont use, depreciated, still works as before
# offset_x = ...  # same
# flip_x = true   # same
transform = "scale_x(10) flip_y offset_x(3cm)"

It seems like you could even just inline that as a quoted things transform = "scale_x(10) flip_y offset_x(3cm)" Though strictly speaking that's not something that would need to be restricted to gwrite since you might well have a need to apply that kind of arbitrary string of translations to other places. It's actually pretty close to how svg works. In fact, since there's a dependency on svgelements you could even just do Matrix("scaleX(10) scaleY(-1) translate(3cm, 0)") and that would work. Though clearly the flip_x and flip_y aren't part of that since Matrix doesn't know the document size to flip it across the center, but the operations that would be needed for vpype would be pretty straight forward.
See: https://github.com/meerk40t/svgelements/blob/fcf3bdd8997ca48b19fa63487cef42fa0d7d12d1/svgelements/svgelements.py#L2649 for the basic parsing routine.

I like the readability and conciseness of your first proposal (TOML array but SVG-like transform syntax). It somehow strikes a nice balance between self-explanatory, not too hacky in the context of a TOML config file, trivial parsing code (basically a regexp), and not too verbose (like my initial proposal).
IMHO, it wouldn't make sense to force this into direct compatibility with svgelements. The loss in extensibility/readability isn't worth the implementation gains.

I was noting that parsing there is usable prior art, not that we should take it. There is no function in CSS matrix that allows flipping a document which is largely what you we want here. Also, a quick parser for the relevant transforms could probably do either several inline operations or singletons as you could send "translate(20, 40) scale(1.5) translate(-20,-40)" just as easily as the singletons.
In vpype-gcode we're calling commands like:
    document.scale(scale_x / unit_scale, scale_y / unit_scale)
    document.translate(offset_x, offset_y)
    document.translate(-origin[0], -origin[1])
    ...
    document.scale(-1 if invert_x else 1, -1 if invert_y else 1)
    document.translate(origin[0], origin[1])

        class DummyDocument:
            def __getattribute__(self, item):
                print(item)
                return print

        import re
        parse = "translate(2in, 3in) flip_x flip_y rotate(3deg) skew(1.2, 1.8)"
        transform_re = re.compile(r"(?u)(scale|translate|rotate|skew|flip_x|flip_y)[\s\t\n]*(?:\(([^)]+)\))?")
        param_re = re.compile(r"([-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?)[\s\t\n]*(cm|mm|in|deg)?")
        document = DummyDocument()
        for m in transform_re.findall(parse):
            name = m[0]
            params = [(float(mag), unit, mag + unit) for mag, unit in param_re.findall(m[1])]
            if name == "scale":
                assert(len(params) == 2)
                document.scale(params[0][0], params[1][0])
            elif name == "translate":
                assert(len(params) == 2)
                document.translate(params[0][2], params[1][2])
            elif name == "rotate":
                assert (len(params) == 1)
                document.rotate(params[0][0])
            elif name == "skew":
                assert (len(params) == 2)
                document.skew(params[0][0], params[1][0])
            elif name == "flip_x":
                assert (len(params) == 0)
                document.flip_x()
            elif name == "flip_y":
                assert (len(params) == 0)
                document.flip_x()

Is a basic parser. I think things like document.translate() can take "2in", "3in" sorts of things. Given the dummy document this output:
translate
2in 3in
flip_x

flip_x

rotate
3.0
skew
1.2 1.8

Obviously it could take whatever units the documents take for those operations, or just hand it floats if needed. But, in theory that would work.
Then we leave the rest of the stuff untouched, deprecate the forced position flip_x or invert stuff. Not sure if this is better just a short-hand part inside document or restricted to vpype-gcode, this generally is just calling some document functions and you could probably add in some non-transform calls if there's some useful ones to use there.

With the addition of percent as a length (equal to percent of document size) it would be possible to single-line the flip_x flip_y stuff. Namely you'd allow the command scale(-1, 1, 50%, 50%) Which means do a scale based on the given position. And the position would be 50%, 50% which is 50% * document_width and 50% * document_height. Though you might break that into translate(-50%, -50%), scale(-1,1) and translate(50%, 50%) (Note: Several inline operations would use the original and not each subsequent value for the % so scale(0.9,0.9, 50%, 50%) could be seen differently after the scale and the second translate could be based on original or new size).
You could add a document.matrix() function, though we could probably just issue them one at a time in sequence. Though it would imply that rather than gcode_write having the whole flip_x thing programmed into it that maybe that should be done in vpype.
def transform(self, mx):
        for line in self._lines:
            line.real = line.real * mx.a + line.imag * mx.c + 1 * mx.e
            line.imag = line.real * mx.b + line.imag * mx.d + 1 * mx.f

Assuming the matrix bits were a-f, when really a numpy array would also tend to work there. We'd do this for speed, generally it doesn't come up that much but all the affine transformations can be applied within the matrix and then we only multiply the giant set of numbers the one time. But, I'd assume we'd stick to regular parsing, and stick to only modifying vpype-gcode. That little bit of code is pretty easy to setup.

Great input thanks–we could definitely do something like this.
Now, to shake things up, here is a completely different approach that just occurred to me: use actual vpype commands instead this new DSL of sort.
In the TOML:
[gwrite.demo]
# ...
transform = "translate 0 10cm scale -o 0 %vp_page_width.h/2% 1 -1 scale 0.5 0.5"

(The param would probably be better named preprocess instead of transform.)
This would be actual vpype commands, so the implementation becomes a one-liner:
doc = vpype_cli.execute(preprocess_commands, doc)

This would be nice because (1) it's trivial to implement, (2) builds on existing user knowledge instead of introducing yet another DSL, (3) easily extensible by construction.
I see at least these issues (there may be more):

scale -o 0 %vp_page_width.h/2% 1 -1 for flip is extremely ugly. This could be solved by introducing new fliph/flipv commands in vpype, which would be useful anyway.
The scale command doesn't actually scale the page size, just the contents. Adding this to the scale command would be easy/possibly useful, but that would need an explicit option for backward compatibility. Alternatively, seeing that scaling is mainly used either for flipping (as per (1)) or changing units, a new command could be introduced to deal with the latter (units cm?). This would look weird in vpype in general, but be convenient in this particular context.
I wonder if I'd be at risk of some re-entrancy issue with execute() (effectively runs a whole vpype pipeline) launch while executing a vpype pipeline?

I think that's a winner.
If you don't call gwrite with the pre-process, it shouldn't be much of a problem. Though if you did that you should probably crash.
That does seem pretty simple and effective. Even the parsing section, I realized things like reloop could be trivially added. And well, most of that stuff is or should be in the vpype pypeline anyway. We make a copy of the document during saving so we're not modifying it directly. Even the parsing stuff feels like, if it was implemented, it should be in vpype directly. Your default unit is ppi=96 pixels or whatever, and setting the units there is basically just a unit scale and that would also work a bit better in vpype there.
You'd need to make units as a command actually track the units throughout. So if I say units in and then I make a rectangle that is 1 1 2 2 and then do units px to restore back to regular it needs to know I was in in and went back to px rather than doing the scaling for px->in and then px->px which would leave me in inches.
Also, since the goal of this project more or less is to make the project not exist, more utility moving from vpype-gcode to to vpype is quite helpful. A lot of these things feel like it's pulling stuff out of vpype-gcode in to vpype proper and if most of the options were dealt with it might be reasonable or plausible to move it more directly into just write which already does a sort of hybrid svg hpgl thing.
This gets a little weirder since invoking gwrite with a profile that preprocess a write command would, in theory, let you use gwrite for every type of write... which puts things a bit closer to endgame. Since if it was sort of just a write command instead it might actually be somewhat more mergable. Though it might need to be save or something.


selectionChangedListener() not getting called

_selectionChangedListener() not getting called despite changing the selected text?
class _MyHomePageState extends State<MyHomePage> {
  final _selectionController = SelectableController();

  void _selectionChangedListener() {
    print('Changed 1');  //Not called
    setState(() {
      print('Changed 2'); //Not called
    });
  }

  @override
  void initState() {
    super.initState();
    if (kIsWeb) {
      // On web, disable the browser's context menu since this example uses a custom context menu
      BrowserContextMenu.disableContextMenu();
    }
    _selectionController.addListener(_selectionChangedListener);
  }

  @override
  void dispose() {
    if (kIsWeb) {
      BrowserContextMenu.enableContextMenu();
    }
    _selectionController
      ..removeListener(_selectionChangedListener)
      ..dispose();
    super.dispose();
  }

  // The rest of the code...
}

I apologize I found the answer just after posting the issue (like always :") )
For anyone stuck at this too, It turns out that we must set selectionController to Selectable widget too
return Selectable(
selectionController: _selectionController,
...
)

I apologize I found the answer just after posting the issue (like always :") )
For anyone stuck at this too, It turns out that we must set selectionController to Selectable widget too
return Selectable(
selectionController: _selectionController,
...
)


Simplify test runner

@benjaoming @mjs7231 What do you think about ?
I moved runtests to root and moved its settings part to dbbackup.tests.settings.
I also moved all the tests directory into dbbackup/tests/ and dbbackup/tests/testapp
I improved functional tests by creating commands for count and populate database, and I test the results.

Agreeing with this, consolidate the Makefile, and this is a great improvement! Thanks for keeping the project alive and healthy! :)

@benjaoming Makefile updated !

@ZuluPro do you have any idea about the new test failures? It seems they have started because of moving to a different way of calling the test runner?

@benjaoming : From our code the problem come from moto: Mock library for AWS, so it isn't critical as it is supposed to disappear.
More precisely the problem come from Flask+Pypy3, I think since Flask 0.11 (since 5 days) Pypy3 isn't supported anymore. I tried to launch a test from DBBackup master, it failed: https://travis-ci.org/django-dbbackup/django-dbbackup/jobs/120767399
I'm going to add allowed failures on pypy3.

@benjaoming I made it.
I think we should set an older version of Flask in pypy3 requirements (tox.ini).
Pypy3 uses Python 3.2.5 stdlib (Ref), so it could be hard to maintain.
I have something to do, I'll ping you after and you check & merge ?

@benjaoming I've done !
I fixed and added functional tests to CI, but it fails with postgres (failure allowed)
Could you review ?

Changes Unknown when pulling 2b65f4564274ae9a56066b603129ce5a9b62aa24 on ZuluPro:bettertest into ** on django-dbbackup:master**.

Hurray, it passes!! :)

Not seeing anything that isn't an improvement!

:laughing:


Changing colors

Hi, sorry for posting this here, but I cannot find information how to change the colors in this extension.
I also noticed that colors are different in the extension and in the advertising screenshot (I kinda like ones from the screenshot better).
Can I somehow change them to match ones in the screenshot?

Hi, you change settings in the normal color settings dialog of visual studio. If you scroll through it, you will see some semantic colors there.
I could not find a good location to upload the demo settings. So I attached them here for now.
If you are keen enough to try them, please report the results.
arBmind_InputMono_Viasfora_SemanticColorizer_Dark.zip

@arBmind  Thanks for the great extension, I'd suggest you mention that colors can be customized through normal visual studio dialog with some screenshots, cause it might not be immediately obvious to some people, including someone like me, Thanks.

Thanks for the hint. I added both my settings and the hint how to change the colors to the readme and plugin description.


Move credentials to dotenv

Unable to get import dotenv to work after installing python-dotenv. See https://github.com/theskumar/python-dotenv/issues/6

Fixed by using https://github.com/mattseymour/python-env version 1.0.0, instead of https://github.com/theskumar/python-dotenv version 0.6.4
See my comment in https://github.com/theskumar/python-dotenv/issues/6


Add support for audio block

Description
Adds support for Audio block
Fixes # (issue)
#194
Type of change
Please delete options that are not relevant.

[x] New feature (non-breaking change which adds functionality)

Checklist:

[x] My code follows the style guidelines of this project
[x] I have performed a self-review of my own code
[x] I have commented my code, particularly in hard-to-understand areas
[x] My changes generate no new warnings
[x] I have added tests that prove my fix is effective or that my feature works
[x] New and existing unit tests pass locally with my changes
[x] I have checked my code and corrected any misspellings

how would I do this with the python sdk? Im trying to upload a local file, is that possible?


WM5 | Zahra-Khademi | HTML-CSS-Cakes co | week 2

Learners, PR Template
Self checklist

[x] I have committed my files one by one, on purpose, and for a reason
[x] I have titled my PR with COHORT_NAME | FIRST_NAME LAST_NAME | REPO_NAME | WEEK
[x] I have tested my changes
[x] My changes follow the style guide
[ ] My changes meet the requirements of this task

Changelist
Briefly explain your PR.
Questions
Ask any questions you have for your reviewer.

@Zahra-k-b can you talk about why your code doesn't meet the requirements and how you need help to meet them?


Creating team 'TEAM_NAME' via API/UI -> Portus also creates the team 'TEAM_NAME0'

Description
When creating team 'X', Portus also creates a hidden team with the name 'X0'
Steps to reproduce

Create a team 'team-1'
Then try to create the team 'team-10'
API returns http status code '422', UI shows the message: 'Name is reserved or has already been taken'

Expected behavior: the team 'team-10' should be created successfully
Actual behavior: Portus claims the team already exists & prevents the team creation

Deployment information
Portus is deployed on a K8S cluster in GKE
using the image: 'opensuse/portus:2.4.1'
Portus version: Both 2.4 & 2.4.1

I cannot reproduce this in neither 2.4.2 nor head. Could you set the log level to debug and paste the logs?

I'm going to paste the same thing I said in #2143.

I'm not saying that this is wrong but with those steps this is not reproducible.
My guess is that this is somehow related to users created previously and their data still being attached to some entity that could not be wiped and it's causing conflict. Without the exact steps it's kinda hard for us to understand the issue and come up with a fix.


Better deduplication of flats

When doing a search for buying a flat, I get a lot of duplicates: the pictures seem to be the same, but the prices are different! This happens frequently, for flats which price has lowered in the last few weeks.
If you tell me where duplicates are filtered and removed, I'm happy to have a look and propose a PR.
Or is there no duplication removal by default, and I need to set it in the config.json file?

Duplicates are detected based on common info in the first passes (https://github.com/Phyks/Flatisfy/blob/master/flatisfy/filters/duplicates.py#L92-L175).
In the last pass (third pass, enabled by default), there should be a "deep detection", checking for these kind of flats with different prices and same photos. My use case for now is renting a flat in Paris, so the price was not evolving in time and then the price on the posts was only differing by a few euros.
Basically, this deep detection checks for any possible common info, and gives a score based on this to the pair of flats. If the score is too high, they are considered as being duplicates. All the code is here.
For now, the score threshold is 15, but it is totally empirical and may not be really optimized. :/

Closed in favour of https://git.phyks.me/Phyks/flatisfy/issues/59


Frontend usage with Vite?

Is it possible to use node-quadstore in the frontend with Vite instead of webpack?
I tried to adapt https://github.com/beautifulinteractions/node-quadstore-webpack-bundle to Vite in the following way:
import leveljs from "level-js";
import { newEngine } from "quadstore-comunica";
import { Quadstore } from "quadstore";
import { DataFactory } from "rdf-data-factory";

const dataFactory = new DataFactory();

const store = new Quadstore({
	dataFactory,
	backend: leveljs("quadstore"),
	comunica: newEngine(),
});

But it throws the following error:
Uncaught ReferenceError: global is not defined
    ta2str deserialize.js:5
    js deserialize.js:10
    __require2 chunk-FPJRMZPJ.js:14
    js iterator.js:6
    __require2 chunk-FPJRMZPJ.js:14
    js index.js:10
    __require2 chunk-FPJRMZPJ.js:14
    <anonymous> level-js:1

Even prepending this polyfill doesnt help:
if (typeof (window as any).global === "undefined") {
	(window as any).global = window;
}

When I reorder the import statements and add leveljs to the end of them, I get the following error instead:
Uncaught ReferenceError: Buffer is not defined
    js quadstore.js:13
    __require2 chunk-FPJRMZPJ.js:14
    js index.js:15
    __require2 chunk-FPJRMZPJ.js:14
    <anonymous> quadstore:1

@KonradHoeffner seems like you're getting there! This should be fixable by making Vite fallback to something like https://www.npmjs.com/package/@marshallswain/events for the events module.

Next error:
Uncaught ReferenceError: exports is not defined
    <anonymous> http://localhost:3000/node_modules/quadstore/dist/index.js?v=db8b2a82:12
index.js:12:1
    <anonymous> http://localhost:3000/node_modules/quadstore/dist/index.js?v=db8b2a82:12
    InnerModuleEvaluation self-hosted:2371
    InnerModuleEvaluation self-hosted:2371
    evaluation self-hosted:2332

@KonradHoeffner any progress on using quadstore with Vite?

Great advice, thanks! The following doesn't report any errors, I will import and query data and report back if there are any problems with that.
<script src="https://cdn.jsdelivr.net/gh/beautifulinteractions/node-quadstore-webpack-bundle/quadstore.bundle.js"></script>
...
const { leveljs, Quadstore, DataFactory, newEngine } = quadstore;

const dataFactory = new DataFactory();

const store = new Quadstore({
	dataFactory,
	backend: leveljs("quadstore"),
	comunica: newEngine(),
});

That's good! As for the queries, I would suggest starting with using the memdown backend rather than level-js and see where that takes you. level-js uses IndexedDB, which in my experience can be incredibly slow at times.
Other than that, depending on the number of quads and the kinds of queries you are running, you might be stumbling into https://github.com/beautifulinteractions/node-quadstore/issues/115 .
Simple matching queries should be fine, though.


support for stdout output instead of file

for the json

perfect, thanks a lot

There is some garbage at the end of the stdout output. Maybe a wrong buffer size?


The specs logo is outdated

Overview
It's still the blue one - https://specs.frictionlessdata.io/

Please preserve this line to notify @lwinfree (lead of this repository)

@roll good point - these should link to a common url on frictionlessdata.io so if we update in one place it updates everywhere.

@sglavoie do you think you could look at fixing this by linking to https://frictionlessdata.io/img/frictionless-color-full-logo.svg

@rufuspollock done! I've sent this PR: https://github.com/frictionlessdata/specs/pull/729


Sample construction, truth summarization and ROC calculation and plotting

This PR contains a number of infrastructural odds and ends developed while analyzing QuOTA:
build-db.py

adds a 'training' column into the db to keep track of which profiles are being used for algorithm training
filters out (in addition to previous filters):

profiles expressed in standard levels
profiles with depth approx 0 for all levels (lots of these in quota)
profiles with corrupt or missing originator temperature qc decisions at any level that has a nominally valid temperature reading

db-utils.py

Add uid to dataframe in db_to_df, and explicitly randomize selection when unpacking less than the whole database.
summarize_truth makes sure not to count masked qc levels when summarizing per-level flags; addresses edge case where a masked level would be cast to nan, summed with legitimately flagged levels resulting in a sum of nan, which returns false when compared to zero, spoofing a clean profile.

analyze-results.py

now requires specifying a number of profiles to examine, and marks these with a 1 in the training column of the main database. This is so we can develop a ROC curve on a subset of the data, then test its performance on the remainder of the data so we don't get artificially good ROC curve performance estimates.
explicitly drop qc tests that return all true or all false

plot-roc.py

new script to plot all the profiles in the database, sorted by [true | false][positive | negative], with flags defined by a point on the ROC curve specified in roc.json. Default point is highest TP not exceeding 0.1% FP.

Thanks, @s-good - I'll wait to merge until you've had a chance to run and catch any red flags.

I ran the data ingestion and processing on the QuOTA dataset (Jan, Feb, Mar and Jun data only as these were mostly full QCed).
The data ingestion was slower than I remember but seemed to work without problem. The only issue is that the QuOTA data are split across multiple files but the build-db.py program assumes a single input file as the first thing it does is delete existing database tables. It's not a big issue, as I just comment out those lines after running the first file.
The data processing also ran without any problems (at least nothing I've seen so far). I used the new version of the EN increasing depth check for this.
I ran the summarize-results.py program and got the following output:
                       NAME OF TEST   FAILS     TPR     FPR     TNR     FNR
                              Truth   16909  100.0%    0.0%  100.0%    0.0%
            Argo_global_range_check    2274   13.4%    0.0%  100.0%   86.6%
                 Argo_gradient_test    3947   23.3%    0.1%   99.9%   76.7%
          Argo_impossible_date_test      11    0.0%    0.0%  100.0%  100.0%
      Argo_impossible_location_test       0    0.0%    0.0%  100.0%  100.0%
      Argo_pressure_increasing_test     358    0.1%    1.5%   98.5%   99.9%
           Argo_regional_range_test     176    0.8%    0.2%   99.8%   99.2%
                    Argo_spike_test    1012    6.0%    0.0%  100.0%   94.0%
              CSIRO_constant_bottom     275    0.9%    0.5%   99.5%   99.1%
                        CSIRO_depth   28239   60.5%   82.0%   18.0%   39.5%
                CSIRO_long_gradient    3838   21.9%    0.6%   99.4%   78.1%
               CSIRO_short_gradient    7478   37.5%    5.1%   94.9%   62.5%
               CSIRO_surface_spikes   20352   46.7%   56.7%   43.3%   53.3%
                   CSIRO_wire_break    3713   22.0%    0.0%  100.0%   78.0%
      CoTeDe_Argo_density_inversion    3176    9.5%    7.2%   92.8%   90.5%
          CoTeDe_GTSPP_WOA_normbias   13673   67.9%   10.0%   90.0%   32.1%
          CoTeDe_GTSPP_global_range    2398   14.1%    0.1%   99.9%   85.9%
              CoTeDe_GTSPP_gradient    3338   19.7%    0.1%   99.9%   80.3%
       CoTeDe_GTSPP_profile_envelop    4388   25.8%    0.1%   99.9%   74.2%
           CoTeDe_GTSPP_spike_check    1179    6.9%    0.0%  100.0%   93.1%
                 CoTeDe_Morello2014   24498   59.1%   66.0%   34.0%   40.9%
                CoTeDe_WOA_normbias    6023   34.8%    0.6%   99.4%   65.2%
           CoTeDe_anomaly_detection   21281   68.6%   44.1%   55.9%   31.4%
             CoTeDe_digit_roll_over    4049   23.7%    0.2%   99.8%   76.3%
                 CoTeDe_fuzzy_logic   12616   65.4%    7.1%   92.9%   34.6%
                    CoTeDe_gradient    3518   20.7%    0.1%   99.9%   79.3%
        CoTeDe_location_at_sea_test     227    0.8%    0.4%   99.6%   99.2%
              CoTeDe_rate_of_change    6489   30.9%    5.7%   94.3%   69.1%
                       CoTeDe_spike     410    2.4%    0.0%  100.0%   97.6%
               CoTeDe_tukey53H_norm    1181    4.8%    1.7%   98.3%   95.2%
      EN_background_available_check    1651    7.8%    1.5%   98.5%   92.2%
                EN_background_check    7715   44.7%    0.7%   99.3%   55.3%
            EN_constant_value_check     110    0.6%    0.0%  100.0%   99.4%
          EN_increasing_depth_check    3485   18.3%    1.8%   98.2%   81.7%
                     EN_range_check    2068   12.2%    0.0%  100.0%   87.8%
            EN_spike_and_step_check     738    4.3%    0.0%  100.0%   95.7%
          EN_spike_and_step_suspect    6054   35.6%    0.2%   99.8%   64.4%
                 EN_stability_check      66    0.2%    0.2%   99.8%   99.8%
     EN_std_lev_bkg_and_buddy_check    2740   13.1%    2.4%   97.6%   86.9%
                     EN_track_check   16882   53.1%   35.9%   64.1%   46.9%
            ICDC_aqc_01_level_order       0    0.0%    0.0%  100.0%  100.0%
            ICDC_aqc_02_crude_range    4852   28.6%    0.1%   99.9%   71.4%
          ICDC_aqc_04_max_obs_depth       8    0.0%    0.0%  100.0%  100.0%
            ICDC_aqc_05_stuck_value     287    1.7%    0.0%  100.0%   98.3%
  ICDC_aqc_06_n_temperature_extrema     408    2.3%    0.1%   99.9%   97.7%
            ICDC_aqc_07_spike_check     471    2.8%    0.0%  100.0%   97.2%
         ICDC_aqc_08_gradient_check    5499   30.1%    1.8%   98.2%   69.9%
ICDC_aqc_09_local_climatology_check   16439   70.7%   20.4%   79.6%   29.3%
                 WOD_gradient_check    5449   29.8%    1.9%   98.1%   70.2%
                    WOD_range_check    4848   28.5%    0.1%   99.9%   71.5%
              loose_location_at_sea     153    0.5%    0.3%   99.7%   99.5%
Number of profiles was 38890

I also ran the whole profile set through the analyse-results.py program and got the ROC curve below. In future I will look at running on multiple smaller sets to find a robust set of tests, but in this test set we can use combinations of tests to can find 40% of bad profiles without any mistakes.

The ROC is formed from the following tests:
ROC point:  25.6463349701 0.0 CSIRO_depth&ICDC_aqc_02_crude_range&WOD_range_check
ROC point:  35.3132580015 0.0 CoTeDe_GTSPP_WOA_normbias&EN_background_check&EN_increasing_depth_check
ROC point:  38.4014671952 0.0 CSIRO_long_gradient&CoTeDe_fuzzy_logic&ICDC_aqc_08_gradient_check&ICDC_aqc_09_local_climatology_check
ROC point:  39.5551085606 0.0 CSIRO_depth&EN_background_available_check&ICDC_aqc_02_crude_range
ROC point:  40.6259243921 0.0 CoTeDe_Argo_density_inversion&EN_background_check&EN_spike_and_step_suspect&EN_track_check
ROC point:  45.7019464 0.0272888525038 CoTeDe_fuzzy_logic&EN_increasing_depth_check&EN_track_check&ICDC_aqc_09_local_climatology_check
ROC point:  46.7550139029 0.0363851366717 CoTeDe_fuzzy_logic&EN_spike_and_step_suspect&EN_track_check&ICDC_aqc_09_local_climatology_check
ROC point:  47.9382358161 0.0545777050075 CSIRO_depth&CSIRO_long_gradient&CSIRO_short_gradient&ICDC_aqc_08_gradient_check
ROC point:  49.0504644146 0.0727702733433 CSIRO_depth&CoTeDe_Argo_density_inversion
ROC point:  50.3046796427 0.136444262519 CoTeDe_Argo_density_inversion&CoTeDe_fuzzy_logic&EN_std_lev_bkg_and_buddy_check&EN_track_check
ROC point:  51.3577471455 0.186473825442 ICDC_aqc_02_crude_range&ICDC_aqc_09_local_climatology_check
ROC point:  53.2213216589 0.304725519625 EN_background_check&EN_track_check&ICDC_aqc_09_local_climatology_check
ROC point:  54.5997751878 0.400236503388 CSIRO_surface_spikes&CoTeDe_fuzzy_logic&EN_track_check&ICDC_aqc_09_local_climatology_check
ROC point:  55.7001715672 0.495747487151 CoTeDe_fuzzy_logic&EN_std_lev_bkg_and_buddy_check&EN_track_check&ICDC_aqc_09_local_climatology_check
ROC point:  59.9242737976 0.968754263883 CoTeDe_GTSPP_WOA_normbias&CoTeDe_fuzzy_logic&EN_track_check&ICDC_aqc_09_local_climatology_check
ROC point:  61.7286872153 1.19616136808 CSIRO_surface_spikes&EN_background_check
ROC point:  63.3437851269 1.41447218811 CoTeDe_Morello2014&CoTeDe_anomaly_detection&EN_background_available_check&EN_track_check
ROC point:  64.5388392593 1.5873015873 EN_spike_and_step_suspect
ROC point:  65.5741584334 1.80561240733 EN_background_check&ICDC_aqc_09_local_climatology_check
ROC point:  66.7337159084 2.05576022195 EN_std_lev_bkg_and_buddy_check&EN_track_check
ROC point:  68.5381293262 2.6379224087 CoTeDe_GTSPP_WOA_normbias&CoTeDe_anomaly_detection&EN_track_check&ICDC_aqc_09_local_climatology_check
ROC point:  69.7627640064 3.16095874835 CoTeDe_GTSPP_WOA_normbias&CoTeDe_fuzzy_logic&EN_track_check
ROC point:  71.7919895876 4.08877973348 CoTeDe_GTSPP_WOA_normbias&CoTeDe_anomaly_detection&CoTeDe_fuzzy_logic&ICDC_aqc_09_local_climatology_check
ROC point:  72.8746376383 4.6209123573 CSIRO_long_gradient
ROC point:  74.7973732474 5.64879246828 CoTeDe_GTSPP_WOA_normbias&EN_track_check
ROC point:  76.1462462285 6.48565061173 CSIRO_depth&CSIRO_short_gradient&EN_track_check
ROC point:  78.1695557002 7.86828580525 EN_increasing_depth_check
ROC point:  79.3468615039 8.7324328012 CoTeDe_Morello2014&EN_background_available_check
ROC point:  80.4117612258 9.59657979715 CoTeDe_fuzzy_logic&ICDC_aqc_09_local_climatology_check
ROC point:  82.523812341 11.5340883249 CSIRO_surface_spikes&CoTeDe_anomaly_detection&EN_track_check
ROC point:  83.6715375969 12.8848865239 CoTeDe_anomaly_detection&EN_track_check&ICDC_aqc_09_local_climatology_check
ROC point:  85.2629710702 15.7320234684 CSIRO_short_gradient
ROC point:  86.3456191209 17.9742575158 CoTeDe_Argo_density_inversion&CoTeDe_anomaly_detection
ROC point:  87.7299887594 22.2813480693 CoTeDe_GTSPP_WOA_normbias
ROC point:  89.0019523162 26.324646382 CSIRO_surface_spikes&EN_track_check
ROC point:  94.9003135538 46.2591531359 EN_track_check
ROC point:  96.4148376028 56.1831991631 ICDC_aqc_09_local_climatology_check
ROC point:  97.722297817 68.7042343203 CoTeDe_anomaly_detection
ROC point:  99.4438857008 95.7929685723 CoTeDe_Morello2014

So it seems like things are working well!.

@s-good looks consistent with what I reported to @BoyerWOD earlier this month, so these changes should be good to go; regarding the table drop, that's there for the sake of idempotency, which is a good default but not required. The last commit drops this, making it simpler to ingest multiple files, but will require us to be careful not to run over the same data twice (which is actually not so risky now that uids are a primary key - sqlite will throw an error if we make this mistake).


Emoji Colours

It occurs to me that these symbols may be seen as Emoji (even though they're not in that block).
Creating a colour version of the font may aid adoption in, for example

https://github.com/eosrei/emojione-color-font
https://github.com/twitter/twemoji
http://emojione.com/

If so, which colours would you suggest?

⏻ Red
⏼ Red
⏽ Green
⏾ Silver
⭘ Red

Thoughts?

I've seen the power symbol on devices in green, blue, and white---never
red, I think. It makes sense, though, in combination with green and red for
on and off. [Silver for the moon---of course!]
The very first question UTC will ask, naturally, is `is there already a
published standard for HMI colours, since these are all HMI related?' I'll
bet the military has one.
Joe
On Sat, Mar 5, 2016 at 11:28 AM, Terence Eden<EMAIL_ADDRESS>wrote:

It occurs to me that these symbols may be seen as Emoji (even though
they're not in that block).
Creating a colour version of the font may aid adoption in, for example

https://github.com/eosrei/emojione-color-font
https://github.com/twitter/twemoji
http://emojione.com/faq/

If so, which colours would you suggest?

⏻ Red
⏼ Red
⏽ Green
⏾ Silver
⭘ Red

Thoughts?
—
Reply to this email directly or view it on GitHub
https://github.com/jloughry/Unicode/issues/9.

I'd like to add the b&w glyphs to https://github.com/eosrei/emojione-color-font Q: Are the power symbol code points approved for color emoji versions? Seems as though only certain code points are "supposed" to have color versions.

@eosrei There's no "official" colouring - but, for example ⚛ doesn't have any colour associated with it in unicode, but it's blue and red in your font. Similarly, I don't think that (absent of skin tone modifiers) there's anything which says 😌 should be yellow.  And I don't think that 💃 specifies a red dress (or male/female - but that's another question!)
For use in "regular" fonts, the colour doesn't add any semantic meaning - so I don't think it's up to UTC to agree on a set colour.
For adoption on popular social networking sites, I think it would be helpful (and more fun) to have them coloured.
We currently use red on the website, but I'm happy to see it changed to a more interesting / useful colour.

There's no "official" colouring - but, for example ⚛ doesn't have any colour associated with it in unicode, but it's blue and red in your font.

According to: https://github.com/Ranks/emojione/issues/171#issuecomment-166461932 Emoji One uses: http://www.unicode.org/emoji/charts/full-emoji-list.html (warning HUGE page) to determine which whether to make emoji. So there isn't an official specific color, but Unicode does specify whether there should be color at all. That being said, I believe these power symbols should be added to that list, so I have no problem adding before it's official: http://www.unicode.org/emoji/selection.html

For adoption on popular social networking sites, I think it would be helpful (and more fun) to have them coloured.

I completely agree. Colorize all the symbols! I'm already planning on adding the BTC glyph with a color emoji since reading this issue.

Similarly, I don't think that (absent of skin tone modifiers) there's anything which says :relieved: should be yellow.

Unicode specifies that faces/people should be non-realistic colors in the absence of skin tone modifiers: http://www.unicode.org/reports/tr51/#non-realistic
I prefer the green for power, something like this:

src The "emoji" style can be far more complicated.
@maximusmaximus Ping! Want to make the official SVG color emoji?


Add NotifySyncPushCommits to indexer notifier

Thanks to @simon-on-gh for tracking down the issue.
Fix #11200
Signed-off-by: Andrew Thornton<EMAIL_ADDRESS>

make lg-tm


Create subpackage for functionality reliant on tableauhyperapi.

Background
This is a fix for https://github.com/hoverinc/tableau-utilities/issues/75.  On newer apple computers installation fails because tableauhyperapi is not compatible with Apple Silicon machines: https://tableau.github.io/hyper-db/docs/installation#hardware-requirements
This PR:

Changes hyperapi dependent functionality into a optionally installed subpackage
Updates the cli and Airflow example to use new subpackage
Change short cli commands to be all lowercase and multiple letters. This conforms to the style in the rest of the cli.
Adds new attribute of max_varchar_size to Connection object.  This appears in a Snowflake extract with Tableau 2024.1
Adds Python Version specification as Pandas installation dependency will fail if the user has Python 3.7

Testing
Installation
pip install ./ this installed the tableau_utilities but did not install the tableauhyperapi dependency
pip install ./[hyper] this DID install the tableauhyperapi dependency
CLI Commands
cli throws error when package is not installed
-ee flag
tableau_utilities --token_name $TABLEAU_PAT_NAME --token_secret $TABLEAU_PAT_VALUE --site $TABLEAU_SITE_NAME --server $TABLEAU_SERVER  --location online --name call_center --project_name 'default' -f Datasource.tdsx datasource -ee
usage: tableau_utilities [-h] [--version] [-d] [-s SERVER] [-sn SITE_NAME] [--api_version API_VERSION] [-u USER] [-p PASSWORD] [-ts TOKEN_SECRET] [-tn TOKEN_NAME]
                         [--settings_path SETTINGS_PATH] [-o OUTPUT_DIR] [-c] [-l {local,online}] [-i ID] [-n NAME] [-pn PROJECT_NAME] [-f FILE_PATH]
                         [--definitions_csv DEFINITIONS_CSV] [--include_extract] [-tds] [--conn_user CONN_USER] [--conn_pw CONN_PW] [--conn_type CONN_TYPE]
                         [--conn_db CONN_DB] [--conn_schema CONN_SCHEMA] [--conn_host CONN_HOST] [--conn_role CONN_ROLE] [--conn_warehouse CONN_WAREHOUSE]
                         {server_info,server_operate,datasource,generate_config,csv_config,merge_config} ...
tableau_utilities: error: --filter_extract and --empty_extract require the tableau_utilities[hyper] subpackage.  See installation notes if you are on an Apple Silicon (Apple M1, Apple M2, ...)

-fe flag
tableau_utilities --token_name $TABLEAU_PAT_NAME --token_secret $TABLEAU_PAT_VALUE --site $TABLEAU_SITE_NAME --server $TABLEAU_SERVER  --location online --name call_center --project_name 'default' -f Datasource.tdsx datasource -fe 'Cc Class = medium'
usage: tableau_utilities [-h] [--version] [-d] [-s SERVER] [-sn SITE_NAME] [--api_version API_VERSION] [-u USER] [-p PASSWORD] [-ts TOKEN_SECRET] [-tn TOKEN_NAME]
                         [--settings_path SETTINGS_PATH] [-o OUTPUT_DIR] [-c] [-l {local,online}] [-i ID] [-n NAME] [-pn PROJECT_NAME] [-f FILE_PATH]
                         [--definitions_csv DEFINITIONS_CSV] [--include_extract] [-tds] [--conn_user CONN_USER] [--conn_pw CONN_PW] [--conn_type CONN_TYPE]
                         [--conn_db CONN_DB] [--conn_schema CONN_SCHEMA] [--conn_host CONN_HOST] [--conn_role CONN_ROLE] [--conn_warehouse CONN_WAREHOUSE]
                         {server_info,server_operate,datasource,generate_config,csv_config,merge_config} ...
tableau_utilities: error: --filter_extract and --empty_extract require the tableau_utilities[hyper] subpackage.  See installation notes if you are on an Apple Silicon (Apple M1, Apple M2, ...)

Testing Functions WITH sub-page installed
Download empty extract
tableau_utilities --token_name $TABLEAU_PAT_NAME --token_secret $TABLEAU_PAT_VALUE --site $TABLEAU_SITE_NAME --server $TABLEAU_SERVER  --location online --name call_center --project_name 'default' -f Datasource.tdsx datasource -ee
...Downloading call_center...
✅  (Done in 1 sec) Downloaded Datasource: /Users/jayrosenthal/code/tableau-utilities/tmp_tdsx_and_config/call_center.tdsx

Added empty .hyper extract for /Users/jayrosenthal/code/tableau-utilities/tmp_tdsx_and_config/call_center.tdsx
...Saving datasource changes...
✅ (Done in 0 sec) Saved datasource changes: /Users/jayrosenthal/code/tableau-utilities/tmp_tdsx_and_config/call_center.tdsx

Publish Empty Extract
tableau_utilities --token_name $TABLEAU_PAT_NAME --token_secret $TABLEAU_PAT_VALUE --site $TABLEAU_SITE_NAME --server $TABLEAU_SERVER --name call_center --project_name 'default' -f '/Users/jayrosenthal/code/tableau-utilities/tmp_tdsx_and_config/call_center.tdsx' server_operate --publish datasource
PUBLISHING DATASOURCE → ID: cda42c94-d287-4ab2-9935-225ceb3a7d6a ║ NAME: call_center ║ PROJECT NAME: default
✅  default / call_center:
Workbook can be created but the data is empty

Download with Filter
tableau_utilities --token_name $TABLEAU_PAT_NAME --token_secret $TABLEAU_PAT_VALUE --site $TABLEAU_SITE_NAME --server $TABLEAU_SERVER  --location online --name call_center --project_name 'default' -f Datasource.tdsx --include_extract datasource -fe ""CC_REC_START_DATE" < '1/1/2001'"
...Downloading call_center...
✅  (Done in 1 sec) Downloaded Datasource: /Users/jayrosenthal/code/tableau-utilities/tmp_tdsx_and_config/call_center.tdsx
...Filtering extract data...
✅ (Done in 0 sec) Filtered extract data for /Users/jayrosenthal/code/tableau-utilities/tmp_tdsx_and_config/call_center.tdsx
(venv) jaysmacbookhome:tableau-utilities jayrosenthal$
Publish filtered datasets
tableau_utilities --token_name $TABLEAU_PAT_NAME --token_secret $TABLEAU_PAT_VALUE --site $TABLEAU_SITE_NAME --server $TABLEAU_SERVER --name call_center --project_name 'default' -f '/Users/jayrosenthal/code/tableau-utilities/tmp_tdsx_and_config/call_center.tdsx' server_operate --publish datasource
PUBLISHING DATASOURCE → ID: cda42c94-d287-4ab2-9935-225ceb3a7d6a ║ NAME: call_center ║ PROJECT NAME: default
✅  default / call_center:
Pre-filtered set has data in 1998 and 2000

Publish after filter on has data in 2001 and 2002

@JustinGrilli  this is ready for review.  I tested all functionality in the cli and it works like a charm!  Replacing the functions in Airflow and setting the new import should be really really easy.
If you're willing to merge this without testing Airflow that would be great. I have a couple of things to do before I can get Airflow working with extracts and all that stuff.  If I'm a total insomniac this weekend then I'll try to get to it otherwise it'll be later this week.


how can i update the slider value when the zoom has been updated by others

Description
Please provide a brief description of the issue including what you are seeing as well as the expected behavior.
CodeSandbox
Please provide a CodeSandbox that clearly reproduces the issue. Issues without a CodeSandbox are less likely to get resolved quickly.

If you go to the documentation, there is an example that shows you how to programmatically resize the slider.


Authorized error on a query with a parent list with a nested object which has @auth

Not sure if it is a bug, but it feels like one. With the following code i get: Not Authorized to access ad on type Person
The query itself works, but with the above error. A person can have one ad and an ad can have multiple persons.
When i query the ads alone it works and i only get the back ads where the ads.editor array field contains the username. For Example ["myUsername","anotherOne"]
Amplify CLI Version
4.40.1
Node: v14.15.3
To Reproduce
type Person
  @auth(
    rules: [
      {
        allow: owner
        ownerField: "customerID"
        identityClaim: "custom:customerID"
      }
    ]
  )
  @key(
    name: "byCustomerID"
    fields: ["customerID"]
    queryField: "personByCustomerID"
  )
  @model {
  id: ID!
customerID: ID!
  firstname: String
  lastname: String!
  ad: Ad @connection(fields: ["adID"])
  adID: ID!
}

type Ad
  @model
  @key(
    name: "byCustomerID"
    fields: ["customerID"]
    queryField: "adByCustomerID"
  )
  @auth(
    rules: [
       { allow: owner, ownerField: "editors" }
    ]
  ) {
  id: ID!
customerID: ID!
  name: String
  editors: [String]
}

Query:
API.graphql(
      graphqlOperation(queries.personList)
    );

Expected behavior
When i query the Person table, the persons where the username isn´t in the ads.editors array field are ignored.

@benjamin79 Could you share the query used here in both Person and Ad. You could try runing these queries in  appsync  console  and easily switch users.
One other thing I would be interested in knowing is is for the Person type that you get from the query, is the corresponding Ad in Person.ad, does it have the current users username as editor?

@benjamin79 Could you share the query used here in both Person and Ad. You could try runing these queries in  appsync  console  and easily switch users.
One other thing I would be interested in knowing is is for the Person type that you get from the query, is the corresponding Ad in Person.ad, does it have the current users username as editor?

@benjamin79 Could you share the query used here in both Person and Ad. You could try runing these queries in appsync console and easily switch users.
One other thing I would be interested in knowing is is for the Person type that you get from the query, is the corresponding Ad in Person.ad, does it have the current users username as editor?

@yuth
thanks for helping
query PersonByCustomerId(
  $customerID: ID
  $sortDirection: ModelSortDirection
  $filter: ModelPersonFilterInput
  $limit: Int
  $nextToken: String
) {
  personByCustomerID(
    customerID: $customerID
    sortDirection: $sortDirection
    filter: $filter
    limit: $limit
    nextToken: $nextToken
  ) {
    items {
      id
      firstname
      lastname
      customerID
      ad {
        id
        customerID
        editor
        name
        editors
        createdAt
        updatedAt
      }
      adID
      adIDName
      createdAt
      updatedAt
    }
    nextToken
  }
}

query MyQuery {
  adByCustomerID(customerID: "1") {
    nextToken
    items {
      id
      editor
      editors
      name
    }
  }
}

I get the same error in the appsync console with the first query
Regarding our last question:
No, not ever ad should be visible to all users. So no, the current user is not alway in the editors field.
For example:
I have 2 ads in the db:
One editors field  might look like:
  "id: 1",
  "editors": {
    "L": [
      {
        "S": "user1"
      },
      {
        "S": "user3"
      }
    ]
  },

Another ad editors field:
 "id: 2",
  "editors": {
    "L": [
      {
        "S": "user2"
      }
    ]
  },

So if user2 for example is the current logged in user id only like to get back persons where the editors field in the connected ad lists the user2 in the array. At the moment i get back all persons and also the above error.
So for example if there are 2 persons in the db table and person 1 has the ad Id 1 and the next one ad id 2. I would expect only to get back one person when the current user is user2.

@benjamin79 Could you share the query used here in both Person and Ad. You could try runing these queries in appsync console and easily switch users.
One other thing I would be interested in knowing is is for the Person type that you get from the query, is the corresponding Ad in Person.ad, does it have the current users username as editor?

@yuth
thanks for helping
query PersonByCustomerId(
  $customerID: ID
  $sortDirection: ModelSortDirection
  $filter: ModelPersonFilterInput
  $limit: Int
  $nextToken: String
) {
  personByCustomerID(
    customerID: $customerID
    sortDirection: $sortDirection
    filter: $filter
    limit: $limit
    nextToken: $nextToken
  ) {
    items {
      id
      firstname
      lastname
      customerID
      ad {
        id
        customerID
        editor
        name
        editors
        createdAt
        updatedAt
      }
      adID
      adIDName
      createdAt
      updatedAt
    }
    nextToken
  }
}

query MyQuery {
  adByCustomerID(customerID: "1") {
    nextToken
    items {
      id
      editor
      editors
      name
    }
  }
}

I get the same error in the appsync console with the first query
Regarding our last question:
No, not ever ad should be visible to all users. So no, the current user is not alway in the editors field.
For example:
I have 2 ads in the db:
One editors field  might look like:
  "id: 1",
  "editors": {
    "L": [
      {
        "S": "user1"
      },
      {
        "S": "user3"
      }
    ]
  },

Another ad editors field:
 "id: 2",
  "editors": {
    "L": [
      {
        "S": "user2"
      }
    ]
  },

So if user2 for example is the current logged in user id only like to get back persons where the editors field in the connected ad lists the user2 in the array. At the moment i get back all persons and also the above error.
So for example if there are 2 persons in the db table and person 1 has the ad Id 1 and the next one ad id 2. I would expect only to get back one person when the current user is user2.

@benjamin79 I see you have updated the schema to include @auth directive for Person type with identityClaim to be present in custom:customerID.  What error do you get when you run the first query? Do you manage to get any of the Person listed with that query.
Since you are using a custom identity claim, I am assuming you already have configured Cognito Lambda trigger to update the JWT token with custom:customerID field and you're using Id JWT token instead of Access JWT Token as custom claims won't be present in Access Token

@benjamin79 I see you have updated the schema to include @auth directive for Person type with identityClaim to be present in custom:customerID.  What error do you get when you run the first query? Do you manage to get any of the Person listed with that query.
Since you are using a custom identity claim, I am assuming you already have configured Cognito Lambda trigger to update the JWT token with custom:customerID field and you're using Id JWT token instead of Access JWT Token as custom claims won't be present in Access Token

@benjamin79 I see you have updated the schema to include @auth directive for Person type with identityClaim to be present in custom:customerID. What error do you get when you run the first query? Do you manage to get any of the Person listed with that query.
Since you are using a custom identity claim, I am assuming you already have configured Cognito Lambda trigger to update the JWT token with custom:customerID field and you're using Id JWT token instead of Access JWT Token as custom claims won't be present in Access Token

@yuth
It doesn´t matter if the claim is in it or not. The error is the same. I made sure by creating two new tables with a different name without the claim and did a new push.

@benjamin79 I see you have updated the schema to include @auth directive for Person type with identityClaim to be present in custom:customerID. What error do you get when you run the first query? Do you manage to get any of the Person listed with that query.
Since you are using a custom identity claim, I am assuming you already have configured Cognito Lambda trigger to update the JWT token with custom:customerID field and you're using Id JWT token instead of Access JWT Token as custom claims won't be present in Access Token

@yuth
It doesn´t matter if the claim is in it or not. The error is the same. I made sure by creating two new tables with a different name without the claim and did a new push.

I can't think of any reason for getting Not Authorized to access ad on type Person. I used the your schema except for the identityClaim and managed to get the results for personByCustomerID. Could you share the your complete schema and also share the default auth mode used for API. Also wondering if you have overridden any of the resolvers

I can't think of any reason for getting Not Authorized to access ad on type Person. I used the your schema except for the identityClaim and managed to get the results for personByCustomerID. Could you share the your complete schema and also share the default auth mode used for API. Also wondering if you have overridden any of the resolvers

@yuth To make sure nothing else got in the way i made a complete new project with amplify init. Mostly with default values. ->

https://gist.github.com/benjamin79/178a6666e8c44d8ec21dc74e5ba0ba50

It then put in the following schema:

type Person
  @model
 {
  id: ID!
  firstname: String
  lastname: String
  ad: Ad @connection(fields: ["adID"])
  adID: ID!
  adIDName: String
}

type Ad
  @model
    @auth(
    rules: [
       { allow: owner, ownerField: "editors" }
    ]
  )
  {
  id: ID!
  editor: String
  name: String
  editors: [String]
}

In the tables i put:
Person:

{
  "id": {
    "S": "e623e897-f246-4b97-a37a-c20c468fb449"
  },
  "firstname": {
    "S": "John"
  },
  "__typename": {
    "S": "Person"
  },
  "lastname": {
    "S": "Doe"
  },
  "adID": {
    "S": "c0b29e30-93db-4fce-8bda-2a17f0a7f98c"
  }
}

{
  "id": {
    "S": "b829d7c9-9159-4d73-ac21-960090f42c6e"
  },
  "firstname": {
    "S": "foo"
  },
  "__typename": {
    "S": "Person"
  },
  "lastname": {
    "S": "faa"
  },
  "adID": {
    "S": "9644a286-a5db-4932-af63-aba4f1373629"
  }
}

Ad:
 {
  "id": {
    "S": "c0b29e30-93db-4fce-8bda-2a17f0a7f98c"
  },
  "__typename": {
    "S": "Ad"
  },
  "editors": {
    "L": [
      {
        "S": "travis"
      },
      {
        "S": "gravis"
      }
    ]
  },
  "editor": {
    "S": "travis"
  },
  "name": {
    "S": "MyAd1.pdf"
  }
}

{
  "id": {
    "S": "9644a286-a5db-4932-af63-aba4f1373629"
  },
  "__typename": {
    "S": "Ad"
  },
  "editors": {
    "L": [
      {
        "S": "fravis"
      }
    ]
  },
  "editor": {
    "S": "fravis"
  },
  "name": {
    "S": "MyAd2.pdf"
  }
}

Created user fravis in cognito user pools and added custom attribute customerID  (not necessary). Set password.

Authenticated in the appsnc console and run following query:

query MyQuery {
  listPersons {
    items {
      adID
      firstname
      lastname
      adIDName
      ad {
        name
      }
    }
  }
}

Got following result with same error:
{
  "data": {
    "listPersons": {
      "items": [
        {
          "adID": "c0b29e30-93db-4fce-8bda-2a17f0a7f98c",
          "firstname": "John",
          "lastname": "Doe",
          "adIDName": null,
          "ad": null
        },
        {
          "adID": "9644a286-a5db-4932-af63-aba4f1373629",
          "firstname": "foo",
          "lastname": "faa",
          "adIDName": null,
          "ad": {
            "name": "MyAd2.pdf"
          }
        }
      ]
    }
  },
  "errors": [
    {
      "path": [
        "listPersons",
        "items",
        0,
        "ad"
      ],
      "data": null,
      "errorType": "Unauthorized",
      "errorInfo": null,
      "locations": [
        {
          "line": 8,
          "column": 7,
          "sourceName": null
        }
      ],
      "message": "Not Authorized to access ad on type Person"
    }
  ]
}

Expected result should be:
...
 "items": [
        {
          "adID": "9644a286-a5db-4932-af63-aba4f1373629",
          "firstname": "foo",
          "lastname": "faa",
          "adIDName": null,
          "ad": {
            "name": "MyAd2.pdf"
          }
        }
      ]
...

Cause user fravis is only listed in the ad MyAd2.pdf in he editors array list.
When i query only the ads:
query MyQuery {
  listAds {
    items {
      editor
      editors
      id
      name
    }
  }
}

I correctly returns only the one ad where the current user fravis is listed.
Hope this helps.
thanks

@yuth To make sure nothing else got in the way i made a complete new project with amplify init. Mostly with default values. ->

https://gist.github.com/benjamin79/178a6666e8c44d8ec21dc74e5ba0ba50

It then put in the following schema:

type Person
  @model
 {
  id: ID!
  firstname: String
  lastname: String
  ad: Ad @connection(fields: ["adID"])
  adID: ID!
  adIDName: String
}

type Ad
  @model
    @auth(
    rules: [
       { allow: owner, ownerField: "editors" }
    ]
  )
  {
  id: ID!
  editor: String
  name: String
  editors: [String]
}

In the tables i put:
Person:

{
  "id": {
    "S": "e623e897-f246-4b97-a37a-c20c468fb449"
  },
  "firstname": {
    "S": "John"
  },
  "__typename": {
    "S": "Person"
  },
  "lastname": {
    "S": "Doe"
  },
  "adID": {
    "S": "c0b29e30-93db-4fce-8bda-2a17f0a7f98c"
  }
}

{
  "id": {
    "S": "b829d7c9-9159-4d73-ac21-960090f42c6e"
  },
  "firstname": {
    "S": "foo"
  },
  "__typename": {
    "S": "Person"
  },
  "lastname": {
    "S": "faa"
  },
  "adID": {
    "S": "9644a286-a5db-4932-af63-aba4f1373629"
  }
}

Ad:
 {
  "id": {
    "S": "c0b29e30-93db-4fce-8bda-2a17f0a7f98c"
  },
  "__typename": {
    "S": "Ad"
  },
  "editors": {
    "L": [
      {
        "S": "travis"
      },
      {
        "S": "gravis"
      }
    ]
  },
  "editor": {
    "S": "travis"
  },
  "name": {
    "S": "MyAd1.pdf"
  }
}

{
  "id": {
    "S": "9644a286-a5db-4932-af63-aba4f1373629"
  },
  "__typename": {
    "S": "Ad"
  },
  "editors": {
    "L": [
      {
        "S": "fravis"
      }
    ]
  },
  "editor": {
    "S": "fravis"
  },
  "name": {
    "S": "MyAd2.pdf"
  }
}

Created user fravis in cognito user pools and added custom attribute customerID  (not necessary). Set password.

Authenticated in the appsnc console and run following query:

query MyQuery {
  listPersons {
    items {
      adID
      firstname
      lastname
      adIDName
      ad {
        name
      }
    }
  }
}

Got following result with same error:
{
  "data": {
    "listPersons": {
      "items": [
        {
          "adID": "c0b29e30-93db-4fce-8bda-2a17f0a7f98c",
          "firstname": "John",
          "lastname": "Doe",
          "adIDName": null,
          "ad": null
        },
        {
          "adID": "9644a286-a5db-4932-af63-aba4f1373629",
          "firstname": "foo",
          "lastname": "faa",
          "adIDName": null,
          "ad": {
            "name": "MyAd2.pdf"
          }
        }
      ]
    }
  },
  "errors": [
    {
      "path": [
        "listPersons",
        "items",
        0,
        "ad"
      ],
      "data": null,
      "errorType": "Unauthorized",
      "errorInfo": null,
      "locations": [
        {
          "line": 8,
          "column": 7,
          "sourceName": null
        }
      ],
      "message": "Not Authorized to access ad on type Person"
    }
  ]
}

Expected result should be:
...
 "items": [
        {
          "adID": "9644a286-a5db-4932-af63-aba4f1373629",
          "firstname": "foo",
          "lastname": "faa",
          "adIDName": null,
          "ad": {
            "name": "MyAd2.pdf"
          }
        }
      ]
...

Cause user fravis is only listed in the ad MyAd2.pdf in he editors array list.
When i query only the ads:
query MyQuery {
  listAds {
    items {
      editor
      editors
      id
      name
    }
  }
}

I correctly returns only the one ad where the current user fravis is listed.
Hope this helps.
thanks

@benjamin79 Following up on this, are you still running into this issue?
I based on the last schema you provided I was able to create an ad and then create a person with said ad. I also had no issues getting access to listPersons.
Could you provide the auth mode which you have setup for your project? I tried it with the following authConfig
You can find this config in amplify/backend/backend-config.json
"api": {
    "fern": {
      "service": "AppSync",
      "providerPlugin": "awscloudformation",
      "output": {
        "authConfig": {
          "defaultAuthentication": {
            "authenticationType": "AMAZON_COGNITO_USER_POOLS",
            "userPoolConfig": {
              "userPoolId": "authfernaXXXXXX"
            }
          },
          "additionalAuthenticationProviders": []
        }
      }
    }
  }

@benjamin79 Following up on this, are you still running into this issue?
I based on the last schema you provided I was able to create an ad and then create a person with said ad. I also had no issues getting access to listPersons.
Could you provide the auth mode which you have setup for your project? I tried it with the following authConfig
You can find this config in amplify/backend/backend-config.json
"api": {
    "fern": {
      "service": "AppSync",
      "providerPlugin": "awscloudformation",
      "output": {
        "authConfig": {
          "defaultAuthentication": {
            "authenticationType": "AMAZON_COGNITO_USER_POOLS",
            "userPoolConfig": {
              "userPoolId": "authfernaXXXXXX"
            }
          },
          "additionalAuthenticationProviders": []
        }
      }
    }
  }

@SwaySway thanks for looking into it. Yes same error. The authConfig is the same.
You need to put in a second item in the Ad table where the current user is not listet. So when the current user is: fravis and you list only travis and gravis in the editors field the error will come up. If you change for example travis to fravis the error is gone.
 {
  "id": {
    "S": "c0b29e30-93db-4fce-8bda-2a17f0a7f98c"
  },
  "__typename": {
    "S": "Ad"
  },
  "editors": {
    "L": [
      {
        "S": "travis"
      },
      {
        "S": "gravis"
      }
    ]
  },
  "editor": {
    "S": "travis"
  },
  "name": {
    "S": "MyAd1.pdf"
  }
}

@SwaySway thanks for looking into it. Yes same error. The authConfig is the same.
You need to put in a second item in the Ad table where the current user is not listet. So when the current user is: fravis and you list only travis and gravis in the editors field the error will come up. If you change for example travis to fravis the error is gone.
 {
  "id": {
    "S": "c0b29e30-93db-4fce-8bda-2a17f0a7f98c"
  },
  "__typename": {
    "S": "Ad"
  },
  "editors": {
    "L": [
      {
        "S": "travis"
      },
      {
        "S": "gravis"
      }
    ]
  },
  "editor": {
    "S": "travis"
  },
  "name": {
    "S": "MyAd1.pdf"
  }
}

@benjamin79
Yea the flow here is an entity such as fravis is logged on and they can create a person with a linked ad as there are no auth rules on person. Same thing would apply if running a query such as listPersons. Though since there are auth rules added on Ad a person such as fravis should not be able to read ads where they are not the editor or in editors. If you are looking at only protecting create/update/delete and not read you can specify that in the auth rule for Ad this way anyone can read Ads. Where fravis would be able to read records. Read more on auth rules here: https://docs.amplify.aws/cli/graphql-transformer/auth

@benjamin79
Yea the flow here is an entity such as fravis is logged on and they can create a person with a linked ad as there are no auth rules on person. Same thing would apply if running a query such as listPersons. Though since there are auth rules added on Ad a person such as fravis should not be able to read ads where they are not the editor or in editors. If you are looking at only protecting create/update/delete and not read you can specify that in the auth rule for Ad this way anyone can read Ads. Where fravis would be able to read records. Read more on auth rules here: https://docs.amplify.aws/cli/graphql-transformer/auth

@SwaySway
I´m not sure how this can be done.
I´ve added public / private  to the ad type. But this doesn´t solve it. Now i still get back 2 persons. Just without the error message. But it should return only 1 Person. Cause the fravis is not listed in the editors array of "MyAd1.pdf"
How do i do that?
type Ad
  @model
    @auth(
    rules: [
       { allow: owner, ownerField: "editors" },
       { allow: public, operations: [read] }
    ]
  )
  {
  id: ID!
  editor: String
  name: String
  editors: [String]
}

@SwaySway
I´m not sure how this can be done.
I´ve added public / private  to the ad type. But this doesn´t solve it. Now i still get back 2 persons. Just without the error message. But it should return only 1 Person. Cause the fravis is not listed in the editors array of "MyAd1.pdf"
How do i do that?
type Ad
  @model
    @auth(
    rules: [
       { allow: owner, ownerField: "editors" },
       { allow: public, operations: [read] }
    ]
  )
  {
  id: ID!
  editor: String
  name: String
  editors: [String]
}

It sounds like you are looking for authorization logic on the person type perhaps you can keep it consistent by adding owner auth on the person model type as well?

It sounds like you are looking for authorization logic on the person type perhaps you can keep it consistent by adding owner auth on the person model type as well?

@SwaySway
No, that is not possible cause of the dynamic nature. For example if i have 10.000 persons which have the assigend the same ad. Now if the ad gets added or removed a user, i would have to update 10.000 persons. That seems like a costly operation if it happens multiple times.
Any idea how to solve this?

@SwaySway
No, that is not possible cause of the dynamic nature. For example if i have 10.000 persons which have the assigend the same ad. Now if the ad gets added or removed a user, i would have to update 10.000 persons. That seems like a costly operation if it happens multiple times.
Any idea how to solve this?

@benjamin79
One thing you can do is create an auth rule to limit access to how many persons a user can see. The second thing could be to create an auth rule that only allows users to read into Ad. This way any person can read the ad that is assigned to them. Additionally if that user runs listPersons. They should only see records related to them via some auth rule.
This is more a discussion based question. For this I recommend our discord server: https://discord.com/invite/jWVbPfC
Here you can speak with other members on how to potentially address this further.
Closing this issue as there are no actionable items to take in the CLI.

@benjamin79
One thing you can do is create an auth rule to limit access to how many persons a user can see. The second thing could be to create an auth rule that only allows users to read into Ad. This way any person can read the ad that is assigned to them. Additionally if that user runs listPersons. They should only see records related to them via some auth rule.
This is more a discussion based question. For this I recommend our discord server: https://discord.com/invite/jWVbPfC
Here you can speak with other members on how to potentially address this further.
Closing this issue as there are no actionable items to take in the CLI.

@SwaySway Please allow me once more:
Something like this:
type User @model {
  id: ID!
  something:
    @connection(name: "UserSomethings")
    @auth(rules: [{ allow: owner, ownerField: "usernames" }])
}

type Something @model(queries: null) {usernames: [String] }

Is not possible? So i can´t do auth on a field in a connection?

@SwaySway Please allow me once more:
Something like this:
type User @model {
  id: ID!
  something:
    @connection(name: "UserSomethings")
    @auth(rules: [{ allow: owner, ownerField: "usernames" }])
}

type Something @model(queries: null) {usernames: [String] }

Is not possible? So i can´t do auth on a field in a connection?


Slower check rate on battery

Is your feature request related to an idea? Please describe and specify functionality.
Slow the check cycle and rate down when on battery power to conserve battery
Describe the solution you'd like
Something like make the program check and update status every 5 seconds to save battery

Yes!


Unknown Model while trying to pretrain

I keep getting this error while following the readme to start a "Pre-train eva02_Ti_pt_in21k_p14 on IN-21K using 5 nodes x 8 gpus per node (click to expand).":
Traceback (most recent call last):
  File "EVA-02/asuka/run_eva02_pretraining.py", line 501, in <module>
    main(opts, ds_init)
  File "EVA-02/asuka/run_eva02_pretraining.py", line 288, in main
    model = get_model(args)
  File "EVA-02/asuka/run_eva02_pretraining.py", line 234, in get_model
    model = create_model(
  File "miniconda3/envs/eva2/lib/python3.9/site-packages/timm/models/factory.py", line 71, in create_model
    raise RuntimeError('Unknown model (%s)' % model_name)
RuntimeError: Unknown model (eva02_tiny_patch14_xattn_fusedLN_SwiGLU_preln_RoPE_xavier_normal_init)

Problem was a mismatch in time version..


ImportError: ~/anaconda3/lib/python3.7/site-packages/inplace_abn/_backend.cpython-37m-x86_64-linux-gnu.so: undefined symbol: _ZN6caffe26detail36_typeMetaDataInstance_preallocated_7E

Using CUDA 11.3 , PyTorch v1.7, Ubuntu 18.04.5 LTS. While executing:
python -m torch.distributed.launch --nproc_per_node=1 test_panoptic.py --meta metadata.bin --log_dir ~/logs config.ini seamseg_r50_vistas.tar /home/rapires/images /home/rapires/predictions
Given the following error. If anyone can provide help it will be much appreciated:
Traceback (most recent call last):
File "test_panoptic.py", line 16, in
import seamseg.models as models
File "/home/rapires/anaconda3/lib/python3.7/site-packages/seamseg-0.1.dev37+g3d10aea-py3.7-linux-x86_64.egg/seamseg/models/init.py", line 1, in
from .resnet import *
File "/home/rapires/anaconda3/lib/python3.7/site-packages/seamseg-0.1.dev37+g3d10aea-py3.7-linux-x86_64.egg/seamseg/models/resnet.py", line 6, in
from inplace_abn import ABN
File "/home/rapires/anaconda3/lib/python3.7/site-packages/inplace_abn/init.py", line 1, in
from .abn import ABN, InPlaceABN, InPlaceABNSync
File "/home/rapires/anaconda3/lib/python3.7/site-packages/inplace_abn/abn.py", line 7, in
from .functions import inplace_abn, inplace_abn_sync
File "/home/rapires/anaconda3/lib/python3.7/site-packages/inplace_abn/functions.py", line 9, in
from . import _backend
ImportError: /home/rapires/anaconda3/lib/python3.7/site-packages/inplace_abn/_backend.cpython-37m-x86_64-linux-gnu.so: undefined symbol: _ZN6caffe26detail36_typeMetaDataInstance_preallocated_7E
Traceback (most recent call last):
File "/home/rapires/anaconda3/lib/python3.7/runpy.py", line 193, in _run_module_as_main
"main", mod_spec)
File "/home/rapires/anaconda3/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/rapires/anaconda3/lib/python3.7/site-packages/torch/distributed/launch.py", line 260, in
main()
File "/home/rapires/anaconda3/lib/python3.7/site-packages/torch/distributed/launch.py", line 256, in main
cmd=cmd)
subprocess.CalledProcessError: Command '['/home/rapires/anaconda3/bin/python', '-u', 'test_panoptic.py', '--local_rank=0', '--meta', '/home/rapires/metadata.bin', '--log_dir', '/home/rapires/logs', '/home/rapires/seamseg_vistas/config.ini', '/home/rapires/seamseg_vistas/seamseg_r50_vistas.tar', '/home/rapires/images', '/home/rapires/predictions']' returned non-zero exit status 1.

@rapires96
I have same problem. Did you figure out how to resolve it?

@rapires96
I have same problem. Did you figure out how to resolve it?

Unfortunately not, ended up not using seamseg at all


Alert only on new builds that are failing

[x] The commits are squashed in a cohesive manner and have meaningful messages.
[x] JIRA link(s): https://issues.redhat.com/browse/RHODS-2051
[x] The Jira story is acked
[x] An entry has been added to the latest build document in Build Announcements Folder.

@sugarraysam can you PTAL?

LGTM

I can confirm that the alert looks correct after upgrade.
I wasn't sure how to test it out, however

/lgtm
I've tested it, and it stop the alert after 10 minutes.

@maulikjs Can you add an entry to the build announcement document?

@anishasthana done


Issue while importing tensorflow

Facing issue while importing tensorflow.
OS: Windows 8
Python version 2.7
Installation method anaconda.
Traceback (most recent call last):
File "", line 1, in
File "C:\Anaconda2\envs\tensorflow_env\lib\site-packages\tensorflow_init_.py", line 23, in
from tensorflow.python import *
File "C:\Anaconda2\envs\tensorflow_env\lib\site-packages\tensorflow\python_init_.py", line 46, in
_default_dlopen_flags = sys.getdlopenflags()
AttributeError: 'module' object has no attribute 'getdlopenflags'

Unfortunately, TensorFlow is not yet supported on Windows.


Make labels play animation on crossing a region (similar to goals)

~blocked by #256~

#266 makes this obsolete


U.GG update

As the title says, u.gg had an update recently, so it doesn't parse runes anymore
p.s. maybe you should make an automatic version parser or something in future? releasing a new version just for a sake of single site update is really troublesome

When the plugin was first implemented it supported automatic version parsing. Then the endpoint changed after some months and I didn't find an alternative way to automatically retrieve the version, so I just update it manually since then.
If someone finds a way to do that, I'll be glad to merge the fix.

When the plugin was first implemented it supported automatic version parsing. Then the endpoint changed after some months and I didn't find an alternative way to automatically retrieve the version, so I just update it manually since then.
If someone finds a way to do that, I'll be glad to merge the fix.
Edit: in a couple of days I'll fix it manually as usual, in any case.
You might try contacting u.gg staff<EMAIL_ADDRESS>and see if they're willing to help you with that


⚠ gorzdrav.org has degraded performance

In 45b4148, gorzdrav.org (https://gorzdrav.org) experienced degraded performance:

HTTP code: 200
Response time: 1273 ms

Resolved: gorzdrav.org performance has improved in 607401f.


Unexpected parse results using lambdas between infix operators

The following code compiles but it does not get parsed as expected:
login model =
    Http.fromJson Decode.string
        (Http.send Http.defaultSettings
            { verb = "POST"
            , headers = [("Content-Type", "application/json")]
            , url = loginUrl
            , body = Http.string ""
            })
    `andThen` \resp -> Signal.send actions.address (PostMessage "Thanks for logging in.")
    `onError` \err -> Signal.send actions.address (PostMessage "Something went wrong.")

What it actually gets parsed as is more like the following:
login model =
    Http.fromJson Decode.string
        (Http.send Http.defaultSettings
            { verb = "POST"
            , headers = [("Content-Type", "application/json")]
            , url = loginUrl
            , body = Http.string ""
            })
    `andThen` (\resp -> Signal.send actions.address (PostMessage "Thanks for logging in.")
                        `onError` (\err -> Signal.send actions.address (PostMessage "Something went wrong.")))

I think this is the intended behaviour.
See the section “More Chaining” in http://elm-lang.org/guide/reactivity:
  An anonymous function includes everything after the arrow

I always put parens around my lambdas, which would solve this.

Sure, and the compiler used to not accept lambdas without parens around them.
Now it does, which is nice, but we'll need to look into what behaviour is desired...

Sure, but would any change that fixes this also cause f = \x -> x + 2 to become f = (\x -> x) + 2 and type error?

I think Haskell does it in a way that's different and more intuitive than Elm currently does. And Haskell accepts f = \x -> x + 2 just fine :)
It's only a matter of requiring something following the -> on a new line to be indented more than the line with the \ to be considered part of the lambda body. Then the following two will be different:
login model =
    Http.fromJson Decode.string
        (Http.send Http.defaultSettings
            { verb = "POST"
            , headers = [("Content-Type", "application/json")]
            , url = loginUrl
            , body = Http.string ""
            })
    `andThen` \resp -> Signal.send actions.address (PostMessage "Thanks for logging in.")
        `onError` \err -> Signal.send actions.address (PostMessage "Something went wrong.")

This would be an andThen of the Http.fromJson and (the onError of the first Signal.send and the \err -> ...).
login model =
    Http.fromJson Decode.string
        (Http.send Http.defaultSettings
            { verb = "POST"
            , headers = [("Content-Type", "application/json")]
            , url = loginUrl
            , body = Http.string ""
            })
    `andThen` \resp -> Signal.send actions.address (PostMessage "Thanks for logging in.")
    `onError` \err -> Signal.send actions.address (PostMessage "Something went wrong.")

But this would be the onError of (the andThen of the Http.fromJson and \resp -> ...) and the \err -> ...

I think the sane thing to do here would be to follow what Haskell does. They've been programming with lambdas a long time already.
Jeff indicated on the mailing list that there is some difference in parsing between Haskell and Elm here. But it is not clear enough to me from that thread what the exact difference is. Can we see a simple example of the same lambda-involving-but-parentheses-less code currently being parsed differently by Haskell and Elm? As it stands, I'm not yet convinced there is such code.

Ah, Jeff, I didn't see your comment before posting mine. Are you sure your interpretation of what Haskell does is correct? How did you test that? I doubt that Haskell does anything like requiring "a new line to be indented more than the line with the \ to be considered part of the lambda body".

I have no official source that that's the rule.. I just messed around in ghci with set +m and :{/:} to get multi-line commands. But now as I try to reproduce what I did on another computer, it seems to give me different results. So I don't know what's going on anymore :neutral_face:

My understanding is that OCaml and Haskell (and any other ML-family language I have seen) do it the same as Elm. @Apanatshka, if you can share a valid Haskell file that demonstrates otherwise, we can talk about that. If not, let's close this issue.

Thanks @ThomasWeiser, I had seen that before but didn't make the connection that that was what was happening.

@evancz I don't think I'm going to find an example, I think I just messed up when I first tried to find something different in Haskell.
Ah, I just found in the Haskell 98 Report that let and lambda body adhered to the "maximal munch" (longest match) rule. So I was wrong, Elm does things like Haskell does.
Can we please get a warning in the docs of onError though? This will be a gotcha of the lambda style of programming.

Yeah, for sure, I have been bitten by the onError thing as well. I have actually considered removing that function in favor of something like this:
recoverWith : (e -> Task e' a) -> Task e a -> Task e' a

Such that it does not follow the same pattern and you have to do it first. This way you'd just not get yourself into this situation. Perhaps that'll end up being better?

That sounds like a good idea. Easiest thing would be to just add it, but you can also make a breaking change and replace onError with it.


Add PropTypes object exports

For a resource. Something like:
PropTypes.shape({
  resources: PropTypes.array.isRequired,
  resourceListMeta: PropTypes.shape({
    readXhrStatus: PropTypes.string.isRequired,
    createXhrStatus: PropTypes.string.isRequired
  })
})

This way, you can easily validate a resource as a prop in your app

This would require a dep on prop-types, which I'm not that interested in setting up. Closing as wontfix.


User friendly theme editor

A theme editor inside VS code that would let you see changes to the theme in real-time. It would be nice to have drop-down menus of all different aspects of the editor that could change color with a preview screen off to the side. Preset color options and even color wheels would really help with the user-friendly aspect of it. Functionality to edit pre-made themes and save them would go a long way also. I know there are editors outside of the editor that can do these things, but it would be nice to have a fleshed-out editor within VS code.

Sorry, we don't have any plans for a more sophisticated, graphical, theme editor.
The current approach also lets you try out changes in real-time:

customize the current theme in the settings, see all colors applied live, then generate the theme with the Developer: Generate Color Theme From Current Settings command
or
create a new theme with yo code and open it in VS Code and make changes while testing the theme.


Add whitespaceOnly option to configuration file

Allows configuring whether formatter should add or remove trailing commas in lists.

Thanks for the contribution!
I don't think we want to call a user-configurable trailing comma feature something as general as "whitespace only". We do that in the internal implementation because the linter half of the pretty printer works by looking at runs of whitespace but expects the non-whitespace characters to be the same, and the formatted output for the linter is never otherwise used, but we don't have to (and shouldn't) make the user-facing feature work the same way. If we ever add other situations in the pretty printer where it inserts or removes non-whitespace characters (as a hypothetical, we could do something like add parentheses around long wrapped expressions), we don't want a single setting to turn all of those features on/off.
Instead, let's call it multilineCollectionTrailingCommas. To make it fully configurable, its value should be a tri-state instead of a Boolean, because there are three possible choices:

always: Always require a trailing comma, inserting one if the user didn't have one originally—with the exception that we never do for single-element collections, to avoid awkward situations where array/dictionary sugar is used as a type but in expression context, because we don't want this:
let array = [
  SomeLongElementTypeName,
]()

never: Never allow a trailing comma, removing one if the user had one there.

ignore: Do nothing; leave whatever the user had there, whether the trailing comma was present or not.

This concept is general enough that I can see it applying to future configuration settings, so I think defining a general enum with these three cases would be best rather than tying it specifically to trailing commas. That will help us define a common language for configuration going forward, too.
With that change, you'll need to make the actual change on the pretty-printer side in TokenStreamCreator instead of PrettyPrinter, because you'll have to make a decision about which formatting tokens you insert or which real tokens you skip based on that configuration setting.

Oh, and please make sure your PR is set to merge into master, not into the swift-5.2-branch when it's ready—I know it can be tricky to test against since it's pinned against dev snapshots (and I can help you verify it), but we only merge new changes into master and cherry-pick them into the other release branches.

Possibly even more flexible format is needed, something similar to ESLint's:
https://eslint.org/docs/rules/comma-style
.eslintrc.json
{
    "comma-dangle": ["error", "never"],
    // or
    "comma-dangle": ["error", {
        "arrays": "only-multiline",
        "objects": "never",
        "imports": "never",
        "exports": "never",
        "functions": "never"
    }]
}

ESLint's first parameter is whether the rule results in an error or in a warning, other parameters are rule-specific. Some eslint rules (import sort order etc) require relatively complex configuration.

All lint violations are emitted at the warning level right now, and that's hardcoded. If we want to support different severity levels for different kinds of violations in the future (and we might!), that's an independent change from what we do here for trailing commas today and would be a much larger overhaul of our configuration format, so for the scope of this PR, we should stay focused on the trailing comma issue.
Swift has fewer trailing comma contexts that apply than Javascript/Typescript—only array and dictionary literals. I personally don't see the need to make those two things separately configurable (other folks may disagree), so in the interest of avoiding feature creep, I think it's better to start with just making the feature apply to both arrays and dictionaries in the same way.
If we do need a more complex configuration sub-object in the future (for example, if we determined there was a need to format trailing commas for arrays and dictionaries differently), then that's fairly straightforward to do without breaking users: the custom implementation of Configuration.init(decoder:) can just try decoding the field as multiple types until it finds one that is compatible, or it falls back to the default value.


Link Not Working Properly

Think you found a bug?
Yes
What is the current behavior?
When we visit the  API section  under Subscribe to the store and inject action creators on page at https://react-redux.js.org/introduction/basic-tutorial, it leads to status 404, page not found at https://react-redux.js.org/api/connect.md,

What is the expected behavior?
It would need to show some page instead of 404 at https://react-redux.js.org/api/connect.md,

Can you submit a PR to fix this link?


Development of New Example

@Jeff-Hadley @Mateus-A-R-Braga and I will be developing a new example. It will solve the incompressible Navier-Stokes equations for a two-dimensional stagnation flat plate geometry, with a comparison study to the incompressible Blasius flat plate solution (time permitting). We will build off of existing examples 9, 14, 17, 18 and the Navier miniapp. This is a project for a class at CU Boulder this fall semester, so we plan to have this "issue" resolved by 11/28/2022 via a pull request that will introduce our new example (in order to fit into the timeline necessitated by the class).
@jedbrown

Welcome @como2099, @Jeff-Hardley and @Mateus-A-R-Braga!
Please let us know if you have any questions.


Training notebook not working due to JAX updates

JAX pushed a new updates yesterday after which the Brax training script doesn't work anymore with the following message. I am not sure if the Brax side could help resolve the issue or we need help from JAX team.

Hello!  Thanks for pointing this out.  JAX pushed a fix in 0.2.21.  This version is not yet bundled by default in colab, so you still need to run pip update -U jax at the top of the notebook for it to work.  I've updated the training notebook with this temporary fix - please let me know if that works for you.

Thank you. It works now following the JAX update.