Device dependent margins/config

I have added a DeviceConfig object that contains a configuration for each type of printer/labeler.
I started out with the lookup table, but puzzeled by the "random" margins I figured it out how the principal works.
For every printer we now need a "print head size in pixels" and "print head active size in mm" the rest is calculated.
I think there might only be two versions (128px/18mm and 64px/9mm).
Based on my scans we determined a label-position inaccuracy of 0.7mm. I rounded it up to 1mm to use as safety margin for now.
I´d like to hear your thoughts. Bear in mind that this is my first python code. So you may find a lot of weird things...
This is not done yet, so only a draft PR.
I've tested it on my LabelManager PC II and a  LabelManager PnP both can print valid labels 12mm (and 24mm on the PCII)
I have identified a couple of issues so far:

Supported tape sizes dropdown not cleared in GUI, making a mess. With the config object it should now show only the options supported by the printer
Margins preview in GUI are not correct
Boxed text, left border 1px missing
mm_to_px functions are maybe not accurate. Look into/refactor those?

Thanks @FaBjE for the awesome contribution and @tomers for such a detailed review! I'm pretty excited about finally getting this feature settled.
I agree that we'll want to do another round of review after addressing these structural and stylistic issues.

If possible, try to rebase fixes onto existing commits, to me review easier on us.

I'm wondering what is exactly your preference here @tomers. Most reviewers prefer to avoid rebasing until the end of the review process so that there is a clear history of the changes. However, GitHub introduced a feature that makes it easy to diff before and after a rebase, so this is no longer such a big deal. I don't have such a strong preference, but I'd like to understand your rationale. (For tiny PRs I slightly prefer rebasing, but with larger PRs like this one I like new commits.)

(Comment copied from the issue)
Hm. The point of LUT that I developed was to be prepared for any future Dymo printer. That is why I proposed to measure print area in dots, as well as a single necessary offset, and then only name this settings in mm for user's convenience.
No millimeters handled in the code because frankly we don't need them there at all.
I'm afraid that although your solution is convenient for supporting a subset of Dymo products known to us at the moment, I'm not sure how well this will scale with printers of other brands or series.

I'm wondering what is exactly your preference here @tomers. Most reviewers prefer to avoid rebasing until the end of the review process so that there is a clear history of the changes. However, GitHub introduced a feature that makes it easy to diff before and after a rebase, so this is no longer such a big deal. I don't have such a strong preference, but I'd like to understand your rationale. (For tiny PRs I slightly prefer rebasing, but with larger PRs like this one I like new commits.)

I am not orthodox on this, so I guess I can live with whatever approach used. I guess it is all about the convenience of the author and reviewers. If the author doesn't feel comfortable with rebasing, let him do whatever he wants, as to not put a burden on him. I am not familiar with Github tooling that much. I personally don't like the review system, as it is not straight forward to my opinion, and makes it hard to track progress. In my work we use https://rbcommons.com/ which is a good tool to monitor changes to a given commit.
As you saw in the past, I personally prefer to keep contained list of commits, and keep rebasing the same commits over and over, until the change is stable, and each commit containes a specific subset of the total work. In this approach you will not encounter TODO section, and then a removal of that TODO in a subsequent commit.
I agree that the approach depends on the size of the given review, and the number of iterations in its lifetime. Using the rebase approach indeed makes it harder for reviewers to track changes in the review.
So I'll leave it for @FaBjE to decide how he would like to work on this review. I want him to enjoy his work, and keep his motivation to contribute to the project :-)

@All Thank you for your feedback guys
I completely understand a lot of style issues. I'm not happy with most of them. But it are either issues of me not knowing python syntax well enough or the linter/validator settings not allowing me to.
let me address your points:

Hm. The point of LUT that I developed was to be prepared for any future Dymo printer. That is why I proposed to measure print area in dots, as well as a single necessary offset, and then only name this settings in mm for user's convenience. No millimeters handled in the code because frankly we don't need them there at all.
I'm afraid that although your solution is convenient for supporting a subset of Dymo products known to us at the moment, I'm not sure how well this will scale with printers of other brands or series.

I get your point and to emphasize it. I started out with exactly your solution. But I got stuck and it made me rethink it.
I think I have settled in "middle ground" but let me explain:
In the software there are two units mixed at the moment. Pixels (dots) and millimeters.
There is a "pixels per millimeter" constant somewhere. But I doubt it's validity.
The thing is the tape sizes are only known in millimeters. You could make this in pixels. But than I wondered, how many pixels is a particular tape size. Well, that depends on the printer. (thinking about the future) it depends on the pixels-per-millimeter of the print head. So I need to know the amount of pixels in the print-head.
Than my calculations didn´t workout. Why? Because the print-head pixels don´t match the largest tape-size it can print.
The PC II printhead active area is only 18mm as tested with your test-pattern. (I feel slightly scammed with my 24mm labels now, as they will never be printed full-size 🤔 )
So I added that configuration parameter as well.
I was able to directly determine tape size (in pixels) now. and I started working on the offets LUT.
But not having any 6mm tape for example, I had to calculate them. and than it occurred to me that I had all the input parameters of my calculation in software. So why not add the calculation there. It still uses the tuple group of pixels offsets there.
I was thinking that if we encounter non-centered printers in the future we can add a (subset) of the LUT to the device configuration object.
and make a "if not in LUT use calculation, otherwise use set value" kind of structure. Thinking we have the best of both worlds.
For my two test printers the calculation worked fine. So I left off at that point.
My expectation is that 90% of the printers will be valid, but there is always a exception.
An other "augment" is that I want to make adding printers as easy as possible. The LUT is a bit harder to generate for an inexperienced programmer than just measuring the size of your test-pattern print.
I hope you can agree with me, but I'm open to your thoughts.

So I'll leave it for @FaBjE to decide how he would like to work on this review. I want him to enjoy his work, and keep his motivation to contribute to the project :-)

I'm not really sure what you are on to about rebasing. I'm used to just commiting all the changes. At the end I should do some squashing as I made a pretty mess by now. but I leave that till later.
In case other features are merged to master I rebase this featurebranch on master to be up to date again.
Does that work for you?

I'm not happy with most of them. But it are either issues of me not knowing python syntax well enough or the linter/validator settings not allowing me to.

No worries! Please just do as well as you practically can, and we'll help out with the rest.
I agree that tape sizes are listed in mm, so for the UI it definitely makes a lot more sense than px. But personally I think of it more as a label. Like in my mental model, "12 mm" corresponds to the string "12 mm" rather than a numerical value 12.0 that can be computed with. As a result, doing a sanity check with mm to ensure the pixel counts are roughly correct is one thing, but it seems like a headache to get conversion and rounding to work out in a simultaneously simple and correct way.

The LUT is a bit harder to generate for an inexperienced programmer than just measuring the size of your test-pattern print.

Ya, I think the process could be made simpler, like enhancing the test pattern by stuff like adding numbers to the larger blocks, and to print some additional lines and checkerboard patterns. But we're not generating these LUTs at scale, so I'd rather personally help the inexperienced users to get things dialed in precisely with units of pixels. Does that make sense?
Please don't worry about the rebasing, just do whatever's easiest for you.
Thanks a lot for taking such an ambitious approach here! If this gets to be too much, please let us know and we can think about how to break it apart into smaller features.

I was thinking that if we encounter non-centered printers in the future

I thought we determined that your printer with the 9mm tape is non-centered with a top margin of 37 and a bottom margin of 27.

I agree that tape sizes are listed in mm, so for the UI it definitely makes a lot more sense than px. But personally I think of it more as a label. Like in my mental model, "12 mm" corresponds to the string "12 mm" rather than a numerical value 12.0 that can be computed with. As a result, doing a sanity check with mm to ensure the pixel counts are roughly correct is one thing, but it seems like a headache to get conversion and rounding to work out in a simultaneously simple and correct way.

True, but somewhere we must know the size of the label in pixels. I think we cannot assume that is a constant.
So it should be calculated based on the printer properties, I'll keep it as is for now. Feel free to update it somewhere in the future.

The LUT is a bit harder to generate for an inexperienced programmer than just measuring the size of your test-pattern print.

Ya, I think the process could be made simpler, like enhancing the test pattern by stuff like adding numbers to the larger blocks, and to print some additional lines and checkerboard patterns. But we're not generating these LUTs at scale, so I'd rather personally help the inexperienced users to get things dialed in precisely with units of pixels. Does that make sense?

Yes and no, I think it is more a thing of preference.
But I honestly think the calculation is not that hard. At the moment we have the same precision we would have with pixels.

Please don't worry about the rebasing, just do whatever's easiest for you.
Thanks a lot for taking such an ambitious approach here! If this gets to be too much, please let us know and we can think about how to break it apart into smaller features.
It's OK for now. But I don´t have all the time in the world. So My take is to get the code to an acceptable level to get it merged.
Than we can improve upon that "base"

I was thinking that if we encounter non-centered printers in the future

I thought we determined in #11 that your printer with the 9mm tape is non-centered with a top margin of 37 and a bottom margin of 27.

Yes I thought so too, but than I calculated the following:
My printer is 128 pixels at 18mm. so 7.11p/mm
9 mm tape should be 63.99px, lets round to 64px.
Leaving 64 pixels as margin, for a centered tape this should be 32 at both sides.
37-32= 5, and 27-32=-5, so the tape has deviated 5 pixels from the center.
5 / 7.11 = 0.70mm. So the tape is 0.7mm off-center.
Playing with the tape cartridge a bit that would make sense as there is always a bit of play in the tape guides and position of the tape in the printer.
So in my opinion the 0.7mm (I rounded it to 1mm) is always the manufacturing tolerance we have to deal with.
You can calibrate it pixel-perfect on my printer. But there is no guarantee that somebody else with a (Same model) different printer and different tape is aligned the exact same way.

Regarding px vs mm discussion, please refer to Dymo's LW 550 Technical Reference Document, where they describe the properties of their print head (page 4):

About the LabelWriter 550 Series Printers
The LabelWriter 550 series printers (LabelWriter 550, 550 Turbo, 5XL) are high-performance, low-cost
printers used for printing mailing labels, postage, file folder labels, barcode labels, and more. The
LabelWriter 550 and LabelWriter 550 Turbo printers have a 57 mm wide print head. The LabelWriter 5XL
has a 101 mm wide print head. All printers have 300-dpi print head.
The 57 mm wide thermal print head uses 672 individually addressable dots to form individual raster
lines of data at 300 dots per inch across the print head—the 101 mm wide print head uses 1248 dots.
Both use 300 dots per inch in the travel direction as directed by the print control data.

Note how they describe both the printer head width, the density (in dpi), and the number of pixels.
I think our inner configuration and logic should use pixels. User facing parts should be in millimeters.

