Giter Club home page Giter Club logo

cl-prevalence's Introduction

CL-PREVALENCE

This fork is available from Quicklisp and Ultralisp.org.

Running tests

To run all tests, eval this in the REPL:

` (asdf:test-system :cl-prevalence) `

GitHub should run the testsuite for each pull-request automatically.

History

This is a fork of cl-prevalence, taken from https://bitbucket.org/skypher/cl-prevalence

It is forked from commit 8eef33bfa789 (Mon Jul 05 17:53:21 2010 +0200) by Leslie Polzer.

cl-prevalence's People

Contributors

alanruttenberg avatar ambrevar avatar skypher avatar svetlyak40wt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cl-prevalence's Issues

sexp.lisp: Deserialize struct with `make-instance`

Currently, structures with custom constructors, e.g.

(defstruct (uri (:constructor %make-uri))
  scheme
  userinfo
  host
  port
  path
  query
  fragment)

fail to deserialize because deserialize-sexp-internal tries to call make-uri which does not exist.

Instead, I suggest to:

  • Check if (concatenate 'string "MAKE-" (symbol-name class)) exists.
  • If it does, call it as we do now.
  • If it does not, call make-instance instead.

Thoughts?

Tests fail when run separately by different users

Running tests leaves directories lying around in /tmp owned by the user running the test, which makes it impossible for any other user on the same system to run the tests:

$ ls -ld /tmp/*prevalence*
drwxr-xr-x  3 _nixbld1  wheel   96 Sep 30 22:46 /tmp/master-test-prevalence-system
drwxr-xr-x  3 _nixbld1  wheel   96 Sep 30 22:46 /tmp/slave-test-prevalence-system
drwxr-xr-x  5 _nixbld1  wheel  160 Sep 30 22:46 /tmp/test-managed-prevalence-system

This is particularly apparent with Nix, which uses a daemon with special dedicated system users for building & testing.

The tests assume order of execution of the tests

The tests assume order of execution, because some of them set up things like test-system and other tests use it. But Fiveam does not execute the tests in a specific order, unless there are dependencies that define the order.

Fiveam does loop for the hash table in the suite, so the order execution depends on how hash-table are implemented, and at least in LispWorks that means the order is undefined and can change whenever the hash table is rehashed.

2 tests fail

Hi, I ran the tests and two failed.

 Did 448 checks.
    Pass: 446 (99%)
    Skip: 0 ( 0%)
    Fail: 2 ( 0%)

 Failure Details:
 --------------------------------
 TEST-GET-SLAVE-USER in TEST-MASTER-SLAVE []: 
      Unexpected Error: #<USOCKET:ADDRESS-IN-USE-ERROR {1024902D33}>
Condition USOCKET:ADDRESS-IN-USE-ERROR was signalled..
 --------------------------------
 --------------------------------
 TEST-GET-MASTER-USER in TEST-MASTER-SLAVE []: 
      Unexpected Error: #<UNDEFINED-FUNCTION STOP-SERVER {1024767E73}>
The function S-SYSDEPS::STOP-SERVER is undefined..
 --------------------------------

I am using SBCL 2.1.2 on Linux.
Thanks.

Add method to customize specific slot serialization

Currently we can customize how a specific class instance is serialized. The default function does a good job.

However the API is very impractical for cases where I want to customize a specific slot serialization and use the default serialization for the rest of the slots.

Suggested fix: add a new method for an extra level of indirection. Example:

;; The new _exported_ method, defaults to calling the original behaviour.
(defmethod serialize-sexp-slot ((object standard-object) slot-name stream serialization-state)
  (s-serialization::serialize-sexp-internal (slot-value object slot-name)
                                            stream serialization-state))

; Existing function, tweaked to use the new method.
(defmethod serialize-sexp-internal ((object standard-object) stream serialization-state)
  "Hack of `s-serialization::serialize-sexp-internal' to allow for extensible slot serialization."
  (let ((id (s-serialization::known-object-id serialization-state object)))
    (if id
	(progn
	  (write-string "(:REF . " stream)
	  (prin1 id stream)
	  (write-string ")" stream))
        (let ((serializable-slots (s-serialization::get-serializable-slots serialization-state object)))
	  (setf id (s-serialization::set-known-object serialization-state object))
	  (write-string "(:OBJECT " stream)
	  (prin1 id stream)
	  (write-string " :CLASS " stream)
	  (s-serialization::print-symbol (class-name (class-of object)) stream)
          (when serializable-slots
            (princ " :SLOTS (" stream)
            (loop :for slot :in serializable-slots
                  :do (when (slot-boundp object slot)
                        (write-string " (" stream)
                        (s-serialization::print-symbol slot stream)
                        (write-string " . " stream)
                        (serialize-sexp-slot object slot stream serialization-state)
                        (write-string ")" stream))))
	  (write-string " ) )" stream)))))


;; Example customization on the user's side:
(defmethod serialize-sexp-slot ((my-object my-object-class) (slot (eql 'foo-slot)) stream serialization-sexp-slot)
  (if slot ...))

Thoughts? Should I send a patch?

Support custom hash tables?

https://github.com/metawilm/cl-custom-hash-table provides us with a portable way to define custom hash tables.
These are still of the hash-table type and thus are serialized by prevalence like any other hash table, but with the test set to the custom test.
The new hash-function, however, is not serialized.

This causes problems on deserialization because the custom test alone is not enough to make the custom hash table: the hash function must be provided.
Otherwise, the following condition is raised:

Unknown :TEST for MAKE-HASH-TABLE: MY-TEST-FUNCTION

One way to work around this would be to serialize the hash-function name. Then, to deserialize it, the library would use cl-custom-hash-table.
The problem is that I can't find a way to access the hash-function used for a hash-table value. Any idea?

sexp.lisp: Option to omit a specific package prefix

The symbol package prefix can get really verbose at times, it'd be nice to have an option to omit it.

For instance

(export '*local*)
(defvar *local-package* nil
  "If `*local-package*' designates a package instance, don't print the package
  prefix of its symbols.")

(defun print-symbol (symbol stream)
  (let ((package (symbol-package symbol))
	(name (prin1-to-string symbol)))
    (cond ((eq package +cl-package+) (write-string "CL:" stream))
	  ((eq package +keyword-package+) (write-char #\: stream))
          ((eq package *local-package*)
           ;; Don't print the package prefix.
           nil)
	  (package (s-xml:print-string-xml (package-name package) stream)
                   (write-string "::" stream))
          (t (write-string "#:" stream)))
    (if (char= (char name (1- (length name))) #\|)
        (write-string name stream :start (position #\| name))
      (write-string name stream :start (1+ (or (position #\: name :from-end t) -1))))))

Function serialization

Working on Next I have to deal with many structure / class slots whose values are function names (e.g. #'format) since they are configuration variables set by the user.

It'd be nice to be able to serialize those functions in the #' printed representation.
The problem is that the user could technically also specify a lambda, which is not serializable (unless we try really hard, but let's skip that).

So what about adding support for named functions?
Here is an example for s-exp serialization:

(defmethod serialize-sexp-internal ((object function) stream serialization-state)
  "Serialize function OBJECT.
If the function is named FOO, serialized is to \"#'FOO\".
Note: Function serialization is not part of the original cl-prevalence."
  (declare (ignore serialization-state))
  (let ((function-symbol (nth-value 2 (function-lambda-expression object))))
    (unless (symbolp function-symbol)
      (error "Cannot serialize anonymous functions (lambdas)"))
    (write-string "(:FUNCTION . " stream)
    (print-symbol function-symbol stream)
    (write-string ")" stream)))

Then at the end of deserialize-sexp-internal:

(:function (symbol-function (rest sexp)))

Thoughts?

Pathname support?

It looks like s-exp serialization chokes on pathnames. This simple method fixes it:

(defmethod serialize-sexp-internal ((object pathname) stream serialization-state)
  "Serialize pathname OBJECT to it's printed representation starting with #P.
Note: Function serialization is not part of the original cl-prevalence."
  (declare (ignore serialization-state))
  (prin1 object stream))

Thoughts?

sexp.lisp: Option to insert line breaks.

Instead of outputting everything on one line, it's be nice to leave some customization options to the users so that they can decide when to insert line breaks.

For instance:

(export '*one-element-per-line*)
(defvar *one-element-per-line* nil
  "If non-nil, print one element per line in sequence types.")

(defun maybe-newline (stream)
  (when *one-element-per-line*
    (write-char #\newline stream)))

(defmethod serialize-sexp-internal ((object sequence) stream serialization-state)
  "Like the original `serialize-sexp-internal' but uses `*one-element-per-line* to "
  (flet ((proper-sequence (length)
           (let ((id (set-known-object serialization-state object)))
             (write-string "(:SEQUENCE " stream)
             (prin1 id stream)
             (write-string " :CLASS " stream)
             (print-symbol (etypecase object (list 'list) (vector 'vector)) stream)
             (write-string " :SIZE " stream)
             (prin1 length stream)
             (unless (zerop length)
               (write-string " :ELEMENTS (" stream)
               (maybe-newline stream)
               (map nil
                    #'(lambda (element)
                        (write-string " " stream)
                        (serialize-sexp-internal element stream serialization-state)
                        (maybe-newline stream))
                    object))
             (write-string " ) )" stream)))
         (improper-list ()
           (let ((id (set-known-object serialization-state object)))
             (write-string "(:CONS " stream)
             (prin1 id stream)
             (write-char #\Space stream)
             (serialize-sexp-internal (car object) stream serialization-state)
             (write-char #\Space stream)
             (serialize-sexp-internal (cdr object) stream serialization-state)
             (write-string " ) " stream))))
    (let ((id (known-object-id serialization-state object)))
      (if id
          (progn
            (write-string "(:REF . " stream)
            (prin1 id stream)
            (write-string ")" stream))
          (multiple-value-bind (seq-type length) (sequence-type-and-length object)
            (ecase seq-type
              ((:proper-sequence :proper-list) (proper-sequence length))
              ((:dotted-list :circular-list) (improper-list))))))))

The above function is like the original except for the maybe-newline calls.

sexp.lisp: Follow *print-case*

Much of the serialization functions output hard-coded strings such as "(:SEQUENCE ", etc.

When *print-case* is set to :downcase or :capitalize, the result is a mix of difference cases.

It would be nice if all hard-coded strings would be cased according to *print-case*.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.