-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support device selection, migrate CLI to Typer #12
Conversation
7d0202a
to
087913b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! But now the CLI is broken for me.
$ labelle --verbose a
[DEBUG] Read config file: ~/.config/dymoprint.ini
[DEBUG] Found single device
[DEBUG] <DEVICE ID 0922:1001 on Bus 001 Address 012>
manufacturer: Dymo
product: DYMO LabelManager PnP
serial: 10581529032012
configurations:
- <CONFIGURATION 1: 500 mA>
interfaces:
- <INTERFACE 0: Human Interface Device>
- <INTERFACE 1: Mass Storage>
[DEBUG] Recognized device as LabelManager PnP (no mode switch)
[DEBUG] Active device configuration already found.
[DEBUG] Opened HID interface: <INTERFACE 0: Human Interface Device>
[DEBUG] Printing label..
[ERROR]
Traceback (most recent call last):
File "~/repos/dymoprint/src/labelle/lib/utils.py", line 49, in system_run
yield
File "~/repos/dymoprint/src/labelle/cli/cli.py", line 351, in main
run()
File "~/repos/dymoprint/src/labelle/cli/cli.py", line 345, in run
dymo_labeler.print(bitmap)
File "~/repos/dymoprint/src/labelle/lib/devices/dymo_labeler.py", line 331, in print
self._functions.print_label(label_matrix)
File "~/repos/dymoprint/src/labelle/lib/devices/dymo_labeler.py", line 264, in _functions
assert self._device is not None
AssertionError
There are some problems in the surrounding code that should have been caught by mypy, so I opened #13. Sorry about that!!! Hopefully mypy will just work from here on out.
In terms of the UI layout, having the selector in the upper-left makes the window taller. I think it'd be more natural to place the selector to the left of the print icon, but no need to do that in this PR.
Not a big deal, but I'm not such a fan of declaring the private interfaces with a leading _
. The reason is that the benefit of most conventions is to decrease entropy, but this does the opposite. Now when I'm trying to remember a name or come up with a new name, it's another thing I must think about, and it seems to me like a very subjective decision. Probably you have a clear idea in your head, but it's not entirely clear to me. So it might slightly increase friction for other contributors, and it'll probably be up to you to maintain the private/public distinction. Please don't change anything though, we'll just see how the code evolves.
As for how to proceed, what do you think of merging or rebasing on #13, turning the CI green, and cutting a new release? It'd be nice to ensure that you can run the release workflow yourself.
Note: sorry for the many edits I had with this reply... I guess you got flooded by email notification.
I agree that UI is sub optimal. I think we should reshape the entire UI, but it is not in my focus at the moment, and I believe changing anything at the moment will be premature optimization, as things might change soon.
I agree. I think that at some point we had file with many functions, and it was hard to notice which was internal function and which function intended to be used from outside. While making latest changes, I also felt that I am slowly being trapped by these new convention, with no significant gain. So maybe we should indeed remove this in the near future. I'll keep it as it is now, since I want to merge my changes soon.
Sure. I would like to try this. I would need the keys for https://pypi.org/project/labelle/. |
087913b
to
739e757
Compare
There are no keys. I set things up with the new OIDC mechanism. GitHub Actions is trusted by PyPI, and it generates a certificate saying that a package upload request is coming from labelle-org/labelle under the release environment. And PyPI is configured to accept exactly such a certificate: So if everything is set up correctly, then all you have to do is "Draft a new release": Choose a new tag name according to semver and set to "Create new tag on publish": Click "Generate release notes" to get automatic release notes based on the merged PRs, add any additional notes, and hit "Publish release". That will trigger a pending Actions workflow to upload to PyPI that requires manual approval from a maintainer. Approve, then it will run, and should create a release. |
3b43eed
to
671eeea
Compare
Hmm, Line 194 in dd5b3b3
|
That should fix the mypy errors from Would you be able to revert the changes to pip install vendoring
vendoring sync (Alternatively, there's |
Any ideas about how to do device selection from the CLI? It'd be nice to get that sorted out before the next release. |
I'd like to point out that from GUI perspective, the printer must be known before the user starts their design as label printers vary in capabilities obviously. It was a very hard thing to do with existing code, as far as I can remember. One way to do it in CLI is to have a switch for listing all available printers, and another switch to select one of them for an actual print job. But for the reason stated above, perhaps we should consider another approach: Persistent printer configuration. One command line switch to set a printer, which will be remembered until reset into something else. This will be more in line with GUI experience and simplify batch job scripts. Better yet, a CLI switch for selecting a printer while the job is run, and the last used printer is to be treated as the default. |
Are you sure? The way I see things is that we have an abstract representation, e.g. "barcode, then some particular text, then QR code", and this representation works for any printer. It's just the rendering process from the abstract representation to the bitmap that requires knowledge of the printer. Perhaps the simplest way would be to use
Note that this makes it inconvenient to print alternately to multiple devices, since it requires editing a file each time. Perhaps in I could imagine a common use case would be having two or more LabelManager PnP devices, each with a different tape color. So it would be nice if we could distinguish between different devices of the same model. (This should be straightforward using the serial number.) @systeemkabouter, once we have both a CLI and GUI solution I think that will close computerlyrik/dymoprint#109. |
I think the user has to pick the printer first, and tape width / label size, so Labelle knows the dimensions and colors of a canvas. I'm against complicating the printer selection logic. I'm considering a few user cases now:
Here's my proposed algorithm:
This way, the casual user will unknowingly configure their only printer, and the industrial user will not print a batch of labels on a wrong printer by accident. I agree that "Printer identification string", whatever it might be, should be unique enough to differentiate between two printers of the same make and model. A serial number alone could be sufficient if only we knew for sure that all thermal printers have unique S/Ns. Some cheaper USB devices are known to not have unique S/Ns. |
This is wrong, since src is NOT a module. It seems that I added it for Python 2.7 compatibility a long time ago, so it's definitely no longer needed.
This is mainly coding convention alignment to other parts of the code, where internal methods and attributes are prefixed with underscore. In this specific top level class it is a rather off to have everything prefixed, but I think it is important that we stick to some coding conventions.
This line is a leftover from earlier commits
Currently 'actions' is only print button and an error label. In the future we might have actions such as 'save to image'.
We will soon need to use it from other functions
78cbd82
to
0e38a93
Compare
We present image in imagemagick as output from the PrintPreviewRenderEngine. This image object is of mode=RGBA, while invert only support RGB, so it needs to be converted.
Remove some bloat from cli.py and move output handling to a dedicated file.
The logic in this module does not use this enum yet, but for good order it should be there.
❯ labelle --help Usage: labelle [OPTIONS] COMMAND [ARGS]... ╭─ Options ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ --version Show application version │ │ --verbose -v Increase logging verbosity │ │ --test-pattern INTEGER Prints test pattern of a desired dot width [default: None] │ │ --output [printer|console|console_inverted|browser|imagemagick] Destination of the label render [default: printer] │ │ --install-completion Install completion for the current shell. │ │ --show-completion Show completion for the current shell, to copy it or customize the installation. │ │ --help Show this message and exit. │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─ Device Configuration ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ --device TEXT Select a particular device by filtering for a given substring in the device's manufacturer, product or serial number [default: None] │ │ --tape-size-mm INTEGER Tape size [mm] [default: None] │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─ Elements ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ --text TEXT Text, each parameter gives a new line [default: None] │ │ --qr TEXT QR code [default: None] │ │ --barcode TEXT Barcode [default: None] │ │ --barcode-type [code39|code128|ean|ean13|ean8|gs1|gtin|isbn|isbn10|isbn13|issn|jan|pzn|upc Barcode type [default: (code128)] │ │ |upca] │ │ --barcode-with-text TEXT Barcode with text [default: None] │ │ --picture PATH Picture [default: None] │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─ Design ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ --style [regular|bold|italic|narrow] Set fonts style [default: regular] │ │ --frame-width-px INTEGER Draw frame around the text, more arguments for thicker frame [default: None] │ │ --align [left|center|right] Align multiline text [default: left] │ │ --justify [left|center|right] Justify content of label if label content is less than the minimum or fixed length [default: left] │ │ --font TEXT User font. Overrides --style parameter [default: None] │ │ --font-scale FLOAT Scaling font factor, [0,100] [%] [default: 90] │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─ Label Dimensions ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ --min-length FLOAT Minimum label length [mm] [default: None] │ │ --max-length FLOAT Maximum label length [mm], error if the label won't fit [default: None] │ │ --fixed-length FLOAT Fixed label length [mm], error if the label won't fit [default: None] │ │ --margin-px FLOAT Horizontal margins [px] [default: 56] │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─ Commands ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ list-devices │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Update the list from the package's source [1]. I sorted the keys, to the sake of readability. [1] https://github.com/WhyNotHugo/python-barcode/blob/main/barcode/__init__.py#L35
I still don't understand. Change Amazing work with Typer!!! 🤩 |
This PR is pretty crazy. Before it made a lot more sense when you were refactoring everything, but I don't think it makes sense to have these two completely different features (USB device selection and Typer) in the same PR. Let's keep it for now, but not make this a habit. |
Who said text label is a must? What makes text any more important than, say, a QR code? I wanted to reflect that in the API, that text is just something that we add, with no assumptions that this is what most people do with labels. |
I totally agree in principle, but this is still a breaking change, and I don't see any necessity. Think of it from the user perspective. We're asking people to switch from dymoprint to Labelle, and then they try it out and it doesn't work in the same way. The interface has been like this for the entire lifetime of the dymoprint project. People would need to adapt their habits, and also they may have built scripts that they now have to adjust. I don't think it's that huge of a deal, and I agree that we should switch eventually, but the benefit of this seems the benefit over the disruption of introducing such a breaking change over the previous long-standing interface of many years shortly after a new release. This is also a reason I dislike these long PRs. This discussion is holding all your previous work hostage. How about this: let's convert it to |
This is done to avoid breaking compatibility.
ok, I agree with what you said. |
Note that following my change from |
We cannot execute any command, as long as text label is an argument and not an option. For now, we will hide this new functionality, and relase a new minor version. Then we can introduce a --text CLI option, and expose this command (and any future commands).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks @tomers!
@tomers, feel free to give the release process a try for v1.2.0. I hope it is extremely easy. If not, please let me know. |
Sure, @maresb. I am going for a 2 days vacation, so I would only be able to do it afterwards. If you want, and don't want to wait, you can release yourself, and I'll do the next release. |
Ok, sure, I'll take care of it then. Enjoy your vacation!!! 🏖️ |
This is a breaking change. It puts text on the same level as the other options like image or barcode. It is breaking because it now requires any text to be preceeded by `--text`. Ref: <labelle-org#12 (comment)> and below.
This reverts commit c767a0a. This changes --text from typer.Argument to typer.Option This is a breaking change. It puts text on the same level as the other options like image or barcode. It is breaking because it now requires any text to be preceeded by `--text`. Ref: <labelle-org#12 (comment)> and below.
This reverts commit c767a0a. This changes --text from typer.Argument to typer.Option This is a breaking change. It puts text on the same level as the other options like image or barcode. It is breaking because it now requires any text to be preceeded by `--text`. Ref: <labelle-org#12 (comment)> and below.
This reverts commit c767a0a. This changes --text from typer.Argument to typer.Option This is a breaking change. It puts text on the same level as the other options like image or barcode. It is breaking because it now requires any text to be preceeded by `--text`. Ref: <labelle-org#12 (comment)> and below.
No description provided.