It's not a veto but I don't agree that LUTs with two numerical parameters are more complicated than anything else.
Because that's what we ultimately need, a printout width in dots, and offset (bottom margin) in dots, for tapes smaller than a print head. Top margin isn't required.
All the rest about my LUTs may have been suboptimal because I suck at Python, but certainly I wouldn't bother amassing any more information than two dot values of our concern.
The formula that you brought up could be used by us internally to get estimated LUT values in case none of us has a printer or tape of interest.
Disclaimer: I am heavily biased towards simplicity and minimal logic, because most of my coding is for FPGAs. ;)
The test pattern was designed so it gives all the necessary information in one go. The idea was that an owner of an unsupported printer would share a test pattern photo, and we would update the LUT based on that. Ben said he could do that and certainly I could too. I also promised to write a manual before we all inevitably step down from our posts here.
Millimeters were a nightmare of the legacy code and I made it a point to remove them from everywhere except UI strings. Yes, that conversion constant wasn't precise anyway, and will not be even remotely true once we turn our attention to other thermal printers. At the very least, if we decide to stick to millimeters in cases like print margins settings and so on, these should be defined separately for each printer.
Printers with different resolutions across x and y axes are so rare I wouldn't worry about that.

Thanks for the changes @FaBjE! This is shaping up very nicely.

So the tape is 0.7mm off-center.
Playing with the tape cartridge a bit that would make sense as there is always a bit of play in the tape guides and position of the tape in the printer.
So in my opinion the 0.7mm (I rounded it to 1mm) is always the manufacturing tolerance we have to deal with.
You can calibrate it pixel-perfect on my printer. But there is no guarantee that somebody else with a (Same model) different printer and different tape is aligned the exact same way.

It makes a lot more sense to me now, thanks for the context!
I'm disturbed by a discrepancy in the technical reference where they claim 300 dpi = 11.811 px/mm. But @FaBjE computes and verifies 7.11 px/mm. Any ideas what's going on here?

I measured my old test pattern from PnP, there are 48 dots across about 6.85mm -> 7.01/mm, or 178 dpi.
The most common thermal printer resolutions are 203dpi (8/mm), 300dpi and 600 dpi. I've never heard of thermal print heads below 200dpi.
My best guess is that they use >300dpi print head and do pixel doubling in firmware due to some problems found at the development stage.

Thanks for the changes @FaBjE! This is shaping up very nicely.

Not done yet 😉  But I won´t be able to finish everything today.

So the tape is 0.7mm off-center.
Playing with the tape cartridge a bit that would make sense as there is always a bit of play in the tape guides and position of the tape in the printer.
So in my opinion the 0.7mm (I rounded it to 1mm) is always the manufacturing tolerance we have to deal with.
You can calibrate it pixel-perfect on my printer. But there is no guarantee that somebody else with a (Same model) different printer and different tape is aligned the exact same way.

It makes a lot more sense to me now, thanks for the context!

No problem.

I'm disturbed by a discrepancy in the technical reference where they claim 300 dpi = 11.811 px/mm. But @FaBjE computes and verifies 7.11 px/mm. Any ideas what's going on here?

The example with 300dpi is about the newer model printers. We have different older style printers. with about 180 dpi (180.6222)

I will try to give the changes a more thorough inspection/test later today.

About that, do I click the "Resolve conversation" button, or do you do that when my changes are verified?

About that, do I click the "Resolve conversation" button, or do you do that when my changes are verified?

Ideally the person making the request (asking a question, requesting a change) resolves. If it's clear that you've decisively addressed the request and no followup is needed, then you can close yourself. It's also fine to leave them open. There are no rules, only common sense and etiquette.

About that, do I click the "Resolve conversation" button, or do you do that when my changes are verified?

Ideally the person making the request (asking a question, requesting a change) resolves. If it's clear that you've decisively addressed the request and no followup is needed, then you can close yourself. It's also fine to leave them open. There are no rules, only common sense and etiquette.

Good to know. Makes sense to me, I've left most open as I think my fixed should be check too if they are the desired way.
I think I addressed all comments now.

I did a big change for the DPI values. https://github.com/labelle-org/labelle/pull/54/commits/7246473e2914ffa7574c58155b7ca9147eba96a3
I'm not sure if I should make a separate PR for that, or include it here.

Thanks so much @FaBjE for your work here.

Ok, I'm going to be brutally honest here. Not that I want to, but I think it needs to happen.Up until this point I liked to contribute something to labelle and getting my label printer to work under linux.
But this is starting to change.
The current codebase is/was not made for printers with different properties. (Supported tape sizes, dpi, etc) I tried to integrate this, but I needed to touch a lot of stuff.
Trying to to change as little as possible (within reason) I did this. But there is a lot of stuff I think that can be handled different/better with the things we know now. Some may be personal preference or coding style preference.
In my opinion, either we accept it is not as pretty as we want it, but it works. Or we do a big overhaul of the code and make everything pretty.
But I think we are stuck in a no-mans-land between the two at this point.
As I said in the opening post of this PR this code is not perfect. There are issues with it, mostly caused by my changes "conflicting" the current setup of the codebase.
Let me address the points:

