Flask flash not working with Turbo

I stumbled upon flash not working when using turbo.
controller:
    @route("/delete/<id>", methods=["POST"])
    def delete(self, id):
        if self.measurement.is_used:
            flash("You can not delete this!")
            return redirect(url_for("MeasurementsView:index"))

If I remove turbo from page head, flash is working. If turbo is in, it's not (rest of the code is working no problem).
I can imagine replacing flash mechanism with turbo-stream in future (it would be neat actually), but not sure what to do now.
If I understand correctly, it's because turbo turns my redirect to fetch, and flash is not rerendered. So I need to force flash element reloading. Not sure how tho.
(Also, the flash message is rendered next time page is "properly" reloaded.)
Thanks for your help!

This is an indirect result of how turbo frames work. When you click a link or submit a form only the turbo frame in which this was done is updated. The rest of the page is not. If you want to trigger updates in several parts of the page you have to not use turbo-frames or in the case of a response to a form submission use a turbo stream that includes updates in all the areas of the page.

Understand that.
So, at least for now I made some helper code to solve this (only working for cases with form+POST).
I put it here, so it may help someone dealing with this later :)
# helpers/turbo_flash.py
def turbo_flash(message):
    from app import turbo
    from flask import render_template as template

    if turbo.can_stream():
        return turbo.stream(
            turbo.replace(
                template("base/_turbo_flashing.html.j2", message=message, category="error"),
                target="turbo-flash",
            )
        )
    else:
        return False

