Changelog¶
2.4.3 - December 25, 2024¶
✨ Improved¶
Add typing for the
CluGroupdecorator.Update
sdsstoolsto 1.9.1.
2.4.2 - December 23, 2024¶
🔧 Fixed¶
Do not require keywords when the schema passed is a Pydantic model.
2.4.1 - December 23, 2024¶
🔧 Fixed¶
Do not hardcode
is_file=TrueinBaseActor.load_schema().
2.4.0 - December 22, 2024¶
💥 Breaking changes¶
Removed the
loopargument fromBaseClient.Renamed
clu.model.BaseModeltoCluModelto avoid confusion withpydantic.BaseModel.
🚀 New¶
#121 Support passing a
pydantic.BaseModelsubclass toModel.
🔧 Fixed¶
Use
datetime.datetime.now()instead ofutcnow().Prevent case when incoming message headers may not be present.
2.3.1 - November 27, 2024¶
🏷️ Changed¶
Change the error message when a command does not exist or cannot be parsed by
ClickParser.
2.3.0 - November 19, 2024¶
✨ Improved¶
Add the option to raise the error when a command fails in
ClickParserinstead of only logging it.
⚙️ Engineering¶
Use
uvfor packaging and update workflows.
2.2.7 - May 20, 2024¶
✨ Improved¶
CluGroupnow inherits fromClickAliasGroupto allow for aliases in the CLI.
2.2.6 - March 26, 2024¶
✨ Improved¶
Removed use/setting of the event loop in
BaseClient.__init__().
2.2.5 - March 19, 2024¶
✨ Improved¶
AMQP
REPLYlog messages now include the header of the message.
🏷️ Changed¶
#120 Callbacks that are synchronous functions are now called immediately instead of being scheduled with
call_soon().
2.2.4 - February 26, 2024¶
✨ Improved¶
Log the command string when a new command is received by an actor.
2.2.3 - January 20, 2024¶
✨ Improved¶
#119 If an exception object is passed to
BaseActor.write(), the filename and line number where the exception where raised are included in the output. The user can choose what traceback frame to output by passingtraceback_frametowrite().
🔧 Fixed¶
Handle cases when a message tries to be pushed to an non-existing exchange.
⚙️ Engineering¶
Update workflows and docs building.
2.2.2 - November 10, 2023¶
✨ Improved¶
Prevent multiple reconnections when using the
AMQPClientcontext manager.
2.2.1 - November 10, 2023¶
🚀 New¶
AMQPClientnow supports an asynchronous context manager that starts the client and closes the connection on exit.
2.2.0 - August 25, 2023¶
🚀 New¶
Added support for tasks. Tasks are coroutines that can be commanded remotely and receive a simple dictionary payload. They don’t provide command completion tracking or replies to users. See more here.
🔧 Fixed¶
In
ActorHandler, error messages are output as"e"instead of as"f".Start the file logging even if a custom log instance is provided to
BaseClient.
⚙️ Engineering¶
Use
rufffor linting.Use
sphinx_autodoc_typehintsand updated pygments in documentation.
2.1.3 - July 27, 2023¶
✨ Improved¶
Added
write_to_logargument toBaseClient.write()to decide whether a reply should be written to the log. Changed several commands (get-command-model,help) to emit replies without logging them.
2.1.2 - July 20, 2023¶
⚙️ Engineering¶
Updated
unclickto 0.1.0b5.
2.1.1 - July 13, 2023¶
✨ Improved¶
Allow to add a model to a
ModelSetafter initialisation.Flush messages after printing them to the CLU CLI.
2.1.0 - June 21, 2023¶
🚀 New¶
#117 Added a
WebsocketServerclass to implement a pass-through websocket client-server connection to the AMQP exchange.
✨ Improved¶
AMQPClientcan be called without aname, in which case a unique random one will be generated.
2.0.2 - May 24, 2023¶
🔧 Fixed¶
Prevent commands sends to the CLU CLI to block until finished.
2.0.2b1 - May 23, 2023¶
⚙️ Engineering¶
Remove pin on
setuptoolsversion.
2.0.1 - March 12, 2023¶
🚀 New¶
Added
AMQPClient.add_reply_callback()which allows to register callback functions that are called with anAMQPReplyobject every time a reply is received. These replies are not filtered and the callback is called for each valid reply.
2.0.0 - March 10, 2023¶
💥 Breaking changes¶
By default
AMQPClient.send_command()will await the command itself when the method is awaited. This means thatcmd = await client.send_command('my_actor', 'ping')will await until thepingfinishes and the replies are received. The previous behaviour can be forced withawait_command=False, e.g.,cmd = await (await client.send_command('my_actor', 'ping', await_command=False)). In general this should not be a breaking change since awaiting a done command will return immediately, but it’s marked as breaking since in some corner cases there could be some unexpected behaviour.
✨ Improved¶
Added an
internalargument inCluCommandthat marks the received command as internal.Bump
unclickto0.1.0b4.
🏷️ Changed¶
When a command status changes to running, the status is emitted as internal.
2.0.0b2 - March 10, 2023¶
🔧 Fixed¶
Fixed asserting of
command_idanduser_idin testing module.
2.0.0b1 - March 10, 2023¶
💥 Breaking changes¶
Removed support for Python 3.7.
🚀 New¶
Support Python 3.11.
Use
aio_pika>=9.0.0andaiormq>=6.6.4.Support internal replies that are not shown in the CLI. Modified some command to use internal replies.
Added
get-command-modelcommand that uses unclick to return a JSON representation of a command or the entire command parser. This can be used to create a programmatic API that interfaces with an actor using command strings.Allow to filter by actor(s) in the CLI.
⚙️ Engineering¶
Added
MessageCodeenumeration.
1.9.2 - January 24, 2022¶
✨ Improved¶
The
clickcontext object can now be access asCommand.contextif theclickparser is being used.
1.9.1 - December 2, 2022¶
🔧 Fixed¶
Deal with replies without value in
MockReplyList.
1.9.0 - October 19, 2022¶
🚀 New¶
#111 If a
LegacyActoruses the Click parser, and a connection to Tron is defined, adds atron-reconnectcommand that can be used to force recreating the connection from the actor to Tron.
🔧 Fixed¶
Avoid setting the event loop on init in
CallbackMixIn. This caused the event loop to not be running in some cases whennotify()was invoked.Reworked how
TronConnectionuses the reconnecting protocol so that it actually reconnects.
1.8.2 - September 15, 2022¶
🔧 Fixed¶
#110 If the content of a keyword in
LegacyActoris empty, output the keyword without the equal sign (e.g.,testinstead oftest=).
1.8.1 - September 1, 2022¶
💥 Breaking changes¶
Removed the
create_setup.pyfile. Poetry should now support all its use-cases.
🚀 New¶
Added a
KeywordStorethat stores each time a keyword was output. It can be enabled by passingstore=Truewhen instantiating an actor and accessed asactor.store. See the documentation for more details.Added
cancel_command(),get_current_command_name(), andget_current_command_name()to click parser.
1.7.0 - August 14, 2022¶
💥 Breaking changes¶
The client model for an actor is now updated if the actor outputs a property that is not in its schema. This is not necessarily a breaking change, but it modifies the expectation that the client will validate replies against the actor schema. With this change we indicate that validating and respecting its own schema is a task for the actor and not for the client. There are at least a couple cases for which having the client enforce the actor schema was problematic: if the actor has
patternPropertiesthose are legal properties but are not updated in the client model; and if the actor decides to output a non-validated message. With this change, if the client receives a property that is not in the actor schema, a newPropertyis created int eh actorModeland its value is updated. ThatPropertyhasProperty.in_schema=Falseto indicate that the property has not been validated. Note that this change does not affect theTronConnectionmodels since those are defined by actorkeys.
🚀 New¶
Command.write()can now be called with alogginglevel instead of a string message code. For exampleCommand.write(logging.DEBUG, text="Hi")is equivalent toCommand.write("d", text="Hi").
🔧 Fixed¶
Fixed a
ConnectionResetErrorwhen closing the connection to aTCPStreamServer.
1.6.2 - May 25, 2022¶
✨ Improved¶
The commander of a command sent to Tron is now
actor.actorby default, instead ofactor.actor.target_actor.Trying to change the status of a done command will issue a
CluWarningand return, instead of raising aRuntimeError.
🔧 Fixed¶
Prompted by COS-74, it was possible for a reply from a command with the same MID but different commander to be processed and mark a running command as complete. Now we are checking now only the MID but the commander as well.
1.6.1 - May 11, 2022¶
🚀 New¶
New
Command.child_command()method that allows to run a child command in the same actor already runningCommand. The practical effect is to run another of the same actor’s commands as if it were part of the currentCommand.
✨ Improved¶
Allow AMQP clients to listen to their own replies. This allows an actor sending a command to itself to know when the command is done.
Command.send_command()now accepts anew_commandargument. Whennew_command=True, the new command will receive a new command ID and the commander ID will be the actor running the command (to all effects this is equivalent toBaseClient.send_command()). Ifnew_command=False, the command ID and commander of the current actor will be used. In this case, and if the target actor is the same actor running the current command, consider usingCommand.child_command()instead.
1.6.0 - April 25, 2022¶
🚀 New¶
Actors can use
set_message_processor()to set a function that will receive the message dictionary before being output to the users and can make modification on before it’s emitted. This is useful, for example, to improve compatibility in actors that can be run as legacy or AMQP actors.
🧱 Support¶
Relax sdsstools dependency to
>=0.4.13. This is desirable since sdsstools is not yet at the 1.0 level and minor version changes block poetry.
1.5.8 - February 10, 2022¶
🔧 Fixed¶
#107 Add an alias
Reply.bodytoReply.messageto allow backwards compatibility.
1.5.7 - February 5, 2022¶
✨ Improved¶
Command.repliesis now a list ofReplyinstances with agetmethod. Replies are unified for all kinds of clients.
1.5.6 - January 6, 2022¶
🚀 New¶
#106
Commandnow accepts atime_limitargument that will mark it asTIMED_OUTand done after an interval.time_limitcan also be passed tosend_command().
✨ Improved¶
Command.actoris always typed as an actor type.
1.5.5 - December 14, 2021¶
🚀 New¶
Added a
FakeCommandthat writes to the log and that can be used when a command may not be present.
✨ Improved¶
#104 The existing
@cancellabledecorator did not work in subcommands. The decorator has been removed and now it’s possible to passcancellable=Trueto the command decorator (e.g.,@command.parser.command(cancellable=True)). This takes care of adding a--stopoption to the command. The underlying behaviour of command cancellation has not changed.
1.5.4 - November 26, 2021¶
🔧 Fixed¶
Do not try to update model when a keyword from Tron cannot be parsed.
1.5.3 - November 26, 2021¶
🔧 Fixed¶
Do not use a task to update the model. This caused failures when messges where being sent from a function called with an executor.
1.5.2 - November 7, 2021¶
🔧 Fixed¶
Fixed a bug in which commanders with multiple dot-separated components would not be correctly interpreted by
handle_reply()and the CLI.Command code
edoes not fail the command. This prevents cases of finishing/failing the command after it has already been failed.Improved the performance of the CLI by outputting all the parts of the message at once.
1.5.1 - November 6, 2021¶
🚀 New¶
Support Python 3.10.
✨ Improved¶
#101 The legacy actor now accepts command strings with a commander id (e.g.,
APO.Jose 10 status). The commander id is stored in theCommandobject. Added aCommand.send_command()that will call the remote command propagating the commander ID. For example, if a command has commanderAPO.Joseand sends a command toguider, theguideractor will receive a command with commanderAPO.Jose.guider.#102 When calling a model or property callback, ensure that the arguments sent are a frozen copy of the state of the model/property at the time of the callback. This prevents that if a model is updated twice in quick succession, the callback may receive only the second value. A consequence of this change is that the model callback now receives a flattened dictionary with all the model keywords as the first argument.
If not specified, a message with code
eorf, or an exception, will use the keyworderror.
1.5.0 - October 12, 2021¶
✨ Improved¶
#99 Add
exception_modulevalue to the output of an exception.sdss/sdsstools#29 Allow to pass a custom PyYAML loader in
from_config()that will be forwarded toread_yaml_file().Actors now accept
<actor> --helpwith the same result as<actor> help.Add
additional_propertiesparameter toLegacyActor.When a legacy actor starts, if there is a
TronConnectionavailable it will try to send ahub startNubs <actor>to initiate the connection.
🔧 Fixed¶
Use
clu.clientforTronConnection.send_command().If a command in a
LegacySurveyactor is left running after the client closes the connection, it would still try to output messages to it, causing asocket.send() raised exceptionerror. Now if the client exists the command continues running, but outputs to that client are ignored.
1.4.0 - September 27, 2021¶
🚀 New¶
#98 Add
unique()andcancellable()decorators for Click command parsers.
✨ Improved¶
#95 Cast all arguments to string in
ProxyClient.send_command().Add
get_keysparameter toLegacyActor.start()that is passed toTronConnection.start()Use
.clientas default commander forTronConnectionand{actor}.{target}for actor.
🔧 Fixed¶
Avoid and error in the callback when a connection to the TCP server is closed.
1.3.0 - September 17, 2021¶
💥 Breaking changes¶
#86
additionalPropertiesis set tofalseby default if not specified, including ifschema=Nonewhen initialising an actor.
🚀 New¶
#85 Added
BaseClient.proxy()method.
✨ Improved¶
#90 If an exception object is passed as a keyword in a command or actor message, it will be unpacked into the exception type and message.
Make the error output when a reply fails to validate more clear.
🔧 Fixed¶
#91 Documentation example for testing with CLU.
🧹 Cleanup¶
Add
invoke_mock_command()stub method toBaseClientto simplify type checking.
1.2.1 - June 20, 2021¶
🚀 New¶
🔧 Fixed¶
LegacyActornow accepts theconfigparameter sent byfrom_config().
✨ Improved¶
Subcommands now won’t write to the users when they start running.
1.2.0 - June 3, 2021¶
🚀 New¶
CommandandBaseActor.write()now accept asilentargument that ifTruewill execute the command normally and update the status and internal model, but won’t write to the user. Timed command can be run in silent mode the first iteration by initialising them withfirst_silent=True.
✨ Improved¶
#77 Child commands will never emit
:orfmessages that may be confused as the parent being done.Timed commands are run immediately when started.
from_config()now passes the configuration to the client__init__()so that it is accessible during initialisation.If a timed command takes longer to run than the interval at which the poller checks if new timed commands should be run, prevent it from being issued multiple times.
1.1.2 - May 31, 2021¶
🔧 Fixed¶
Revert previous changes to the typing of
Commandthat were causing problems, but keep the generic for the command future.
1.1.1 - May 30, 2021¶
🔧 Fixed¶
Correctly assign the type of the actor in a
Command.Fix error when
TopicListener.stop()is called and there is not an active connection.
✨ Improved¶
Device.start()now returnsself.#84
send_commandnow accepts multiple arguments before the keyword arguments. If they are passed, they will be concatenated to create the full command string. For example:client.send_command('my_actor', 'sum', '-v', 2, 4, command_id=5)is equivalent toclient.send_command('my_actor', 'sum -v 2 4', command_id=5)
1.1.0 - May 29, 2021¶
🚀 New¶
#82
send_commandnow accepts acallbackargument. If set, the callback will be called each time the actor replies and will receive the reply itself (AMQPReplyin case ofAMQPClient/Actorandclu.legacy.types.messages.ReplyforTron/TronConnection). Thanks to Florian Briegel for the idea.
✨ Improved¶
#81 Improve typing of
BaseCommandand command replies.In
TronConnection, do not fail with aParseErrorif one of the keywords cannot be parsed. Instead, issue a warning and move on to the next one.The CLI now checks that the preferred style (
solarized-dark) is available. Otherwise defaults topygmentsdefault style.Copy
Propertybefore notifying the callbacks. This prevents the value passed being updated in the time that it takes for the callback to go out.Property,BaseModel, andTronModelnow have alast_seenattribute that is updated with the Unix time when the model or property/key are updated.When the AMQP client is handling replies for a command, it will update the status every time it changes, not only when it is done or failed.
StatusCommandcallbacks now receive the status itself as an argument.
1.0.3 - May 20, 2021¶
✨ Improved¶
When tracking the status of a command sent to Tron, update the status with each received reply, and store all the replies.
When
as_complete_failercancels the tasks after an exception, suppress all possible exceptions, not onlyCancelledError, since the original exception will be raised again. Add tests foras_complete_failer.
1.0.2 - May 18, 2021¶
🔧 Fixed¶
#78 Fixes a bug in which an actor with a defined
TronConnectionthat had failed to start would still try to send commands to Tron.
✨ Improved¶
#79
TronConnectionnow uses aReconnectingTCPClientProtocolthat will try to keep the socket to Tron open, allowing Tron to restart without losing connection.
🧹 Cleanup¶
releaseswas misbehaving once we reached1.x, and its interpretation of semantic versioning was a bit too extreme. Instead, we are now using a Markdown file withmyst-parser. The previous changelog is still available here.
1.0.1 - May 16, 2021¶
✨ Improved¶
BaseActorreceives avalidateparameter that can be used to globally define whether the actor should validate its own messages against the model.
1.0.0 - May 12, 2021¶
🚀 New¶
Transition CLU to stable!
🧹 Cleanup¶
Upgrade
clickto^8.0.0.
The Pre-history¶
The changelog for versions previous to 1.0.0 can be found here.