When I run labelle-gui with my LabelManager PnP, I get the following stack trace:
qt.gui.icc: fromIccProfile: failed size sanity 2
Traceback (most recent call last):
  File "/home/mares/repos/labelle/src/labelle/gui/gui.py", line 108, in _on_settings_changed
    height_px=self._dymo_labeler.label_height_px,
  File "/home/mares/repos/labelle/src/labelle/lib/devices/dymo_labeler.py", line 277, in label_height_px
    return self.tape_print_properties.usable_tape_height_px
  File "/home/mares/repos/labelle/src/labelle/lib/devices/dymo_labeler.py", line 305, in tape_print_properties
    raise ValueError(
ValueError: Unsupported tape size 24mm. Supported sizes: [6, 9, 12]mm
Aborted (core dumped)

I believe this is indicative of a structural problem that we are introducing here. (Although the rest of the codebase is not innocent.) I strongly disapprove of the use of properties here. Accessing class attributes should be a completely safe operation. (The type checker should guarantee that they're defined.) In the stack trace we see two nested attribute accesses, which is an insane obfuscation. Unless there are exceptional circumstances, attributes should be static and functions should compute stuff. Note also how tape_print_properties is a huge block of (thankfully well-documented) code.

Yes, this is caused by a structural problem the GUI has. For starters: I didn´t notice this as my printer supports all tapes.
But the GUI can´t (properly) handle changing printers (properties).
More low level: when the printer properties are loaded (like supported tape sizes) the change-event of the control fires every time a item like a tape size is added/removed.
It starts with the default (simulator) config. (which has all supported tape sizes) Than the USB printer is initialized and "attached" to the GUI. Than the weird stuff/problems starts to happen. The "backend" already has the USB printer. But the GUI controls still have the old data. Change events fire, and the GUI tries to set properties (left over from the default) that the printer doesn´t support. So boom, exception.
IMHO: The change events should not fire when the printer properties are being loaded.1. Disable change events, 2. Clear GUI controls, 3. Load new printer properties to controls, 4. Enable change events.

Instead of having a property called label_height_px I'd like to instead see an ordinary function get_label_height_as_px. The benefits to this approach are that:
1. we define an honest interface where attributes are attributes and functions are functions

2. it makes us actually think about what should be an attribute vs a function instead of lazily reencoding everything imaginable as a property, creating needless layers of indirection

For starters, this label_height_px was always in the codebase. Originally it was named height_px as a property of the labeler object. Which is weird imho, because it is not the height of the labeler. (as I read it) but the tape height. So i did a rename.
Second, there already were a lot of properties that do either the same or something similar to eachother.
Third, I was specifically asked to make this a property. https://github.com/labelle-org/labelle/pull/54#pullrequestreview-2133618583 If you are 100% sure you want it a function I will convert it back to a function, but that will be the last time I'm changing it.

But then this also brings up the issue of whether or not we should even have mm in the first case.
A tape has:
* height in mm

Correct

* height in px

No. The PRINTER has a height in px for a tape. There are no pixels on a tape.

* dpi / pixels_per_mm

No. The PRINTER has a DPI.

  and any two determines the third. As far as I can tell, we don't need DPI for anything, and it doesn't seem like we even need height in mm if we treat "tape size" as a label. While we can do some clever stuff with dpi for DYMO printers, I wonder if it's actually worth all this code complexity.

You need DPI for the GUI (margins display) and CLI, calculations of tape size in pixels (for a particular printer)
FYI: In my last commit the DPI from the CLI was set different than the DPI of the constants.
If I were to setup this code today, I would make the two of classes of
1: Printer Config object, containing static data of a printer
2: Printer runtime object, containing all functions of a printer and the "runtime" calculations. Of say for example the amount of pixels the printer can print on a (selected) tape size.
After that, pass the printer object to all classes that needs to to something. Like the renderers, GUI etc. They can retrieve the data they need from the printer object.
They may need some more input, like for example a text or barcode that needs to be rendered. But all printer/tape specific data can just be retrieved from the printer object instead of passing around lots of separate variables.
Well, these are just my two cents.
I´d like you to define a strategy, prospect, view or design or whatever you want to call it how you want to continue.
And I'll see if I want to be a part of that.

Third, I was specifically asked to make this a property. https://github.com/labelle-org/labelle/pull/54#pullrequestreview-2133618583 If you are 100% sure you want it a function I will convert it back to a function, but that will be the last time I'm changing it.

I suggested it, but I am not orthodox about it, and I do accept the reasoning raised earlier, as to why this was a bad suggestion. I am sorry for causing you to waste your eneregy, and lose some motivation to work on this codebase.
I hope you'll continue your excellent work, and keep improving it. The architecture indeed needs some thoughts and design in order to make it better. I love the idea of separating contant printer data (print head specification, etc.) and runtime data (current tape loaded).

Hi @FaBjE, I'm really sorry that my criticism caused frustration and discouragement. I completely agree with everything you wrote. My criticism of the overuse of properties is more about the existing codebase and the need to change course rather than your contribution in particular. It was not so tactful for me to single out your code as an example of why property overuse leads to confusion. Especially since the previous review requested use of properties.
As you have realized, there are still a lot of structural issues in the codebase. A lot of things snuck in because I didn't review code as carefully as I should have. So it's a challenging situation. I want to be encouraging of contributions from people like you. But I also want the code to remain maintainable, and avoid further entrenching our previous bad design decisions.
You ask me to lay out a vision, but I think you already lay out a very clear vision in your last comment. The one thing I'd adjust is to avoid the idea of a monolithic printer object. I'd rather design things so that we have isolated stages, each of which only requires limited information. (Like the Linux philosophy of piping together simple commands.)
To figure out what these isolated stages should look like, let's suppose we were designing a web client as a replacement for the GUI. I think the first thing we'd need is a high-level specification of the label elements (e.g. text, barcode, etc.) that are to be horizontally combined. These shouldn't depend on the tape size or device, and it should ideally be easily serializable. Next would come the rasterization step that, for a given tape size in pixels, converts the elements into a bitmap to print. Finally, with the bitmap in hand, it should be passed to the printer for printing. So there are these steps: element specification, rasterization, printing to device, which I'd like to see as isolated as possible.
As for concrete next steps for this PR, let's try and make sure things are running without any errors. Let's try within reason to reduce the amount of stuff that's being added to interfaces and being passed around. And for these structural problems, let's keep track of what's wrong, and build in a way that will facilitate eventually fixing those structural problems.
And I'll try and to better to keep things fun. I think we're all here to build cool stuff in a relaxing environment. Sorry if I was being too up-tight.

Since the project has a new name and a new scope (all label printers, ideally), it makes sense to define a sustainable architecture and overhaul it, thus bump the major release number. This might cost us less work in the long run, as with a few Dymos we already struggle to keep it tidy.
@maresb's general idea has some merit. I think that each printer model should be a different "object", with its own renderer code, attributes and so on.
One thing that worries me about this proposed approach is the second stage that composes the pieces together. I am thinking about barcodes and QR codes in particular, that will not work if scaled improperly. Thus this stage has to know how many dots it's working with, something that definitely is the domain of the third stage.
I guess we'll need a graph, and a space for this discussion :)

One thing that worries me about this proposed approach is the second stage that composes the pieces together. I am thinking about barcodes and QR codes in particular, that will not work if scaled improperly. Thus this stage has to know how many dots it's working with, something that definitely is the domain of the third stage.

Right, the pipeline can't be strictly one-way. In pseudocode I'd propose something like:
def print_label(label_specification, device, tape):
    bitmap_height = device.usable_tape_height_px(tape)
    bitmap = rasterize(label_specification, bitmap_height)
    device.print(bitmap, tape)

Of course it probably will end up more complicated than this in practice due to implementation details.
So for this PR I think my specific question would be if, instead of passing around the DymoLabeler object, would it be sufficient and feasible to compute the bitmap height upfront and pass around only that instead? My hope is that this would be able to considerably simplify the code in this PR, and make it easier in the future to refactor. (It may well be that I'm wrong and that would require rewriting the whole codebase, but I hope not! :see_no_evil:)

I suggested it, but I am not orthodox about it, and I do accept the reasoning raised earlier, as to why this was a bad suggestion. I am sorry for causing you to waste your eneregy, and lose some motivation to work on this codebase. I hope you'll continue your excellent work, and keep improving it. The architecture indeed needs some thoughts and design in order to make it better. I love the idea of separating contant printer data (print head specification, etc.) and runtime data (current tape loaded).

I would not call it a bad suggestion. Because every other thing is put into a property in the dymo labeler class.
So in that way it made sense to me, and I changed it.

Hi @FaBjE, I'm really sorry that my criticism caused frustration and discouragement. I completely agree with everything you wrote. My criticism of the overuse of properties is more about the existing codebase and the need to change course rather than your contribution in particular. It was not so tactful for me to single out your code as an example of why property overuse leads to confusion. Especially since the previous review requested use of properties.

Well, you didn´t exactly put my code on the spot as the propery already existed. (I only renamed it).
The confusing/frustrating part for me is that this PR is instead of discussing my changes is becoming more and more discussion about the global architecture of the project.
Something I had nothing to do with, and should not overhaul in this PR.
I did the best I could with the current codebase. But as stated before, most things I encountered would not be my first choice (either). But made sense if you would set this up for 1 printer type.

As you have realized, there are still a lot of structural issues in the codebase. A lot of things snuck in because I didn't review code as carefully as I should have. So it's a challenging situation. I want to be encouraging of contributions from people like you. But I also want the code to remain maintainable, and avoid further entrenching our previous bad design decisions.

Yes, but what you are currently doing now from my perspective is criticizing stuff out of scope of this PR.

You ask me to lay out a vision, but I think you already lay out a very clear vision in your last comment. The one thing I'd adjust is to avoid the idea of a monolithic printer object. I'd rather design things so that we have isolated stages, each of which only requires limited information. (Like the Linux philosophy of piping together simple commands.)

Well, yes, but that is my vision. I have no clue in where you are standing on this or what the goal of the project is.
My advice on your view would be that it might be the most ideal design. (keeping stages separate) But be realistic and keep it simple. This is at the moment a tiny project with about no-one with time to code on it. You will introduce a abstraction and challenges with it. Which all require effort to code.

To figure out what these isolated stages should look like, let's suppose we were designing a web client as a replacement for the GUI. I think the first thing we'd need is a high-level specification of the label elements (e.g. text, barcode, etc.) that are to be horizontally combined. These shouldn't depend on the tape size or device, and it should ideally be easily serializable. Next would come the rasterization step that, for a given tape size in pixels, converts the elements into a bitmap to print. Finally, with the bitmap in hand, it should be passed to the printer for printing. So there are these steps: element specification, rasterization, printing to device, which I'd like to see as isolated as possible.

Brutally honest, I (would like to) see labelle as the simple "simple but functional"/no-nonsense portable application that came on the Dymo PnP labeler (for windows) and I think you are 80% there atm.
Thats what I am looking for at least. Just printing some labels from a GUI. nothing fancy.
An example that I read in the GUI issue is about the office setting. But not to ruin your dreams or anything.
But the likely hood of something like labelle to be used in the foreseeable future are slim imho. For (professional) office settings there are much better (and expensive) solutions available.
I think labelle's strength will be in supporting the "older" hardware. and keeping it alive. reducing e-waste.
Even on windows the official dymo software is pretty much out of support for these types of printers.
But nothing is wrong with the label printers, I can buy tape cheaply at discount stores. and it can print labels fine.
Again, it may be fine ambitions, but something (too) far in the future imho.
Especially considering the amount of active coders on the project.
On the pratical side as @tomek-szczesny pointed out in it's next post, the bitmap that needs to be rendered is direct dependent on the printer (dpi) and label (size).

As for concrete next steps for this PR, let's try and make sure things are running without any errors. Let's try within reason to reduce the amount of stuff that's being added to interfaces and being passed around. And for these structural problems, let's keep track of what's wrong, and build in a way that will facilitate eventually fixing those structural problems.
And I'll try and to better to keep things fun. I think we're all here to build cool stuff in a relaxing environment. Sorry if I was being too up-tight. I really hope that you stick around.

I have a different suggestion for this PR. I would like to see a "develop" branch.
For this branch we use this PR as starting point.
A separate overhaul of the design may be implemented on top of that.
Maybe just in tiny steps to keep it manageable. (again, amount of available coders/time)
Whenever we are happy with it, the develop branch can be merged to the main branch.

So for this PR I think my specific question would be if, instead of passing around the DymoLabeler object, would it be sufficient and feasible to compute the bitmap height upfront and pass around only that instead? My hope is that this would be able to considerably simplify the code in this PR, and make it easier in the future to refactor. (It may well be that I'm wrong and that would require rewriting the whole codebase, but I hope not! 🙈)

The dymo labeler object is current passed around for the DPI. Label height is already passed around.
there are lots more things to consider if you want to support more devices. (for example, label width, all newer types have fixed size labels instead of our "endless" tape).
But again, practically. This works.
So again my view. Merge this to develop, agree on a global design, rework everything (in tiny steps), have a proper codebase.

So again my view. Merge this to develop, agree on a global design, rework everything (in tiny steps), have a proper codebase.

I'd be happy to do this. That way we can follow up separately with the structural issues I've raised before merging to main, people can build on that if they'd like, and we avoid further blocking on this PR. Great suggestion!
I just work on this project to screw around. I have no serious ambitions. For quite a while I was the only active maintainer, and I was just trying to keep the project alive. I do have things I'd like to eventually see implemented, like a web client and server, but unfortunately I don't have the free time to implement that stuff myself.
Also, to be honest I don't understand the details of how all these classes are implemented, and whenever I look at the details I'm surprised and confused. It used to be way worse until @tomers came along and rewrote major portions of the codebase. He took us from 20% to 80% of having a stable functional app.


URL-encoded filenames not un-encoded

Our server returns url-encoded filenames in the Content-Disposition header for compatibility reasons (e.g. to support accented characters). If our header looks like this:
Content-Disposition: attachment; filename="MetLife%20MET%20US.xlsx"; filename*=UTF-8''MetLife%20MET%20US.xlsx

the library downloads the file as:
MetLife%20MET%20US.xlsx

It would be great if the library un-encoded the filenames maybe using decodeURIComponent().

Hi @micthiesen!
I have made a new release introducing a callback for the file name.
In your case you could use it like:
new Downloader({
  ...,
  nameCallback: function(name) {
    return  decodeURIComponent(name);
  }
})

Let me know.

Nice thank you that’s perfect!


Feat/see response code

Fulfilled https://github.com/Codeception/CodeceptJS/issues/244

Updated code as grabbing the statusCode of current URL and make assertion against it.

Fixed failed helper tests

Sorry, still no.
Here is the thing. When you send requests via 3rd party library (which is got) you are not inside the session of current browser so the results will be different from what you get in browser.
How I think it should be implemented

Nightmare has API for status codes: https://github.com/segmentio/nightmare/issues/656
Puppeteer has its API too.
WebDriver/Protractor doesn't have such API at all.

In Nightmare/Puppeteer you can just create a property for a status code and update it after each request. When you call seeResponseCodeIs it will compare expected value with the value of the last request.

I‘m trying to implement this with your suggestions

Updated function seeResponseCodeIs, right now, after doing a amOnPage, the statusCode will be updated and seeResponseCodeIs will make the assertion against this statusCode

I'm not sure if we really need this anymore. So closed this


Audio encoding (Lyon's Ear Model + BSA)

Codecov Report

Merging #91 (d5865c8) into update-0.2.0 (2c2dbd9) will decrease coverage by 1.44%.
The diff coverage is 58.06%.

@@               Coverage Diff                @@
##           update-0.2.0      #91      +/-   ##
================================================
- Coverage         83.65%   82.20%   -1.45%
================================================
  Files                36       40       +4
  Lines              1034     1096      +62
  Branches            110      117       +7
================================================
+ Hits                865      901      +36
- Misses              147      173      +26
  Partials             22       22

Flag
Coverage Δ

unittests
82.20% <58.06%> (-1.45%)
:arrow_down:

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

Impacted Files
Coverage Δ

miv/coding/temporal/spiker.py
31.25% <31.25%> (ø)

miv/coding/temporal/protocol.py
71.42% <71.42%> (ø)

miv/coding/temporal/__init__.py
100.00% <100.00%> (ø)

miv/coding/temporal/lyon.py
100.00% <100.00%> (ø)

miv/typing.py
100.00% <100.00%> (ø)

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.


Great work!

This extension is great! And your source code looks so clean. Hats off! Are you working for the Azure DevOps team? Is this derived from the original code?
In particular
https://github.com/c4rth/ado-task-viewer/blob/main/app/helper/VisibilityHelper.ts
It is unfortunate that the task rendering engine didn't implement just the full javascript expression syntax.
Btw in order to get the data binding working for real, one could leverage plugging an AAD access token or PAT to call out to the service connection's endpoint proxy. Maybe a PR I should start working on 😅

Hi,
Thanks for the compliment, much appreciated. 🙏
I'm not related to Azure DevOps team but I use it a lot for my daily work.
Indeed I used this class for the vscode-deploy-azure extension.
Unfortunately there is no npmjs package containing it.
Feel free to participate, enrich, improve.
Best Regards,

This extension is awesome! The main ADO task I develop is extremely complex and takes about 30 minutes to build/publish to our  environments. This extension reduces the development cycle time to nearly 0, Azure DevOps team should work with you to get this fully integrated/supported IMO.

Actually you can also take a look at the oh my mock chrome extension which
can mock the tasks payload. This enables real data binding testing. I still
need to write a blog about this approach.
https://chrome.google.com/webstore/detail/oh-my-mock/egadlcooejllkdejejkhibmaphidmock
Op do 14 apr. 2022 19:38 schreef Brian @.***>:

This extension is awesome! The main ADO task I develop is extremely
complex and takes about 30 minutes to build/publish to our environments.
This extension reduces the development cycle time to nearly 0, Azure DevOps
team should work with you to get this fully integrated/supported IMO.
—
Reply to this email directly, view it on GitHub
https://github.com/c4rth/ado-task-viewer/issues/4#issuecomment-1099457725,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/ABPIYJE5RWYP2IEMEX4KXITVFBJZTANCNFSM5SVY6YBA
.
You are receiving this because you authored the thread.Message ID:
@.***>

just want to echo the sentiment expressed here. I came across this extension today and it really helped me. I would love to read more about tips/tricks you have for developing extensions.


URGENT: Upgrade Paloma to reduce the number of calls for eth_getlogs so that we do not overwhelm the validator endpoints.

As a validator, I want the number of eth_getlogs to be reduced given that paloma block times have increased.
Acceptance Criteria

Reduce eth_getlogs calls given the updated block time.
Ensure that we have not lost ability to execute or secure the valsets.

Closing due to old Palomabot usage


chore: another build.gradle update

Proposed changes

Types of changes

[X] Build (changes that affect the build system)

Codecov Report

Merging #14 into master will not change coverage.
The diff coverage is n/a.

@@            Coverage Diff            @@
##             master      #14   +/-   ##
=========================================
  Coverage     88.12%   88.12%
  Complexity      154      154
=========================================
  Files            37       37
  Lines           480      480
  Branches         41       41
=========================================
  Hits            423      423
  Misses           35       35
  Partials         22       22

Continue to review full report at Codecov.

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


Don't force -auto-all

Cabal now allows you to set profiling detail in a more fine-grained way using
--profiling-detail.
Forcing -auto-all significantly decreases the signal-to-noise when profiling a larger project using mwc-random.

Actually I started restoring test suite and nuked -auto-sall along the way 10 minutes ago (:


Add concat_ws function

Is this for translation from Hive? If so, we can translate into Presto code:
array_join(sep, filter(ARRAY[a, b, c], e -> e IS NOT NULL))

@electrum  This is one of our internal patches added long back (to provide same functionality as hive's concat_ws), that we want to get rid of. Our workload contains a significant number of these queries using this function. Not sure if this can become a simple function plugin, because of the variable number of arguments and type comparison for nulls. What would you recommend?

@dain can this be done as a plugin with the new function API?

I think this is how the array_join function works today, so this would just be an alias.  Assuming that is true, I think you can  add a custom annotated function in a plugin with a dependency on array_join today, and just delegate. See the TeradataStringFunctions for an example: https://github.com/prestosql/presto/blob/master/presto-teradata-functions/src/main/java/io/prestosql/teradata/functions/TeradataStringFunctions.java#L40-L43

Learnt from @dain that upcoming changes to the functions API will make it easy to support varargs, enabling concat_ws function to be added as a plugin. Closing this PR since concat_ws can be rewritten using other functions as David mentioned.

The conclusion of our offline discussion was that adding this function in presto-main would be useful, modulo a better name for it.
This function is not included in ANSI SQL, however, the following engines implement it in addition to hive (with the same name).

MySQL: https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_concat-ws
Postgres: https://www.postgresql.org/docs/9.1/functions-string.html
SqlServer: https://docs.microsoft.com/en-us/sql/t-sql/functions/concat-ws-transact-sql?view=sql-server-ver15

however, I agree that "ws" is not descriptive enough. Should we change it to concat_delimited or concat_with_delimiter ? cc @martint

Interesting. A few thoughts come to mind. When I first saw the name "concat_ws", the first thing that came to my mind was "ws == whitespace" (maybe I'm biased from working with antlr grammars, where that's the name that's commonly assigned to the whitespace token). If most other databases call it that way, we may want to do that, too, for familiarity. Otherwise, concat_with_delimiter seems fine to me.
@prestosql/maintainers, thoughts?

The fact that function exists in MySQL, PostgreSQL and SQL Server and apparently has the same semantics (NULL treatment) is pretty compelling one.
Hive also have this (docs don't cover NULL treatment howeveR).
FWIW i did not find this function in Oracle, DB2, Teradata or Vertica (not sure why i picked these in particular)
If i were to choose, I would go with concat_ws name.

@findepi Thanks for your comment, verified again the null behavior on hive, and it seems to be the same as others. (At least on hive 1.x)
hive (default)> SELECT concat_ws(null, 'a', 'b');
NULL
OK

hive (default)> SELECT concat_ws(',', 'a', '', 'b', null, 'c');
a,,b,c
OK

May be we can wait for a few more days for other maintainers to provide their input. If there're no conflicting opinions, we could go with concat_ws.

concat_ws sounds good given it's used in three others.

Ok, it's settled. Let's go with concat_ws.

I've added some documentation too. This is ready for review.

@martint Thanks for the suggestion, learnt how cool the combinators are :) . The implementation is much simpler now, the PR is ready for review. Failure seems unrelated, #5527.
I've also made similar changes to concat function, not sure if there were other reasons to use bytecode generation there. cc @sopel39


Lint workflow doesnt seem to be working

https://github.com/code100x/cms/blob/main/.github/workflows/lint.yml isnt triggering on PRs

I want to work on this @hkirat please assign this to me


[SeaTunnel]Simply seatunnel e2e test.

Purpose of this pull request
Now, Seatunnel e2e test need compile and package some modules in seatunnel root project, it consume us lots of time to rebuild after e2e tests failed, so we want to improve the efficiency when we develop a new connector.
In this pull request, we use flink minicluster to support e2e test in local environment. User just need to add seatunnel-flink-connector-v2-e2e-local and fakesource or console-sink to the connector's pom file, then can test the connector directly.
I add an example in the module connector-fake.
Check list

[ ] Code changed are covered with tests, or it does not need tests for reason:
[ ] If any new Jar binary package adding in your PR, please add License Notice according
New License Guide
[ ] If necessary, please update the documentation to describe the new feature. https://github.com/apache/incubator-seatunnel/tree/dev/docs

Thank you for your contribute, It seems you don't use a connector jar to submit job. In this case, is there any difference between it and example？

Thank you very much.


Can't get items to add to InventoryGrid node

ok I've been banging my head against this for the past half week. I'm having a heck of a time getting items to add to my inventory. Also, if you don't want these kind of question in the issues feel free to just close it. I'll completely understand.
I have a basic scene for my inventory with a CtrlInventoryGrid as a child node. I'm creating the InventoryGrid in code (see below). I'm fairly certain the InventoryGrid node is getting created and linked to the CtrlInventoryGrid via the inventory_path property. However when I try to find a free place for the item or add an item I get an error that says:

Invalid call. Nonexistent function 'get_property' in base 'NiL'.

Additionally,  inventory_grid_node.get_item_by_id("laptop") seems to be null so it's acting like it's not even finding the item in the protoset.
[
    {
        "id": "laptop",
        "width": 2,
        "height": 2,
        "name": "Laptop",
        "description": "A general purpose laptop for business.",
        "image": "res://items/assets/laptop.png"
    }
]

I see that get_property is a method of InventoryItem. is the get_item_by_id function I'm trying to call just searching for the item id in the exiting inventory? also if thats the case, how does one add an item to an inventory in code?
func _ready():
	var inventory_grid = initialize_inventory_grid()
	create_inventory_grid(inventory_grid)
	assign_inventory_grid_to_panel(inventory_grid)

        var inventory_grid_node = get_node("InventoryGrid")

	add_item(inventory_grid_node)

func initialize_inventory_grid() -> InventoryGrid:
	var inventory_grid = load("res://addons/gloot/inventory_grid.gd").new()
	inventory_grid.size = Vector2(4, 5)
	inventory_grid.item_protoset = load("res://items/ItemProtoset.tres")
	inventory_grid.name = "InventoryGrid"
	return inventory_grid

func create_inventory_grid(inventory_grid):
	add_child(inventory_grid)

func assign_inventory_grid_to_panel(inventory_grid: InventoryGrid):
	var inventory_panel = get_node("CtrlInventoryGrid")
	inventory_panel.inventory_path = inventory_grid.get_path()

func add_item(inventory_grid_node):
	var item = inventory_grid_node.get_item_by_id("laptop")
	var item_position = inventory_grid_node.find_free_place(item)
	inventory_grid_node.add_item_at(item, item_position)

I think get_item_by_id is taking stuff from the current inventory item list and not from the protoset. I'm currently facing the same issue.

I think get_item_by_id is taking stuff from the current inventory item list and not from the protoset. I'm currently facing the same issue. There should be a function implemented, that creates items based on the id from the protoset.

Thats what I'm also thinking based on what I'm seeing. I originally thought get_item_by_id would automatically search the protoset attached to the inventory. So either thats not how it work, or my code isn't actually attaching the protoset to the item_protoset property.

@tupcakes
I've modified inventory.gd script and added this function
`
func create_and_add_item(id: String) -> InventoryItem:
var items = parse_json(item_protoset.json_data)
var item_to_create = null
for item in items:
if item.id == id:
item_to_create = item
break
assert(item_to_create != null, "Item with ID not found")
var item = InventoryItem.new()
item.deserialize(item_to_create)
self.add_item(item)
return item

`
You call this on any inventory and the item should be created and added. It also returns the created item if you'd need it etc. Hope it helps.

Hey, thanks for the input!

is the get_item_by_id function I'm trying to call just searching for the item id in the exiting inventory? also if thats the case, how does one add an item to an inventory in code?

Yes, get_item_by_id searches through the items that are already in the inventory. It is not used to create an InventoryItem based on the given prototype ID. The current way of adding items in code would be the following:
var item = InventoryItem.new()
item.prototype_id = "laptop"
inventory_grid_node.add_item(item)

(find_free_place is not really necessary, as InventoryGrid.addItem() already looks for a free place)
It's not very intuitive, especially since it is not mentioned anywhere in the docs, but that's because I was mostly focusing on inventory manipulation using the editor and the GDScript API is still a bit lacking.
However, I still think adding items from code should be straight forward and there should definitely be a helper method (similar to what @filipinyo suggested) that does that in one line.
I will rename this issue to be more descriptive, but I will keep it open until something like that is implemented (shouldn't take long).

Thank you both!
item.prototype_id = "laptop"

above, is what I was missing. I'd tried so many things. It seems so simple now.


Update to latest Flutter SDK

Overall this is great, just some minor issues.

@hixie Do I need to do something more, or better ?

Let me know once you've fixed the two trivial issues I just pointed out and I can land it for you!
Thanks so much for your contribution! And sorry about the delay in responding.

@hixie Thanks for the review. the two last issues are fixed now !
( so happy to make my first PR to the Flutter repo ( and to a major OSS project ) !  :) )

Hm, I just noticed the cla bot didn't trigger. Let me look into that before I land it.

Oh never mind, it did trigger, we just don't have the labels set.

Ok, all's good! I'm landing it! Thanks so much for the contribution!


E0002 Unknown exception while processing rule E2532: can only concatenate list (not "NoneType") to list

*cfn-lint version: 0.7.1
I have an existing SAM template that creates a Step Function amongst other resources. Since installing version 0.7.1 (from 0.6, I believe) it produces this error.
I'm not sure if it is the Step Function JSON that is causing the failure so I've added the complete template.yaml file below.
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description:
Globals:
Function:
Runtime: python3.6
Parameters:
EnvironmentType:
Type: String
Default: dev
AllowedValues:
- dev
- test
- prod
Description: 'The environment to create the resource in'
UserEnv:
Type: String
Description: 'Specific to the user, e.g. dev-neil'
SecurityStack:
Description: The name of the stack that contains the SNS topics and KMS IDs
Type: String
GeneralStack:
Description: Stack for general resources
Type: String
Conditions:
IsProd:
Fn::Equals:
- Ref: EnvironmentType
- prod
Resources:
Queue:
Type: 'AWS::Serverless::Function'
Properties:
Handler: eloqua_queue.lambda_handler
Description: 'Populates a queue of items to process'
MemorySize: 128
Timeout: 30
Role: !GetAtt EloquaRole.Arn
Environment:
Variables:
USERENV:
Ref: UserEnv
ENV:
Ref: EnvironmentType
START_YYYYMMDD: "today-2"
END_YYYYMMDD: "today"
DeadLetterQueue:
Type: SNS
TargetArn:
Fn::ImportValue:
!Sub "${GeneralStack}:SNSTopic"
QueueLog:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "Queue" ] ]
RetentionInDays: 60
Process:
Type: 'AWS::Serverless::Function'
Properties:
Handler: eloqua.lambda_handler
Description: 'Pulls data from Eloqua and pushes it to a file in S3'
MemorySize: 320
Timeout: 300
Role: !GetAtt EloquaRole.Arn
Environment:
Variables:
USERENV:
Ref: UserEnv
ENV:
Ref: EnvironmentType
DeadLetterQueue:
Type: SNS
TargetArn:
Fn::ImportValue:
!Sub "${GeneralStack}:SNSTopic"
ProcessLog:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "Process" ] ]
RetentionInDays: 60
ClearQueue:
Type: 'AWS::Serverless::Function'
Properties:
Handler: clear_queue.lambda_handler
Description: 'If the step function fails, clear the queue ready for a retry'
MemorySize: 128
Timeout: 15
Role: !GetAtt EloquaRole.Arn
Environment:
Variables:
USERENV:
Ref: UserEnv
ENV:
Ref: EnvironmentType
DeadLetterQueue:
Type: SNS
TargetArn:
Fn::ImportValue:
!Sub "${GeneralStack}:SNSTopic"
ClearQueueLog:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "ClearQueue" ] ]
RetentionInDays: 60
ClearS3:
Type: 'AWS::Serverless::Function'
Properties:
Handler: clear_s3.lambda_handler
Description: 'If the step function fails, clear the S3 path ready for the retry'
MemorySize: 128
Timeout: 15
Role: !GetAtt EloquaRole.Arn
Environment:
Variables:
USERENV:
Ref: UserEnv
ENV:
Ref: EnvironmentType
DeadLetterQueue:
Type: SNS
TargetArn:
Fn::ImportValue:
!Sub "${GeneralStack}:SNSTopic"
ClearS3Log:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "ClearS3" ] ]
RetentionInDays: 60
StepFunctionError:
Type: 'AWS::Serverless::Function'
Properties:
Handler: step_function_error_mail.lambda_handler
Description: 'An extra control to email if the step function does not complete as expected'
MemorySize: 128
Timeout: 15
Role: !GetAtt EloquaRole.Arn
Environment:
Variables:
USERENV:
Ref: UserEnv
ENV:
Ref: EnvironmentType
DeadLetterQueue:
Type: SNS
TargetArn:
Fn::ImportValue:
!Sub "${GeneralStack}:SNSTopic"
StepFunctionErrorLog:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "StepFunctionError" ] ]
RetentionInDays: 60
EloquaTrigger:
Type: "AWS::Events::Rule"
Condition: IsProd
Properties:
Description: Runs the Eloqua Step Function
Name: !Sub "${EnvironmentType}-eloqua-${AWS::Region}"
ScheduleExpression: "cron(2 2 * * ? *)"
State: "ENABLED"
Targets:
- Arn: !Ref EloquaStepFunction
Id: EloquaStep1
RoleArn:
Fn::ImportValue:
!Sub "${SecurityStack}:StepFunctionTriggerRoleArn"
EloquaStepFunction:
Type: "AWS::StepFunctions::StateMachine"
Properties:
StateMachineName: !Sub "${EnvironmentType}-eloqua"
RoleArn: !Sub "arn:aws:iam::${AWS::AccountId}:role/service-role/StatesExecutionRole-${AWS::Region}"
DefinitionString:
!Sub
- |-
{
"Comment": "Put Eloqua activities and dates on a queue and put the data in S3",
"StartAt": "eloqua-put-on-queue",
"States": {
"eloqua-put-on-queue": {
"Type": "Task",
"Resource": "${QueueArn}",
"Next": "eloqua-get",
"Catch": [ {
"ErrorEquals": ["States.ALL"],
"Next": "clear-s3"
} ]
},
"eloqua-get": {
"Type": "Task",
"Resource": "${ProcessArn}",
"Next": "ChoiceStateMessagesOnQueue",
"Catch": [ {
"ErrorEquals": ["States.ALL"],
"Next": "clear-s3"
} ]
},
"clear-s3": {
"Type": "Task",
"Resource": "${ClearS3Arn}",
"Next": "clear-queue"
},
"clear-queue": {
"Type": "Task",
"Resource": "${ClearQueueArn}",
"Next": "send-email-failure"
},
"send-email-failure": {
"Type": "Task",
"Resource": "${StepFunctionErrorArn}",
"Next": "finish"
},
"finish": {
"Type": "Pass",
"Result": "Nothing to do",
"End": true
},
"ChoiceStateMessagesOnQueue": {
"Type" : "Choice",
"Choices": [
{
"Variable": "$.messagesonqueue",
"StringEquals": "Yes",
"Next": "eloqua-get"
},
{
"Variable": "$.messagesonqueue",
"StringEquals": "No",
"Next": "finish"
}
],
"Default": "DefaultState"
},
"DefaultState": {
"Type": "Fail",
"Cause": "No Matches!"
}
}
}
- {QueueArn: !GetAtt [ Queue, Arn ],
ProcessArn: !GetAtt [ Process, Arn ],
ClearQueueArn: !GetAtt [ ClearQueue, Arn ],
ClearS3Arn: !GetAtt [ ClearS3, Arn ],
StepFunctionErrorArn: !GetAtt [ StepFunctionError, Arn ]}
EloquaRole:
Type: "AWS::IAM::Role"
DeletionPolicy: Delete
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- "sts:AssumeRole"
RoleName:
!Sub '${EnvironmentType}-lambda-eloqua-${AWS::Region}'
Policies:
-
PolicyName:
!Sub '${EnvironmentType}-lambda-eloqua-${AWS::Region}'
PolicyDocument:
Version: '2012-10-17' # Policy Document
Statement:
-
Effect: "Allow"
Action:
- "ssm:GetParameters"
Resource:
- !Sub 'arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${EnvironmentType}/eloqua/creds'
-
Effect: "Allow"
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
- "sqs:ListQueues"
Resource:
- ""
-
Effect: "Allow"
Action:
- "s3:List"
Resource:
- !Sub 'arn:aws:s3:::economist-analytics-${AWS::Region}-'
-
Effect: "Allow"
Action:
- "s3:Get"
- "s3:Put*"
- "s3:DeleteObject"
Resource:
- !Sub 'arn:aws:s3:::economist-analytics-${AWS::Region}-/eloqua//staging/'
-
Effect: "Allow"
Action:
- "sns:Publish"
Resource:
- !Sub 'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${EnvironmentType}'
-
Effect: Allow
Action:
- "sqs:CreateQueue"
- "sqs:ReceiveMessage"
- "sqs:DeleteMessage"
- "sqs:GetQueueAttributes"
- "sqs:SendMessage"
- "sqs:PurgeQueue"
Resource:
- !Sub "arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${UserEnv}-lambda-eloqua-activities.fifo"
Outputs:
EloquaRole:
Value: !Ref EloquaRole
Export:
Name: !Join [ ":", [ !Ref "AWS::StackName", EloquaRole ] ]

`AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Pulls data from Eloqua and pushes it to a file in S3
Globals:
Function:
Runtime: python3.6
Parameters:
EnvironmentType:
Type: String
Default: dev
AllowedValues:
- dev
- test
- prod
Description: 'The environment to create the resource in'
UserEnv:
Type: String
Description: 'Specific to the user, e.g. dev-neil'
SecurityStack:
Description: The name of the stack that contains the SNS topics and KMS IDs
Type: String
GeneralStack:
Description: Stack for general resources
Type: String
Conditions:
IsProd:
Fn::Equals:
- Ref: EnvironmentType
- prod
Resources:
Queue:
Type: 'AWS::Serverless::Function'
Properties:
Handler: eloqua_queue.lambda_handler
Description: 'Populates a queue of items to process'
MemorySize: 128
Timeout: 30
Role: !GetAtt EloquaRole.Arn
Environment:
Variables:
USERENV:
Ref: UserEnv
ENV:
Ref: EnvironmentType
START_YYYYMMDD: "today-2"
END_YYYYMMDD: "today"
DeadLetterQueue:
Type: SNS
TargetArn:
Fn::ImportValue:
!Sub "${GeneralStack}:SNSTopic"
QueueLog:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "Queue" ] ]
RetentionInDays: 60
Process:
Type: 'AWS::Serverless::Function'
Properties:
Handler: eloqua.lambda_handler
Description: 'Pulls data from Eloqua and pushes it to a file in S3'
MemorySize: 320
Timeout: 300
Role: !GetAtt EloquaRole.Arn
Environment:
Variables:
USERENV:
Ref: UserEnv
ENV:
Ref: EnvironmentType
DeadLetterQueue:
Type: SNS
TargetArn:
Fn::ImportValue:
!Sub "${GeneralStack}:SNSTopic"
ProcessLog:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "Process" ] ]
RetentionInDays: 60
ClearQueue:
Type: 'AWS::Serverless::Function'
Properties:
Handler: clear_queue.lambda_handler
Description: 'If the step function fails, clear the queue ready for a retry'
MemorySize: 128
Timeout: 15
Role: !GetAtt EloquaRole.Arn
Environment:
Variables:
USERENV:
Ref: UserEnv
ENV:
Ref: EnvironmentType
DeadLetterQueue:
Type: SNS
TargetArn:
Fn::ImportValue:
!Sub "${GeneralStack}:SNSTopic"
ClearQueueLog:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "ClearQueue" ] ]
RetentionInDays: 60
ClearS3:
Type: 'AWS::Serverless::Function'
Properties:
Handler: clear_s3.lambda_handler
Description: 'If the step function fails, clear the S3 path ready for the retry'
MemorySize: 128
Timeout: 15
Role: !GetAtt EloquaRole.Arn
Environment:
Variables:
USERENV:
Ref: UserEnv
ENV:
Ref: EnvironmentType
DeadLetterQueue:
Type: SNS
TargetArn:
Fn::ImportValue:
!Sub "${GeneralStack}:SNSTopic"
ClearS3Log:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "ClearS3" ] ]
RetentionInDays: 60
StepFunctionError:
Type: 'AWS::Serverless::Function'
Properties:
Handler: step_function_error_mail.lambda_handler
Description: 'An extra control to email if the step function does not complete as expected'
MemorySize: 128
Timeout: 15
Role: !GetAtt EloquaRole.Arn
Environment:
Variables:
USERENV:
Ref: UserEnv
ENV:
Ref: EnvironmentType
DeadLetterQueue:
Type: SNS
TargetArn:
Fn::ImportValue:
!Sub "${GeneralStack}:SNSTopic"
StepFunctionErrorLog:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "StepFunctionError" ] ]
RetentionInDays: 60
EloquaTrigger:
Type: "AWS::Events::Rule"
Condition: IsProd
Properties:
Description: Runs the Eloqua Step Function
Name: !Sub "${EnvironmentType}-eloqua-${AWS::Region}"
ScheduleExpression: "cron(2 2 * * ? *)"
State: "ENABLED"
Targets:
- Arn: !Ref EloquaStepFunction
Id: EloquaStep1
RoleArn:
Fn::ImportValue:
!Sub "${SecurityStack}:StepFunctionTriggerRoleArn"
EloquaStepFunction:
Type: "AWS::StepFunctions::StateMachine"
Properties:
StateMachineName: !Sub "${EnvironmentType}-eloqua"
RoleArn: !Sub "arn:aws:iam::${AWS::AccountId}:role/service-role/StatesExecutionRole-${AWS::Region}"
DefinitionString:
!Sub
- |-
{
"Comment": "Put Eloqua activities and dates on a queue and put the data in S3",
"StartAt": "eloqua-put-on-queue",
"States": {
"eloqua-put-on-queue": {
"Type": "Task",
"Resource": "${QueueArn}",
"Next": "eloqua-get",
"Catch": [ {
"ErrorEquals": ["States.ALL"],
"Next": "clear-s3"
} ]
},
"eloqua-get": {
"Type": "Task",
"Resource": "${ProcessArn}",
"Next": "ChoiceStateMessagesOnQueue",
"Catch": [ {
"ErrorEquals": ["States.ALL"],
"Next": "clear-s3"
} ]
},
"clear-s3": {
"Type": "Task",
"Resource": "${ClearS3Arn}",
"Next": "clear-queue"
},
"clear-queue": {
"Type": "Task",
"Resource": "${ClearQueueArn}",
"Next": "send-email-failure"
},
"send-email-failure": {
"Type": "Task",
"Resource": "${StepFunctionErrorArn}",
"Next": "finish"
},
"finish": {
"Type": "Pass",
"Result": "Nothing to do",
"End": true
},
"ChoiceStateMessagesOnQueue": {
"Type" : "Choice",
"Choices": [
{
"Variable": "$.messagesonqueue",
"StringEquals": "Yes",
"Next": "eloqua-get"
},
{
"Variable": "$.messagesonqueue",
"StringEquals": "No",
"Next": "finish"
}
],
"Default": "DefaultState"
},
"DefaultState": {
"Type": "Fail",
"Cause": "No Matches!"
}
}
}
- {QueueArn: !GetAtt [ Queue, Arn ],
ProcessArn: !GetAtt [ Process, Arn ],
ClearQueueArn: !GetAtt [ ClearQueue, Arn ],
ClearS3Arn: !GetAtt [ ClearS3, Arn ],
StepFunctionErrorArn: !GetAtt [ StepFunctionError, Arn ]}
EloquaRole:
Type: "AWS::IAM::Role"
DeletionPolicy: Delete
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- "sts:AssumeRole"
RoleName:
!Sub '${EnvironmentType}-lambda-eloqua-${AWS::Region}'
Policies:
-
PolicyName:
!Sub '${EnvironmentType}-lambda-eloqua-${AWS::Region}'
PolicyDocument:
Version: '2012-10-17' # Policy Document
Statement:
-
Effect: "Allow"
Action:
- "ssm:GetParameters"
Resource:
- !Sub 'arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${EnvironmentType}/eloqua/creds'
-
Effect: "Allow"
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
- "sqs:ListQueues"
Resource:
- ""
-
Effect: "Allow"
Action:
- "s3:List"
Resource:
- !Sub 'arn:aws:s3:::economist-analytics-${AWS::Region}-'
-
Effect: "Allow"
Action:
- "s3:Get"
- "s3:Put*"
- "s3:DeleteObject"
Resource:
- !Sub 'arn:aws:s3:::economist-analytics-${AWS::Region}-/eloqua//staging/'
-
Effect: "Allow"
Action:
- "sns:Publish"
Resource:
- !Sub 'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${EnvironmentType}'
-
Effect: Allow
Action:
- "sqs:CreateQueue"
- "sqs:ReceiveMessage"
- "sqs:DeleteMessage"
- "sqs:GetQueueAttributes"
- "sqs:SendMessage"
- "sqs:PurgeQueue"
Resource:
- !Sub "arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${UserEnv}-lambda-eloqua-activities.fifo"
Outputs:
EloquaRole:
Value: !Ref EloquaRole
Export:
Name: !Join [ ":", [ !Ref "AWS::StackName", EloquaRole ] ]`

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Pulls data from Eloqua and pushes it to a file in S3
Globals:
  Function:
    Runtime: python3.6