using template
{# base/_turbo_flashing.html.j2#}
<turbo-frame id=turbo-flash>

{{ message }}

</turbo-frame>

like this
# some controller

if turbo.can_stream():
                return turbo_flash("Message I want flashed")

and in template, where I use turbo (so normal flask flashing is not working)
{% block flashing %}
    {% include('base/_turbo_flashing.html.j2') %}
{% endblock %}

I was thinking how this could be more automatic, here's some thought:
Could every turbo.stream automatically check for messages with get_flashed_messages, and if there are messages, it would replace flashing part of page (set in config, with some reasonable defaults like FLASHING_TEMPLATE='flashing.j2' and FLASHING_ID="flashing", and delete messages from session.

@janmpeterka this is something that I think would be hard to generalize, but in your own application you can add an after_request handler that checks for a turbo stream response and in that case appends the rendered alert as an additional stream.

Thanks for answer!
You are right, it doesn't make much sense to add this here.
I didn't think of after_request, that sounds like a great way to solve this :) I will add some code here for reference.

I will add some code here for reference.
@janmpeterka Did you already find time to add the code? Looking at the same problem right now and would be interested in seeing how you worked around the problem! Thank you :)

@tnaescher I tried that, but for some reason I wasn't able to make it run correctly :(
No time now (exams ahead), I will probably look into it later (~ in two weeks).
Here's my WIP code:
@application.after_request
def flash_if_turbo(response):
    from app import turbo
    from flask import render_template as template
    from flask import session, get_flashed_messages

    # if turbo
    if response.headers["Content-Type"] == "text/vnd.turbo-stream.html; charset=utf-8":
        messages = get_flashed_messages(with_categories=True)
        session.pop("_flashes", None)

        if messages:
            flash_turbo_response = turbo.replace(
                template("base/_flashing.html.j2", messages=messages), target="flashing"
            )
            response.response.append(flash_turbo_response)

    return response

Ok, here is my (hopefully) working code, if anyone wants to solve this in their applications.
So, in my controller, I want to call flash. In my code, I do this:
    @route("/toggle-reaction", methods=["POST"])
    def toggle_reaction():
       (...)

        turbo_flash("Reaction was noted.", "success")

       # return either turbo.stream or normal response

The important new part here is my function turbo_flash. How does it work?
def turbo_flash(message, category=None):
    if turbo.can_stream():
        save_flash_to_session(message, category)
    else:
        flash(message, category)

So, it checks if turbo is active, and if not, it changes it to normal flash, nothing interesting there.
But if turbo is applicable, we instead save our message to session like this:
def save_flash_to_session(message, category):
    session["turbo_flash_message"] = message
    session["turbo_flash_message_category"] = category

Easy, right?
Ok, we have our message in session, what now? We will check on the end of each request if there's some flash message in our session:

@application.after_request
def flash_if_message(response):
    from flask import session, flash
    from app.helpers.turbo_flash import turbo_flash_partial, remove_flash_from_session

   # we try to load our message from session..
    message = session.get("turbo_flash_message", None)
    category = session.get("turbo_flash_message_category", "info")

    if message:
       # we check if our response is turbo (meaning we used return turbo.stream in controller)
        if _is_turbo_response(response):
           # if it is, we append html to our response. It replaces our typical flash template (shown later)
            turbo_flash = turbo_flash_partial(message, category)
            remove_flash_from_session()
            response.response.append(turbo_flash)

        else:
           # if it is not (we used redirect in controller for example), we turn it into normal flash.
            flash(message, category)
            remove_flash_from_session()

    return response

def _is_turbo_response(response) -> bool:
    return (
        response.headers["Content-Type"] == "text/vnd.turbo-stream.html; charset=utf-8"
    )

def turbo_flash_partial(message, category):
    return turbo.replace(
        template("base/_flashing.html.j2", messages=[(category, message)]),
        target="flashes",
    )

So,
Note: I don't guarantee it working in all cases. For example, if you split your page with turbo-frames, it might be possible that your flashing area is not replaced (if you dont target _top). This probably might be solved easily, but as I was working for solution on my app, I didn't solve that.

Here are complete codes, I didn't include some parts to simplify my thought process and workflow:
# app.helpers.turbo_flash.py

from flask import session, flash
from flask import render_template as template

from app import turbo

def turbo_flash(message, category=None):
    if turbo.can_stream():
        save_flash_to_session(message, category)
    else:
        flash(message, category)

def turbo_flash_partial(message, category):
    return turbo.replace(
        template("base/_flashing.html.j2", messages=[(category, message)]),
        target="flashes",
    )

def save_flash_to_session(message, category):
    session["turbo_flash_message"] = message
    session["turbo_flash_message_category"] = category

def remove_flash_from_session():
    session.pop("turbo_flash_message")
    session.pop("turbo_flash_message_category")

def is_flash_in_session() -> bool:
    return "turbo_flash_message" in session

# myapplication.py

@application.after_request
def flash_if_message(response):
    from flask import session, flash
    from app.helpers.turbo_flash import turbo_flash_partial, remove_flash_from_session

    message = session.get("turbo_flash_message", None)
    category = session.get("turbo_flash_message_category", "info")

    if message:
        if _is_turbo_response(response):
            turbo_flash = turbo_flash_partial(message, category)
            remove_flash_from_session()
            response.response.append(turbo_flash)

        else:
            flash(message, category)
            remove_flash_from_session()

    return response

def _is_turbo_response(response) -> bool:
    return (
        response.headers["Content-Type"] == "text/vnd.turbo-stream.html; charset=utf-8"
    )

<-- base/_flashing.html.j2 -->

  {% for category, message in messages %}

 {{ message }}

  {% endfor %}

Ok, so I am facing an issue on this flash even after trying everything, still my app isn't working. Maybe I am making a silly mistake here. I am making a Sign Up Sign In using Flask and MongoDB. Please help me out. Thanks in advance :)
main.py
from flask import Flask, render_template, request, flash, session
from pymongo import MongoClient
from forms import SignUp, SignIn
from turbo_flask import Turbo

app = Flask(__name__)
turbo = Turbo(app)
app.secret_key = 'Login System'
cluster = "mongodb://localhost:27017"
client = MongoClient(cluster)
db = client['practice']
login = db.login

def turbo_flash(message, category=None):
    if turbo.can_stream():
        save_flash_to_session(message, category)
    else:
        flash(message, category)

def turbo_flash_partial(message, category):
    return turbo.replace(
        render_template("base/_flashing.html.j2", messages=[(category, message)]),
        target="flashes",
    )

def save_flash_to_session(message, category):
    session["turbo_flash_message"] = message
    session["turbo_flash_message_category"] = category

def remove_flash_from_session():
    session.pop("turbo_flash_message")
    session.pop("turbo_flash_message_category")

def is_flash_in_session() -> bool:
    return "turbo_flash_message" in session

@app.after_request
def flash_if_message(response):

    message = session.get("turbo_flash_message", None)
    category = session.get("turbo_flash_message_category", "info")

    if message:
        if _is_turbo_response(response):
            turbo_flash = turbo_flash_partial(message, category)
            remove_flash_from_session()
            response.response.append(turbo_flash)

        else:
            flash(message, category)
            remove_flash_from_session()

    return response

def _is_turbo_response(response) -> bool:
    return (
        response.headers["Content-Type"] == "text/vnd.turbo-stream.html; charset=utf-8"
    )

@app.route("/", methods=['GET', 'POST'])
def index():
    signup = SignUp()
    signin = SignIn()
    if signup.signup.data and signup.validate():
        print('Sign Up')
        name = request.form['name']
        email = request.form['email']
        password = request.form['password']
        confirm_password = request.form['confirm_password']

        if password != confirm_password:
            turbo_flash("Passwords don't match")
        else:
            dict = {'name': name, 'email': email, 'password': password, 'confirm_password': confirm_password}
            login.insert_one(dict)
            turbo_flash("User Added")

    if signin.signin.data and signin.validate():
        print('Sign In')
        email = request.form['email']
        password = request.form['password']
        data = login.find_one({'email': email})
        if data is None:
            turbo_flash("No such email exist")
        elif password != data['password']:
            turbo_flash('Password is wrong', "success")
        else:
            turbo_flash("User Logged In")

    return render_template("sign_up_in.html", signup=signup, signin=signin)

if __name__ == "__main__":
    app.run(use_reloader=True)

forms.py
from flask_wtf import FlaskForm
from wtforms.validators import DataRequired, Email
from wtforms import StringField, SubmitField, PasswordField

class SignUp(FlaskForm):
    name = StringField("Name", validators=[DataRequired()])
    email = StringField("Email", validators=[DataRequired(), Email()])
    password = PasswordField("Password", validators=[DataRequired()])
    confirm_password = PasswordField("Confirm Password", validators=[DataRequired()])
    signup = SubmitField("Sign Up")

class SignIn(FlaskForm):
    email = StringField("Email", validators=[DataRequired(), Email()])
    password = PasswordField("Password", validators=[DataRequired()])
    signin = SubmitField("Sign In")

sign_up_in.html
<!DOCTYPE html>

<meta charset="UTF-8">
<title>Sign Up OR Sign In</title>

{{ turbo() }}

  {% for category, message in messages %}

 {{ message }}

  {% endfor %}

Sign Up Form

<form name="signup_form" method="POST">

        {{ signup.csrf_token }}
        {{ signup.name.label.text }}: {{ signup.name }}
        {{ signup.email.label.text }}: {{ signup.email }}
        {{ signup.password.label.text }}: {{ signup.password }}
        {{ signup.confirm_password.label.text }}: {{ signup.confirm_password }}
        {{ signup.signup }}

</form>

Sign In Form

<form name="signin_form" method="POST">

        {{ signin.csrf_token }}
        {{ signin.email.label.text }}: {{ signin.email }}
        {{ signin.password.label.text }}: {{ signin.password }}
        {{ signin.signin }}

</form>

I have now added a small example in this repo that shows how to flash a message in a turbo-stream response. It is actually simpler then the code shown above. https://github.com/miguelgrinberg/turbo-flask/tree/main/examples/flash

nice, thank you!
but this still doesn't solve flashing with turbo-frame.
I went another route for that - I created Stimulus controller that is attached to body and on frame-render/stream-render calls /flashing endpoint that loads messages. its somewhat cumbersome, but I didn't find better way how to solve this for all possible ways page changes.

Correct, this solution is for turbo-stream. To solve for turbo-frame, include the flash area in your frame.

sure, you can always target whole page with _top, but it sort of defeats a purpose of turbo-frames, doesn't it? and you have to explicitly call _top ewerywhere.
or you can just hook a bit of logic tu frame-render to always re-render flashing. I don't like that there needs to be separate logic for normal load, frame load and stream, but still it seems like possibly the most clean solution.

sure, you can always target whole page with _top, but it sort of defeats a purpose of turbo-frames, doesn't it? and you have to explicitly call _top ewerywhere.

That's not what I'm saying. If you have a turbo frame for the content area of your page, then including the alerts inside this frame will resolve the issue completely, without you having to do anything differently.
If including the alerts in the turbo frame isn't feasible, then the solution I'm showing in the example linked above, which pushes the update directly to the alert section is also fairly straightforward.
What case(s) aren't covered by the two solutions I proposed? The whole point of turbo.js is avoiding the use of JS, so why would you resort to a JS solution when there are no-JS solution available to you?

sorry, didn't realize you are suggesting including flash in my frame. that's possible, but as I want to have one place with flashes, not what I'm looking for.
your example works only with Streams, doesn't it?


Update highlighting

Hi,
I want to update highlighting on key up (text editor), so I tried to do this:
function highlight() {
	hljs.initHighlighting.called = false;
	$('#text-content').each(function(i, block) {
		hljs.highlightBlock(block);
	});
}

$('#text-content').keyup(function(e) {
	highlight();
})

But this is not working and the cursor is set back to first position.
How can I do it?
Thanks

But this is not working and the cursor is set back to first position.

That's what's going to happen as you're replacing the full content each time.  You'd have to save the cursor and try to put it back yourself - not sure how much luck you'll have with that.
Are you sure highlightBlock is intended to be called multiple times for the same thing?  That'd be where to spend your time looking.

Following the example from the other thread:

This is unfortunately outside the scope of this library.

Highlight.js is not intended for usage as a real-time code editor.  Good luck if you get it working, but we can't support that.


NeoHDF5 files created with Python 2 cannot be read with Python 3

This is because _f_getAttr("_type") is read as a bytes type, not string.

I have the same problem. Do you guys have any progress on this issue?

Hello,
Thanks to the new version of neo 0.5, it is now possible with Python 3 to read NeoHDF5 files, created from Python 2, with neo 0.4 and neo 0.5.
To verified it, I have created an HDF5 file dset_Python2_Neo_04.h5 and a datasets /dset_Python2_Neo_04 in it, like this :
import h5py
import numpy as np
#
# Create a new file using defaut properties.
#
file = h5py.File('/dset_Python2_Neo_04.h5','w')
#
# Create a dataset under the Root group.
#
dataset = file.create_dataset("dset_Python2_Neo_04",(4, 6), h5py.h5t.STD_I32BE)
print("Dataset dataspace is", dataset.shape)
print("Dataset Numpy datatype is", dataset.dtype)
print("Dataset name is", dataset.name)
print("Dataset is a member of the group", dataset.parent)
print("Dataset was created in the file with Python 2 and NEO 0.4", dataset.file)
#
# Initialize data object with 0.
#
data = np.zeros((4,6))
#
# Assign new values
#
for i in range(4):
    for j in range(6):
        data[i][j]= i*6+j+1
#
# Write data
#
print("Writing data...")
dataset[...] = data
#
# Close the file before exiting
#
file.close()

Then , I readen with Python 3 the file obtained
import h5py
import numpy as np
#
# Open an existing file using default properties.
#
file = h5py.File('/dset_Python2_Neo_04.h5','r+')
#
# Open "dset_Python2_Neo_04" dataset under the root group.
#
dataset = file['/dset_Python2_Neo_04']
#
# Read data back and print it.
#
print("Reading data back...with Python 2 NEO 0.4")
data_read = dataset[...]
print("Printing data...")
print(data_read)
#
# Close the file before exiting
#
file.close()

The NeoHDF5 file created with Python 2, regardless of which version of neo is used, is correctly read by Python 3. I get the following result :
Reading data back...with Python 2 NEO 0.4
Printing data...
[[ 1  2  3  4  5  6]
[ 7  8  9 10 11 12]
[13 14 15 16 17 18]
[19 20 21 22 23 24]]

Hi @legouee
Unfortunately this test, by using h5py directly, does not use the neo.io.NeoHdf5IO class to create or read the file.  To test this, you will need to create (with Python 2 and Neo 0.4) a neo Block containing some data (AnalogSignals and SpikeTrains) and then create the HDF5 file using something like:
io = NeoHdf5IO("dset_Python2_Neo_04.h5")
io.write(block)

You should then read it into Neo 0.5 under Python 3:
io = NeoHdf5IO("dset_Python2_Neo_04.h5")
data = io.read()

Hello,
I just created, with Python 2.7 and Neo 0.4, a HDF5 file. To do this, I created a neo block containing three segments with random data from AnalogSignals and SpikeTrain. Here is the code I use:
import sys
import numpy as np
import tables as tb
import neo
from neo.io import NeoHdf5IO
from neo.core import Block,Segment,AnalogSignalArray, SpikeTrain, AnalogSignal
from quantities import kHz, nA

create a Block with 3 Segment

blk = Block()
for ind in range(3):
seg = Segment(name='segment %d' % ind, index=ind)
blk.segments.append(seg)

Populate the Block with AnalogSignalArray and SpikeTrain objects

for seg in blk.segments:
# AnalogSignal
a = AnalogSignalArray(np.random.randn(10000, 64)nA, sampling_rate=10kHz)
seg.analogsignalarrays.append(a)
# SpikeTrain
train0 = SpikeTrain(times=[.01, 3.3, 9.3], units='sec', t_stop=10)
seg.spiketrains.append(train0)

write a NeoHdf5IO

io = NeoHdf5IO('dset_Python2_Neo_04.h5')
io.write(blk)
The file 'dset_Python2_Neo_04.h5' is created.
I now go under Python 3.6 and Neo 0.5 to read this file. I use the following code:
import neo
from neo.io import NeoHdf5IO
io = NeoHdf5IO('dset_Python2_Neo_04.h5')
data = io.read()
The h5 file is read correctly.

Great. It looks as though this issue was resolved at some point in the Neo 0.5 development branch.


Async Computed Values

I've been wanting something like vue-async-computed for Vue's composition API, but couldn't find anything so I created it myself. I made a gist with an explainer and an initial implementation here.
Because of its generic nature and broad use cases, the useAsyncComputed function may be a nice counterpart to the existing useAsyncState.
What do you think?

I want it several times too! It's looks promising and let's have it!
Some thoughts,

for the naming, I think asyncComputed is simpler & neater.
for the returning value, I am thinking if we could get rid of the tuple, I would like it to be more like computed (sometimes ppl don't care if it's evaluating)

How about:
  const state = reactive({ value: defaultValue, evaluating: false }) as { value: T, evaluating: Boolean }
  /* ... */
  return state

I agree on the naming thing, I just decided on use* to stick with the rules. 😁
However, I disagree on the usage of reactive, for various reasons:

It wouldn't actually bring it close enough to computed. While access in code would be equivalent in code usage (computedThing.value vs asyncComputedThing.value), it would differ in template usage (computedThing vs asyncComputedThing.value).
More in general, I'd avoid naming a property of a reactive object value. This would probably be a real stumbling block for people not familiar with the code base, and they might assume asyncComputedThing is a ref because it has a .value.
So, if we'd go the reactive() road, we should probably name it something like state or result.

However, I'd assume that people mostly really don't care for the evaluating part. Returning a tuple makes it easy to just ignore that part by omitting it from destructuring. Having an object with two properties, on the other hand, would mean additional work for all those people who don't care about evaluating because they had to use the extra accessor to get the computed value.

Alternative solutions:

Omit the evaluating part.
This was how I implemented the function in the first place. However, I realized that there are probably enough use cases for it (e.g. showing a loading state instead of stale data) that having this would be desirable.

Provide the data in another way.
We would not have to return the evaluating data. An alternative approach would be to provide another callback.
So instead of using the function like this...
const [downloads, isEvaluating] = asyncComputed(onCancel => {
  onCancel(() => { /* abort fetch */ })

  return fetch(/* and so on */)
}, 0)

...we could provide something like a onStartStop (naming is debatable, don't like it quite yet) callback which is triggered when the computed starts/finishes evaluating:
const isEvaluating = ref(false)
const downloads = asyncComputed(({ onCancel, onStartStop }) => {
  onCancel(() => { /* abort fetch */ })
  onStartStop(state => {
    isEvaluating.value = state
  })

  return fetch(/* and so on */)
}, 0)

Advantage: It would keep the return value clean, which would supposedly remove noise and mental burden for most users.
Disadvantage: It would slightly complicate the previously very simple callback argument (we'd have to provide a destructurable object à la { onCancel, onStartStop } instead of just pass the onCancel function) for a smaller fraction of users.

Actually, you can pretend any object to be a ref like
const data = ref(defaultValue)
const evaluating = ref(false)

const state = {
  __v_isRef: true,  // this will make Vue think it's a ref
  get value() {
    return data.value
  },
  get evaluating() {
    return evaluating.value
  }
} as Readonly<Ref<T> & { evaluating: Boolean }>

return state

This is also how toRef implemented.
So basically, asyncComputed will return a Ref but with an additional property evaluating. Just like the computed ref actually has an additional property effect if you don't know.
What do you think?

This is fascinating.
Still one complaint though: evaluating now is no longer reactive. We could of course return the ref itself instead of its value (so it could be accessed as state.evaluating.value), but this modification of the ref type seems to be a little off the beaten track for Vue stuff.
Is there any known prior art using this technique? (The question is probably moot, given the relatively young age of the Composition API, but anyway.)
So, while I find this solution pretty cool from a DX point of view, I'd be careful to mess with known patterns. But I don't dislike it at all. Do you have any further place to gather feedback from regarding the shape of the API?

evaluating now is no longer reactive

Not I believe it is. You can have a try.

Is there any known prior art using this technique?

AFAIK, no. I know some of my friends are using them in their private apps. And I am experimenting with a lot of things in @vue-reactivity (private too). I always want to use them in VueUse in order to get some clean interface but I haven't got time to do so. Let's be the first one!

I'd be careful to mess with known patterns

I will be your eyes XD

evaluating now is no longer reactive

No, I believe it is. You can have a try.

Sorry, I have not been clear enough with what I meant.
Of course, the state.evaluating getter would always return the correct value. But it would not be reactive in Vue's eyes (i.e. you could not use it in a template and could not watch it).
This would be fixable though by implementing it like this:
const data = ref(defaultValue)
const evaluating = ref(false)

const state = {
  __v_isRef: true,  // this will make Vue think it's a ref
  get value() {
    return data.value
  },
  evaluating
} as Readonly<Ref<T> & { evaluating: Boolean }>

return state

So we'd not return the current value for state.evaluating, but the ref itself, so it could be used in a template and accessed via state.evaluating.value.

One drawback though, is that you can't direct access evaluating in the template then. Might be better to pass it as a ref (or evaluating & evaluatingRef as the same time, not sure)

See comment above. 😁

evaluating as Getter
const data = asyncComputed(async () => { /*...*/ })

return {
  data,
  evaluating: computed(() => data.evaluating)
}

evaluating as Ref
const data = asyncComputed(async () => { /*...*/ })

return {
  data,
  evaluating: data.evaluating
}

As an object of refs
const { data, evaluating } = asyncComputed(async () => { /*...*/ })

return {
  data,
  evaluating,
}

Or
return {
  ...asyncComputed(async () => { /*...*/ })
}

As an array of refs
const [data, evaluating] = asyncComputed(async () => { /*...*/ })

return {
  data,
  evaluating,
}

Yeah, I agree that the hack is not ideal to be used in templates. Maybe it's head back to the traditional implementation.

Any concrete objections against the onStartStop approach from above?

I don't think we actually need onStartStop as I can just put it at the end of my async function. About the onCancel part, I don't think we should provide a function call here. Instead, an object called cancelToken might be better:
something like:
asyncComputed((cancelToken)=>{
	const a = await fetch(xxx)

    if (cancelTolen.cancelled)
       return // early return

    cosnt b = await fetch(a)

    return [a, b]
})

Inspiration from https://vscode.readthedocs.io/en/stable/extensions/patterns-and-principles/#cancellation-tokens

I don't think we actually need onStartStop as I can just put it at the end of my async function.

Sorry, I don't get it. Could you elaborate on that? What could you put at the end of your async function?

Instead, an object called cancelToken might be better

I don't really care about the implementation details. (My inspiration for onCancel came from the Composition API's very own watchEffect.)
Regarding the cancel token: How would you implement a notification system on the cancel token? EventEmitter is a Node-only API, EventTarget is web-only. Implementing an event emitter just for that function would be overkill, so the remaining options would probably be a Vue instance with $on/$emit or a very reduced emitter?

onStartStop

Let's keep the evaluating state inside the function, using events and let users doing that might be too much.

onCancel

I see. I agree it's better to stay with the Vue style. How about just keep it named as onInvalidate?

Sorry for being a bit nitpicking, this is a good direction and I'd say let's go for it. Thanks a lot 👍

No worries, that's great. Let's be nitpicky now — we probably won't be able to change the design later. 🙂

Let's keep the evaluating state inside the function

Sorry, still don't get it — where would you like to keep it?

How about just keep it named as onInvalidate?

I deviated from the original name on purpose because the behavior is slightly different: watchEffect has no mechanisms to detect whether previous callbacks finished their work, therefore onInvalidate is always called when the next effect is invoked — whereas onCancel is only called when the next evaluation is started and the previous evaluation has not finished yet (which we can track thanks to the returned promise).
Of course we could resort to calling it onInvalidate, but then we'd also have to adopt the described watchEffect to avoid confusion. However,

we would somehow still need to tell the user whether the previous evaluation finished, likely with a parameter to the callback onInvalidate invokes:
asyncComputed(onInvalidate => {
  onInvalidate(hasFinished => {
    // `hasFinished` would be a boolean indicating whether the
    // previous evaluation has finished, naming is up for debate.
  })

  return somePromise
})

However, this would then again deviate from the watchEffect behavior as their onInvalidate does not provide such a boolean.

I think it's reasonable to not provide users with more information than they need.
They should be notified when evaluation is canceled because they may have to do cleanup work, but I don't see any value in them being notified about the next evaluation if their own task has already finished.

Therefore I settled for onCancel.

Let's keep the evaluating state inside the function

I think it's good to keep your original version :p
const [downloads, isEvaluating] = asyncComputed(onCancel => { })

Therefore I settled for onCancel

I got it, thanks for the detailed explanation. Let's go for it!

My pleasure. Want me to create a PR?

It will be great if you don't mind. Thanks 😁

I'll give it a try. First contact with Storybook for me, but the other functions should provide enough learning material. 🙂


Stencil support

Hi, can we expect the new release with stencil support? As I can see, the code is already there, but it was committed after the latest official 4.1.0. Thanks!

Hi! I just got access to this repo, I do intend to release a new version of this in the not too far future, though I seem to have some problems building the project locally. But I think I'll be able to figure it out.

I will postpone this to 4.3.0

This is fixed in #86


Crash on startup

Suddenly, my game is crashing after testing it with More Bundles since the beggining of its creation. I'm afraid that this won't get resolved since it's been a while since last update, so please at least if you could provide some solution for it it would be wonderful <3
latest.log
crash-2023-04-12_21.16.48-client.txt
config.txt (converted for uploading directly)

So, after deleting the morebundles config folder, the first try running it after each run it loads without problem but then it crashes. I don't know what could be causing this issue after loading the default configs...

I think the problem with your original config is that in newer versions I removed the "WARN" (and also "IGNORE") error policies as they lead to too many issues (although the wiki doesn't reflect that change - most of the info on the config is out of date and I intend on updating it at some point). Instead try the "FAIL ON ERROR" policy.
As for it crashing with the default config, I'm not sure what could be causing that. Could you provide more details? Thanks :)

Forgive me I couldn't reply earlier! I've been trying to mess with the configs in many different approaches, but at the end I get this message in the crash report. Also sending you the config again:
config.txt
crash-2023-04-13_22.07.09-client.txt

And yes, I'm sending you the config tweaked to my tastes, as I'm using your mod for a pack where I want to use the custom tooltip when you hover the bundle (it is perfect I must say), then this is the crash I get. Also, from my previous log, you can see what other mods I'm using.
config.txt
crash-2023-04-13_22.22.36-client.txt

And last but not least, this are my configs and mods I was using in a previous version of the pack everything was working fine. Hope all this info help you to spot any problems:
config.txt
mods.txt

For the first crash I'm not exactly sure what's causing it. It seems either minecraft's bundle texture or my base bundle textures are somehow getting corrupted? I have attached a build of the mod which should hopefully circumvent the issue. Please test it if you have the time and if it does work I will upload it to curseforge.
As for the second crash, it looks like you added a file directly into the resources/assets or resources/data folder of the config without placing it in the proper namespace folder and the code panics because it can't extract the namespace from that. Admittedly, this probably shouldn't cause a crash so this should also be fixed in the jar attached. If you don't understand what I mean by this or need help fixing this I'd be happy to help.
If you do have issues with this new jar, it might also be helpful if you also send a full log through, as this could shine more light on what is happening in the first crash if what I have done hasn't fixed it.
Thanks a lot for your help :)
morebundles-fabric-1.19.2-0.3.0.zip (I have attached the file as a zip because github doesn't allow me to upload jars directly)

Well, you made magic sir. Works like a charm! I don't think I changed anything in the assets folder, but if the log says it... It's just I can't remember, the only thing I did was to delete the generated data folder to remove the recipes, but I will leave it as it is and I will try to change the recipe then.
But to the point, the jar works well. I couldn't load the game after the first run and now everything is fine. And to show my genuine enthusiasm (or annoyance, like you want to take it), will you update your mod for 1.20 when it comes out? Now that Mojang "somehow" has implemented the bundle, your mod is like a pretty needed upgrade for the capabilities it can offer.
Thank you so much for your assistance : )

Thanks a lot! I probably will update this to 1.20. I haven't looked at 1.20 much but I don't expect the changes to break the mod too much.

don't work even with the mod you shared in the zip file


META: Updating Responsible Units/Collection names

Problem Description:
In LUX we have four Campus Divisions: Yale University Library (YUL), Yale Peabody Museum, (YPM), Yale University Art Gallery (YUAG), Yale Center for British Art (YCBA). This raised an issue as there are some categories which could not be found within these Campus Divisions/Collections.  For example, Elizabeth Club is not a collection but not a campus division. A user does not have the ability to filter on the Elizabeth Club and instead has to filter between one of the four Campus Divisions, which may or may not show results of the Elizabeth Club collection.
Since we are rebranding Campus Divisions to Responsibility Units (See issue FE-132) we will now expand to include such categories as Elizabeth club (and others) and their collections to allow users to better refine their searches.
This issue will serve as a meta ticket for all the work needed to include the new responsible units/collections.
Expected Behavior/Solution:
Add additional Responsible Units such as: Paul Mellon Centre, Yale School of Music, Elizabeth Club, Yale Campus Art, and Institute for the Preservation of Cultural Heritage
Add additional collections such as: Library Collection, Archives, Photo Collection Collection of Musical Instruments, Elizabethan Club Collection, Campus Art Collection any other collection needed.
Requirements:
The following Responsible Units/Collections will be added to Responsible Unit and Collection Facets:
Paul Mellon Centre (UK)

[x] -  Library Collection, Paul Mellon Centre (UK)
[x] -  Archives, Paul Mellon Centre (UK)
[x] -  Photo Collection, Paul Mellon Centre (UK)

Yale School of Music

[x] -  Morris Steinert Collection of Musical Instruments, Yale School of Music

Elizabethan Club of Yale University

[x] -  Elizabethan Club Collection, Yale University

Yale Campus Art

[x] -  Campus Art Collection, Yale University

Institute for the Preservation of Cultural Heritage

[ ] - TBD

Needed for promotion:
If an item on the list is not needed, it should be crossed off but not removed.

[ ] Wireframe/Mockup - Mike
[ ] Committee discussions - Sarah
[ ] Feasibility/Team discussion - Sarah
[ ] Backend requirements - TBD
[ ] Frontend requirements- TBD
[ ] Questions
List of questions for discussions. Answers should be documented within the issue.

UAT/LUX Examples:
Object Sun Results (TST):
https://lux-front-tst.collections.yale.edu/view/results/objects/?q={"text"%3A"sun"%2C"_lang"%3A"en"}&sq=sun
Dependencies/Blocks:

Blocked By: units making their data available.

Related Github Issues:

Front End: https://github.com/project-lux/lux-frontend/issues/132
ML: https://github.com/project-lux/lux-marklogic/issues/68

Related links:

BugHerd: https://www.bugherd.com/projects/284041/tasks/1977?text=elizab

Wireframe/Mockup:
Place wireframe/mockup for the proposed solution at end of ticket.

@kamerynB  I have updated ML in DEV such that it can support this ticket

Awaiting decision on a name for The Institute for Preservation of Cultural Heritage.
@prowns will meet with them today and confirm/have an update.

proposed close. Believe this to be complete.

Closing as this is finished. (UAT 8/7)


Makefile does not generate dependencies for third-party libraries

For libraries not in src (like FatFs), the makefile does not generate dependency files. Therefore, C files are not correctly recompiled after changing a corresponding header. This is a minor issue, as third-party libraries are not changed that much usually.
In my eyes, the correct way to deal with this would be to treat the libraries just like the code in src, resp. the other way round. Currently, there is a unnecessary differentiation between those source directories although they could be treated alike.

Just like proposed, the makefile treats every C source directory the same now.


set number of digits after the decimal place in the result of bc math functions functions

Fixes #78.

Thanks!


Fixed issue with SDK_API_HttpParentProxySet_Fail regression test

When testing 9.2.0 RC0 I ran into an issue with the regression tests (-R 3 -r SDK_API_HttpParentProxySet_Fail) crashing with the debug build.  I tracked down the commit that caused the issue to be  #7976.
s->current.state changed from being CONNECTION_CLOSED to BAD_INCOMING_RESPONSE and the debug assert doesn't handle that condition.
Regression test before #7976
+++++++++ Incoming O.S. Response +++++++++
-- State Machine Id: 0
HTTP/1.0 0

[Jan 11 18:05:57.124] [ET_NET 14] DEBUG: <HttpTransact.cc:3499 (HandleResponse)> (http_seq) [0] [HttpTransact::HandleResponse] Response not valid
[Jan 11 18:05:57.124] [ET_NET 14] DEBUG: <HttpTransact.cc:3634 (handle_response_from_parent)> (http_trans) [0] [handle_response_from_parent] (hrfp)
[Jan 11 18:05:57.124] [ET_NET 14] DEBUG: <HttpTransact.cc:3667 (handle_response_from_parent)> (http_trans) [0] [hrfp] connection not alive
[Jan 11 18:05:57.124] [ET_NET 14] DEBUG: <HttpTransact.cc:3680 (handle_response_from_parent)> (http_trans) [0] [0] failed to connect to parent <IP_ADDRESS>
[Jan 11 18:05:57.124] [ET_NET 14] DEBUG: <HttpTransact.cc:3706 (handle_response_from_parent)> (http_trans) [0] [handle_response_from_parent] 1 per parent attempts exhausted
[Jan 11 18:05:57.124] [ET_NET 14] DEBUG: <HttpTransact.cc:260 (nextParent)> (parent_down) [0] sm_id[0] connection to parent <IP_ADDRESS> failed, conn_state: CONNECTION_CLOSED, request to origin: trafficserver.apache.org
[Jan 11 18:05:57.124] [ET_NET 14] DEBUG: <ParentSelection.cc:176 (nextParent)> (parent_select) ParentConfigParams::nextParent(): parent_table: 0x1d1ee50, result->rec: 0xeeeeffff
[Jan 11 18:05:57.124] [ET_NET 14] DEBUG: <ParentSelection.cc:188 (nextParent)> (parent_select) Retry result for trafficserver.apache.org was PARENT_SPECIFIED
[Jan 11 18:05:57.124] [ET_NET 14] DEBUG: <HttpTransactHeaders.cc:1147 (add_server_header_to_response)> (http_trans) Adding Server: ATS/10.0.0

Regression test after #7976
+++++++++ Incoming O.S. Response +++++++++
-- State Machine Id: 0
HTTP/1.0 0

[Jan 11 17:53:32.904] [ET_NET 11] DEBUG: <HttpTransact.cc:359 (is_response_valid)> (http_trans) [0] Response Error: Missing status code
[Jan 11 17:53:32.904] [ET_NET 11] DEBUG: <HttpTransact.cc:3434 (HandleResponse)> (http_seq) [0] Response not valid
[Jan 11 17:53:32.904] [ET_NET 11] DEBUG: <HttpTransact.cc:3569 (handle_response_from_parent)> (http_trans) [0] (hrfp)
Fatal: ../../../proxy/http/HttpTransact.cc:313: failed assertion `(s->current.state == CONNECTION_ERROR) || (s->current.state == OPEN_RAW_ERROR) || (s->current.state == PARSE_ERROR) || (s->current.state == CONNECTION_CLOSED) || (s->current.state == INACTIVE_TIMEOUT) || (s->current.state == ACTIVE_TIMEOUT) || s->current.state == OUTBOUND_CONGESTION`

Regression test after this change
+++++++++ Incoming O.S. Response +++++++++
-- State Machine Id: 0
HTTP/1.0 0

[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <HttpTransact.cc:359 (is_response_valid)> (http_trans) [0] Response Error: Missing status code
[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <HttpTransact.cc:3434 (HandleResponse)> (http_seq) [0] Response not valid
[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <HttpTransact.cc:3569 (handle_response_from_parent)> (http_trans) [0] (hrfp)
[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <HttpTransact.cc:3615 (handle_response_from_parent)> (http_trans) [0] [hrfp] connection not alive
[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <HttpTransact.cc:3628 (handle_response_from_parent)> (http_trans) [0] [0] failed to connect to parent <IP_ADDRESS>
[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <HttpTransact.cc:3654 (handle_response_from_parent)> (http_trans) [0] [handle_response_from_parent] 1 per parent attempts exhausted
[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <HttpTransact.cc:278 (nextParent)> (parent_down) [0] connection to parent <IP_ADDRESS> failed, conn_state: BAD_INCOMING_RESPONSE, request to origin: trafficserver.apache.org
[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <ParentSelection.cc:176 (nextParent)> (parent_select) ParentConfigParams::nextParent(): parent_table: 0x223a360, result->rec: 0xeeeeffff
[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <ParentSelection.cc:188 (nextParent)> (parent_select) Retry result for trafficserver.apache.org was PARENT_SPECIFIED
[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <HttpTransact.cc:3883 (handle_server_connection_not_open)> (http_trans) [0] (hscno)
[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <HttpTransact.cc:3884 (handle_server_connection_not_open)> (http_seq) [0] Entering HttpTransact::handle_server_connection_not_open
[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <HttpSM.cc:4348 (do_hostdb_update_if_necessary)> (http) [0] server info = <IP_ADDRESS>:3300
[Jan 11 17:54:04.784] [ET_NET 10] DEBUG: <HttpTransactHeaders.cc:1165 (add_server_header_to_response)> (http_trans) Adding Server: ATS/10.0.0

Cherry-picked to v9.1.x branch.


API does not work properly when merging into main.

When merging into main, the isGroupMember function in the API does not work properly anymore because it returns false when a member is part of the group.
This issue seems to be related to cached groups because, apparently, they don't sync correctly each time the main branch is updated.

My guess is that we are not waiting for this._cacheGroups() to execute (await is missing in this line)
@vplasencia

My guess is that we are not waiting for this._cacheGroups() to execute (await is missing in this line)
@vplasencia

Potentially, we can study and implement a NestJS caching mechanism. Ref: https://docs.nestjs.com/techniques/caching @vplasencia just for note taking here


prepend commands with test- if on staging environment

This enables us to separate commands/reactions to have a test- prepended to them to denote staging.
This change also adds a hint message when running /[test-]scrappy command in slack

Be careful as you deploy this to avoid issues in prod

will deploy on Wednesday


Pypi repo

Hi, Vitaly. Can you update pypi repo?

Hi! Can u make me as maintainer in PyPI project?

Hi! Done, gave you rights to PyPI and repo.


youtubedl.exec is missing cancel() function

It looks like it is due to migration to tinyspawn.
Unfortunately, I can't provide the code to reproduce the stuck request. I use the tool to fetch JSON (--dump-single-json) from youtube and I cancel requests that are longer than 5 secs. Usually, it happens when there are many simultaneous requests and a slow network.

without a reproduction I can't work in the darkness
Did you try to setup timeout and kill signal? In this way
https://github.com/microlinkhq/tinyspawn#extending-behavior

without a reproduction I can't work in the darkness

okay, here's the code to reproduce the issue
const proc = youtubedl.exec(url);
proc.cancel() // error!

Unfortunately extend won't work in my case. I need cancel()

What I need is a reproduction of a stuck request

it's not a stuck request (sorry, I misinformed you) it's just a long request.
I guess you can simulate slow network with some OS tools (there are for mac and linux)

anyway, I checked execa, and cancel is just ChildProcess.kill
seems updating to tinyspawn introduced this breaking change

The third parameter is for passing options against tinyspawn, so you can have the same behavior passing timeout and kill signal, in this way
await youtubedl.exec('https://www.youtube.com/watch?v=6xKWiCMKKJg',{
  dumpSingleJson: true
}, {
  timeout: 5000,
  killSignal: 'SIGKILL'
})

Does it make sense to you?

i can confirm as well that youtubedl.exec doesn't expose any of the Child Process function.

Thanks for reporting, this is actually a bug, I filled a new issue https://github.com/microlinkhq/tinyspawn/issues/10

fixed tinyspawn
upgrade the dependency
added a doc section

It should work fine now, can you confirm?

It now works now, Thank you.


Adds support for Iceberg rewrite files operation

GitHub issue link: #23
Problem:
Need a way to replace/rewrite iceberg data files.
Solution:
Add an option to rewrite files. The operation takes a datafile string consisting of files to be deleted (replaced) and those that should be added.
Testing:
Updated functional test.
Documentation:
Updated README file

rewrite option does not make a sense ... what is the use case? may be there is a valid usecase

Rewrite option can be used when we want to changes data files without changing the actual data. This option allows the user to atomically replace the data file path(s). Some of the scenarios that can use this option:

Split larger data file(s) into smaller files
Combine smaller data files into bigger file(s)
Move data files from one location to another


Update OpenSDS Source Code

In OpenSDS latest version, we standardize the OpenSDS SourthBound Interface and improve the functionality of system. Right now we have finished OpenSDS integration of Cinder and the show and list method of volume have worked.

Solved by #2


⚠ T:Riza Community Forum has degraded performance

In d5e8551, T:Riza Community Forum (https://community.triza.dev) experienced degraded performance:

HTTP code: 200
Response time: 1768 ms

Resolved: T:Riza Community Forum performance has improved in dae461e.


Extract the MarkDown editor into an extension

@bpasero please document the features that are still missing

@egamma @kieferrm @Tyriar I started a markdown extension last milestone and you can find it here: https://github.com/bpasero/vscode-markdown
It was created using the TM language from [1] and it leverages our virtual document preview support to show a preview. It depends on markdown-it [2] and highlight.js for the preview rendering.
There is functionality missing to make it a replacement of our markdown support:

we need to investigate how to support embedded languages in the markdown editor so that code blocks get colored properly. according to @aeschli TM supports the notion of referencing other grammars from within a grammar. ideally we could reference our installed TM bundles for any code block that is being used in the markdown source
we need to change the extension to update the preview based on document edits so that the preview updates while the user is typing
we need to finish the CSS styling for the preview so that it is in sync with what we have today and also works in dark and light theme and any other theme from extensions (also depends on https://github.com/Microsoft/vscode/issues/5737)
we need to bring back the functionality that the preview scroll position stays stable when you make changes or even find a way to scroll the preview in sync with the editor scrolling (that would be a cool feature)
we currently do not have support to contribute actions to the context menu of the explorer or to the editor title area, but we have actions there to open a preview from a markdown file in both places and we also have an action to jump back to the source from a markdown preview
there is a setting in our markdown preview to configure a custom CSS style to use and this setting needs to be added to the extension too
anything labeled markdown [3] is something to revisit once we work on the extension

[1] https://github.com/textmate/markdown.tmbundle/blob/master/Syntaxes/Markdown.tmLanguage
[2] https://github.com/markdown-it/markdown-it
[3] https://github.com/Microsoft/vscode/issues?q=is%3Aopen+is%3Aissue+label%3Amarkdown

@bpasero I love that you are switching from marked to markdown-it, it seems much more active and is pluggable. I would really love to see checklists integrated by default, it is awesome for ToDo-lists - would it work to actually check a checkbox in the preview and it would change the source file? That would be awesome

Returning to source in the markdown preview is related to this issue #6941
There is no way to detect a virtual document with focus when a command is triggered.

Current state:

markdown as an extension is in https://github.com/Microsoft/vscode/tree/kieferrm/markdown
we miss the editor title area contribution: #7064
markdown source colorization needs to be beautified: #7068
the display performance is sub-par: #7066
there are several defects: #5038, #7067
extension needs to be part of the regular translation process: #7065

Current state:

Code is ready for merging into master (see https://github.com/Microsoft/vscode/issues/7656).
We miss the editor title area contribution. This is being addressed in #3192.
The display performance is sub-par. See updates in #7066.
Toggling between source and preview using the same keyboard shortcut is limited by #6941. Current workaround is to use the workbench.action.navigateBack command.

Done-Done criteria:

[x] Test Plan Item created
[x] Keyboard accessible
[x] Screen reader accessible
[x] Works with the different themes, including the high contrast theme
[x] Telemetry events in place
[ ] Release notes updated


Ignore/disable prettier didn't works

I tried to add comments like:
// prettier-ignore
// prettier-disable
/* eslint-disable prettier/prettier */
Or add external file '.prettierignore'
But your loder still modify file I'd like to ignore. Is there any way to ignore files when modifying?

strange, what versions of prettier and prettier-loader do you use?

and could you provide examples of code with comments?

"prettier": "^1.10.2",
"prettier-loader": "^2.0.1",

Well. I user prettier loader with webpack-dev-server. And I'v got file with react routes. Each route is longer, than 120 symbols (that I set in prettier-loader config), but event after adding 'ignore', 'disable' etc. comments it changes file with routes.
Config for prettier loader in webpack
{       test: /\.jsx?$/,       use: {         loader: 'prettier-loader',         options: {           useTabs: false,           tabWidth: 2,           singleQuote: true,           printWidth: 120,           trailingComma: 'all',           bracketSpacing: true,           arrowParens: 'always'          },       }     }

Could you please provide example of jsx code where you write comments

I mean how you write comments inside jsx?

Like this
http://take.ms/JbJ8w
Just at the top of the file.

Thanks, I think I'll add test for this case today, and take a look what's going on

Sorry for so long waiting, as @rchaser53 just wrote in another issue, his own version of prettier-loader does support of .prettierignore files, so you can try it:
https://github.com/rchaser53/prettier-loader, or wait for a week (I hope so) until I’ll fix it in this package

So, I just added test for ignoring prettier using comments, and it works, see this commit, because it's the same as if you just tried to run prettier-cli on your code.
The next thing is to check/fix work with .prettierignore file, working on it

What about trying to prevent formatting with comment, I think the problem that

A JavaScript comment of // prettier-ignore will exclude the next node in the abstract syntax tree from formatting.

And the next node in the abstract syntax tree in your example is // prettier-disable and all next code will be formatted.
So yes, if you want to ignore the whole file it's better to keep it in .prettierignore

fixed in #12
npm version 2.1.0


Add support for Door_Window_M sensor type

Before submitting this form

[X] I have checked that this sensor type was not suggested for addition before; I know that it could
be in open or closed issues, and if there was another issue mentioning this sensor type I could
simply comment in it instead

[X] I have updated the <sensor type> mention in the title of the issue, but left the issue title
as it was otherwise

[X] I understand that if I want to suggest the addition of more than a single sensor type, I need
to file that form for each separate type

Sensor type
Door_Window_M
Home Assistant device class
door and window contact and vibration combo
Does the panel send sensor status updates?

[X] Yes, I can see the Open/Close messages (I have been able to capture ZONE_ACTIVE messages)
[ ] No, it seems to only tell us the sensor exists, but never update its state

Sensor data from an INFO message
WARNING qolsys_panel: sensor of unknown type: {'id': 'E911A9', 'type': 'Door_Window_M', 'name': 'Master Bed Window 1', 'group': 'instantperimeter', 'status': 'Closed', 'state': '0', 'zone_id': 10, 'zone_physical_type': 1, 'zone_alarm_type': 3, 'zone_type': 110, 'partition_id': 0}
WARNING qolsys_panel: sensor of unknown type: {'id': 'E911A9', 'type': 'Door_Window_M', 'name': 'Master Bed Window 1', 'group': 'instantperimeter', 'status': 'Open', 'state': '0', 'zone_id': 10, 'zone_physical_type': 1, 'zone_alarm_type': 3, 'zone_type': 110, 'partition_id': 0}
Sensor data from a ZONE_EVENT's ZONE_UPDATE message
WARNING qolsys_panel: sensor of unknown type: {'id': 'E911A9', 'type': 'Door_Window_M', 'name': 'Master Bed Window 1', 'group': 'instantperimeter', 'status': 'Closed', 'state': '0', 'zone_id': 10, 'zone_physical_type': 1, 'zone_alarm_type': 3, 'zone_type': 110, 'partition_id': 0}
WARNING qolsys_panel: sensor of unknown type: {'id': 'E911A9', 'type': 'Door_Window_M', 'name': 'Master Bed Window 1', 'group': 'instantperimeter', 'status': 'Open', 'state': '0', 'zone_id': 10, 'zone_physical_type': 1, 'zone_alarm_type': 3, 'zone_type': 110, 'partition_id': 0}
Sensor data from a ZONE_EVENT's ZONE_ACTIVE message
WARNING qolsys_panel: sensor of unknown type: {'id': 'E911A9', 'type': 'Door_Window_M', 'name': 'Master Bed Window 1', 'group': 'instantperimeter', 'status': 'Closed', 'state': '0', 'zone_id': 10, 'zone_physical_type': 1, 'zone_alarm_type': 3, 'zone_type': 110, 'partition_id': 0}
WARNING qolsys_panel: sensor of unknown type: {'id': 'E911A9', 'type': 'Door_Window_M', 'name': 'Master Bed Window 1', 'group': 'instantperimeter', 'status': 'Open', 'state': '0', 'zone_id': 10, 'zone_physical_type': 1, 'zone_alarm_type': 3, 'zone_type': 110, 'partition_id': 0}
Additional context
I have these sensors as part of my ADP system, they are combination contact and vibration sensors. The only information I was able to find in logs was the above information.

They switch to open both for a window opening and for a vibration ?

They switch to open both for a window opening and for a vibration ?

that is correct,


indicate next edit suggestion availability to screen reader users

Enable a screen reader and the settings to have edit suggestions
Make an edit - here, I accepted an inline completion (thus the view this in the accessible view message)
Visually, I see an edit suggestion. There's no indication of this to screen reader users. We probably should have an accessibility signal for this and want to indicate how to navigate there via keyboard in the editor's a11y help dialog. cc @afre100

@meganrogge good call! I return in December, so should be able to have this in December/Jan

@meganrogge Since my leave is going to last a few weeks later than expected, let's update the ETA to early Feb


Build static site from documentation

It's a much more convenient and extensible way to add information about new printers and the various nuances of printing.
This PR replaces #5.

Here is a preview: https://orhideous.github.io/niimprint/hardware/
If all goes well, we'll need to replace the repository URL in the mkdocs.yml

@AndBondStyle Please, take a look :)

Taking a look... Well, I see what's cool about a separate site with docs, however with the python library of this size, is it really necessary? I think right now it's more important to just write more docs in plain markdown than migrate them to mkdocs.
With that in mind, I still appreciate the work you did. Maybe let's merge it into the "docs" branch, take some time to add more info (info about supported printers, more info about the protocol etc.), and when it'll start to look substantial, we merge it into master?


fix: remove duplicate locale in matchPath

This is already set on the lines above

poke @jimmyn - looks like this is a long term issue.

poke @jimmyn

poke @jimmyn


Update README.md

Added TPU Bumper link

Sorry, I'm not going to put promotional links on the list.


Patch image for Starlink 24 is wrong

The patch image for Starlink 24 is currently set to the patch of the Crew 2 mission 😛

Should be resolved per #749


Format time duration to nanos

The scroll time was being formatted based on the Go time.Duration format. So for one minute
it would use 16666h40m0s. Elasticsearch supports nanoseconds as a time unit so so it can
pass the Go time.Duration value through without any conversion just by appending "nanos".
This updates the generator but doesn't regenerate the API sources.
Fixes #25

I finally had a proper look into this, sorry for the delay. This is a critical bug indeed, probably coming from some naïve sketching à la time.Duration(100), where the value has been passed from outside.
I re-generated the API source and ran the test suite against current 7.0.0-SNAPSHOT, to verify the tests are not impacted. It looks like the YAML test suite doesn't actually use the timeout values at all.
Thinking about it more broadly, I have two concerns now:

I think that we "leak" too much implementation here, with the strconv.FormatInt(int64(r.Timeout), 10) + "nanos" part. Wouldn't it be better to create a helper method in the esapi package, like eg. the BoolPtr() one, and call it? It would make the code more readable, and hide the implementation (in the good sense of the word).

While it's correct that we can use the nanos unit, as it is supported by Elasticsearch, I can see how people would be confused when they see it in a logging output, for example. After all, a timeout of one hour would be<PHONE_NUMBER>000nanos. Therefore, what if we would convert the duration to milliseconds, with something like this: strconv.FormatInt(int64(1*time.Hour)/int64(time.Millisecond), 10)+"ms"). (I don't think that, practically, anybody would set an HTTP timeout to a nanosecond resolution.)

What do you think? I can work on the implementation, but would like to hear your thoughts.

You're probably right that no one will require nanosecond precision. Regarding (1), is this a helper method to simplify the generated code? Or is this not what you mean? You could wrap the time.Duration in a custom type that marshals to milliseconds only. Like
type Duration time.Duration
func (d Duration) MarshalText() ([]byte, error) { return /* N ms */ }

Correct, a helper method to simplify the generated code.
I wouldn't like to use a custom type (wrapper), because that would prevent users from simply using the stdlib's time.Duration one.
So I'm thinking about a function like this in the esapi package:
func FormatDuration(d time.Duration) string {
	if d <= time.Millisecond {
		return d.String()
	}
	return strconv.FormatInt(int64(d)/int64(time.Millisecond), 10) + "ms"
}

fmt.Println("1hour |", FormatDuration(time.Duration(time.Hour)))
// => 1hour | 3600000ms

Working version at https://play.golang.org/p/V_8kGdsQ0RY.

I wouldn't like to use a custom type (wrapper), because that would prevent users from simply using the stdlib's time.Duration one.

Right, I was thinking you would keep the user-facing API as is using time.Duration. But when building up the params map you would populate it with params["timeout"] = esapi.Duration(r.Timeout).String(). (I just now realized that params is a map[string]string so disregard my earlier comment about MarshalText.)
Having your own FormatDuration is a fine solution too. I personally wouldn't rely on time.Duration.String() just to be insulated from upstream formatting changes. And make sure you account for microseconds.
I added my Duration type example to your example: https://play.golang.org/p/oAofKWqXx2f

Many thanks for updating the playground code, Andrew. I've lifted the test cases and the implementation, and created a pull request at https://github.com/elastic/go-elasticsearch/pull/36.
I went with the helper method, unexported for now, esapi.formatDuration(). Can you have a look at that patch? I'll update the generator after it's merged.


Make interface display names more human readable

Temporary solution for #588 until next NeuroConv release with the display names as class variables for each interface. cc @bendichter
We don't need to merge this if the NeuroConv release schedule is relatively fast.
Result:

After adding an interface, the key is still the name of the interface:

I wasn't sure what the downstream effects of changing that are so I left that as is.

Temporary solution for https://github.com/NeurodataWithoutBorders/nwb-guide/issues/588 until next NeuroConv release with the display names as class variables for each interface

We don't need a release of NeuroConv to make it work; NWB GUIDE packages the main branch

I'm not sure what the "(All Data)" part adds; what are you trying to say with that?

I wouldn't do this on the TypeScript side; I'd modify the values returned by the NeuroConv query on the backend since that's a lot more customizable: https://github.com/NeurodataWithoutBorders/nwb-guide/blob/interface_display_name/pyflask/manageNeuroconv/manage_neuroconv.py#L165-L170
You can also set it up there to retrieve the 'display_name' if set as an attribute on the data interface classes
Did you want to work on that @rly?

Updated to align with NeuroConv and the rest of the GUIDE repo, as displayName should've just been used in GuidedStructure.js as the key value, rather than replacing key in the Search and List components.
Note that several converters and interfaces need to be named in NeuroConv still:

LGTM except for failing tests
Fine with getting this through as is and adding more display names on NeuroConv over time

Thanks for flagging that. Tests are passing now!

Just updated so that the info attribute is used preferentially to __doc__. Also enabled searching by suffix.
Holding off on the use of associated_suffixes in the Data Formats page for a follow-up. That is the desired target location for both the informational and programmatic use of this attribute, right?

Just updated so that the info attribute is used preferentially to doc.

Yeah I thought about just defering to the doc but the downside is our class docstrings have a lot of .rst and sphinx formatting for the autogeneration in the API section. So the info is intended to be a shorter, text-only version of that.

That is the desired target location for both the informational and programmatic use of this attribute, right?

The NeuroConv PR currently has an attribute on every class called associated_suffixes which is a tuple of strings. If that PR is merged as is what would be the target location for retrieving the information

@garrettmflynn an e2e conflict on this one

@garrettmflynn https://github.com/catalystneuro/neuroconv/pull/734 is mostly ready to go now; shall we do a pass and see if this is ready for review?

With that PR you can use a new function to get what you need
get_format_summaries imported by from neuroconv import get_format_summaries

Updated! However, for using get_format_summaries to make much sense, I've declared the results as a global variable. Otherwise, I was grabbing the values on an as-needed basis directly from the interface.

@garrettmflynn Still a merge conflict with the e2e tests

Ah missed the merge conflict. Was just trying to nail the test failure down

@CodyCBakerPhD All of these tests are now going to fail because of the reliance on the NeuroConv branch. Previously, I was just using fallbacks if things didn't exist—but that new function can't be handled the same way.
How do you want to mediate that in the meantime?

I'm fine with the latter if you're fine merging with tests failing 😅

Oh no, not what I meant lol 😆 this should either not be merged until upstream is, or pin to NeuroConv dev branch it's compatible with and immediately update the pins after that merge

Ah gotcha lol

Yep, this looks great now
Just need a better search functionality in a follow-up to find things like "phy" or "sorted" (as in, "spike sorted" currently only finds "sorting")


Some known lyrics not found

I would really agree to add my own lyrics because if the app can't find Queen - Bohemian Rhapsody then what's the reason for me using it.
Yesterday the app crashed and I wanted to report that but today it hasn't done that so it's good

I am sorry I am not using any crash reporting tool atm. I should probably get that set up.
As far as not finding lyrics for that song is concerned, can you please make sure your song contains the proper tags? It was able to find the lyrics for me with these tags

Closing due to inactivity. Please feel free to open another issue if you are still having problems!


Check URL Updater issues

We are logging a summary of our URL Updater.  We need to check what is causing this.
2024-11-18T04:05:03.4932538Z android-studio/android-studio versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 3 failed, 1530 succeeded, 1533 total, 0.20% error
2024-11-18T04:05:03.4933870Z aws/aws versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 1 failed, 1608 succeeded, 1609 total, 0.06% error
2024-11-18T04:05:03.4935076Z az/az versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 13 failed, 64 succeeded, 77 total, 16.88% error
2024-11-18T04:05:03.4936299Z docker/docker versions added: 0 failed, 87 succeeded, 87 total, 0.00% error - versions verified: 0 failed, 0 succeeded, 0 total, 0.00% error
2024-11-18T04:05:03.4937561Z dotnet/dotnet versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 67 failed, 1509 succeeded, 1576 total, 4.25% error
2024-11-18T04:05:03.4938961Z eclipse/cpp versions added: 0 failed, 10 succeeded, 10 total, 0.00% error - versions verified: 12 failed, 84 succeeded, 96 total, 12.50% error
2024-11-18T04:05:03.4940268Z eclipse/jee versions added: 0 failed, 10 succeeded, 10 total, 0.00% error - versions verified: 12 failed, 84 succeeded, 96 total, 12.50% error
2024-11-18T04:05:03.4941542Z eclipse/eclipse versions added: 0 failed, 10 succeeded, 10 total, 0.00% error - versions verified: 11 failed, 86 succeeded, 97 total, 11.34% error
2024-11-18T04:05:03.4942809Z gcloud/gcloud versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 0 failed, 947 succeeded, 947 total, 0.00% error
2024-11-18T04:05:03.4944084Z gcviewer/gcviewer versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 1 failed, 11 succeeded, 12 total, 8.33% error
2024-11-18T04:05:03.4945341Z gh/gh versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 108 failed, 632 succeeded, 740 total, 14.59% error
2024-11-18T04:05:03.4946601Z graalvm/community versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 0 failed, 52 succeeded, 52 total, 0.00% error
2024-11-18T04:05:03.4947884Z graalvm/graalvm versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 99 failed, 109 succeeded, 208 total, 47.60% error
2024-11-18T04:05:03.4949266Z gradle/gradle versions added: 0 failed, 144 succeeded, 144 total, 0.00% error - versions verified: 0 failed, 144 succeeded, 144 total, 0.00% error
2024-11-18T04:05:03.4950537Z helm/helm versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 107 failed, 610 succeeded, 717 total, 14.92% error
2024-11-18T04:05:03.4951783Z intellij/intellij versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 0 failed, 396 succeeded, 396 total, 0.00% error
2024-11-18T04:05:03.4953189Z jasypt/jasypt versions added: 0 failed, 1 succeeded, 1 total, 0.00% error - versions verified: 0 failed, 16 succeeded, 16 total, 0.00% error
2024-11-18T04:05:03.4954436Z java/java versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 50 failed, 196 succeeded, 246 total, 20.33% error
2024-11-18T04:05:03.4955709Z jenkins/jenkins versions added: 0 failed, 163 succeeded, 163 total, 0.00% error - versions verified: 0 failed, 162 succeeded, 162 total, 0.00% error
2024-11-18T04:05:03.4956951Z jmc/jmc versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 6 failed, 18 succeeded, 24 total, 25.00% error
2024-11-18T04:05:03.4958183Z kotlinc/kotlinc versions added: 0 failed, 26 succeeded, 26 total, 0.00% error - versions verified: 12 failed, 32 succeeded, 44 total, 27.27% error
2024-11-18T04:05:03.4959617Z kotlinc-native/kotlinc-native versions added: 0 failed, 17 succeeded, 17 total, 0.00% error - versions verified: 68 failed, 100 succeeded, 168 total, 40.48% error
2024-11-18T04:05:03.4961017Z lazydocker/lazydocker versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 50 failed, 159 succeeded, 209 total, 23.92% error
2024-11-18T04:05:03.4962267Z mvn/mvn versions added: 0 failed, 37 succeeded, 37 total, 0.00% error - versions verified: 0 failed, 0 succeeded, 0 total, 0.00% error
2024-11-18T04:05:03.4963444Z mvn/mvn versions added: 0 failed, 13 succeeded, 13 total, 0.00% error - versions verified: 0 failed, 0 succeeded, 0 total, 0.00% error
2024-11-18T04:05:03.4964651Z node/node versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 49 failed, 2507 succeeded, 2556 total, 1.92% error
2024-11-18T04:05:03.4965853Z npm/npm versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 0 failed, 481 succeeded, 481 total, 0.00% error
2024-11-18T04:05:03.4967189Z oc/oc versions added: 0 failed, 398 succeeded, 398 total, 0.00% error - versions verified: 1 failed, 1193 succeeded, 1194 total, 0.08% error
2024-11-18T04:05:03.4968451Z pgadmin/pgadmin versions added: 0 failed, 11 succeeded, 11 total, 0.00% error - versions verified: 3 failed, 21 succeeded, 24 total, 12.50% error
2024-11-18T04:05:03.4969682Z pip/pip versions added: 0 failed, 8 succeeded, 8 total, 0.00% error - versions verified: 0 failed, 8 succeeded, 8 total, 0.00% error
2024-11-18T04:05:03.4970916Z python/python versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 300 failed, 634 succeeded, 934 total, 32.12% error
2024-11-18T04:05:03.4972196Z quarkus/quarkus versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 88 failed, 296 succeeded, 384 total, 22.92% error
2024-11-18T04:05:03.4973476Z docker/rancher versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 55 failed, 146 succeeded, 201 total, 27.36% error
2024-11-18T04:05:03.4974727Z sonar/sonar versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 69 failed, 143 succeeded, 212 total, 32.55% error
2024-11-18T04:05:03.4976010Z terraform/terraform versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 7 failed, 877 succeeded, 884 total, 0.79% error
2024-11-18T04:05:03.4977290Z tomcat/tomcat versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 120 failed, 1 succeeded, 121 total, 99.17% error
2024-11-18T04:05:03.4978526Z vscode/vscode versions added: 0 failed, 0 succeeded, 0 total, 0.00% error - versions verified: 47 failed, 733 succeeded, 780 total, 6.03% error
2024-11-18T04:05:03.4979404Z END OF FINAL URL UPDATER REPORT

The tools with the highest error rate tomcat and graalvm seem to have the same issue in common. Both tools use the GithubUrlUpdater and try to fetch the version numbers from the official github tags. Unfortunately the tag versions and the available downloads are not synchronized e.g. missing versions for tomcat 7.0.7 but download URL for 7.0.70.

Why is kotlin not using the GithubUrlUpdater instead of the WebsiteUrlUpdater?
Instead we could use: https://api.github.com/repos/JetBrains/kotlin/releases
Follow the assets_url and grab the browser_download_url with content_types "application/x-gzip" and "application/zip" from f.e. https://api.github.com/repos/JetBrains/kotlin/releases/131180439/assets
We would need a GithubUrlUpdater for releases instead of tags then though.

For tomcat we could use the download URLs from: https://github.com/apache/tomcat/tags instead of the official apache ones.
F.e. https://github.com/apache/tomcat/archive/refs/tags/7.0.7.tar.gz


Generating random objects from TS interfaces

I don't know if it's a proper place to ask questions like this, but is it possible to have a ts interface like this:
export interface Employment {
  location: string;
  workload: number;
  from: Date;
  to: Date;
}
interface Employee {
  shortName: string;
  firstName: string;
  lastName: string;
  currentLocation: string;
  employments: Array<Employment>;
}

and get an real object full of auto-filled properties like here?
const e: Employee = TypeMoq.Mock.generateRandomOfType<Employee>();
e.shortName === 'some random string';
e.employments[0].workload === 42;

It's not really possible in this way, not yet anyhow.
Using a Proxy instance you can capture any property invocation, but at runtime you don't have type information for the property and typescript doesn't eject reflection metadata for interfaces so there's no way to do it completely as described i.e. you wouldn't be able to return the right types of data.
However, if you had a class you could get typescript to emit reflection metadata for properties and then read that metadata to automatically setup the properties with correct types. Couple that with something like fakerjs and it's possible to create such a mechanism.
That will only work with simple types - complex types aren't serialized into the reflection metadata in a way that would support this (yet).


Output folder widening

VSCode Version: Code 1.18.1 (929bacba01ef658b873545e26034d1a8067445e9, 2017-11-16T18:32:36.023Z)
OS Version: Windows_NT x64 10.0.15063
Extensions:

Extension
Author (truncated)
Version

cpptools
ms-
0.14.2

vscode-arduino
vsc
0.2.10

Every bulid add more deepher direcory path in output folder, until it is to long where it is imposible to build project any more.
This is folder structure after first compile, where output folder is "build":
..\build\sketch
after second compile:  \build\sketch\build\sketch
third compile: \build\sketch\build\sketch\build\sketch
4th compile: \build\sketch\build\sketch\build\sketch\build\sketch
and so on...
..
Steps to Reproduce:

Add output folder in arduino.jsdon as follow:
{
"board": "arduino:avr:nano",
"configuration": "cpu=atmega328",
"sketch": "Trusioma.ino",
"output": "build"
}
Bould project (ctrl-alt-r) several times

Reproduces without extensions: Yes/No

This is final error:
open sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\preproc\ctags_target_for_gcc_minus_e.cpp: The system cannot find the path specified.
[Error] Exit with code=1
and this is path created:
..\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\sketch\build\preproc

This looks like a problem of the vscode-arduino extension. Please file the bug report against that extension here https://github.com/Microsoft/vscode-arduino


added feather mo wifi

added support

Hey @MyloniteMaine thanks for contributing!
This looks mostly great, cleanup the blank lines in the json, and link to the correct product learn guide (scroll to end of product page - select 2nd variant - to find the relevant learn guides https://learn.adafruit.com/adafruit-feather-m0-wifi-atwinc1500 ).
The pinout might be missing a few pin definitions, I feel it's better to add more that may not work and remove them again later if needed after testing them all, as they may not work for certain purposes or conflict (I haven't looked properly yet).
If you want to try building the firmware and pretending to be another board id, then you can at least get past the compile stage and watch the serial monitor and see if wifi then mqtt connects, then it will fail to register device, or may register but all the pin info it receives will be wrong until this is merged. We'll have a look next week, hopefully my colleague @brentru has one to hand, unfortunately I haven't got this board (I can order one).


Fixed links not working in explore section of footer and added hover effect on subscribe button

Description
Links of explore section of footer was not working I linked them to appropriate pages.
Also I added hover effect on subscribe button
Related Issues
[Cite any related issue(s) this pull request addresses. If none, simply state “None”]

Closes #637

Type of PR

[X] Bug fix
[X] Feature enhancement

Screenshots / videos (if applicable)
Before:
https://github.com/Anishkagupta04/RAPIDOC-HEALTHCARE-WEBSITE-/assets/162733812/9261a610-f338-4ab5-9eba-34fe7a8e1816
After:
https://github.com/Anishkagupta04/RAPIDOC-HEALTHCARE-WEBSITE-/assets/162733812/70ddd276-2466-452e-abda-f9639e22534b
Checklist

[X] I have gone through the contributing guide
[X] I have updated my branch and synced it with project main branch before making this PR
[X] I have performed a self-review of my code
[X] I have tested the changes thoroughly before submitting this pull request.
[X] I have provided relevant issue numbers, screenshots, and videos after making the changes.
[X] I have commented my code, particularly in hard-to-understand areas.

Additional Context
closed #639 and created this PR

@Anishkagupta04 Please review and merge my PR under gssoc level

@Anishkagupta04 Please review and merge my PR under gssoc level

@Anishkagupta04 Please review and merge my PR under gssoc level

@Maana-Ajmera Any updates on this?


Remove unused declarations

Current coverage is 80.96% (diff: 100%)

Merging #4264 into master will decrease coverage by 0.06%

@@             master      #4264   diff @@
==========================================
  Files          1304       1304
  Lines         44305      44300     -5
  Methods           0          0
  Messages          0          0
  Branches       7083       7081     -2
==========================================
- Hits          35901      35866    -35
- Misses         5740       5764    +24
- Partials       2664       2670     +6

Powered by Codecov. Last update 8cf63c5...10d7de8

@matriv please review


Updated NATS exporter link

@brian-brazil - I've updated the NATS Exporter to be the one maintained by the NATS team, which was released this week. The previous link was to Lovoo's exporter - Markus (maintainer of Lovoo's) is aware of this change and fine with it.

This new exporter appears to be talking to multiple NATS servers, whereas the current one has the one-to-one mapping we recommend in our guidelines for exporters. May I ask why you've chosen to ignore this guideline?

Also as an exporter you should be using ConstMetrics rather than GaugeVec/CounterVec.

@brian-brazil , Thank you for the comments.
Concerning the one-to-one mapping, a NATS server cluster (multiple NATS servers linked together) operates as one entity from perspective of NATS clients, so I designed the exporter to be able to mirror this for monitoring.  That being said, one could easily configure a one-to-one mapping with multiple NATS exporter instances, and I'd be happy to describe that as a Prometheus recommended best practice in our own documentation.
We have had discussions about instrumenting the NATS server directly, which would certainly be a one-to-one mapping, but that is still in the design/discussion phase at this point.
I appreciate the note about ConstMetrics, and will certainly take a look at that.  Do you see any other areas we can improve on?
Thanks,
Colin

I designed the exporter to be able to mirror this for monitoring

How a user uses a system isn't always how it should be monitored, and we pretty strongly recommend against the exporter architecture you've implemented as service discovery is the responsibility of Prometheus - not of the exporter. If you wish to replace the existing exporter which is 1:1, you also need to be 1:1. See https://prometheus.io/docs/instrumenting/writing_exporters/#deployment

Do you see any other areas we can improve on?

Nothing else from a quick peek, bar the PrometheusMetricConfig struct being unused.

@brian-brazil , I updated the README, usage, etc for the 1:1 usage pattern in the guidelines.  Can you update the link at this point?

As far as I can tell, it's still possible with the compiled binary. An internal API is fine, but we've found users repeatedly think their standard use case is advanced.
The tag parameter should also be removed from the CLI (or at least the docs), as that's the responsibility of Prometheus SD+relabelling.

Thinking on this a bit more, removing the reference to the tag parameter would be sufficient as that's the only anti-pattern the readme currently mentions.

@brian-brazil , Finally got back to this!  I've removed all references to tags.  Are we good to go once @bjflanne resolves conflicts?
Thanks,
Colin

https://github.com/nats-io/prometheus-nats-exporter/blob/master/README.md#monitoring is still mentioning the server-id, which I understand won't be there now.

It looks like the existing one listed is completely abandoned, so there's no much point continuing to list it even if it is technically more compliant. Thanks for the PR!


operand "length" doesn't work as expected

Category

[ ] Question
[x] Bug
[ ] Enhancement

Expected or Desired Behavior
Operator "length" should return the number of characters inside a "string"
Observed Behavior
I'm trying to apply a conditional rendering inside a column by checking the length of a substring, but "length" always return "1"
Steps to Reproduce
{   "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json",   "elmType": "div",   "txtContent": {     "operator": "length",     "operands": [       {         "operator": "substring",         "operands": [           "@currentField",           0,           18         ]       }     ]   } }
Thanks!

@PrasadKasireddy is completely correct in how the length operator works. However, to your point it makes very little sense that there isn't a length operator for string length. Until we get that, there is a workaround that can be used utilizing the indexOf operator:
"txtContent": "=indexOf('dogfood' + '|', '|')" results in 7
You can see this explained with more details in this demo: https://www.youtube.com/watch?v=k5bSKcMiJcc


Working with the omnisharp-roslyn codebase (question)

Hi Peeps,
When you work on the codebase, which IDE do you use? Visual Studio? Visual Studio Code? I'm having a hard time making any of them work. Is there some info about setting up a developer environment?
I'm on windows, and when i use Visual Studio Code, i get a deluge of:
'A compatible SDK version for global.json version: [2.1.301] from [C:\projects\omnisharp-roslyn\global.json] was not found
Did you mean to run dotnet SDK commands? Please install dotnet SDK from:
https://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409'
I have both the .NET 4.6 targeting pack and the above dotnet core SDK installed.
When i use visual studio with the latest resharper, It cannot find any of the nuget packages, and hence thousands of reference errors etc.
There must be something very basic I'm missing. Do you have any ideas?
br
Frederic

Please make sure to run the build command upfront.
Also, the pinned version of the SDK is necessary as well as some other considerations mentioned here https://github.com/OmniSharp/omnisharp-roslyn/blob/master/BUILD.md.


feature/smartpoi

Hi!
I tried to use ajv  to validate the schema.json file, but it raises the next error:
Hopu@DESKTOP-DAVID MINGW64 ~/Desktop/datamodels/new/dataModels (feature/smartpoi)
$ ajv validate -s PointOfInteraction/SmartPointOfInteraction/doc/schema.json -r common-schema.json -r geometry-schema.json -d PointOfInteraction/SmartPointOfInteraction/doc/example.json
schema geometry-schema.json is invalid
error: no schema with key or ref "http://json-schema.org/draft-04/schema#"
I tried also with an existing example:
Hopu@DESKTOP-DAVID MINGW64 ~/Desktop/datamodels/new/dataModels (feature/smartpoi)
$ ajv validate -s Parking/OffStreetParking/schema.json -r common-schema.json -r geometry-schema.json -d Parking/OffStreetParking/example.json
schema geometry-schema.json is invalid
error: no schema with key or ref "http://json-schema.org/draft-04/schema#"
Can someone explain me what I'm doing wrong?
BR,
David

Hi David,
ajv was recently updated, to work with draft-schema-4, you need to use the old version: npm install ajv@^4

Thanks you @chicco785, I was able to correct and pass the schema/example files.

Hi! I closed the PR since 'smartpoi' data model has been introduced in the parent repository (fiware/datamodels), it will be obtained in the next pull from parent.
Thanks you @chicco785 and Federico


add podspec

Just got this in and working as the first working Swift pod in Eidolon

swiftc segfaults for me when running with a different optimization level though, shame.

+1

It would be great to have cocoapods integration. Should impact popularity of framework significantly.

+1

I've added this in. I don't use CocoaPods so I'm not entirely sure it's 100% correct, but it appears to work.Thanks for the PR.
https://cocoapods.org/pods/XCGLogger


Normalize Bugfixes and Tests

Cool. So to recap, except the escape characters that are missing (I will add this in a separate commit, as I have to slightly change the EscapeInlineParser and Inline node for this), are all core CommonMark nodes all handled by this PR?

To my very humble understanding, yes. I mean you coded most of it, I just fixed the bugs I found and extended the unit tests.


Reusing nim method for wrapping C++ methods

When interfacing with C++ classes and methods, it is necessary to re-wrap methods as procedures for each derived class. E.g. if I have Base and Derived I would have to repeat wrapping of the Base methods for Derived type. I tried using method, but it gives me 'invalid pragma: importcpp: "#.toOverride(@)"'  error on the following code, so it looks like I can't benefit from nim OOP features in this case.
  {.emit: """/*TYPESECTION*/
struct Base {
  int baseField;
  int baseMethod() { return 12; }
  virtual int toOverride() { return 42; }

};
struct Derived : public Base {
  int derivedField;
  int toOverride() override { return 45; }
};
""".}

type
  CxxBase {.importcpp: "Base", bycopy, inheritable.} = object
    baseField: cint

  CxxDerived {.importcpp: "Derived", bycopy.} = object of CxxBase
    derivedField: cint

# All methods of the base class must be repeated for each derived. For
# cases like `QWidget` that has 214 base methods and 37 derived it classes results
# in **7918!** repetitions.
proc baseMethod(base: CxxBase): cint {.importcpp: "#.baseMethod(@)".}
proc baseMethod(base: CxxDerived): cint {.importcpp: "#.baseMethod(@)".}

proc toOverride(base: CxxBase): cint {.importcpp: "#.toOverride(@)".}
proc toOverride(base: CxxDerived): cint {.importcpp: "#.toOverride(@)".}

proc toOverrideTypeclass(base: CxxBase | CxxDerived): cint {.importcpp: "#.toOverride(@)".}

# Ideally I would like to import C++ methods as **methods**, but I get
# 'Error: invalid pragma: importcpp: "#.toOverride(@)"'

when false:
  method toOverrideMethod(base: CxxBase): cint {.importcpp: "#.toOverride(@)".}

block:
  let derived = CxxDerived(baseField: 123123)
  echo derived.baseField

  echo CxxBase().toOverride()
  echo CxxDerived().toOverride()

  echo CxxBase().toOverrideTypeclass()
  echo CxxDerived().toOverrideTypeclass()

type
  NimBase {.inheritable.} = object
    baseField: cint

  NimDerived = object of NimBase
    derivedField: cint

method baseMethod(base: NimBase): int {.base.} = 12
method toOverride(base: NimBase): int {.base.} = 42
method toOverride(base: NimDerived): int = 45

block:
  let derived = NimDerived(baseField: 123123)
  echo derived.baseField

  echo NimBase().toOverride()
  echo NimDerived().toOverride()

I specifically repeated the implementation in nim as well to illustrate how I would like wrapper to behave. It is not difficult to generate additional wrappers for all derived classes, but as indicated in comment it could lead to multi-thousand repetitions (again QWidget has 37 derived classes, and it would repeat at least 214 methods for each of them. And I used QWidget as and example. With QObject it could be even bigger).
I thought about possible solutions, but they don't seem particularly plausible to me:

Using typeclasses - proc toOverride(base: CxxBase | CxxDerived): cint {.importcpp: "#.toOverride(@)".}. It might look fine for such a small example, but in the end it would mean putting all derived class wrappers in a single file, and declare all procedures afterwards, creating one giant file from a library instead of keeping things separated.
Implementing wrappers as a macro that checks if the argument has been derived from required base class - this might work, but it seems like a horrible hack where I have to mix {.emit.} with macro code and traverse full inheritance tree on each call encountered in code.

So the question is - can method somehow be used to solve this issue, or I need to generate repeated wrappers for each derived class (right now I'm doing this, which results in tons of repetitions)?

Originally asked in forum thread, but also copied here because it is particularly important, but unlikely to be answered soon.

the following "almost works":
when true:
  {.emit: """/*TYPESECTION*/
  struct Base {
    int baseField;
    int baseMethod() { return 12; }
    virtual int toOverride() { return 42; }

  };
  struct Derived : public Base {
    int derivedField;
    int toOverride() override { return 45; }
  };
  """.}

  type
    CxxBase {.importcpp: "Base", bycopy, inheritable.} = object
      baseField: cint

    CxxDerived {.importcpp: "Derived", bycopy.} = object of CxxBase
      derivedField: cint

  proc baseMethodImpl(base: CxxBase): cint {.importcpp: "#.baseMethod(@)".}
  method baseMethod(base: CxxBase): cint {.base.} = baseMethodImpl(base)
  proc toOverrideImpl(base: CxxBase): cint {.importcpp: "#.toOverride(@)".}
  method toOverride(base: CxxBase): cint {.base.} = toOverrideImpl(base)
  when defined case2b:
    proc toOverrideImpl2(base: CxxDerived): cint {.importcpp: "#.toOverride(@)".}
    method toOverride(base: CxxDerived): cint = toOverrideImpl2(base)

  block:
    let derived = CxxDerived(baseField: 123123)
    echo derived.baseField

    echo CxxBase().baseMethod()
    echo CxxDerived().baseMethod()

    echo CxxBase().toOverride()
    when defined case2b:
      echo CxxDerived().toOverride()

nim r -b:cpp main works
nim r -b:cpp -d:case2b main gives cgen error:
/Users/timothee/git_clone/nim/timn/build/nimcache/@mt12445.nim.cpp:222:14: error: no member named 'm_type' in 'Base'
                if (!(base.m_type == (&NTIcxxderived__5KCvJiTlz3Lz1sFqYEsBSQ_))) goto LA3_;
                      ~~~~ ^
/Users/timothee/git_clone/nim/timn/build/nimcache/@mt12445.nim.cpp:223:20: error: no member named 'm_type' in 'Base'
{               if (!isObj(base.m_type, (&NTIcxxderived__5KCvJiTlz3Lz1sFqYEsBSQ_))){ raiseObjectConversionError(); }
                           ~~~~ ^
/Users/timothee/git_clone/nim/timn/build/nimcache/@mt12445.nim.cpp:230:29: error: no member named 'm_type' in 'Base'
                if (!(isObjWithCache(base.m_type, (&NTIcxxbase__AnOdMbGZliGJzFUoc6fCJA_), Nim_OfCheck_CACHE3))) goto LA6_;
                                     ~~~~ ^

This issue can be partially solved if only ref/ptr types are used. It still breaks on the
{.emit: """/*TYPESECTION*/
struct Base {
  int baseField;
  int baseMethod() { return 12; }
  virtual int toOverride() { return 42; }

};
struct Derived : public Base {
  int derivedField;
  int toOverride() override { return derivedField; }
};

struct Other {};
""".}

type
  CxxBase {.importcpp: "Base", bycopy, inheritable.} = object
    baseField: cint

  CxxDerived {.importcpp: "Derived", bycopy.} = object of CxxBase
    derivedField: cint

  CxxOther {.importcpp: "Other", bycopy.} = object

proc aux() {.header: "<new>", importc: "//".}

proc toOverride(base: ref CxxBase): cint {.importcpp: "#->toOverride(@)".}
  # {.emit: "return `base`->toOverride();".}

proc newCxxBase(): ref CxxBase  =
  aux()
  new(result)
  {.emit: "new ((void*)result) Base();".}

proc newCxxDerived(): ref CxxDerived  =
  aux()
  new(result)
  {.emit: "new ((void*)result) Derived();".}

proc newCxxOther(): ref CxxOther =
  aux()
  new(result)
  {.emit: "new ((void*)result) Other();".}

echo newCxxBase().toOverride()
echo newCxxDerived().toOverride()
# echo newCxxOther().toOverride()

Actually I just realized I can drop bycopy and replace it with byref:
{.emit: """/*TYPESECTION*/
struct Base {
  int baseField;
  int baseMethod() { return 12; }
  virtual int toOverride() { return 42; }

};
struct Derived : public Base {
  int derivedField;
  int toOverride() override { return derivedField; }
};

struct Other {};
""".}

type
  CxxBase {.importcpp: "Base", byref, inheritable.} = object
    baseField: cint

  CxxDerived {.importcpp: "Derived", byref.} = object of CxxBase
    derivedField: cint

  CxxOther {.importcpp: "Other", byref.} = object

proc aux() {.header: "<new>", importc: "//".}

method toOverride(base: CxxBase): cint {.base.} =
  {.emit: "return `base`->toOverride();".}

echo CxxBase().toOverride()
echo CxxDerived().toOverride()
# echo newCxxOther().toOverride()

now works corectly

cool!
nim manual is in desperate need for a beefed up section (ideally a separate rst file, eg interop.rst) dedicated to interop, are you interested in a PR that would show this example?
needs a bit of cleanup, eg remove aux and add
  var a = CxxDerived()
  a.derivedField = 123
  assert a.toOverride() == 123

Feel free to add it to any manual section, but after releasing alpha version of hcparse I wanted to spend some time summarizing all my solution in a series of articles, something like "Nim for C++ programmer". Also, I'm not really sure I'd this is the correct approach, so I'd prefer to mass-test it on some library (like Qt, which was the reason for this question) and then say "yes, this is the correct way that would not bite you on some edge case"

the correct way should (IMO) still involve supporting method+importcpp and avoid resorting to emit (which has its own issues, eg not working in templates (i can link the issue if needed), eg:
template fn =
  method toOverride(base: CxxBase): cint {.base.} =
    {.emit: "return `base`->toOverride();".}

)
but in the meantime it's good to show what's possible to unblock ppl that need interop; it's more of a living document given that C++ interop is still in flux

method toOverride(derived: CxxDerived2): cint =
  echo "Overide method impementation from nim side"
  return 1231.cint

echo newCxxDerived2().toOverride()
``` does not work as it fails with C++ codegen compilation error
```c++
/mnt/workspace/clean-clone/hack/testing/nim/c_interop/cpp_tests/cache/@minheritance.nim.cpp:330:31: error: ‘struct Base’ has no member named ‘m_type’
  330 |                 if (!((*base).m_type == (&NTI__5WdQBNAaXBHGF2AaoSDNJQ_))) goto LA3_;

i see, so it's same error as above (https://github.com/haxscramper/hcparse/issues/1#issuecomment-865166616)
maybe file an issue in nim repo? RFC or not RFC, this should be fixed

Well, the issue seems obvious - object is not derived from a RootObj so it does not have an m_type field. Since I also want to derive from from C++ issue it would be unsolvable without multiple inheritance.

it would be unsolvable without multiple inheritance.

there should be a solution for this case that doesn't require solving MI (which is more complex and can be addressed seperately), ie allowing (possibly with a pragma) method toOverride(base: CxxDerived2): cint = 33 to work even though CxxDerived2 doesn't derive from a RootObj
(and yes, an RFC would be good)

Alternatively to hacks (generating byref types or bruteforce solutions with copypasting every method) I can just require explicit type conversion using 'as' operator -
var slider = cnewQSlidwe()
slider.as(QWidget)[].someQWidetMethod()