Tutorial: HLS access issues thread

A tutorial for HLS data access. Encountered issues:
I'm working on a HLS tutorial and it looks like the "cloud cover" parameter we use for filtering is missing. So based on our current approach we can't filter our data by all of our parameters. It looks like the dict search return has changed so the NASA CMR STAC endpoints may not be what we expect anymore. The cloud cover param is still in the umm.json info but we can't use pySTAC then. I can live without it for now, but this should be noted as something to look at.
link to source code with query_stac function: https://ade.ops.maap-project.org/serverk0n2pki4-ws-jupyter/server-3100/lab/tree/Developer/icesat2_boreal/lib/fetch_HLS.py
link to code where error was found: https://ade.ops.maap-project.org/serverk0n2pki4-ws-jupyter/server-3100/lab/tree/Developer/MAAP_Tutorials/HLS/HLS_search.ipynb
link to CMR: https://cmr.earthdata.nasa.gov/stac/LPCLOUD/collections/HLSL30.v2.0/items/HLS.L30.T17SPC.2020154T155208.v2.0
link to umm_json: https://cmr.earthdata.nasa.gov/search/concepts/G2176833025-LPCLOUD.umm_json

As a placeholder, I have been able to apply a cloud cover threshold by parsing the metadata of each image file:
for feature in features:
            umm_json = feature['links'][6]['href']
            umm_data = !curl -i {umm_json}
            for line in umm_data:
                if "CLOUD_COVERAGE" in line:
                    cc_perc = (int(line.split("CLOUD_COVERAGE")[-1].split('"')[4]))
                    if cc_perc > cloud_cover:
                        pass
                    else:
                        try:
                            for band in bands:
                                output_file = feature['assets'][band]['href'].replace('https://data.lpdaac.earthdatacloud.nasa.gov/', s3_path)
                                bucket_name = output_file.split("/")[2]
                                s3_key = "/".join(output_file.split("/")[3:])
                                head = s3.head_object(Bucket = bucket_name, Key = s3_key, RequestPayer='requester')
                                if head['ResponseMetadata']['HTTPStatusCode'] == 200:
                                    feature['assets'][band]['href'] = output_file
                            clean_features.append(feature)

@nmt28 can you update with the latest findings, as it seems to be working now?

I found that the cloud cover parameter was in the geojson, but the code I copied across from 3_1_2_dps.py was giving me an error. I have re-written the code in the HLS tutorial so that tit is able to find the parameter I need:
def write_local_data_and_catalog_s3(catalog, bands, save_path, cloud_cover, s3_path="s3://"):
    '''Given path to a response json from a sat-api query, make a copy changing urls to local paths'''
    creds = maap.aws.earthdata_s3_credentials('https://data.lpdaac.earthdatacloud.nasa.gov/s3credentials')
    aws_session = boto3.session.Session(
        aws_access_key_id=creds['accessKeyId'],
        aws_secret_access_key=creds['secretAccessKey'],
        aws_session_token=creds['sessionToken'],
        region_name='us-west-2')
    s3 = aws_session.client('s3')

    with open(catalog) as f:
        clean_features = []
        asset_catalog = json.load(f)

        # Remove duplicate scenes
        features = asset_catalog['features']

        for feature in features:
            cc_perc = int(feature['properties']['eo:cloud_cover'])
            if cc_perc > cloud_cover:
                pass
            else:
                try:
                    for band in bands:
                        output_file = feature['assets'][band]['href'].replace('https://data.lpdaac.earthdatacloud.nasa.gov/', s3_path)
                        bucket_name = output_file.split("/")[2]
                        s3_key = "/".join(output_file.split("/")[3:])
                        head = s3.head_object(Bucket = bucket_name, Key = s3_key, RequestPayer='requester')
                        if head['ResponseMetadata']['HTTPStatusCode'] == 200:
                            feature['assets'][band]['href'] = output_file
                    clean_features.append(feature)
                except botocore.exceptions.ClientError as e:
                    if e.response['Error']['Code'] == "404":
                        print(f"The object does not exist. {output_file}")
                    else:
                        raise
        # save and updated catalog with local paths
        asset_catalog['features'] = clean_features
        local_catalog = catalog.replace('sample', 'local-s3')
        with open(local_catalog,'w') as jsonfile:
            json.dump(asset_catalog, jsonfile)

        return local_catalog

Paul is currently re-registering 3_1_2_dps.y and will attempt. ops run. We will see if the problem occurs in that code (original code) nd whether we need to use the code block above. Either way it seems a solution is available.

This has been resolved. The parameters we needed were located without having to make edits


Support partial parsing

Description
dbt uses partial_parse.msgpack to make rendering things a lot faster. This PR adds support for partial_parse.msgpack in the following places:

ExecutionMode.LOCAL
ExecutionMode.VIRTUALENV
LoadMode.DBT_LS