Parameters:
  EnvironmentType:
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - test
      - prod
    Description: 'The environment to create the resource in'
  UserEnv:
    Type: String
    Description: 'Specific to the user, e.g. dev-neil'
  SecurityStack:
    Description: The name of the stack that contains the SNS topics and KMS IDs
    Type: String
  GeneralStack:
    Description: Stack for general resources
    Type: String
Conditions:
  IsProd:
    Fn::Equals:
    - Ref: EnvironmentType
    - prod

Resources:
  Queue:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: eloqua_queue.lambda_handler
      Description: 'Populates a queue of items to process'
      MemorySize: 128
      Timeout: 30
      Role: !GetAtt EloquaRole.Arn
      Environment:
        Variables:
          USERENV:
            Ref: UserEnv
          ENV:
            Ref: EnvironmentType
          START_YYYYMMDD: "today-2"
          END_YYYYMMDD: "today"
      DeadLetterQueue:
        Type: SNS
        TargetArn:
          Fn::ImportValue:
              !Sub "${GeneralStack}:SNSTopic"

  QueueLog:
    Type: "AWS::Logs::LogGroup"
    Properties:
      LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "Queue" ] ]
      RetentionInDays: 60

  Process:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: eloqua.lambda_handler
      Description: 'Pulls data from Eloqua and pushes it to a file in S3'
      MemorySize: 320
      Timeout: 300
      Role: !GetAtt EloquaRole.Arn
      Environment:
        Variables:
          USERENV:
            Ref: UserEnv
          ENV:
            Ref: EnvironmentType
      DeadLetterQueue:
        Type: SNS
        TargetArn:
          Fn::ImportValue:
              !Sub "${GeneralStack}:SNSTopic"
  ProcessLog:
    Type: "AWS::Logs::LogGroup"
    Properties:
      LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "Process" ] ]
      RetentionInDays: 60

  ClearQueue:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: clear_queue.lambda_handler
      Description: 'If the step function fails, clear the queue ready for a retry'
      MemorySize: 128
      Timeout: 15
      Role: !GetAtt EloquaRole.Arn
      Environment:
        Variables:
          USERENV:
            Ref: UserEnv
          ENV:
            Ref: EnvironmentType
      DeadLetterQueue:
        Type: SNS
        TargetArn:
          Fn::ImportValue:
              !Sub "${GeneralStack}:SNSTopic"
  ClearQueueLog:
    Type: "AWS::Logs::LogGroup"
    Properties:
      LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "ClearQueue" ] ]
      RetentionInDays: 60

  ClearS3:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: clear_s3.lambda_handler
      Description: 'If the step function fails, clear the S3 path ready for the retry'
      MemorySize: 128
      Timeout: 15
      Role: !GetAtt EloquaRole.Arn
      Environment:
        Variables:
          USERENV:
            Ref: UserEnv
          ENV:
            Ref: EnvironmentType
      DeadLetterQueue:
        Type: SNS
        TargetArn:
          Fn::ImportValue:
              !Sub "${GeneralStack}:SNSTopic"
  ClearS3Log:
    Type: "AWS::Logs::LogGroup"
    Properties:
      LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "ClearS3" ] ]
      RetentionInDays: 60

  StepFunctionError:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: step_function_error_mail.lambda_handler
      Description: 'An extra control to email if the step function does not complete as expected'
      MemorySize: 128
      Timeout: 15
      Role: !GetAtt EloquaRole.Arn
      Environment:
        Variables:
          USERENV:
            Ref: UserEnv
          ENV:
            Ref: EnvironmentType
      DeadLetterQueue:
        Type: SNS
        TargetArn:
          Fn::ImportValue:
              !Sub "${GeneralStack}:SNSTopic"
  StepFunctionErrorLog:
    Type: "AWS::Logs::LogGroup"
    Properties:
      LogGroupName: !Join [ "/", [ "", "aws", "lambda", !Ref "StepFunctionError" ] ]
      RetentionInDays: 60

  EloquaTrigger:
    Type: "AWS::Events::Rule"
    Condition: IsProd
    Properties:
      Description: Runs the Eloqua Step Function
      Name: !Sub "${EnvironmentType}-eloqua-${AWS::Region}"
      ScheduleExpression: "cron(2 2 * * ? *)"
      State: "ENABLED"
      Targets:
        - Arn: !Ref EloquaStepFunction
          Id: EloquaStep1
          RoleArn:
            Fn::ImportValue:
              !Sub "${SecurityStack}:StepFunctionTriggerRoleArn"

  EloquaStepFunction:
    Type: "AWS::StepFunctions::StateMachine"
    Properties:
      StateMachineName: !Sub "${EnvironmentType}-eloqua"
      RoleArn: !Sub "arn:aws:iam::${AWS::AccountId}:role/service-role/StatesExecutionRole-${AWS::Region}"
      DefinitionString:
        !Sub
          - |-
            {
              "Comment": "Put Eloqua activities and dates on a queue and put the data in S3",
              "StartAt": "eloqua-put-on-queue",
              "States": {
                "eloqua-put-on-queue": {
                  "Type": "Task",
                  "Resource": "${QueueArn}",
                  "Next": "eloqua-get",
                  "Catch": [ {
                    "ErrorEquals": ["States.ALL"],
                    "Next": "clear-s3"
                   } ]
                 },
                "eloqua-get": {
                  "Type": "Task",
                  "Resource": "${ProcessArn}",
                  "Next": "ChoiceStateMessagesOnQueue",
                  "Catch": [ {
                    "ErrorEquals": ["States.ALL"],
                    "Next": "clear-s3"
                  } ]
                },
                "clear-s3": {
                  "Type": "Task",
                  "Resource": "${ClearS3Arn}",
                  "Next": "clear-queue"
                },
                "clear-queue": {
                  "Type": "Task",
                  "Resource": "${ClearQueueArn}",
                  "Next": "send-email-failure"
                },
                "send-email-failure": {
                  "Type": "Task",
                  "Resource": "${StepFunctionErrorArn}",
                  "Next": "finish"
                },
                "finish": {
                  "Type": "Pass",
                  "Result": "Nothing to do",
                  "End": true
                },
                "ChoiceStateMessagesOnQueue": {
                  "Type" : "Choice",
                  "Choices": [
                  {
                    "Variable": "$.messagesonqueue",
                    "StringEquals": "Yes",
                    "Next": "eloqua-get"
                  },
                  {
                    "Variable": "$.messagesonqueue",
                    "StringEquals": "No",
                    "Next": "finish"
                  }
                  ],
                  "Default": "DefaultState"
                },
                "DefaultState": {
                  "Type": "Fail",
                  "Cause": "No Matches!"
                }
              }
            }
          - {QueueArn: !GetAtt [ Queue, Arn ],
             ProcessArn: !GetAtt [ Process, Arn ],
             ClearQueueArn: !GetAtt [ ClearQueue, Arn ],
             ClearS3Arn: !GetAtt [ ClearS3, Arn ],
             StepFunctionErrorArn: !GetAtt [ StepFunctionError, Arn ]}

  EloquaRole:
    Type: "AWS::IAM::Role"
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          -
            Effect: "Allow"
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      RoleName:
        !Sub '${EnvironmentType}-lambda-eloqua-${AWS::Region}'
      Policies:
        -
          PolicyName:
            !Sub '${EnvironmentType}-lambda-eloqua-${AWS::Region}'
          PolicyDocument:
            Version: '2012-10-17' # Policy Document
            Statement:
              -
                Effect: "Allow"
                Action:
                  - "ssm:GetParameters"
                Resource:
                  - !Sub 'arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${EnvironmentType}/eloqua/creds'
              -
                Effect: "Allow"
                Action:
                  - "logs:CreateLogGroup"
                  - "logs:CreateLogStream"
                  - "logs:PutLogEvents"
                  - "sqs:ListQueues"
                Resource:
                  - "*"
              -
                Effect: "Allow"
                Action:
                  - "s3:List*"
                Resource:
                  - !Sub 'arn:aws:s3:::economist-analytics-${AWS::Region}-*'
              -
                Effect: "Allow"
                Action:
                  - "s3:Get*"
                  - "s3:Put*"
                  - "s3:DeleteObject"
                Resource:
                  - !Sub 'arn:aws:s3:::economist-analytics-${AWS::Region}-*/eloqua/*/staging/*'
              -
                Effect: "Allow"
                Action:
                  - "sns:Publish"
                Resource:
                  - !Sub 'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${EnvironmentType}*'
              -
                Effect: Allow
                Action:
                  - "sqs:CreateQueue"
                  - "sqs:ReceiveMessage"
                  - "sqs:DeleteMessage"
                  - "sqs:GetQueueAttributes"
                  - "sqs:SendMessage"
                  - "sqs:PurgeQueue"
                Resource:
                  - !Sub "arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${UserEnv}-lambda-eloqua-activities.fifo"

