Skip to content

Commit

Permalink
Merge pull request #9 from ahyatt/eldev
Browse files Browse the repository at this point in the history
Add eldev and fix lint issues
  • Loading branch information
ahyatt authored Aug 31, 2024
2 parents 7936509 + ed22395 commit 068a69e
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 42 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: CI

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "*" ]

jobs:
test:
runs-on: ubuntu-latest
environment: Continuous Integration
strategy:
matrix:
emacs_version:
# 28.1 and 28.2 should be tested, but they are not working for reasons
# I haven't figured out yet, and I haven't been able to test manually
# for other reasons I haven't figured out yet.
- 29.1
- 29.2
steps:
- name: Set up Emacs
uses: jcs090218/setup-emacs@master
with:
version: ${{matrix.emacs_version}}

- name: Install Eldev
uses: emacs-eldev/setup-eldev@v1

- name: Check out the source code
uses: actions/checkout@v4

- name: Lint the project
run: |
eldev -p -dtT lint
- name: Test the project
run: |
eldev -p -dtT test
13 changes: 13 additions & 0 deletions Eldev
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
; -*- mode: emacs-lisp; lexical-binding: t -*-

(eldev-use-package-archive 'melpa)
(eldev-use-plugin 'maintainer)
(eldev-add-extra-dependencies 'test '(:package emacsql))
(eldev-add-extra-dependencies 'test '(:package kv))
(eldev-add-extra-dependencies 'emacs '(:package emacsql))
(eldev-add-extra-dependencies 'emacs '(:package kv))

;; To both deal with emacsql and built-in sqlite in various versions, we need to
;; weird things that package linting doesn't like. So we disable this specific
;; kind of linting.
(add-to-list 'eldev-lint-disabled 'package)
18 changes: 11 additions & 7 deletions triples-backups.el
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:
;; This provides backup functionality. The information about how and when to do
;; This provides backup functionality. The information about how and when to do
;; backups lives in the database itself, on a special entity `database'.

(require 'triples)

;;; Code:

(defun triples-backups-setup (db num-to-keep strategy)
"Set DB's backup strategy.
NUM-TO-KEEP is the number of backup files to keep. Older ones are
removed. STRATEGY is a symbol that corresponds to a function
`triples-backups-strategy-STRATEGY'. This function must always be
NUM-TO-KEEP is the number of backup files to keep. Older ones
are removed. STRATEGY is a symbol that corresponds to a function
`triples-backups-strategy-STRATEGY'. This function must always be
loaded before any client of this db calls
`triples-backups-maybe-backup', so adding your own may not always
be appropriate."
Expand All @@ -40,8 +42,10 @@ be appropriate."
:strategy strategy :last-update-time (time-convert (current-time) 'integer))))

(defun triples-backups-configuration (db)
"Returns the backup configuration set by `triples-backups-setup'.
If no one has ever run that on this database, `nil' is returned."
"Return the backup configuration set by `triples-backups-setup'.
If no one has ever run that on this database, nil is returned.
DB is the database to get the configuration for."
(triples-get-type db 'database 'backup))

(defun triples-backups-last-update-time (db)
Expand All @@ -57,7 +61,7 @@ default to the standard triple database given in
(strategy-func (intern (format "triples-backups-strategy-%s"
(plist-get backup-info :strategy)))))
(unless backup-info
(error "`triples-backups-setup' needs to be called on this database before trying to back up."))
(error "`triples-backups-setup' needs to be called on this database before trying to back up"))
(unless (fboundp strategy-func)
(display-warning
'triples
Expand Down
9 changes: 5 additions & 4 deletions triples-upgrade.el
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

;;; Commentary:
;; Occasionally, changes in the triples library are not backwards-compatible,
;; and require upgrading the database. This file contains functions to do those
;; and require upgrading the database. This file contains functions to do those
;; ugprades, along with instructions an how and when to use them.

;;; Code:
Expand All @@ -32,10 +32,10 @@
(defun triples-upgrade-to-0.3 (db)
"Upgrade the DB to version 0.3.
This will convert all stringified integers stored with sqlite to
actual integers. On emacs version before 29, it will not do
actual integers. On Emacs version before 29, it will not do
anything, since only the built-in sqlite data needs upgrading.
Callers should force a backup to happen before calling this,
with `(triples-backup db file most-positive-fixnum)'.
by calling triples-backup with `most-positive-fixnum'.
This function only handles the case where users transition from
emacsql to sqlite, it is assumed that users don't transition from
Expand Down Expand Up @@ -83,4 +83,5 @@ be correct by default."
(message "Upgraded all stringified integers in triple database to actual integers"))))

(provide 'triples-upgrade)
;; triples-upgrade ends here

;;; triples-upgrade.el ends here
80 changes: 49 additions & 31 deletions triples.el
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@

;;; Commentary:
;; Triples is a library implementing a data storage based on the idea of
;; triples: subject, predicate, objects, plus some extra metadata. This data
;; triples: subject, predicate, objects, plus some extra metadata. This data
;; structure provides a way to store data according to an extensible schema, and
;; provide an API offering two-way links between all information stored.
;;
;; This package requires either emacs 29 or the emacsql package to be installed.
;; This package requires either Emacs 29 or the emacsql package to be installed.


(require 'cl-lib)
Expand All @@ -48,18 +48,19 @@
'builtin
'emacsql)
"The interface to sqlite to use.
Either `builtin' or `emacsql'. Defaults to builtin when
available. Builtin is available when the version is Emacs 29 or
Either `builtin' or `emacsql'. Defaults to builtin when
available. Builtin is available when the version is Emacs 29 or
greater, and emacsql is usable when the `emacsql' package is
installed.")

(defconst triples-sqlite-executable "sqlite3"
"If using emacs 29 builtin sqlite, this specifices the executable.
"If using Emacs 29 builtin sqlite, this specifices the executable.
It is invoked to make backups.")

(defconst triples-default-database-filename (locate-user-emacs-file "triples.db")
"The default filename triples database. If no database is
specified, this file is used.")
"The default filename triples database.
If no database is specified, this file is used.")

(defmacro triples-with-transaction (db &rest body)
"Create a transaction using DB, executing BODY.
Expand Down Expand Up @@ -101,7 +102,7 @@ If FILE is nil, use `triples-default-database-filename'."
('builtin
(and (fboundp 'sqlite-available-p) (sqlite-available-p)))
('emacsql (require 'emacsql nil t)))
(error "The triples package requires either Emacs 29 or the emacsql package to be installed."))
(error "The triples package requires either Emacs 29 or the emacsql package to be installed"))
(let ((file (or file triples-default-database-filename)))
(pcase triples-sqlite-interface
('builtin (let* ((db (sqlite-open file)))
Expand Down Expand Up @@ -154,19 +155,19 @@ The first argument is unused, but later may be used to specify
the running database.
This uses the same backup location and names as configured in
variables such as `backup-directory-alist'. Due to the fact that
variables such as `backup-directory-alist'. Due to the fact that
the database is never opened as a buffer, normal backups will not
work, therefore this function must be called instead.
Th DB argument is currently unused, but may be used in the future
if emacs's native sqlite gains a backup feature.
if Emacs's native sqlite gains a backup feature.
FILENAME can be nil, if so `triples-default-database-filename'
will be used.
This also will clear excess backup files, according to
NUM-TO-KEEP, which specifies how many backup files at max should
exist at any time. Older backups are the ones that are deleted."
exist at any time. Older backups are the ones that are deleted."
(let ((filename (expand-file-name (or filename triples-default-database-filename))))
(call-process (pcase triples-sqlite-interface
('builtin triples-sqlite-executable)
Expand All @@ -190,10 +191,11 @@ exist at any time. Older backups are the ones that are deleted."
(intern (format ":%s" sym)))

(defun triples-standardize-val (val)
"If VAL is a string, return it as enclosed in quotes
"If VAL is a string, return it as enclosed in quotes.
This is done to have compatibility with the way emacsql stores
values. Turn a symbol into a string as well, but not a quoted
one, because sqlite cannot handle symbols. Integers do not need
values. Turn a symbol into a string as well, but not a quoted
one, because sqlite cannot handle symbols. Integers do not need
to be stringified."
;; Do not print control characters escaped - we want to get things out exactly
;; as we put them in.
Expand All @@ -218,7 +220,7 @@ the string itself is wrapped in quotes."
"Insert triple to DB: SUBJECT, PREDICATE, OBJECT with PROPERTIES.
This is a SQL replace operation, because we don't want any
duplicates; if the triple is the same, it has to differ at least
with PROPERTIES. This is a low-level function that bypasses our
with PROPERTIES. This is a low-level function that bypasses our
normal schema checks, so should not be called from client programs."
(unless (symbolp predicate)
(error "Predicates in triples must always be symbols"))
Expand All @@ -243,8 +245,8 @@ normal schema checks, so should not be called from client programs."

(defun triples--emacsql-andify (wc)
"In emacsql where clause WC, insert `:and' between query elements.
Returns the new list with the added `:and.'s. The first element
MUST be there `:where' clause. This does reverse the clause
Returns the new list with the added `:and.'s. The first element
MUST be there `:where' clause. This does reverse the clause
elements, but it shouldn't matter."
(cons (car wc) ;; the :where clause
(let ((clauses (cdr wc))
Expand All @@ -257,7 +259,10 @@ elements, but it shouldn't matter."

(defun triples-db-delete (db &optional subject predicate object properties)
"Delete triples matching SUBJECT, PREDICATE, OBJECT, PROPERTIES.
If any of these are nil, they will not selected for. If you set
DB is the database to delete from.
If any of these are nil, they will not selected for. If you set
all to nil, everything will be deleted, so be careful!"
(pcase triples-sqlite-interface
('builtin (sqlite-execute
Expand Down Expand Up @@ -290,7 +295,9 @@ all to nil, everything will be deleted, so be careful!"
(seq-filter #'identity (list subject predicate object properties)))))))

(defun triples-db-delete-subject-predicate-prefix (db subject pred-prefix)
"Delete triples matching SUBJECT and predicates with PRED-PREFIX."
"Delete triples matching SUBJECT and predicates with PRED-PREFIX.
DB is the database to delete from."
(unless (symbolp pred-prefix)
(error "Predicates in triples must always be symbols"))
(pcase triples-sqlite-interface
Expand All @@ -301,11 +308,14 @@ all to nil, everything will be deleted, so be careful!"
subject (format "%s/%%" (triples--decolon pred-prefix))))))

(defun triples-db-select-pred-op (db pred op val &optional properties)
"Select triples matching predicates with PRED having OP relation to VAL.
OP is a comparison operator, and VAL is the value to compare. OP,
the comparison operator, is a symbol for a standard numerical
comparison such as `=', `!=', `>', or, when `val' is a strings,
`like'. All alphabetic comparison is case insensitive.
"Select matching predicates with PRED having OP relation to VAL.
DB is the database to select from.
OP is a comparison operator, and VAL is the value to compare. It
is a symbol for a standard numerical comparison such as `=',
`!=', `>', or, when `val' is a strings, `like'. All alphabetic
comparison is case insensitive.
If PROPERTIES is given, triples must match the given properties."
(unless (symbolp pred)
Expand Down Expand Up @@ -344,7 +354,7 @@ If PROPERTIES is given, triples must match the given properties."
pred val properties)))))

(defun triples-db-select-pred-prefix (db subject pred-prefix)
"Return rows matching SUBJECT and PRED-PREFIX."
"Return rows in DB matching SUBJECT and PRED-PREFIX."
(pcase triples-sqlite-interface
('builtin (mapcar (lambda (row) (mapcar #'triples-standardize-result row))
(sqlite-select db "SELECT * FROM triples WHERE subject = ? AND predicate LIKE ?"
Expand All @@ -355,8 +365,11 @@ If PROPERTIES is given, triples must match the given properties."

(defun triples-db-select (db &optional subject predicate object properties selector)
"Return rows matching SUBJECT, PREDICATE, OBJECT, PROPERTIES.
DB is the database to select from.
If any of these are nil, they are not included in the select
statement. The SELECTOR is list of symbols subject, precicate,
statement. The SELECTOR is list of symbols subject, precicate,
object, properties to retrieve or nil for *."
(pcase triples-sqlite-interface
('builtin (mapcar (lambda (row) (mapcar #'triples-standardize-result row))
Expand Down Expand Up @@ -404,7 +417,7 @@ object, properties to retrieve or nil for *."
Any references to OLD-SUBJECT as an object are also replaced.
This will throw an error if there is an existing subject
NEW-SUBJECT with at least one equal property (such as type
markers). But if there are no commonalities, the OLD-SUBJECT is
markers). But if there are no commonalities, the OLD-SUBJECT is
merged into NEW-SUBJECT."
(pcase triples-sqlite-interface
('builtin
Expand Down Expand Up @@ -521,7 +534,7 @@ them."
pprops))))))))

(defun triples-remove-schema-type (db type)
"This removes the schema for TYPE in DB, and all associated data."
"Remove the schema for TYPE in DB, and all associated data."
(triples-with-transaction
db
(let ((subjects (triples-subjects-of-type db type)))
Expand Down Expand Up @@ -561,13 +574,15 @@ PROPERTIES is a plist of properties, without TYPE prefixes."
(triples--add db op)))

(defmacro triples--eval-when-fboundp (sym form)
"Delay macroexpansion to runtime if SYM is not yet `fboundp'."
"Delay macroexpansion to runtime if SYM is not yet `fboundp'.
FORM is the code to delay."
(declare (indent 1) (debug (symbolp form)))
(if (fboundp sym)
form
`(eval ',form t)))

(defun triples--with-transaction (db body-fun)
"Wrap BODY-FUN in a transaction for DB."
(pcase triples-sqlite-interface
('builtin (condition-case err
(progn
Expand All @@ -584,7 +599,7 @@ PROPERTIES is a plist of properties, without TYPE prefixes."
(defun triples-set-types (db subject &rest combined-props)
"Set all data for types in COMBINED-PROPS in DB for SUBJECT.
COMBINED-PROPS is a plist which takes combined properties such as
:named/name and their values. All other data related to the types
:named/name and their values. All other data related to the types
given in the COMBINED-PROPS will be removed."
(let ((type-to-plist (make-hash-table)))
(triples--plist-mapc
Expand Down Expand Up @@ -759,7 +774,10 @@ FN must take two arguments: the key and the value."
triple type (type-of (nth 2 triple)))))

(defun triples-verify-base/virtual-reversed-compliant (_ triple)
"Virtual reversed properties shouldn't be set manually, so are never compliant."
"Reject any TRIPLE with a virtual reversed property.
Virtual reversed properties shouldn't be set manually, so are
never compliant."
(error "Invalid triple found: %s, should not be setting a `base/virtual-reversed' property"
triple))

Expand Down

0 comments on commit 068a69e

Please sign in to comment.