This PR also allows users to explicitly turn off partial parsing. If this is done, then --no-partial-parse will be passed as an explicit flag in all dbt command invocations (i.e. all ExecutionModes and LoadMode.DBT_LS, albeit not the dbt deps invocation.)
This should address some performance complaints that users have, e.g. this message from Slack: https://apache-airflow.slack.com/archives/C059CC42E9W/p1704483361206829 Albeit, this user will also need to provide a partial_parse.msgpack.
My experimentation and looking at dbt-core source code confirms that dbt does not use manifest.json when partial parsing. It appears that these are just output artifacts, but not input artifacts. Only partial_parse.msgpack is used. (There are a couple ways to confirm this other than just checking source code
Also, I added a minor refactor of a feature I added a year ago: I added send_sigint() to the custom subprocess hook, since this custom subprocess hook did not exist back when I added it (if you want me to split this refactor into a different PR then let me know).
API change
I decided the best way to go about this would be to just add a partial_parse: bool to both the execution config and render config. For example:
dbt_group = DbtTaskGroup(
    ...,
    execution_config=ExecutionConfig(
        ...,
        partial_parse=True
    ),
    render_config=RenderConfig(
        ...,
        partial_parse=False
    )
)

That said, in all honesty users will not need to set this at all, except unless they want to suppress the little warning message about not being able to find the partial_parse.msgpack. This is because by default this addition searches for a msgpack if it exists, which is already the existing behavior in a sense, except right now the msgpack file never exists (dbt does look for it though).
When inserting into the AbstractDbtBaseOperator, I did not use global_boolean_flags. See the subsection below for why.
Other execution performance improvements
The main reason I am adding this feature is that it should dramatically improve performance for users. However, it is not the only way to improve
It's possible that we should add a way to add the flag --no-write-json as an explicit kwarg to the dbt base operator. Right now users can support this via dbt_cmd_global_flags=["--no-write-json"]. Some users (e.g. those using Elementary, or those using the dbt local operator callback kwarg) will want to write the JSON, but I suspect the majority of users will not. Similarly, --log-level-file is not used at all, and at minimum dbt should work best the vast majority of time with --no-cache-selected-only set.
It's also possible there should be some sort of "performant" mode that automatically sets all these defaults for optimal performance:

--no-write-json
--log-level-file=none
--no-cache-selected-only

Perhaps a "performant" config would be too cumbersome to implement (I would agree with that). In which case the docs could also have a section on performance tips.
A note on global_boolean_flags
I did not add the partial parse support to global_boolean_flags because it doesn't quite fit into the existing paradigm for this. Right now the default for each of these global_boolean_flags is False, whereas the default for partial parse is actually True. This makes fitting it in awkward.
I think it's possible that just having a tuple[str] is insufficient here, as some flags you may want to add (not just --no-partial-parse but also --no-write-json are by default True and must be explicitly turned off. Meaning that the parsing Cosmos does with flags of '--{flag.replace("_", "-")}' is ineffective for flags like this.
Right now, we have an example of putting no in front with no_version_check. Meaning that the default behavior of version checking is True, but the flag itself starts as negated so the default is actually False.
My proposal is, instead of global_boolean_flags: tuple[str], this should instead be global_boolean_flags: tuple[str | tuple[str, str | None, str | None]]. In the case that a global flag is a tuple[str, str | None, str | None], then the first arg should be the flag, the second should be "if true," and the third should be "if false." None indicates, when true/false (respectively), then do nothing.
For example:
class AbstractDbtBaseOperator(BaseOperator, metaclass=ABCMeta):
    ...
    global_boolean_flags = (
        ("no_version_check", "--no-version-check", None),
        ("cache_selected_only", "-cache-selected-only", None),
        ("partial_parse", None, "--no-partial-parse"),
    )

And Cosmos want to support str parsing for backwards compatibility. It's pretty straightforward to convert the data type:
if isinstance(flag, str):
    flag = (flag, '--{flag.replace("_", "-")}', None)

Related Issue(s)

Resolves #791
Partially resolves #785

#785 should probably be split up into two different stages: (1) support for partial parsing (2) (a) dbt project dir / manifest / partial_parse.msgpack is allowed to come from cloud storage. (b) dbt compile is able to dump into cloud storage.

Breaking Change?
Should not break anything. This doesn't do anything when partial_parse.msgpack is missing, and the default behavior (partial_parse=True) does not alter the dbt cmd flags.
Checklist

[x] I have made corresponding changes to the documentation (if required)
[x] I have added tests that prove my fix is effective or that my feature works

I don't know how the coverage thing works and if it is checking for 100% coverage of new commits vs just making sure the coverage goes up, but I vastly increased the coverage of the code by adding tests for the subprocess hook.

run dbt parse locally / in CICD (pre-deploying), which generates the necessary artifacts

Yes or dbt compile. Both of these commands will produce a manifest.json and partial_parse.msgpack. (A note: This code addition only uses partial_parse.msgpack; however a user making use of pre-compilation for performance reasons would also probably want to use manifest.json as a load method similarly for performance reasons. So two birds with one stone.)

push the entire project to the Airflow deployment
set the partial_parse flag

By default, partial_parse is True. They wouldn't need to explicitly set it unless they wanted to.
I made this API decision in part because the user already receives the following warning from dbt when they are not using partial parsing:
Unable to do partial parsing because saved manifest not found. Starting full parse.

Meaning that a user who intended on using partial parsing, and one who did not, is already being warned by dbt that they are not; and by default dbt is looking for it. So I think having the default behavior of the operator match the default behavior of dbt is sensible. (Also, the performance implications of checking for the existence of the file, and failing to find it, are negligible, so very low harm in doing so.)

I agree the performant mode is nice in theory but may be difficult to maintain. Maybe we should create a docs page specifically on performance with our recommendations? Inclusive of this flag, using the manifest parsing method, install LibYAML, etc. That way, for users who care about performance, there's a single doc for all optimization recommendations.

I do like this approach. I agree that this would be better than a "performant" mode.

Also, I just got my act together and got to full test coverage for this PR. 😅

holding this until https://github.com/astronomer/astronomer-cosmos/pull/827 is complete so we can measure the before/after!

My question would be why target is excluded here: https://github.com/astronomer/astronomer-cosmos/blob/72690d31ba6822ae6df56f4d56f26196234c80b5/cosmos/dbt/project.py#L15C39-L15C58
We pre-compile our projects on a shared volume, so and option to copy the whole target would probably solve all our issues

@ms32035 The history of Cosmos runtime is:

Initially they just ran out of the dbt project dir directly.
Then users quickly noted this is a non-starter because Airflow runtimes will often have the dags folder mounted as a read-only volume, so they switched to creating a temporary directory and copying the contents (see #233).
But this causes issues because of the Celery executor: shared workers on a small compute instance can clog the tmpdir and, if virtual storage runs out, this will cause a very very nasty SIGKILL deadlock (see #362 for description of the problem). So they (I believe very briefly, and never fully released?) switched to setting the --target-dir as a (blank) temporary directory (see #414).
But this only works for more recent versions of dbt; older versions don't let you specify a target dir via CLI or env vars. So they stopped doing that and instead started using symlinks (see #488).
 Hence this PR.

So why not just remove that line which excludes the target dir? Because that would cause a symlink to be created to the target dir, which would mean you're writing to the target dir, which is a non-starter for users with read-only mounts to their dags dir. OK, why use symlinks, why not just copy instead? Because that causes those nasty virtual storage issues for large dbt projects running on small Celery workers[*]. Why not symlink the read only files and copy the target dir? Because that's unnecessary; only partial_parse.msgpack is read by the dbt runtime pre-execution.[**]
Speaking as someone who has dealt with these problems pre-Cosmos and figured out a lot of the same lessons that Cosmos did, I think the way Cosmos works right now is very close to optimal, but they also have the added handicap of needing to support tons of different users and all their wacky idiosyncratic needs. The main suboptimality I see is the lack of partial parsing, which is why I wrote this PR. But the part where you don't symlink the target dir is absolutely correct, if you ask me. I don't see anything else I'd change with how Cosmos does parsing during task execution.
[*] Fun fact: there was a point when the popular dbt-expectations library shipped with a 3.03 MB .gif file after running dbt deps, kid you not. So imagine a Celery worker with max concurrency of 5 tasks, that's 15 MB devoted to a single .gif file. That may not sound like that much but this did cause a problem for me once, insofar that updating the package version to one without the .gif actually fixed my problems. The SIGKILL deadlock thing is not theoretically, it literally happened to me!
[**] In very niche situations, some extensions may use non-msgpack dbt artifacts. I believe dbt elementary is the most popular one. However, I believe it also uses these artifacts in post-hooks which would be generated via the command execution inside the temporary directory.

Thanks for detailed explanation @dwreeves . Never suggested that would copy would be a complete solution for every usecase, and can't wait to see this merged

Yeah I get it, I'm just giving a very thorough history of how we ended up here and what all the alternatives are. 😁

I made updates as per everyone's suggestions. Thanks.

The docs will have to make it clear that it's only used for rendering when dbt_ls is used and execution for local or virtualenv.

A note on the documentation. I am not documenting the behavior for LoadMode.DBT_LS. I think, in most cases, it will be rare for a user to both be using DBT_LS and have a partial_parse.msgpack. This would not be completely unheard of and can be a reasonable deliberate decision if the dbt project mutates a lot, but the partial_parse.msgpack is not being updated frequently, so you either set the load mode deliberately or just forego the manifest.json but keep the partial parse file. But all told this is a pretty niche situation-- I think a lot of users on DBT_LS mode are likely foregoing the use of dbt artifacts altogether. And I wasn't sure where it would fit in without feeling like it was adding clutter and potential confusion to the docs for most users. Let me know if you want to document this regardless.

@jbandoro Done


Move ToSerial and ToEnum to SerializationProviders from EnumProvider class

Currently ToSerial and ToEnum are on the EnumProvider class. They do not belong here -  as they are currently used for serialization. If we move To{Type.Name} to SerializationProviders we can ensure that the method will always have an implementation (in case the enum is overriden and doesn't have a ToName method).
Addresses this comment: https://github.com/microsoft/typespec/pull/3621#discussion_r1651524779

So I think we have a contradiction with the comment here if make the suggested change here: https://github.com/microsoft/typespec/pull/3642#discussion_r1651718517

https://github.com/microsoft/typespec/issues/4018


[eas-cli] device:create - implement typing in UDIDs

This is the last PR for eas device:create for now:

the first PR (#28) added the foundation for the command
the second PR (#33) added the actual implementation for the registration URL method

This PR adds the UDID input method. It means that the user can choose to input all device UDIDs without opening the URL on his devices.
The user is prompted for the following data:

device UDID (required)
device name (optional)
device class (iPhone/iPad/unknown)

https://github.com/expo/universe/pull/6165 is needed for this code to work.

@fson please check out the last two commits :)


Remove mem registry

Simplified redo of https://github.com/istio/istio/pull/11515. Deferring other debug controls to 1.2.

[APPROVALNOTIFIER] This PR is NOT APPROVED
This pull-request has been approved by: ostromart
To fully approve this pull request, please assign additional approvers.
We suggest the following additional approver: vadimeisenbergibm
If they are not already assigned, you can assign the PR to them by writing /assign @vadimeisenbergibm in a comment when ready.
The full list of commands accepted by this bot can be found here.
The pull request process is described here

Needs approval from an approver in each of these files:

pilot/OWNERS

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ostromart: The following test failed, say /retest to rerun them all:

Test name
Commit
Details
Rerun command

prow/istio-unit-tests.sh
8086d1ff3d6626447372323db183532f4deb8caf
link
/test istio-unit-tests

Instructions for interacting with me using PR comments are available here.  If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@ostromart: The following tests failed, say /retest to rerun them all:

Test name
Commit
Details
Rerun command

prow/istio-unit-tests.sh
8086d1ff3d6626447372323db183532f4deb8caf
link
/test istio-unit-tests

prow/istio-presubmit.sh
8086d1ff3d6626447372323db183532f4deb8caf
link
/test istio-presubmit

Instructions for interacting with me using PR comments are available here.  If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@ostromart: The following tests failed, say /retest to rerun them all:

Test name
Commit
Details
Rerun command

prow/istio-presubmit.sh
8086d1ff3d6626447372323db183532f4deb8caf
link
/test istio-presubmit

prow/istio-unit-tests.sh
1dbb9d95d11d6054bfffde9c03f3b221eac39355
link
/test istio-unit-tests

Instructions for interacting with me using PR comments are available here.  If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@ostromart: The following test failed, say /retest to rerun them all:

Test name
Commit
Details
Rerun command

prow/istio-unit-tests.sh
a07825c8f67da418e37f17a5a77e716e37dfc443
link
/test istio-unit-tests

Instructions for interacting with me using PR comments are available here.  If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@ostromart: The following tests failed, say /retest to rerun them all:

Test name
Commit
Details
Rerun command

prow/istio-unit-tests.sh
a07825c8f67da418e37f17a5a77e716e37dfc443
link
/test istio-unit-tests

prow/istio-presubmit.sh
a07825c8f67da418e37f17a5a77e716e37dfc443
link
/test istio-presubmit

Instructions for interacting with me using PR comments are available here.  If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

[APPROVALNOTIFIER] This PR is APPROVED
This pull-request has been approved by: costinm, ostromart
The full list of commands accepted by this bot can be found here.
The pull request process is described here

Needs approval from an approver in each of these files:

pilot/OWNERS [costinm]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment


Throw a runtime error while trying to concatenate CSSSelector with String

We've tried to  have an syntax sugar for combining selector via plus operator:
operator fun String.plus(selector: CSSSelector)

However the problem is that this approach still wont work due to the very design of Kotlin language.
class Something  {
	override fun toString(): String {
		return "Something"
	}

    fun asString(): String {
		return "::As::Something"
	}
}

operator fun String.plus(s: Something) = this + s.asString()

fun main() {
    println("HEY!!! " + Something())
}

Here we we always have Something::toString called.
That said, selectors like this:
  "h1" + self { ... }

just don't work as expected.
We need to address this in a more thorough fashion (in other words we should completely redesign our CSS API)
however as of now suggestion is to do following: toString for self should throw an Exception with a short explanation what is the current workaround (which, fortunately, exists).

https://github.com/JetBrains/compose-jb/pull/1462

the PR was merged. closing this issue

Making toString() throw isn't super nice 😕 . It's in the CSSSelfSelector (internal) class.
I'm unable to find how to do what I could do before:
"$self.some-class"

Which function does the equivalent?
Also, the desc CSS operator has this in its code, where parent could be self:
override fun toString(): String = "$parent $selected"

It means self's throwing toString() will be called. I'm in a dead end.
The error message doesn't help me much:

You can't concatenate String + CSSSelector which contains self or root. Use selector(<your string>) to convert String to CSSSelector for proper work. https://github.com/JetBrains/compose-jb/issues/1440

I'm reverting from 1.0.1 back to 1.0.0-alpha1-rc4 because of that.

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.


npx prisma migrate resolve --applied 0_init + The migration 0_init could not be found. + Windows PowerShell

Placeholder issue

Duplicate of https://github.com/prisma/prisma/issues/17558


Heph distributed

To do distributed message I've been thinking about a lot of things over the last couple of months. I've come to the conclusion that instead of determining the way to do it, it's better to come up with a pattern that works for different kinds of (distributed) communication. This means that the user isn't forced into an implementation that might not be a good fit for them. Furthermore if they need to communication with a non-Heph application it's likely that it doesn't implement any Heph specific protocol.
The pattern is fairly simple; for each connection to an external application (that can e.g. be another (micro) service, a database or even an external HTTP API) an actor is started with a message type that reflects the API of the external service. As actor references support one-way messaging and RPC already most external applications can be used this way. An supported pattern is the pub-sub pattern. This allows existing client libraries to be reused, but still achieves concurrency through message passing.
The following is an example for this pattern for Redis:
use heph::actor_ref::RpcMessage;

/// Redis command.
pub enum Command {
    /// Get command.
    Get(RpcMessage<String, Response<Option<Vec<u8>>>>),
    /// Set command.
    Set(RpcMessage<(String, String), Response<()>>),
}

pub type Response<T> = Result<T, Error>;

Actors using this Redis client would get a ActorRef<Command> and use it like normal. For example a get command would look like the following:
let redis: ActorRef<Command> = // ...
let get_rpc = redis.rpc("my_key".to_owned());
let response: Result<Option<Vec<u8>>>, redis::Error> = get_rpc.await?;

This makes testing a lot easier as well as the actor connecting to Redis can easily be changed without knowledge of the actor ref actor.
I think this pattern can be quite useful without forcing users into using a Heph specific protocol.

Related issue:

#188 tracking issue for remote actor ref,
#214, #278 message (de)serialisation,
#21 documenting best practices when dealing with back-end connections, this could be a/the solution.


Flip camera while recording in-progress

✏ Big changes:

videoCapture use case is now a parameter of createUseCaseGroup.
CameraInfo is moved to TransientSettings instead of PersistentSettings

Single Camera session no longer restarts when switching lens

move torch management outside of runVideoRecording
✅  What works:
if flash is set to on, torch will be  enabled whenever the rear camera is active during a recording
Can zoom between either lens
can tap to focus on either lens
torch stops when switching lenses and when recording stops
Pausing works fine as long as you don't flip the camera while paused.

❌ Current Issues:

flipping a paused recording freezes the paused frame for a duration until resumed.

Frozen frame is appended to the video for the length of the realtime pause duration
Flaky Issues with rotation changes when unpaused
Audio is out of sync

Flipping recording while camera is stabilized will cause the recording to freeze on the last frame before switching lens directions.
Zoom ratio is not persisted between flips.
Auto Torch for video recording is effectively off

Is the plan to add the toggle to switch camera in a future PR?

Yeah, I thought the current UI on the bottom screen would be a bit too overloaded with the addition of a flip-camera element. Unlike pause or mute, user is still able to flip the camera without the use of an extra UI element, so I didn't think it was necessary for now.
I think it should come in a UI refactor once a video can continue recording without holding the capture button.


#5 Add license badge to readme

Just added the licence badge to the README, using the following:
[![license](https://img.shields.io/github/license/DAVFoundation/n3m0.svg?style=flat-square)](https://github.com/DAVFoundation/n3m0/blob/master/LICENSE)

LGTM @vincent-persyn 👍
RIght now its saying missing because the `LICENSE' file it is pointing to is not added to the repo yet! :)


runProguard is deprecated

http://stackoverflow.com/questions/20115391/gradle-and-proguard-could-not-find-method-runproguard-for-arguments-true

No idea what this does, but cool! Thanks! :)

Just allows people to build this with the latest Android Studio.  Thanks for merging :+1:


5256 gtm link update with 7376

Ticket(s)

[Replace with link to Airtable ticket]

Type of change
Please delete any options that are not relevant

[ x] Bug fix (non-breaking change which fixes an issue)

Description
Google tag was not firing on all pages. I removed the google tag manager from app.tsx and now it only exists on document.tsx. I also added a trigger for GTM tags to show history change. Now the tag is firing on all pages.
Screenshots
current error

/### Checklist:
Please delete any options that are not relevant

[x] I have performed a self-review of my own code
[x] I have commented my code, particularly in hard-to-understand areas
[x] My changes generate no new warnings in the console
[x] I have filled this PR out fully, and cleaned up any extraneous items so that it is clear and easy to understand

Hi Eleni,  the EsLint issues have been resolved. Is there another change request?

@shondriane nope I thought I approved/merged this the other day when we were talking about it, oops!


Fix line drawing during IME operations.

Summary of the Pull Request
Restores proper line drawing during IME operations in conhost
PR Checklist

[x] Closes #803
[x] I work here.
[x] Tested manually.
[x] Check the performance of this and see if it's worse-enough to merit a more confusing algorithm. It was worse for the majority case so I scoped it.
[x] No doc, it should have worked this way.
[x] Am core contributor.

Detailed Description of the Pull Request / Additional comments

Changed ConsoleImeInfo::s_ConvertToCells to be less confusing. It's doing about the same thing, but it's way easier to read now and the compiler/linker/optimizer should just be the same.
Edited Renderer::_PaintBufferOutputHelper to check each attribute for line drawing characters as the right half of a two-col character might have different line drawing characters than the left-half.

Validation Steps Performed

[x] Manual operation of IME in conhost with Japanese IME.
[x] Manual operation of IME in conhost with Chinese IME.
[x] Manual operation of IME in conhost with Chinese (Traditional) IME.
[x] Manual operation of IME in conhost with and Korean IME. - @leonMSFT says Korean doesn't work this way. But Korean is broken worse in that it's not showing suggestions at all. Filing new bug. #6227

@j4james, this is my proposal.

OK, this is much better than what I had. I ended up having to extend the OutputCellView and TextBufferCellIterator which is the part I hated the most (I need to look at the code again to see what made me think that was necessary). I was also concerned about the renderer having to draw the grid one character at a time, and wondering whether we might be able to optimise that a bit. But having that as a special case for wide characters does at least limit when that happens, so that's not too bad either.
I'm busy geeking out over the upcoming SpaceX launch at the moment, so I'll try and look at this in more detail later, but my initial impression is very positive.

I hate that this is possible. :smile:
#6224 probably needs separate "line drawing runs" ...
that actually makes this way easier.

I hate that this is possible. 😄
#6224 probably needs separate "line drawing runs" ...
that actually makes this way easier.

Agreed. Each thing should probably be its own pass. If it can be efficient enough.

I've had a chance to run some more tests now, and I'm not sure this is working as well as I had thought. I have a little test case that tries to render every combination of grid flag around a wide character, and that doesn't seem to work with this PR. This is my test code:
#include <windows.h>
#include <stdio.h>

void test(WORD attr)
{
  HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  SetConsoleTextAttribute(handle, 0x07);
  printf(" ");
  SetConsoleTextAttribute(handle, 0x07 | attr);
  printf("\xE5\xA4\xA7");
  SetConsoleTextAttribute(handle, 0x07);
}

void main()
{
  SetConsoleOutputCP(CP_UTF8);
  printf("\n");
  test(COMMON_LVB_GRID_LVERTICAL);
  test(COMMON_LVB_GRID_HORIZONTAL);
  test(COMMON_LVB_GRID_RVERTICAL);
  test(COMMON_LVB_UNDERSCORE);
  test(COMMON_LVB_UNDERSCORE | COMMON_LVB_GRID_LVERTICAL);
  test(COMMON_LVB_GRID_LVERTICAL | COMMON_LVB_GRID_HORIZONTAL);
  test(COMMON_LVB_GRID_HORIZONTAL | COMMON_LVB_GRID_RVERTICAL);
  test(COMMON_LVB_GRID_RVERTICAL | COMMON_LVB_UNDERSCORE);
  test(COMMON_LVB_UNDERSCORE | COMMON_LVB_GRID_HORIZONTAL);
  test(COMMON_LVB_GRID_LVERTICAL | COMMON_LVB_GRID_RVERTICAL);
  test(COMMON_LVB_GRID_LVERTICAL | COMMON_LVB_GRID_RVERTICAL | COMMON_LVB_UNDERSCORE);
  test(COMMON_LVB_GRID_LVERTICAL | COMMON_LVB_GRID_RVERTICAL | COMMON_LVB_GRID_HORIZONTAL);
  test(COMMON_LVB_GRID_LVERTICAL | COMMON_LVB_GRID_RVERTICAL | COMMON_LVB_GRID_HORIZONTAL | COMMON_LVB_UNDERSCORE);
  printf("\n");
}

This is what I expected it to look like (more or less - not sure about the center grid lines, but I think that's a separate issue):

This is what I'm seeing with this PR:

I'm hoping maybe I've just screwed up the build somehow. Will do some more digging.

One other thing I wanted to mention. It's not essential for this PR, but I thought while you're looking at this grid code, it might be a good time to get rid of COMMON_LVB_GRID_SINGLEFLAG. As far I could make out, it doesn't actually serve any purpose, and that would free up another bit for us to use in the attributes.

大 is

encoding
code

UTF-8
0x35 0xa4 0xa7

UTF-16
0x59 0x27

Shift-JIS
0x91 0xe5

Conhost v1 with the scratch code:

Repaired OpenConsole on commit https://github.com/microsoft/terminal/pull/6223/commits/e1c757fdc5ba80e989c3ff6de768c647ff4637e8:

One other thing I wanted to mention. It's not essential for this PR, but I thought while you're looking at this grid code, it might be a good time to get rid of COMMON_LVB_GRID_SINGLEFLAG. As far I could make out, it doesn't actually serve any purpose, and that would free up another bit for us to use in the attributes.

I went and read the code for this from conhostv1.
COMMON_LVB_GRID_SINGLEFLAG literally indicated to the IME output-buffer writer code that it needed to remove RVERTICAL from the left half of a two column character and LVERTICAL from the right half of a two column character. You know. Instead of determining that some other way and just stripping it out or only applying it to half the character.
So yeah, I think it can go away and/or be repurposed.

I believe this is good for merge. It restores the behavior to match v1 conhost in both through-the-API and IME cases.

For the record this looked good to me too. Your solution turned out much simpler than what I thought would be required. 👍


Handle 404 better. Make 404 impossible with search terms.

User should be able to recover from 404. Possibly being shown the homepage/dashboard with an explanation why 404 happened. 404 should not happen with any search terms.
Search terms could simply disallow some characters that are problematic.

Is this relevant with our current design?

This is not an issue in the new design.


Compatibility with Neogit

Describe the bug
I'm running into some compatibility issues with Neogit, specifically around this message/input when making a commit.
Are you sure you want to commit?
[Y]es, (N)o:

With noice, I get a blank input box.

Which version of Neovim are you using?
NVIM v0.9.0-dev-348+gf2b30b4d6
latest commit as of this issue
To Reproduce
Steps to reproduce the behavior:
First without noice to understand expected behavior

get my noice_minimal.lua and comment out the setup call for noice
nvim . -u noice_minimal.lua
after everything has installed, edit some file to commit
:Neogit, navigate over a file and s to stage, cc to make a commit, enter some commit message and :wq
should see the "Are you sure you want to commit? [Y]es, (N)o:" message, hitting either y or <cr> will make the commit.
git reset --soft HEAD~ to undo the last commit

Next with noice

uncomment the setup call for noice in noice_minimal.lua
repeat steps 2-4 from above
a box appears (as shown in ss above), hitting y or <cr> will confirm the commit but the box will remain until to :q out of the neogit buffer.

Expected Behavior
The "Confirm" input box should show the message correctly and disappear after an appropriate input. The strange thing is this behavior seems to work with discarding files (hitting x over a file in the neogit buffer).

Noice Log
Please include any related errors from the Noice log file. (open with :Noice log)

Noice log

Fri 18 Nov 2022 11:25:18 PM EST
vim/_meta.lua:0: Expected lua string
stack traceback:
[C]: in function 'pcall'
...ite/pack/packer/start/noice.nvim/lua/noice/util/call.lua:144: in function <...ite/pack/packer/start/noice.nvim/lua/noice/util/call.lua:143>
[C]: in function 'nvim_get_option_info'
vim/_meta.lua: in function '__index'
vim/_meta.lua: in function ''
vim/_meta.lua: in function '__index'
...site/pack/packer/start/noice.nvim/lua/noice/view/nui.lua:269: in function <...site/pack/packer/start/noice.nvim/lua/noice/view/nui.lua:256>
[C]: in function 'xpcall'
...ite/pack/packer/start/noice.nvim/lua/noice/util/call.lua:152: in function 'try'
...ite/pack/packer/start/noice.nvim/lua/noice/view/init.lua:136: in function 'display'
...ack/packer/start/noice.nvim/lua/noice/message/router.lua:200: in function <...ack/packer/start/noice.nvim/lua/noice/message/router.lua:144>
[C]: in function 'xpcall'
...ite/pack/packer/start/noice.nvim/lua/noice/util/call.lua:149: in function 'try'
.../site/pack/packer/start/noice.nvim/lua/noice/ui/init.lua:93: in function <.../site/pack/packer/start/noice.nvim/lua/noice/ui/init.lua:73>
[C]: in function 'confirm'
...m/site/pack/packer/start/neogit/lua/neogit/lib/input.lua:64: in function 'get_confirmation'
...r/start/neogit/lua/neogit/buffers/commit_editor/init.lua:50: in function <...r/start/neogit/lua/neogit/buffers/commit_editor/init.lua:46>
[string ":lua"]:1: in main chunk

Do you experience crashes when making a second commit in the same editing session like #337
setting disable_commit_confirmation = true seems to work this issue around so maybe the issue lies in Neogit...

What I suspect is happening is:

neogit calls vim.fn.confirm() for its confirmation dialogs
the commit confirmation dialog is called from a BufUnload event handler
the doc for BufUnload says Do not switch buffers or windows!
Noice uses an nui popup to display confirm messages, which does create a new buffer/window, causing issues

I have no idea if that makes any sense and I could be completely wrong though 😅 (or what the fix would be)

You can check if the linked PR works for you.
Initially I wanted clean up the commit editor just a bit, but hopefully improving the compatibility with noice could be done along the way.

@tobealive I can confirm this fixes the issue for me. Nice one!

Well, it couldn't stay like that because it would interfere with other functionalities. I had to rework the PR. Should be a proper solution now :+1: .

@tobealive that's awesome, thank you for looking into this!

Thanks everyone. I'm good to close this issue.

I'm still seeing this issue with latest neovim HEAD, noice and neogit versions.

Yes, the neogit PR that fixes it hasn't been merged yet, unfortunately: https://github.com/TimUntersberger/neogit/pull/441
The workaround for now is to disable commit confirmation in neogit.


Remove Prompt Constants

Removing prompt constants from factory
Is your feature request related to a problem? Please describe.
Currently, the prompt_factory gets all prompts, but includes constants for specific prompts such as BASH_PROMPT and PYTHON_PROMPT. This limits the ability to add or modify prompts without adjusting the module code directly.
Describe the solution you'd like
I would like to see the removal of these prompt constants from the prompts module, allowing for more flexibility in adding or modifying prompts. Instead, prompt configurations can be specified in a separate file or through command line arguments.
Describe alternatives you've considered
One alternative would be to create a separate factory for each prompt type, but this could become unwieldy and require changes to multiple files if new prompt types are added in the future. Another alternative would be to leave the constants in the factory code and modify them as needed, but this approach is not as scalable or modular as separating the configuration from the code

Wrong repository. Oops. See https://github.com/JohnnyIrvin/shell-craft/issues/98


Helpshift 7.6.3

Type: Missing
Summary:
Helpshift 7.6.3
Details:
GitHub license is Apache-2.0: https://github.com/helpshift/helpshift-api
Resolution:
Apache-2.0
Affected definitions:

Helpshift 7.6.3

I think this should be OTHER since the podspec states the license is "Commerical" and points to http://www.helpshift.com/terms/.
https://github.com/CocoaPods/Specs/blob/master/Specs/2/a/d/Helpshift/7.6.3/Helpshift.podspec.json#L5-L7
@AE49 What do you think?

@capfei @LandOfBliss - I agree with OTHER for the commercial license.

@capfei @LandOfBliss I agree with OTHER.


Metachar Dictionary

Little syntax markers like + are a frequent source of headaches for people. I want to fix that if possible by providing a central page with links to elsewhere in the documentation for each notable metachars within dbt projects. Without it, I feel it's much too hard to search for the docs around these symbols.
Incidentally, when I asked if people in slack would want something like that, I got a very engaged response in the form of heart eye emoji.

Check out issue #381 and PR #390 which is a first attempt. I think I had meant to tag you on it, but somehow missed it 😅

Closing as addressed. If we want to add more, we can open a new Docs projects for this in our internal Notion page.


adding extra margin from the top from the target view.

Can you share a code sample to reproduce this?

I cannot share the code sample, but I am using full screen display and enabled edge to edge with the status bar hidden.


Question about Mongo Partial Index

How can this index be achieved?
db.collectionName.createIndex(
   {unique: true, partialFilterExpression: {username: { $exists: true }}}
);

Currently not possible but should be easy to add.


Training Sybil

How are the images fed for training?
If NLST contains 3D dicom of each patient,  then how is each 2D image of each patient fed into the code?
Is there a specific way to give the path to the images?

Hi,
The series of 2D images are concatenated into a 3D tensor that is fed to the model. Please refer to the dataset file for details on processing and preparing the input.


give TOC a min-width

Summary

In the desktop-view mode for the table of contents, as a user shrinks the screen width, the table of contents becomes quite narrow:

This change adds a min width to the TOC that keeps things looking more like:

Use Cases

Checklist

[x] I have viewed, signed, and submitted the Contributor License Agreement.
[ ] I have linked issue(s) that this PR should close using keywords or the Github UI (See docs)
[ ] I have added an integration test, if necessary.
[ ] I have reviewed the styleguide for guidance on my code quality.
[x] I'm happy with the commit history on this PR (I have rebased/squashed as needed).

@fg-j I'm not sure this is a blocker but on the "Getting Started" page or probably any page without and index the left nav div still takes up space. We should probably only render it if there is contents in it. I'd be ok with this being a separate issue though. Thoughts?

Great point. I bet there's some conditional stuff that can be done to sort that out. I'll take a stab at it.

@andymoe let me know what you think about this update 🙂


Add compat overload to Session constructor

Fixes #15433

/cc @anstarovoyt  any way we could have you test this change locally? Let me know how I can help

@RyanCavanaugh tested (RyanCavanaugh:sessionBackCompat), works fine. Thank you for the fix!

@anstarovoyt thanks for the testing and very sorry for the break! I'll think about what we can do to detect this better in the future.


Setup express+MongoDB environment

Need a server to host services.

Database
Express API server
Accessible via Internet
SSL/TLS security

nginx set up with ssl @ https://green.tescobank.pro


Refactor configs.h

As DDL statements make more and more things move from loader to storage, some of the constants that were only needed by loader and storage, which were being kept in common/include/configs.h should also move to storage. We should also go through each field in this class and move it to the lowest  scope they can go in.

This is not relevant now.


6.5.12 “Health IT developer demonstrates support for the Patient Demographics Previous Name USCDI v1 element  - Need clarification.

Hi, we are trying to understand if Patient.name.period is a required element in the patient resource when the Patient has a previous name.  We read the text in the Inferno test case and there is an ambiguity we need to clarify as follows.
ONC certification criteria states that all USCDI v1 data classes and elements need to be supported, including Patient Demographics - Previous Name. However, US Core v3.1.1 does not tag the relevant element (Patient.name.period) as MUST SUPPORT. The Health IT developer must demonstrate support for this USCDI v1 element as described in the US Core Patient Profile implementation guidance.
Here are the 2 potential interpretations:
1)
ONC certification criteria states that all USCDI v1 data classes and elements need to be supported, including Patient Demographics - Previous Name. However, US Core v3.1.1 does not tag the relevant element (Patient.name.period) as MUST SUPPORT. The Health IT developer must demonstrate support for the Patient.name.period USCDI v1 element as described in the US Core Patient Profile implementation guidance.
2)
ONC certification criteria states that all USCDI v1 data classes and elements need to be supported, including Patient Demographics - Previous Name. However, US Core v3.1.1 does not tag the relevant element (Patient.name.period) as MUST SUPPORT. The Health IT developer must demonstrate support for Patient.name USCDI v1 element as described in the US Core Patient Profile implementation guidance.
To confirm for current certification efforts it should be the   US Core Patient Profile implementation 3.1.1  that should be used for latest inferno?

ONC has a clarification on that:
Either the US Core IG Profile “StructureDefinition-us-core-patient” element “name.period” or “name.use” is required for testing and certification in the ONC Certification Program to meet the USCDI requirement to support the “Patient Demographics” data class: “Previous Name” data element.
https://www.healthit.gov/test-method/standardized-api-patient-and-population-services

Reviewing the above information and the specification concludes this issue for this point in time.


⚠ Bofrost.at has degraded performance

In cdcfc48, Bofrost.at (https://www.bofrost.at) experienced degraded performance:

HTTP code: 200
Response time: 1213 ms

Resolved: Bofrost.at performance has improved in 012ac91 after 20 minutes.


Bug report: file.cday resolves to UNIX Epoch (Jan 01, 1970)

What happened?
I tried the supplied DQL and instead of seeing the actual creation dated listed for my files, I see January 01, 1970. I suppose that's not the intent of file.cday 😄
Files in the filesystem definitely have the correct dates per a stat command.
If it makes any difference, Obsidian is installed via Flatpak.
DQL
LIST file.cday from "Daily Notes"

JS
No response
Dataview Version
0.5.47
Obsidian Version
1.1.8
OS
Windows

Can you give us steps to repro?

Hello,
I cannot reproduce the behaviour with the provided DQL. I think the cause could be on your setup, that Obsidian cannot read the correct creation data.
Could you try to log the pages to the developer console and inspect the date there?
```dataviewjs
console.log(dv.pages('"Daily Notes"'))
```

Hello,
I cannot reproduce the behaviour with the provided DQL.

I would be surprised if you did, this is too basic functionality to not be something weird in my local instance.

I think the cause could be on your setup, that Obsidian cannot read the correct creation data.

I am thinking the same thing, I am just not familiar enough with Obsidian to dig in more without some guidance.

Could you try to log the pages to the developer console and inspect the date there?
```dataviewjs
console.log(dv.pages('"Daily Notes"'))

And that's what I was looking for! OK, this is weird. After expanding the Proxy object, and the enclosed Array, drilling down to a value in the array, I get this (I snipped all the apparently unrelated stuff like etags/tags/inlinks/outlinks/tasks/lists etc).
{
    "file": {
        "path": "Daily Notes/2022-12-22.md",
        "folder": "Daily Notes",
        "name": "2022-12-22",
        "link": {
            "path": "Daily Notes/2022-12-22.md",
            "embed": false,
            "type": "file"
        },
        "ctime": "1970-01-01T02:00:00.000+02:00",
        "cday": "1970-01-01T00:00:00.000+02:00",
        "mtime": "2022-12-22T10:55:03.066+02:00",
        "mday": "2022-12-22T00:00:00.000+02:00",
        "size": 520,
        "starred": false,
        "frontmatter": {
            "created": "2022-12-22",
            "tags": "daily"
        },
        "ext": "md",
        "day": "2022-12-22T00:00:00.000+02:00"
    },
    "created": "2022-12-22T00:00:00.000+02:00",
    "tags": "daily"
}

Timezone is correct, I am at UTC+2.
Digging deeper into cday property, I see a ts attribute with a value of -7200000. I am assuming this is a timestamp and in fact in milliseconds. Note that the mday property (which works quite fine and I should have noted it already), also a DateTime has the value<PHONE_NUMBER>000 for it (which is the 00:00 local time today, so correct). The day property works fine as well.
I tried looking more into it, but I arrive at the FileStats interface of Obsidian API (https://github.com/obsidianmd/obsidian-api/blob/master/obsidian.d.ts#L1246) and there I am stuck without any obvious path.

Adding the output of the stat CLI command on that file. Modify matches perfectly what mtime reports
Daily Notes$ stat 2022-12-22.md
  File: 2022-12-22.md
  Size: 520       	Blocks: 8          IO Block: 4096   regular file
Device: fe03h/65027d	Inode: 4745811     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/    alex)   Gid: ( 1000/    alex)
Access: 2022-12-22 10:55:03.085900696 +0200
Modify: 2022-12-22 10:55:03.065902436 +0200
Change: 2022-12-22 10:55:03.065902436 +0200
 Birth: 2022-12-22 10:55:03.065902436 +0200

Can you give us steps to repro?

Since this was asked too, I just started a new vault, went straight to install and enable the dataview plugin, created 1 file and put it in
LIST file.cday

I get back a list with the name of the file I just created and January 01, 1970 next to it.
Obsidian was installed weeks ago with flatpak install --user md.obsidian.Obsidian

-7200000 is btw -2 hours in milliseconds. Given I am at UTC +2  this is probably related

Hello,
As far as I can tell, dataview is collecting the ctime/cday directly from Obsidian (here) - that would mean that Obsidian itself does not have access to the creation date, defaulting to 0.
I am not aware if there's a possibility to see the creation date directly from Obsidian to see if it's already wrong there ....
You could go to the graph and hit the magic wand on the right, starting a timelapse animation - and if everything just popping in in the exact same time, I'd presume it's all on the same creation date.

Hello,
As far as I can tell, dataview is collecting the ctime/cday directly from Obsidian (here) - that would mean that Obsidian itself does not have access to the creation date, defaulting to 0.

At least that it provides the wrong value to the API under some circumstances

I am not aware if there's a possibility to see the creation date directly from Obsidian to see if it's already wrong there ....
You could go to the graph and hit the magic wand on the right, starting a timelapse animation - and if everything just popping in in the exact same time, I'd presume it's all on the same creation date.

That one doesn't exhibit the issue. Notes pop up one by one as expected. It was a good suggestion though!

EDIT: seemingly you can also output the creation date with help of templater: https://forum.obsidian.md/t/how-to-retrieve-creation-date-from-metadata-of-a-note/31246/5 If you have this plugin, you could try if you get the same behaviour.

Yeah, it appears templater suffers from the exact same issue. I used the exact template in the link you posted and just got
---
creation_date: 1970-01-01 02:00
modification_date: Sunday, 25th December 2022, 20:55:07
---

So, this is definitely larger than this plugin. Thanks for helping with narrowing this down. I 'll close this issue and try to bring it with Obsidian developers. If I have something, I 'll make sure to post an update here.

Coming back to this as promised, a search in the obsidian forum reveals this has been reported multiple times:

https://forum.obsidian.md/t/templater-tp-file-creation-date-producing-1-january-1970-when-creation-date-is-not-available/44576
https://forum.obsidian.md/t/tp-file-creation-date-showing-1970/37265
https://forum.obsidian.md/t/linux-creation-date-of-all-notes-is-1970-01-01-read-birth-date-properly/13761/16
https://forum.obsidian.md/t/handle-file-creation-date-modified-date-internally/26148
https://forum.obsidian.md/t/android-obsidian-thinks-it-is-january-1-1970/33060

Looks like it can't be solved, at least not easily.
A workaround is being proposed in https://forum.obsidian.md/t/native-yaml-override-for-filesystem-creation-time/41240 which is, ironically, to what I, independently, ended up doing myself (my yaml stanza is called created, not creation)


Major Alignment Issue fixed : {no functionality removed}

Hello @codervivek5

Fixes Issue #809

Changes done:

Attached CSS
Added team files {css,js,html}
review col added again
minifiied the style.css because taking too much time to reload because of the inappropriate CSS files
Added cart img
Checked the previous commits and added new lines to the see more page js which was logic added by me.
script.js {main} upgraded

Video 1
Screencast from 10-08-23 01:54:38 PM IST.webm
Video 2
Screencast from 10-08-23 01:55:25 PM IST.webm
important Note to reviewers : Please pull the code before pushing and check files are linked or not because this habit damage the alignment.
@codervivek5 Thank You, It was a great 3 Months of journey.

Closes Issue No #809

bro plz pull the code once then make changes ...also solve the conflict

kindly do not make any changes in review file

Sure @codervivek5

bro plz solve conflict

@codervivek5 Sorry for the delay I was busy.

Conflicts are resolved now you can merge this.

@codervivek5 Sorry for the delay I was busy.

No issue 😄

@codervivek5 Thank you.
Btw you can merge it now.

@codervivek5


Skip Ad button not clicked on some machines

On one of my computers, the add-on correctly accelerates but it does not click on the Skip Ad button when it gets available. What more, once the video finishes, it freezes for some seconds until the clock in the top right corner of the video is done. Looking at the console, the add-on correctly detects and clicks on the button but it has no effect. It seems that the JavaScript .click() method behaves differently than a mouse click from the user, hinting that YouTube is using this difference to reject programmatic button clicks. Any idea how to solve it?
Issue already referenced here: https://github.com/TheRealJoelmatic/RemoveAdblockThing/issues/367.

Dear Martin,
This is also the case on Firefox for Android™, the Skip Ad button is never clicked in spite of having set the option in the extension settings.
Thanks a lot for your wonderful work

Thanks for the feedback. If anyone has any idea how to solve it, please let us know below.

This issue is still present for many users (e.g., #18 ). It would help a ton if someone finds a fix.


[Bug]: AttributeError: 'NoneType' object has no attribute 'group'

Bug Description
I try using the llama-index-packs/table/chain-of-table. Skip about the download package is not working, I also use to package llama-index in there but it give me the bug like this
`[llama_index/llama-index-packs/llama-index-packs-tables/llama/packs/tables/chain_of_table/base.py:33], in _get_regex_parser_fn.._regex_parser(output)
[31] output = str(output)
[32] m = re.search(regex, output)
---> [33] args = m.group(1)
[34] if "," in args:
[35]     return [a.strip().strip("'"") for a in args.split(",")]
AttributeError: 'NoneType' object has no attribute 'group'`
Version
0.10.10
Steps to Reproduce
also use to package llama-index in llama-index-packs/table
Relevant Logs/Tracbacks
No response

This just means the LLM did not output the correct output.
Tbh chain-of-table is a cool paper and concept, but not overly reliable unless you use GPT-4

@logan-markewich thank you a lot for the information


Finish up appoffline refactoring

Rebase?

It is reverted

App_offline test is failing in appveyor. Authentication_InProcess seems to be failing too, most likely due to my IIS test changes.
Also see if you can add app_offline tests for full IIS.

Fixed tests.


Unhandled 403 (Access denied)

While playing video which returns from youtube 403 error is not handled and no error is printed on discord as a message, only visible in console and was skipped for long time by that.

This won't be fixes as 1.0 development was abandoned.


strace 4.24

gist-log of a build failure with enabled mpers: https://gist.github.com/7cc60fba21247db8c7cdda84f98b0b71

Thanks, Maxim!


Can you upgrade to handle the case 'wang4 na2 yi1xie1 dong1xi5 le5'? ("忘拿一些东西了")

Can you upgrade to handle the case 'wang4 na2 yi1xie1 dong1xi5 le5'? ("忘 拿 一些 东西 了")
'wang4-na2-yi1xie1-dong1xi5-le5'   , '-' is space.

this should be workingn as expected
from pyzhuyin import pinyin_to_zhuyin

test_case = "wang4 na2 yi1 xie1 dong1 xi5 le5"
print(list(map(pinyin_to_zhuyin, test_case.split(" "))))

Gives: ['ㄨㄤˋ', 'ㄋㄚˊ', 'ㄧ', 'ㄒㄧㄝ', 'ㄉㄨㄥ', '˙ㄒㄧ', '˙ㄌㄜ']


Alternative Approach

Tried implementing a prototype to explain this alternative approach. Here's a rough draft of some of the differences:

No differentiation between app components and widget components
Combines the MicroComponents and Components API together into a more flexible Component trait
Doesn't require a Model trait -- implementing Component is enough to have a fully functioning component
Uses channels for sending events to and from the component, so components do not need to know any type information about a parent type, which makes them reusable
Zero use of Rc and RefCell, because all state is owned by the component's inner event loop.
Watches for the destroy event on the root widget to hang up the component's event loop.

The implementation:
// Copyright 2022 System76<EMAIL_ADDRESS>// SPDX-License-Identifier: MPL-2.0

use gtk4::prelude::*;
use tokio::sync::mpsc;

pub type Sender<T> = mpsc::UnboundedSender<T>;
pub type Receiver<T> = mpsc::UnboundedReceiver<T>;

/// A newly-registered component which supports destructuring the handle
/// by forwarding or ignoring outputs from the component.
pub struct Registered<W: Clone + AsRef<gtk4::Widget>, I, O> {
    /// Handle to the component that was registered.
    pub handle: Handle<W, I>,

    /// The outputs being received by the component.
    pub receiver: Receiver<O>,
}

impl<W: Clone + AsRef<gtk4::Widget>, I: 'static, O: 'static> Registered<W, I, O> {
    /// Forwards output events to the designated sender.
    pub fn forward<X: 'static, F: (Fn(O) -> X) + 'static>(
        self,
        sender: Sender<X>,
        transform: F,
    ) -> Handle<W, I> {
        let Registered { handle, receiver } = self;
        forward(receiver, sender, transform);
        handle
    }

    /// Ignore outputs from the component and take the handle.
    pub fn ignore(self) -> Handle<W, I> {
        self.handle
    }
}

/// Handle to an active widget component in the system.
pub struct Handle<W: Clone + AsRef<gtk4::Widget>, I> {
    /// The widget that this component manages.
    pub widget: W,

    /// Used for emitting events to the component.
    pub sender: Sender<I>,
}

impl<W: Clone + AsRef<gtk4::Widget>, I> Widget<W> for Handle<W, I> {
    fn widget(&self) -> &W {
        &self.widget
    }
}

impl<W: Clone + AsRef<gtk4::Widget>, I> Handle<W, I> {
    pub fn emit(&self, event: I) {
        let _ = self.sender.send(event);
    }
}

/// Used to drop the component's event loop when the managed widget is destroyed.
enum InnerMessage<T> {
    Drop,
    Message(T),
}

/// Provides a convenience function for getting a widget out of a type.
pub trait Widget<W: Clone + AsRef<gtk4::Widget>> {
    fn widget(&self) -> &W;
}

/// The basis of a COSMIC widget.
///
/// A component takes care of constructing the UI of a widget, managing an event-loop
/// which handles signals from within the widget, and supports forwarding messages to
/// the consumer of the component.
pub trait Component: Sized + 'static {
    /// The arguments that are passed to the init_view method.
    type InitialArgs;

    /// The message type that the component accepts as inputs.
    type Input: 'static;

    /// The message type that the component provides as outputs.
    type Output: 'static;

    /// The widget that was constructed by the component.
    type RootWidget: Clone + AsRef<gtk4::Widget>;

    /// The type that's used for storing widgets created for this component.
    type Widgets: 'static;

    /// Initializes the component and attaches it to the default local executor.
    ///
    /// Spawns an event loop on `glib::MainContext::default()`, which exists
    /// for as long as the root widget remains alive.
    fn register(
        mut self,
        args: Self::InitialArgs,
    ) -> Registered<Self::RootWidget, Self::Input, Self::Output> {
        let (mut sender, in_rx) = mpsc::unbounded_channel::<Self::Input>();
        let (mut out_tx, output) = mpsc::unbounded_channel::<Self::Output>();

        let (mut widgets, widget) = self.init_view(args, &mut sender, &mut out_tx);

        let handle = Handle {
            widget,
            sender: sender.clone(),
        };

        let (inner_tx, mut inner_rx) = mpsc::unbounded_channel::<InnerMessage<Self::Input>>();

        handle.widget.as_ref().connect_destroy({
            let sender = inner_tx.clone();
            move |_| {
                let _ = sender.send(InnerMessage::Drop);
            }
        });

        spawn_local(async move {
            while let Some(event) = inner_rx.recv().await {
                match event {
                    InnerMessage::Message(event) => {
                        self.update(&mut widgets, event, &mut sender, &mut out_tx);
                    }

                    InnerMessage::Drop => break,
                }
            }
        });

        forward(in_rx, inner_tx, |event| InnerMessage::Message(event));

        Registered {
            handle,
            receiver: output,
        }
    }

    /// Creates the initial view and root widget.
    fn init_view(
        &mut self,
        args: Self::InitialArgs,
        sender: &mut Sender<Self::Input>,
        out_sender: &mut Sender<Self::Output>,
    ) -> (Self::Widgets, Self::RootWidget);

    /// Handles input messages and enables the programmer to update the model and view.
    fn update(
        &mut self,
        widgets: &mut Self::Widgets,
        event: Self::Input,
        sender: &mut Sender<Self::Input>,
        outbound: &mut Sender<Self::Output>,
    );
}

/// Convenience function for `Component::register()`.
pub fn register<C: Component>(
    model: C,
    args: C::InitialArgs,
) -> Registered<C::RootWidget, C::Input, C::Output> {
    model.register(args)
}

/// Convenience function for forwarding events from a receiver to different sender.
pub fn forward<I: 'static, O: 'static, F: (Fn(I) -> O) + 'static>(
    mut receiver: Receiver<I>,
    sender: Sender<O>,
    transformer: F,
) {
    spawn_local(async move {
        while let Some(event) = receiver.recv().await {
            if sender.send(transformer(event)).is_err() {
                break;
            }
        }
    })
}

/// Convenience function for launching an application.
pub fn run<F: Fn(gtk4::Application) + 'static>(func: F) {
    use gtk4::prelude::*;
    let app = gtk4::Application::new(None, Default::default());

    app.connect_activate(move |app| func(app.clone()));

    app.run();
}

/// Convenience function for spawning tasks on the local executor
pub fn spawn_local<F: std::future::Future<Output = ()> + 'static>(func: F) {
    gtk4::glib::MainContext::default().spawn_local(func);
}

Creation of an InfoButton component:
// Copyright 2022 System76<EMAIL_ADDRESS>// SPDX-License-Identifier: MPL-2.0

use ccs::*;
use gtk::prelude::*;
use gtk4 as gtk;

pub enum InfoButtonInput {
    SetDescription(String),
}

pub enum InfoButtonOutput {
    Clicked,
}

pub struct InfoButtonWidgets {
    description: gtk::Label,
}

#[derive(Default)]
pub struct InfoButton;

impl Component for InfoButton {
    type InitialArgs = (String, String, gtk::SizeGroup);
    type RootWidget = gtk::Box;
    type Input = InfoButtonInput;
    type Output = InfoButtonOutput;
    type Widgets = InfoButtonWidgets;

    fn init_view(
        &mut self,
        (desc, button_label, sg): Self::InitialArgs,
        _sender: &mut Sender<InfoButtonInput>,
        out_sender: &mut Sender<InfoButtonOutput>,
    ) -> (InfoButtonWidgets, gtk::Box) {
        relm4_macros::view! {
            root = info_box() -> gtk::Box {
                append: description = &gtk::Label {
                    set_label: &desc,
                    set_halign: gtk::Align::Start,
                    set_hexpand: true,
                    set_valign: gtk::Align::Center,
                    set_ellipsize: gtk::pango::EllipsizeMode::End,
                },

                append: button = &gtk::Button {
                    set_label: &button_label,

                    connect_clicked(out_sender) => move |_| {
                        let _ = out_sender.send(InfoButtonOutput::Clicked);
                    }
                }
            }
        }

        sg.add_widget(&button);

        (InfoButtonWidgets { description }, root)
    }

    fn update(
        &mut self,
        widgets: &mut InfoButtonWidgets,
        event: InfoButtonInput,
        _sender: &mut Sender<InfoButtonInput>,
        _out_sender: &mut Sender<InfoButtonOutput>,
    ) {
        match event {
            InfoButtonInput::SetDescription(value) => {
                widgets.description.set_text(&value);
            }
        }
    }
}

pub fn info_box() -> gtk::Box {
    relm4_macros::view! {
        container = gtk::Box {
            set_orientation: gtk::Orientation::Horizontal,
            set_margin_start: 20,
            set_margin_end: 20,
            set_margin_top: 8,
            set_margin_bottom: 8,
            set_spacing: 24
        }
    }

    container
}

Creating and maintaining InfoButton components inside of an App component
// Copyright 2022 System76<EMAIL_ADDRESS>// SPDX-License-Identifier: MPL-2.0

use crate::components::{InfoButton, InfoButtonInput, InfoButtonOutput};
use ccs::*;
use gtk::prelude::*;
use gtk4 as gtk;

/// The model where component state is stored.
#[derive(Default)]
pub struct App {
    pub counter: usize,
}

/// Widgets that are initialized in the view.
pub struct AppWidgets {
    list: gtk::ListBox,
    destroyable: Option<Handle<gtk::Box, InfoButtonInput>>,
    counter: Handle<gtk::Box, InfoButtonInput>,
}

/// An input event that is used to update the model.
pub enum AppEvent {
    Destroy,
    Increment,
}

/// Components are the glue that wrap everything together.
impl Component for App {
    type InitialArgs = gtk::Application;
    type Input = AppEvent;
    type Output = ();
    type Widgets = AppWidgets;
    type RootWidget = gtk::ApplicationWindow;

    fn init_view(
        &mut self,
        app: gtk::Application,
        sender: &mut Sender<AppEvent>,
        _out_sender: &mut Sender<()>,
    ) -> (AppWidgets, gtk::ApplicationWindow) {
        let button_group = gtk::SizeGroup::new(gtk::SizeGroupMode::Both);

        // Create an `InfoButton` component.
        let destroyable = InfoButton::default()
            .register((String::new(), "Destroy".into(), button_group.clone()))
            .forward(sender.clone(), |event| match event {
                InfoButtonOutput::Clicked => AppEvent::Destroy,
            });

        // Instruct the component to update its description.
        let _ = destroyable.emit(InfoButtonInput::SetDescription(
            "Click this button to destroy me".into(),
        ));

        // Create a counter component, too.
        let counter = InfoButton::default()
            .register(("Click me too".into(), "Click".into(), button_group))
            .forward(sender.clone(), |event| match event {
                InfoButtonOutput::Clicked => AppEvent::Increment,
            });

        // Construct the view for this component, attaching the component's widget.
        relm4_macros::view! {
            window = gtk::ApplicationWindow {
                set_application: Some(&app),
                set_child = Some(&gtk::Box) {
                    set_halign: gtk::Align::Center,
                    set_size_request: args!(400, -1),
                    set_orientation: gtk::Orientation::Vertical,

                    append: list = &gtk::ListBox {
                        set_selection_mode: gtk::SelectionMode::None,
                        set_hexpand: true,

                        append: destroyable.widget(),
                        append: counter.widget(),
                    },
                }
            }
        }

        window.show();

        (
            AppWidgets {
                list,
                counter,
                destroyable: Some(destroyable),
            },
            window,
        )
    }

    /// Updates the view
    fn update(
        &mut self,
        widgets: &mut AppWidgets,
        event: AppEvent,
        _sender: &mut Sender<AppEvent>,
        _outbound: &mut Sender<()>,
    ) {
        match event {
            AppEvent::Increment => {
                self.counter += 1;

                widgets
                    .counter
                    .emit(InfoButtonInput::SetDescription(format!(
                        "Clicked {} times",
                        self.counter
                    )));
            }

            AppEvent::Destroy => {
                // Components are kept alive by their root GTK widget.
                if let Some(handle) = widgets.destroyable.take() {
                    if let Some(parent) = handle.widget().parent() {
                        widgets.list.remove(&parent);
                    }
                }
            }
        }
    }
}

With application launched via
// Copyright 2022 System76<EMAIL_ADDRESS>// SPDX-License-Identifier: MPL-2.0

extern crate cosmic_component_system as ccs;

mod components;

use self::components::App;
use ccs::Component;
use gtk4 as gtk;

fn main() {
    ccs::run(|app| {
        App::default().register(app.clone());
    });
}

Looks very interesting. I really like this approach in general, especially the forward and destruction mechanisms.
Yet, some parts of this approach violate the philosophy of Relm4. After all, Relm4 is inspired by Elm and Elm is very strict about the separation of application state and UI elements. And I agree with Elm in this point. In my experience mixing state and UI leads to an absolutely unmaintainable mess with lot's of hidden side effects. What looks like unnecessary complexity in regular components is there for a good purpose.
That said, there are cases where this separation has clear disadvantages, for example input forms, where sending updates for each input field can cause the message type to become extremely large.
And there is one other constraint that made components a bit more complex: Dialogs often need to set a transient widget. In your approach it wouldn't be possible to call set_transient_for with a widget from the parent component, if the dialog isn't the root of the components.
Maybe we can come up with a solution that combines the best of both worlds.

I've updated the example with my findings from porting a COSMIC settings panel.
It is possible to use set_transient_for if Component::InitialArgs or the model itself contains the gtk::Window. It should also be possible to get the top level window from any GTK widget, too.

As I said, I think this approach has many good ideas, but as long as it mixes application logic and widget updates, I can't simply use it as the default component type.
Just so that we are on the same page, what are your goals with Relm4 and this approach? I think it's best if we talk about this so that we can coordinate our efforts.

I have my experiment here at the moment. I've added a macro for generating components using this approach, and have a port of the Support panel we made for GNOME Control Center in GTK3. The component that manages the support panel specifically is here, but I'm still experimenting with different ideas, such as separating UI updates from state updates with UI messages, but I'm still not completely sold on the complexity of enforcing the separation.
We are going to be using GTK4 for COSMIC applications, which of course are also entirely written in Rust. Where GNOME is standardizing around libadwaita as their platform library, libcosmic is what we're developing as our platform library. As a platform library, it will offer a range of GTK widgets that are used across all COSMIC applications, with a first class Rust API.
With this approach I have something that precisely models how I normally develop GTK widgets by hand with GTK-rs. Spawn an event loop and capture all state and widgets into it with message passing to control their behaviors. We have some new hires on the team that don't have the same level of experience with GTK, so I'd prefer if everyone that gets involved today and in the future has a better framework to use as a starting point that takes care of all the boilerplate involved in transforming GTK into something fit for Rust applications. But which also creates these components in a way that you can use them in any GTK widget or application without having to adopt a specific approach wholesale top to bottom.
The goal in mind is to make it as simple as possible to write reusable widgets in Rust using best practices for Rust application development. But it should require as little boilerplate as possible because it should be simple for anyone unfamiliar with Rust or GUI development to build widgets and applications. Using GTK-rs directly requires a lot of boilerplate and knowledge of how to set up message passing between widgets and components. Relm4's view macro resolves most of the view-construction ergonomics that I previously used cascade for.
I have started out by trying to rewrite a simpler settings panel in Relm4, but struggled a lot to get something working after half a day. I finally got it working with MicroModel+MicroWidget components, but it was very heavy on matching up traits and types, and overall had no use for the ordinary components.

Thanks for letting me know!
I agree that reusable components are not ideal in the current state and require quite a few traits. I think using input parameters instead of passing the parent model and parent widgets could help with that.
Also, separation of application state and UI isn't a hard requirement to get something added to Relm4 but it won't be the default.
I'm very interested to see what you come up with :)
In general, I hope we can work together on making the experience with gtk-rs even better and simpler.

Sure, I would prefer if we can come up with some reusable bits

I've been thinking about simplifying the Componenttrait.
pub struct ComponentParts<Model, Widgets> {
    model: Model,
    widgets: Widgets,
}

pub trait Component {
    type Msg;
    type Widgets;
    type Root;
    type InitParams;

    fn init_root() -> Self::Root;

    fn init(params: Self::InitParams, root_widget: &Self::Root) -> ComponentParts<Self, Self::Widgets>;

    /* update + view similar to current components */
}

This especially simplifies the initialization. You're still able to access the root widget of child components when creating the widgets of the component so you can connect them in the right order in the view macro. Also, the parent model is not necessary anymore and components are simply stored in the model.
An implementation for a simple component (that itself has a simple button component as child) could look like this then:
pub enum AppMsg {
    Increment,
    Decrement,
}

pub struct AppModel {
    // state
    counter: u8,
    // components
    button: RelmComponent<Button>,
}

pub struct AppWidgets {
    label: gtk::Label,
}

impl Component for AppModel {
    type Msg = AppMsg;
    type Widgets = AppWidgets;
    type Root = gtk::Box;
    type InitParams = u8;

    // Just initialize the root to make it available early for any parent component.
    fn init_root() -> Self::Root {
        gtk::Box::default()
    }

    fn init(params: Self::InitParams, root_widget: &Self::Root) -> ComponentParts<Self::Model, Self::Widgets> {
        // Returns a preliminary type that can already return the root widget of the component.
        let button = RelmComponent::init_root();

        // Initialize widgets
        relm4::view! {
            label = gtk::Label {
                set_text: "Some text",
            }
        }

        // Append everything on the root widget (this can be added as new syntax to the view macro, eventually)
        root_widget.append(&label);
        root_widget.append(button.root_widget());

        // The button component takes (u8, &str) as InitParam, for example.
        // This is trivial in this example but in case we want to use `set_transient_for` with a widget from the parent
        // we are now after the widget initialization and ready to pass widgets as parameters for components.
        let button = button.finish((0, "Button text"));

        // Initialize the model with the InitParams
        let model = AppWidget {
            counter: params,
            button,
        }

        // Initialize the widgets
        let widgets = AppWidgets {
            label,
        }

        ComponentParts {
            model,
            widgets,
        }
    }

    /* update + view similar to current components */
}

This is just a mock up that I quickly wrote down. But I think it looks very promising. It's the best approach to simplify components that still have separation of UI and application state.
It's heavily inspired by your ideas and would even allow us to create another Component trait that can opt-out of the separation stuff to make things even easier for beginners while providing the same interface through RelmComponent.
I'm not entirely sure if that actually works, but if it does we might have an approach that's very flexible and should suit us both.
Let me know what you think :)

I will experiment with this idea and tell you what I find.

Perhaps fn init_root() wouldn't be necessary if Self::Root requires that Root implements Default.

You're right but then it would be awkward if a root widget doesn't implement Default. I already added a lot of Default impls to gtk-rs but maybe someone comes up with a rare use-case where Default isn't implemented.
We could still go that route and recommend wrapper types for things that don't implement Default, or we could work with macros, just like the widget macro that automatically implements root_widget for you. In the macro it would then be default if the user omits it or the user's code if it's specified.

You're right about not enforcing the requirement of a trait. I have just updated my implementation with a similar approach.
// Copyright 2022 System76<EMAIL_ADDRESS>// SPDX-License-Identifier: MPL-2.0

use crate::*;

/// The pieces that make up the state of the component.
pub struct ComponentInner<Model, Widgets, Input, Output> {
    pub model: Model,
    pub widgets: Widgets,
    pub input: Sender<Input>,
    pub output: Sender<Output>,
}

/// The basis of a COSMIC widget.
///
/// A component takes care of constructing the UI of a widget, managing an event-loop
/// which handles signals from within the widget, and supports forwarding messages to
/// the consumer of the component.
pub trait Component: Sized + 'static {
    /// The arguments that are passed to the init_view method.
    type InitParams;

    /// The message type that the component accepts as inputs.
    type Input: 'static;

    /// The message type that the component provides as outputs.
    type Output: 'static;

    /// The widget that was constructed by the component.
    type Root: Clone + AsRef<gtk4::Widget>;

    /// The type that's used for storing widgets created for this component.
    type Widgets: 'static;

    /// Initializes the root widget
    fn init_root() -> Self::Root;

    fn init_inner(
        params: Self::InitParams,
        root_widget: &Self::Root,
        input: Sender<Self::Input>,
        output: Sender<Self::Output>,
    ) -> ComponentInner<Self, Self::Widgets, Self::Input, Self::Output>;

    /// Initializes the component and attaches it to the default local executor.
    ///
    /// Spawns an event loop on `glib::MainContext::default()`, which exists
    /// for as long as the root widget remains alive.
    fn init(params: Self::InitParams) -> Registered<Self::Root, Self::Input, Self::Output> {
        let (sender, in_rx) = mpsc::unbounded_channel::<Self::Input>();
        let (out_tx, output) = mpsc::unbounded_channel::<Self::Output>();

        let root = Self::init_root();

        let mut component = Self::init_inner(params, &root, sender, out_tx);

        let handle = Handle {
            widget: root,
            sender: component.input.clone(),
        };

        let (inner_tx, mut inner_rx) = mpsc::unbounded_channel::<InnerMessage<Self::Input>>();

        handle.widget.as_ref().connect_destroy({
            let sender = inner_tx.clone();
            move |_| {
                let _ = sender.send(InnerMessage::Drop);
            }
        });

        spawn_local(async move {
            while let Some(event) = inner_rx.recv().await {
                match event {
                    InnerMessage::Message(event) => {
                        Self::update(&mut component, event);
                    }

                    InnerMessage::Drop => break,
                }
            }
        });

        forward(in_rx, inner_tx, InnerMessage::Message);

        Registered {
            handle,
            receiver: output,
        }
    }

    /// Handles input messages and enables the programmer to update the model and view.
    #[allow(unused_variables)]
    fn update(
        component: &mut ComponentInner<Self, Self::Widgets, Self::Input, Self::Output>,
        message: Self::Input,
    ) {
    }
}

/// Used to drop the component's event loop when the managed widget is destroyed.
enum InnerMessage<T> {
    Drop,
    Message(T),
}

Updated the macro to utilize this better
pub enum MyCustomInputMessage {
    Variant1,
    Variant2,
}

component! {
    // The model stores the state of this component.
    pub struct MyCustomModel {
        pub state: String,
    }

    // Widgets managed by the view are stored here.
    pub struct MyCustomWidgets {
        description: gtk::Label,
    }

    // The type of the input sender
    type Input = MyCustomInputMessage;

    // The type of the output sender
    type Output = ();

    // Declares the root widget and how it should be constructed.
    type Root = gtk::Box {
        ccs::view! {
            root = gtk::Box {
                set_orientation: gtk::Orientation::Vertical,
            }
        }
    };

    // Constructs the inner component's model and widgets, using the
    // initial parameter given by `args`.
    fn init(args: (), root, input, output) {
        let description = gtk::Label::new();

        root.append(&description);

        ComponentInner {
            model: MyCustomModel { state: String::new() },
            widgets: MyCustomWidgets { description },
            input,
            output
        }
    }

    // Where events are received, with `component` is the `ComponentInner`,
    // and `event` is a `MyCustomInputMessage` which was just received.
    fn update(component, event) {
        match event {
            MyCustomInputMessage::Variant1 => {

            }

            MyCustomInputMessage::Variant2 => {

            }
        }
    }
}

Components can be created and have their output events forwarded:
let counter = InfoButton::init("Clicked 0 times".into(), "Click".into())
    .forward(input.clone(), |event| match event {
        InfoButtonOutput::Clicked => AppEvent::Increment
    });

In process of updating my support panel.

I'm also thinking of an alternative to the update function which consumes the model, and returns a tuple containing the updated model and a command to perform. I think this is closer to the Elm design.

Commands are an interesting concept, that could work great with async functions to fetch resources or something similar that needs to run in the background. At least that seems to be the use-case for commands in Elm.
But I don't think it makes sense to consume and return the model. Elm is purely functional and has a compiler to deal with optimization, but Rust usually makes a memcpy when you move an object, which is not ideal. I think &mut is fine and it also makes it easier to track changes with something like the tracker crate.

I really like the updated version of the new approach.
Yet, I think the macro should be reduced to the relevant parts. The model isn't necessary in the macro and the widgets type can be created by the macro automatically, at least that's what the widget macro does currently. The root widget could also be managed by the macro unless the user wants to overwrite.

This is what I have for an ElmComponent:
while let Some(event) = inner_rx.recv().await {
    match event {
        InnerMessage::Message(event) => {
            if let Some(command) = Self::update(&mut model, event, &mut input, &mut output) {
                let input = input.clone();
                tokio::spawn(async move {
                    if let Some(event) = Self::command(command).await {
                        let _ = input.send(event);
                    }
                });
            }

            Self::update_view(&mut model, &mut widgets, &mut input, &mut output);
        }

        InnerMessage::Drop => break,
    }
}```

```rs
/// Handles input messages and enables the programmer to update the model and view.
fn update(model: &mut Self,
    message: Self::Input,
    input: &mut Sender<Self::Input>,
    output: &mut Sender<Self::Output>,
) -> Option<Self::Command>;

/// Update the UI
fn update_view(
    model: &mut Self,
    widgets: &mut Self::Widgets,
    input: &mut Sender<Self::Input>,
    output: &mut Sender<Self::Output>
);

/// A command to perform in a background thread.
async fn command(message: Self::Command) -> Option<Self::Input>;

Requires using async-trait, but commands are run in the background and optionally return an input message to be consumed by the update function.

Updated the support panel to use ElmComponent. If we could have a similar API in relm4 I could deprecate my current implementation.

The API looks good to me.
I think it's important now that we specify a final Component trait definition, bring in into Relm4 for testing and to gather feedback and then we can start planning and implementing the macros to make it as convenient as possible.

Sure, I'll do that today


⚠ Bofrost.de has degraded performance

In 3e52c13, Bofrost.de (https://www.bofrost.de) experienced degraded performance:

HTTP code: 200
Response time: 997 ms

Resolved: Bofrost.de performance has improved in 7a730f9 after 13 minutes.


Can't Exchange DFI for other coins

Hi,
I'm using the DEX to try to transfer DFI to USDT, BTC and ETH and I keep on getting this error:
"Insufficient UTXO DFI for transaction fees. Please send some DFI from an exchange or another wallet and try again"
Is this because I have insufficient DFI coin?  I remember that there is a way to exchange coin to token but i can't seem to locate the post any more?  Thanks

Hi @jonho79 perhaps this link help: https://defichain-wiki.com/wiki/How_to_"rescue"_stuck_DFI  but it seems that the wallet 2.3.1 has some bugs, i had the same problem, but at the second try it worked. Just take a look at #607

Hi @jonho79 , DFI exist in 2 forms; utxoDFI and accountDFI. utxoDFI is used to pay for transactions fees while rewards received are in accountDFI. You can freely convert between the 2 anytime — at a 1:1 ratio. To convert accountDFI to utxoDFI, the simplest way is to send DFI from your receive address B to your receive address A, the app will automatically convert for you.

Thanks for the solution.  I ended up closing and restarting the app, and
all transactions started working again.
On Thu, Mar 11, 2021 at 3:03 AM Bella @.***> wrote:

Hi @jonho79 https://github.com/jonho79 , DFI exist in 2 forms; utxoDFI
and accountDFI. utxoDFI is used to pay for transactions fees while
rewards received are in accountDFI. You can freely convert between the 2
anytime — at a 1:1 ratio. To convert accountDFI to utxoDFI, the simplest
way is to send DFI from your receive address B to your receive address A,
the app will automatically convert for you.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/DeFiCh/app/issues/608#issuecomment-796654567, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/ASJJS7AISMJOVHNY7N6ALBLTDCPRFANCNFSM4YXQPTIA
.

Hi @jonho79 , thanks for the update! I'll close this issue in the mean time.


Add email form for support and feedback

Proposed solution after discussion: https://www.notion.so/trustmachines/Triage-support-inquiries-and-product-feedback-efficiently-a934773d790140109de7166d91086319
This requires design and can then be added.
related https://github.com/leather-wallet/extension/issues/4747

Replacing with a task here


Add heading anchors to pages in the Hub

Migrated from GitLab: https://gitlab.com/meltano/hub/-/issues/98
Originally created by @edgarrmondragon on 2021-07-04 18:22:20

The Meltano docs have anchors for the headings, like
https://meltano.com/docs/plugin-management.html#custom-plugins.

It would be nice if the Hub did a similar thing so users can shares links to specific sections in the Hub pages, like
https://hub.meltano.com/taps/mssql--singer-io#Incompatible-Language.

The docs use VuePress which automatically handles header anchors and anchors are even activated when the pages scrolls using the plugin-active-header-links plugin.
The Hub is built with Jekyll, though. Maybe something like jekyll-anchor-headings can be used.

View 8 previous comments from the original issue on GitLab


[BUG] Bulk message stops in first error

Nutgram version
nutgram/laravel : ^1.3
PHP version
8.2
Framework
Laravel
Cache driver
Filesystem
OS
Linux
Dev environment
No response
Describe the bug
the bot skips other chats in case one chat produceses an error in bulk message function
To Reproduce
the code :
        $chats = User::all()->pluck('chat_id')->toArray();

        Telegram::getBulkMessenger()->setChats($chats)->setText('test')->startSync();

the error that caused the code to stop
   SergiX44\Nutgram\Telegram\Exceptions\TelegramException

  Forbidden: bot was blocked by the user

Expected behavior
i expected the bot to ignore errors and keep sending messages to other chats

You need to override the bulk logic using the using method:
Telegram::getBulkMessenger()
	->setChats($chats)
	->setText('test')
	->using(function (Nutgram $bot, int|string $chatId): void {
		try{
			$bot->sendMessage(...[...$this->opt, 'chat_id' => $chatId, 'text' => $this->text]);
		} catch(Throwable) {
			//ignore errors
		}
	})
	->startSync();


Replace all Chinese comments

closes https://github.com/dromara/soul/issues/596

Make sure that:

[ ] You have read the contribution guidelines.
[ ] You submit test cases (unit or integration tests) that back your changes.
[ ] Your local test passed mvn clean install -Dmaven.javadoc.skip=true.

Codecov Report

Merging #700 (0987305) into master (bd3a1de) will increase coverage by 0.98%.
The diff coverage is 75.00%.

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


Adding test data and updating mongo models

Added test data for projects and organizations. Updated project so end date is of mixed type (can be null) and added projects and events arrays on user model (user already had organizations array).

It's also in the DB. Those are records that I added in then copied into a JSON file. I was having trouble with the events because I first wanted to get our events, and couldn't remember my password to get a token for the GET /events endpoint.

If you spin up the client there’s a pretty simple form to create a new one! If for some reason it requires you to be logged in, just fetch the latest from my branch 🙂


Non fatal: Null check operator used on a null value. EditableTextState.toggleToolbar [editable_text.dart:3123])

Steps to Reproduce
Unable to reproduce. Crash reported from firebase crashlytics.
Expected results:
Should not crash.
Stack trace:
Non-fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError: Null check operator used on a null value. Error thrown Instance of 'Ria'.
#00 pc 0x8e59f7 com.agendaboa.app (EditableTextState.toggleToolbar [editable_text.dart:3123])
#01 pc 0x8e769b com.agendaboa.app (_TextFieldState._handleSelectionHandleTapped [text_field.dart:1081])
#02 pc 0x8e761b com.agendaboa.app (_TextFieldState._handleSelectionHandleTapped [text_field.dart:1079])
#03 pc 0xcfd78f com.agendaboa.app (GestureRecognizer.invokeCallback [recognizer.dart:253])
#04 pc 0xb948f7 com.agendaboa.app (TapGestureRecognizer.handleTapUp [tap.dart:627])
#05 pc 0x4c02b7 com.agendaboa.app (BaseTapGestureRecognizer._checkUp [tap.dart:306])
#06 pc 0x4c01fb com.agendaboa.app (BaseTapGestureRecognizer.acceptGesture [tap.dart:276])
#07 pc 0x4be49f com.agendaboa.app (GestureArenaManager.sweep [arena.dart:163])
#08 pc 0x5048e3 com.agendaboa.app (GestureBinding.handleEvent [binding.dart:464])
#09 pc 0xce9ec3 com.agendaboa.app (GestureBinding.dispatchEvent [binding.dart:440])
#10 pc 0x3c69ef com.agendaboa.app (RendererBinding.dispatchEvent [binding.dart:337])
#11 pc 0x3c694b com.agendaboa.app (GestureBinding._handlePointerEventImmediately [binding.dart:395])
#12 pc 0x3c62f3 com.agendaboa.app (GestureBinding._flushPointerEventQueue [binding.dart:357])
#13 pc 0x604583 com.agendaboa.app (GestureBinding._handlePointerDataPacket [binding.dart:295])
#14 pc 0x60448f com.agendaboa.app (GestureBinding._handlePointerDataPacket [binding.dart:290])
#15 pc 0x399e0f com.agendaboa.app (_invoke1 [hooks.dart:167])
#16 pc 0x399d57 com.agendaboa.app (PlatformDispatcher._dispatchPointerDataPacket [platform_dispatcher.dart:341])
#17 pc 0x399ce3 com.agendaboa.app (_dispatchPointerDataPacket [hooks.dart:94])

Flutter version
Stable channel 3.3.8
Device details:
Brand:samsung
Model:Galaxy J2 Pro
Orientation: Portrait
RAM free: 283.8 MB
Disk free: 576.64 MB
Operating System
Version:Android 7.1.1
Orientation: Portrait
Rooted:No
Crash
Date:Feb 16, 2023, 3:27:49 PM

This appears to be the same issue as #64471. It was fixed in Flutter 3.7.

Hello @rohansohonee1. I suggest you upgrade you Flutter version to 3.7 :) But indeed, this looks like a duplicate of https://github.com/flutter/flutter/issues/64471. Closing this issue for the same reason. Thank you


Even when the nodeUrl is changed to a different value, near still reports it is accessing testnet

#near --nodeUrl https://rpc.mainnet.near.org state chaenomeles.near

Account chaenomeles.near is not found in testnet

Use export NEAR_ENV=mainnet to use mainnet accounts.

Here, the cli is reporting "not found in testnet" even though the tool is already pointed at mainnet via nodeUrl. This is potentially quite confusing.

now the users can correctly select networks using --networkId


Add OSV-Scanner subcommands

Codecov Report
Attention: 29 lines in your changes are missing coverage. Please review.

Comparison is base (0c88822) 79.03% compared to head (bca7707) 78.72%.
Report is 4 commits behind head on main.

Files
Patch %
Lines

cmd/osv-scanner/scan/main.go
63.75%
20 Missing and 9 partials :warning:

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #748      +/-   ##
==========================================
- Coverage   79.03%   78.72%   -0.32%
==========================================
  Files          86       87       +1
  Lines        6121     6161      +40
==========================================
+ Hits         4838     4850      +12
- Misses       1077     1105      +28
  Partials      206      206

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.


SW-6246 Don't flag application deliverables as errors

We notify the accelerator team when a participant project uploads a document
for a document deliverable, but not when a document is uploaded as part of an
in-progress application. We were logging an error in the latter case thanks to
an outdated sanity check.

#2592  👈
main

This stack of pull requests is managed by Graphite. Learn more about stacking.

Join @sgrimm and the rest of your teammates on  Graphite


es2015 support for older node engines

This is an aggresive (ugly) PR though.
Just to put it here, for people those who want to use nodejs-dashboard for older node engines such as nwjs 0.12.3 (node 1.2.0), etc.

Thanks for the PR @fritx. I think the better solution is to convert the views to es5 syntax to allow compatibility with older engines. Is this something you'd be willing to tackle? If not I can convert it when I have some time.