Outputs:
  EloquaRole:
    Value: !Ref EloquaRole
    Export:
      Name: !Join [ ":", [ !Ref "AWS::StackName", EloquaRole ] ]

Thanks for submitting this!
@kddejong submitted a fix for this that checks to make sure the type is supported.  Should work now.


IconPacks for Uno Platform

[Feature request]
Could be nice to be able to use IconPacks for the Uno Platform.

@byrialsen Sounds interesting, I'll look for this. But need some learning about Uno and how to create packages for it.

I am creating MahApps Icon pack browser (from the browser already available in this repo) in Uno platform. I have UWP version running. If there is support for Uno, probably this application will support all the platforms ( IOS, Android, WebAssembly, UWP
and Linux).
Design will be polished based on different form factor.

Thanks

@pdm19882004 Can you point me to the repo? It would be nice to see the code. 👍

@pdm19882004 Can you point me to the repo? It would be nice to see the code. 👍

I am currently Uploading it and will post the repo link here.
Thanks

https://github.com/pdm19882004/MahAppIcons
(First commit in Github. Sorry if made any mistakes and I hope my Naming of project is not the problem like taking credit of this Project or something)

Hi @ParthMandalia
The idea is great and your first draft is IMO beautiful. But there is more to consider, so for now we want to stick with the current design. Nevertheless we can discuss yours when the uno support is implemented. :-)

