| Commit message (Collapse) | Author | Age | Lines |
|
|
|
| |
We want to use ruff instead of pylint.
|
|
|
|
|
|
| |
We have used this in another project of ours and prefer its interface
over pip's and its toml configuration over setup.py. There should be no
functional change.
|
| |
|
|
|
|
|
|
|
|
|
| |
Some messages (like pastes) occur at exactly the same time and are
inserted into the database with the same timestamp. quarg will print
these messages in a seemingly random order.
Make sure to use the messageid (which should increase monotonically) to
order messages instead.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
argparse's parse_args() does not support intermixed arguments, making
the following invocation of quarg error out:
$ quarg -b foo hello -t privmsg world
quarg: error: unrecognized arguments: world
This can be very confusing to the user, so allow intermixing arguments
by using the parse_intermixed_args() method instead.
|
| |
|
|
|
|
|
|
|
|
| |
The cache_ok flag was added [1] in SQLAlchemy 1.4.14 and emits a warning
if not set to either True or False. Since DateTimeUTC should be fine to
cache, indicate True here.
[1] https://docs.sqlalchemy.org/en/14/core/custom_types.html#sqlalchemy.types.TypeDecorator.cache_ok
|
|
|
|
|
|
|
|
| |
Apparently this keyword is deprecated [1]. We're beginning to get very
tired of Python packaging standards and tooling, so for now just rely on
the distribution putting the manual in the right place.
[1] https://discuss.python.org/t/should-there-be-a-new-standard-for-installing-arbitrary-data-files/7853
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
| |
This will make sure that we will not run into errors caused by an
omission of a comma should sections ever be moved around in the future.
|
|
|
|
|
| |
This is the version we developed with, and we can't give guarantees for
any earlier ones.
|
|
|
|
|
|
| |
This should never have been added in the first place, since quarg is
supposed to work with both SQLite and PostgreSQL databases. Make sure
not to pull in more than we need to.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
If quarg is unable to find the database URL, it immediately exits with
an error message. This happens before parsing any arguments given on the
command line, meaning that users cannot access the built-in help page if
they have not yet created a config file.
This commit makes sure that command line arguments are parsed before
checking the config file so that --help can be used even without a
config file.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Quassel stores its timestamps as INTEGERs when using the SQLite backend. Since
SQLAlchemy expects strings here instead[1], we have to handle this manually.
This commit extends the existing process_result_value() function to handle a
conversion from a unix timestamp to a proper datetime object, makes sure that
the right impl is chosen for both SQLite and PostgreSQL, and adds the
process_bind_param() function which takes care of the conversion back to a unix
timestamp when binding values for SELECT statements.
[1] https://docs.sqlalchemy.org/en/14/core/type_basics.html#sqlalchemy.types.DateTime
|
|
|
|
|
|
|
| |
Whilst not recommended, quarg may happen to be used in conjunction with
head(1), tail(1), or any other program that will send SIGPIPE. This
commit makes sure that we close the database connection properly if we
receive that signal.
|
|
|
|
|
|
|
|
|
|
|
|
| |
This reverts commit efde2954efd636a617702ee1aefb8b1247c9cc5b.
After some more consideration, we feel that referring to modes here is
misleading and confusing. Compromise by keeping the -m flag, but
changing the variable name back to 'prefix' and making clear in the help
message that quarg will match against the "channel membership prefix", a
term that is used in the Modern IRC Client Protocol specification [1]
[1] https://modern.ircdocs.horse/#channel-membership-prefixes
|
|
|
|
|
|
| |
Users may want to cancel queries that are taking a long time. This
commit ensures that the database is left in a clean state and that quarg
exits immediately after closing the database connection.
|
|
|
|
|
|
|
|
|
| |
Instead of giving the user a screen full of backtraces, catch any errors
SQLAlchemy can run into when preparing or executing the query and report
only the error message to the user.
We include the print loop in the try/except block because an upcoming
commit will add a handler for KeyboardInterrupt.
|
|
|
|
|
|
|
| |
This commit cleanly separates the preparation, execution, and timing of
a query. When preparing this commit, we realized that the preparation of
the query was included in the timer calculation. This should not have
been the case and has been fixed.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Up until now we were relying on isoformat() to format timestamps when
printing messages, since that was a simple shortcut to a well-known
format. With the addition of timezone support, however, isoformat()
started adding the timezone offset to the timestamp. This makes
timestamps unnecessarily verbose.
This commit has the formatter use a custom ISO 8601-esque time format
instead which restores the behaviour previous to the introduction of
timezones.
|
|
|
|
|
|
| |
Quassel uses this message type only for very rare and mostly irrelevant
informational messages that users will most likely not be wanting to
search for.
|
|
|
|
|
| |
As mentioned in the previous commit, this change makes it possible to
select the first or last N matches in conjunction with the -l flag.
|
|
|
|
|
|
|
|
|
| |
This is useful if the user already expects a lot of matches but is only
interested in a limited number of them. An upcoming commit will
introduce the option to have quarg list matches in ascending or
descending order (currently we do not pick a default - effectively
listing matches in ascending timestamp order), making it possible to
select the first or last N matches.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Quassel uses UTC message timestamps in its database, but does not save
any timezone information along with them. Up until now, we were reading
those timestamps from the database naively - resulting in datetime
objects that could not be identified as UTC.
The same happened with timestamps we got from dateutil.isoparse. If the
user did not specify an offset explicitly, the timestamp would be parsed
and passed to the program "as is", effectively being interpreted as UTC
because they were compared to database timestamps.
This commit will ensure that the correct timezone is saved for every
datetime object we encounter. Timestamps from the database are marked as
UTC. If the user does not explicitly specify an offset, the timestamp is
assumed to be in local time.
Furthermore, when printing out message timestamps, make sure to convert
them to the user's local timezone first.
|
| |
|
|
|
|
|
| |
This will save the user a look at the program's manual and makes using
the program more convenient.
|
|
|
|
|
|
|
|
| |
Up until now it was only possible to give --around a range specified in
hours. Since most discussions on IRC tend not to last for multiple
hours, and one may only be interested in a few minutes of logs, this
commit adds the ability to specify a unit suffix that takes either 'm'
for minutes or 'h' for hours. If it is missing, 'h' is assumed.
|
|
|
|
|
| |
Previously quarg would simply echo the error message without any
context, making it harder to find exactly which option caused it.
|
|
|
|
|
|
| |
Previously this case was handled by the int() cast in the try/except
block but resulted in a confusing error message. Make clear to the user
what exactly went wrong.
|
|
|
|
|
|
|
|
|
|
| |
Group message matching into two main parts (context and timestamps) and
simplify the help text for each option. Rename 'query' to 'keyword' to
avoid confusion with SQL queries and IRC queries.
Additionally, change some option flags to better communicate the type of
option (upper-case ones are used less frequently) or to make sure no
future option clashes with a less-frequently used one.
|
|
|
|
|
|
|
|
|
| |
Whilst still not perfect, 'umode' signals more closely what this option
does. We do not plan to add matching on channel modes, so -m should be
fine here.
The original name for this option came from the column in the backlog
table, 'senderprefixes'.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
As this program interacts with quassel's database only, it does not have
access to any state the UI carries. Some types (such as DAYCHANGE,
IGNORED, BACKLOG, GROUP) seem to not be represented in the database at
all, most likely only set on data structures in memory by the
quasselclient application.
Some others make no real sense to include in an application like this,
which is more focused on human-readable messages and circumstances. For
example, INVALID, REDIRECTED, SERVERMSG, etc are all of less concern to
the average user than, say, matching on nicknames or buffers.
Therefore, ignore all of these until we find a good use for them.
|
|
|
|
| |
Using / here should be fine.
|
|
|
|
|
| |
These make more sense and are clearer if they're named after the command
line arguments that trigger them.
|
|
|
|
|
|
| |
Using --around does not make much sense if there is also a match on
--after or --before, since the range in --around would most certainly
take precedence. Disallow this behaviour.
|
|
|
|
|
|
| |
Sadly we can not yet rely on BooleanOptionalAction, since that was only
added in Python 3.9. Also remove the FIXME note, it seems that boolean
options like this trigger a standard default setting with argparse.
|
| |
|
| |
|
|
|
|
|
| |
We're going to need this for an upcoming commit that moves all
argparse.Action classes to its own file.
|
|
|
|
|
| |
Instead of adding another indentation level, exit early if a value or a
key can be ignored.
|
|
|
|
|
|
|
| |
The list of users that have quit or joined after a netsplit can become
quite large. Quassel itself cuts reporting off after printing 15 users,
so let's follow that. Note that this will not affect queries - the
search is performed against the whole netsplit message.
|
|
|
|
|
|
|
|
| |
Instead of defining a function for every message format that trivially
returns an f-string, have a generic partially-applied helper function
that applies the Message object as a dictionary to the format()
function. That way, we can inline the formatter definitions directly in
the FORMATTERS dictionary.
|
|
|