(First commit in Github. Sorry if made any mistakes and I hope my Naming of project is not the problem like taking credit of this Project or something)

Please do us (and you) a favour: Instead of creating your own repo for it and copy / paste all the stuff there, fork this repo and create a new branch for your idea. This would make it possible to merge it if it is ready some day.
Happy coding
Tim

I was able to partially build Uno class library for this project. I have only used one icon pack (BoxIcon) to test the project as of now. Since there are many projects to build (15 projects {3 projects with Android, UWP, WASM, IOS, Mac each}), there is a randomly generated bug (Uno.SourceGenerationTasks.targets) in any one of the project and entire library fails to build. Should I upload the project solution here? Note: I have to remove all the WPF components from the project.

I was able to successfully compile the MahAppsIcons UNO class library locally (without github). And trying to link the project with my develop branch.

I was able to successfully compile the MahAppsIcons UNO class library locally (without github). And trying to link the project with my develop branch.


V2 allocation optimizations

This PR applies some easy win optimizations trying to reduce the Object[] allocation in V2. Results are not as good as expected, given that they mostly attack incorrect ArrayList initializations while the actual improvement will be trying to reduce how many ArrayList are created. The latter is something I would like to achieve, but the changes required are not as simple as the ones included here.
Allocations pre change:

Allocations post change:

Notice that:

The improvement is mainly in the gray areas
Flamegraphs show a relative performance
The difference in outside TLAB allocation
Charts were generated after running queries for 5 mins, but I've only made one execution per case, so I'm not sure about repeatability

cc @walterddr @Jackie-Jiang

Codecov Report

Merging #11112 (66bd4da) into master (35d7a8f) will decrease coverage by 0.01%.
The diff coverage is 0.00%.

@@            Coverage Diff             @@
##           master   #11112      +/-   ##
==========================================
- Coverage    0.11%    0.11%   -0.01%
==========================================
  Files        2203     2203
  Lines      118165   118192      +27
  Branches    17879    17882       +3
==========================================
  Hits          137      137
- Misses     118008   118035      +27
  Partials       20       20

Flag
Coverage Δ

integration1temurin11
?

integration1temurin17
?

integration1temurin20
0.00% <0.00%> (ø)

integration2temurin11
?

integration2temurin17
?

integration2temurin20
?

unittests1temurin17
?

unittests1temurin20
?

unittests2temurin11
0.11% <0.00%> (-0.01%)
:arrow_down:

unittests2temurin17
0.11% <0.00%> (-0.01%)
:arrow_down:

unittests2temurin20
0.11% <0.00%> (-0.01%)
:arrow_down:

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

Impacted Files
Coverage Δ

...not/core/operator/query/SelectionOnlyOperator.java
0.00% <0.00%> (ø)

...pinot/query/runtime/operator/HashJoinOperator.java
0.00% <0.00%> (ø)

...inot/query/runtime/operator/TransformOperator.java
0.00% <0.00%> (ø)

.../query/runtime/operator/exchange/HashExchange.java
0.00% <0.00%> (ø)

:mega: We’re building smart automated test selection to slash your CI/CD build times. Learn more


How can I install a new language next to the current language in Business Central?

Could you elaborate on this question?
Are you trying to add a language that has not previously been part of Business Central and build a translation app?

Thank you for your response.
Currently I am working in a BC-nl (the Netherlands) image,  the fieldcaptions are translated to Dutch automatically.
How can I retrieve the fieldcaptions for other languages as well in the Dutch version?
Is this possible or do I have to change fieldcaptionreferences to labels?

To extend this question, what would be the best way to implement a multilingual version of Business Central? Will localizations become extensions?

We are planning to make localizations into extensions. Though long term, since this is a large effort.
Please see this information regarding translations: https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/devenv-work-with-translation-files#translation-and-localization-apps


How to change value programatically?

I have tried following, but it seems doesn't work. Through according to documentation it should.
var dateInput = document.querySelectorAll('input[name="date"]')[0];
dateInput.value = '2016-08-01';

Also I have tried to trigger 'change' event:
triggerEvent(dateInput, 'change');

function triggerEvent(element, eventName) {
    var event; // The custom event that will be created

    if (document.createEvent) {
        event = document.createEvent("HTMLEvents");
        event.initEvent(eventName, true, true);
    } else {
        event = document.createEventObject();
        event.eventType = eventName;
    }

    event.eventName = eventName;

    if (document.createEvent) {
        element.dispatchEvent(event);
    } else {
        element.fireEvent("on" + event.eventType, event);
    }
}

Then I have tried:
DOM.constructor(dateInput).fire("change");

Solved by dateInput.setAttribute('value', '2016-08-01');.

@rafis please read my comments at https://github.com/chemerisuk/better-dateinput-polyfill/issues/80 - they can be useful


Issues with new stylesheet

I appreciate the theme being updated to better support qBittorent v4.5 but I've spotted a number of regressions/oversights.
Edit: Forgot to mention I'm on Windows 11, Qt5

Buttons no longer have a background so are not clear that they are buttons, for example see the OK button in the update dialog in the screenshot.
Backgrounds for tabs, such as in the about dialog, look out of place.
Links, as seen in the about dialog, are too saturated to be easily readable.
Mouse over highlighting of text darkens enough to become harder to read.
Personal opinion: the new scroll bars are rather ugly and do not indicate that they are scroll bars (missing up down arrows as they were before).
Personal opinion: The square download bars are also rather ugly and don't fit the rounded icon design in the rest of the UI.

Thanks for the suggestions, Yes, I also planned to rewrite the stylesheet (on the repo's TODO list), but I want an implementation which can follow a certain template and support more themes (onedark, nord, catpuccin, etc) in the future using a simple script.

Personal opinion: the new scroll bars are rather ugly and do not indicate that they are scroll bars (missing up down arrows as they were before).

I couldn't figure out how to implement the arrows in the stylesheet for the new version, since I used custom icons in the old styles, I used those icons.
But qBittorrent has had a complete new design for their project which I like and removed all of our own icons, but didn't know why the arrow keys showed up white, so I just hid it for the time being. I'll also try to fix this.

Personal opinion: The square download bars are also rather ugly and don't fit the rounded icon design in the rest of the UI.

Can you explain this more? I don't quite understand the term "square download bars". Are there other designs for download bars? can you link those for me?
You're right on all of your points and I'll look more into this when I have more time on my hand.
Other styling suggestions are also welcome in this issue for the future.
Best Regards, Mahdi

Thanks for hearing me out, I was quite quick on the draw for criticisms when the update was rolled out.

Can you explain this more? I don't quite understand the term "square download bars". Are there other designs for download bars? can you link those for me?

It is a rather subtle effect, the corner pixels are removed and a slight gradient applied. I also find the text colouring a lot more readable here:

I've reverted to the previous version of the theme with qBittorent v4.5.0 as even with the bugs I find the visual style more readable and compact (possibly a Windows specific thing, your screen shots look a lot more consistent and compact). Happy to continue with suggestions or even collaborate if I can figure out the stylesheets and don't need to buy Qt dev tools.

I agree the other comments here as well as the two referenced issues. I like some of the changes but it definitely has some issues, although I don't think it needs that much tweaking to be great. IMO it's about readability, colors, and information density.
(I'll also note I'm on Firefox 112.0 for Win10x64, since I'm not sure what parts may be OS-dependent.)

A lot of things need some clearer borders (or really any borders). The search tab is probably the one that needs it the most, since there's multiple elements that are just floating words in a void where you can't see what parts are clickable.

I don't know that I like the inactive tabs on the search page being light gray? Looks very odd and also isn't immediately readable to me when there's only two tabs (obviously when there's more your brain can quickly just go "the active one is the one that looks different"). I think they'd probably look better with subtle line borders instead of just using different background colors, but maybe that's not possible.

Again, not sure what's possible, and I don't know that this quick mockup I made is amazing either but it sort of illustrates what I'm picturing instead of "adjacent rectangles with light gray backgrounds".

I feel like these colors (and the ones in the status sidebar) need to be more pastel/desaturated to match the normal Dracula color scheme. More like this:

I don't know exactly what I'm doing with regards to color but I the current ones just seem way too vibrant for a Dracula theme? (Ignore the fact that I lazily desaturated the background as well.)

The checkboxs also look at-odds with the rest of the theme, but it also looks like some windows default so I don't know what control you have over them. Whenever I'm deleting a torrent the bright contrasting white box catches my eye and makes me think it might be checked.

Maybe something similar to the Dracula theme for Obsidian, if possible?

The only other thing is the spacing between rows of statuses/categories/tags/active torrents/search results seems a bit too large IMO.
That's all I can think of. Still the best theme in its current state though, so thanks for the work!


Replace remaining usages of the word "stage" in the context of ECS

How can Bevy's documentation be improved?
As of Schedule V3, we now design system schedules, not stages. However there's still a few places where the word stage is mentioned. These can be found with a simple recursive directory search.
Example
https://github.com/bevyengine/bevy/blob/f76b3c4230e890e3cdeb01c26809cf4bde8d26f4/errors/B0003.md#L57-L67

Let me know if you need help figuring out how to replace any existing usages!


Add Support for Enhanced SCSt Error Handling

bind input message, raw record to retry context
support recover without retry (recover after a single shot)

requires https://github.com/spring-projects/spring-integration/pull/2091 + polishing commits

Gary, looks like we haven't finished this discussion as well:
https://github.com/spring-projects/spring-integration-kafka/pull/163#discussion_r112732812

Will take a look one more time locally and 99% merge. Finally 😉

@garyrussell , is there anything else to do here?
Maybe we can merge already?
Thanks

Sounds good; maybe we can build 2.1.1 early.

Merged as https://github.com/spring-projects/spring-integration-kafka/commit/236f95b847bfed61fdc59c97a1f53920b246915c and cherry-picked to master as https://github.com/spring-projects/spring-integration-kafka/commit/1de7b67013cca1e5f9cd6e54e49709c90553385b


Jekyll Server

Is it possible to host in IIS and have the paths work without needing to uncomment/comment the subdirectory in yaml?
If-not, find out how to do a custom port #: 4470

Custom port is already implemented


Floodlight Camera not working

Getting an authentication error on Floodlight cams only:
2021-07-23 16:18:05 ERROR (MainThread) [aiohttp.server] Error handling request
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/aiohttp/web_protocol.py", line 422, in _handle_request
resp = await self._request_handler(request)
File "/usr/local/lib/python3.9/site-packages/aiohttp/web_app.py", line 499, in _handle
resp = await handler(request)
File "/usr/local/lib/python3.9/site-packages/aiohttp/web_middlewares.py", line 119, in impl
return await handler(request)
File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 60, in security_filter_middleware
return await handler(request)
File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 77, in forwarded_middleware
return await handler(request)
File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 24, in request_context_middleware
return await handler(request)
File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 78, in ban_middleware
return await handler(request)
File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 144, in auth_middleware
return await handler(request)
File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 135, in handle
result = await result
File "/usr/src/homeassistant/homeassistant/components/camera/init.py", line 507, in get
if not camera.is_on:
File "/config/custom_components/eufy_security/camera.py", line 335, in is_on
return self.entity["enabled"]
KeyError: 'enabled'
2021-07-23 16:18:07 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [140224870635312] Error handling message: Unknown error
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/websocket_api/decorators.py", line 25, in _handle_async_response
await func(hass, connection, msg)
File "/usr/src/homeassistant/homeassistant/components/camera/init.py", line 604, in ws_camera_stream
camera = _get_camera_from_entity_id(hass, entity_id)
File "/usr/src/homeassistant/homeassistant/components/camera/init.py", line 230, in _get_camera_from_entity_id
if not camera.is_on:
File "/config/custom_components/eufy_security/camera.py", line 335, in is_on
return self.entity["enabled"]
KeyError: 'enabled'
2021-07-23 16:18:07 WARNING (MainThread) [homeassistant.components.http.ban] Login attempt or request with invalid authentication from <IP_ADDRESS> (<IP_ADDRESS>). (Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15)

This line is creating an issue, i will fix it soon (on vacation for next 3 days, not that soon :-))
self.entity["enabled"] should be replaced with just True

If this is all you need @fuatakgun
#19

Merged

We should be good here, resolving.


json file does not open for terminal settings

Thanks for the good description. Unfortunately, I cannot find a settings.json. It willl not open as described:

Launch Windows Terminal and then select the small downward-facing arrow in the title bar. This will open a pull-down menu that lists the available profiles on your system (for example, Windows PowerShell and Command Prompt) and some other options. Select Settings, and the settings.json file will open in your default text editor.

However, it ould be the case that this is restricted by administrator settings made by my company.
Is there a way to use json file settings anyway (e.g. if json file is placed in a user related folder)?
Best regards,
Seb
ps.
Windows 10 Enterprise
Version 1809

Document Details
⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

ID: f7ba9c54-6f4a-37e7-7b29-c41b2d7700b1
Version Independent ID: 23155e99-d61f-9bab-261c-46050ece6932
Content: Windows Terminal Color Schemes
Content Source: TerminalDocs/customize-settings/color-schemes.md
Product: dev-environment
Technology: windows-terminal
GitHub Login: @cinnamon-msft
Microsoft Alias: cinnamon

So the settings file should be located at something like
C:\Users\<username>\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json

(or if you're using Preview)
C:\Users\<username>\AppData\Local\Packages\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\LocalState\settings.json

Can you just open that file in an editor on it's own? Or do you need the file to be placed in a totally different location?


Fix_connect

Proposed change

Fix Wrong DI of HassClient
Type of change

[ ] Dependency upgrade
[ ] Bugfix (non-breaking change which fixes an issue)
[ ] New feature (which adds functionality to an existing integration)
[ ] Breaking change (fix/feature causing existing functionality to break)
[ ] Code quality improvements to existing code or addition of tests

Additional information

This PR fixes or closes issue: fixes #
This PR is related to issue:
Link to documentation pull request:

Checklist

[ ] The code change is tested and works locally.
[ ] Local tests pass. Your PR cannot be merged unless tests pass
[ ] There is no commented out code in this PR.
[ ] I have followed the [development checklist][dev-checklist]
[ ] The code compiles without warnings (code quality chek)
[ ] Tests have been added to verify that the new code works.

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

[ ] Documentation added/updated for www.home-assistant.io

Codecov Report

Merging #461 (65641f2) into remodel (e7f6102) will decrease coverage by 0.19%.
The diff coverage is 0.00%.

@@             Coverage Diff             @@
##           remodel     #461      +/-   ##
===========================================
- Coverage    55.97%   55.77%   -0.20%
===========================================
  Files           97       97
  Lines         4802     4803       +1
  Branches       726      726
===========================================
- Hits          2688     2679       -9
- Misses        1890     1897       +7
- Partials       224      227       +3

Flag
Coverage Δ

unittests
55.77% <0.00%> (-0.20%)
:arrow_down:

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

Impacted Files
Coverage Δ

...c/DaemonRunner/DaemonRunner/NetDaemonExtensions.cs
0.00% <0.00%> (ø)

...rc/Daemon/NetDaemon.Daemon/Daemon/NetDaemonHost.cs
50.98% <0.00%> (-1.19%)
:arrow_down:

Continue to review full report at Codecov.

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


Fruitfly 1.2

Main improvements in this PR:

Fixes/Features (commit 098f7e3ddf03fc2454053d0cd50a9827b2729b98 , PR 382):

resolves issues reported in #5, by manually fixing invalid gene ids
change compartment abbreviation from p to x, to sync with changes made in Human-GEM PR 341
update ortholog pairs from Alliance of Genomes to ver 5.1.1

Style (PR #4):

add .gitattributes to ensure consistent LF (\n) line endings
add citation
rename branches: master --> main, devel --> develop

Could you also mention (perhaps in the README) which version of Human-GEM this is based on?

Fruitfly-GEM and other animal GEMs are dependent on Human-GEM and always updated with the latest version of the template. Once updated and exported by the master script, the version of Human-GEM as well as other dependencies are archived here by default.