Monthly Archives: November 2018

[Ann] Teapot on github

Hi,

I just want to let you know that the source code of Teapot was moved from
Smalltalkhub to GitHub.

The new repository is located at:

https://github.com/zeroflag/teapot <https://github.com/zeroflag/teapot>  

Attila
Advertisements

Writing baselines… in Pharo 70

Great resources

https://github.com/pharo-tips-and-tricks/pharo-tips-and-tricks/blob/master/General/Baselines.md

Thanks for writing it.

[Ann] JSONSchema for Pharo

JSONSchema
===========

This is an implementation of JSON Schema for the pharo language. It is used to define the structure and values of a JSON string and to validate it. The schema itself can be externalized for being consumed by a third party.

I like to announce the availability of a JSON schema implementation for pharo. As part of my implementation of OpenAPI (which is to be released a bit later) I factored out the JSON schema part into its own repository because I think it is useful. I release it even it is not really finished. Code is mostly undocumented and a lot of features are missing from the full spec. I will improve it slowly and add features as I need them or they being requested

Hope you like it!

Norbert 

====

The documentation so far (from https://github.com/zweidenker/JSONSchema <https://github.com/zweidenker/JSONSchema>)

It can be loaded by downloading it in pharo via

  Metacello new
    repository: 'github://zweidenker/JSONSchema';
    baseline: #JSONSchema;
    load

Defining a schema
-------------------------

These are the expression to create a schema model inside pharo.

schema := {
  #name -> JSONSchema string.
  #dateAndTime -> (JSONSchema stringWithFormat: 'date-time').
  #numberOfPets -> JSONSchema number } asJSONSchema.


defines as schema that can parse the following JSON:

jsonString := '{
  "name" : "John Doe",
  "dateAndTime" : "1970-01-01T14:00:00",
  "numberOfPets" : 3
}'.

Reading/Writing a value using a schema
------------------------------------------------------

To parse the value from JSON we only need to invoke:

value := schema read: jsonString

The object in value will have name as a string, dateAndTime as a DateAndTime object and numberOfPets as a SmallInteger object.

The schema can also be used to write out the value as JSON. This is especially useful if we want to ensure that only valid JSON is written. For this invoke

jsonString := schema write: value.

Serialize/Materialize a schema
----------------------------------------

Addtionally to reading and writing objects a schema can be serialized to string.

schemaString := NeoJSONWriter toStringPretty: schema.

gives

{
	"type" : "object",
	"properties" : {
		"name" : {
			"type" : "string"
		},
		"numberOfPets" : {
			"type" : "number"
		},
		"dateAndTime" : {
			"type" : "string",
			"format" : "date-time"
		}
	}
}


If we would get a schema as string we can instantiate by invoking

schema := JSONSchema fromString: schemaString.

Nested schemas
-----------------------

Schemas can be nested in any depth. And it can be specified by using the literal Array syntax.

schema := {
  #name -> JSONSchema string.
  #address -> {
    #street -> JSONSchema string.
    #number -> JSONSchema number
  } } asJSONSchema

Constraints
---------------

JSON Schema has a defined set of constraints that can be specified. E.g. for a number the inerval of the value can be specified by

numberSchema := JSONSchema number.
numberSchema interval
  minimum: 1;
  exclusiveMaximum: 100

constraining the number value to be greater or equal to 1 and smaller than 100.

Zinc HTTP Components version 3.0.1

I finally merged and synced all Zinc HTTP Components repos and did a full release on Pharo versions 3 to 7.

  https://github.com/svenvc/zinc/releases/tag/v3.0.1

Main README was updated

  https://github.com/svenvc/zinc

Green build for Pharo 7 RC1 (linux 64-bit) using BaselineOfZincHTTPComponents

  https://travis-ci.org/svenvc/zinc

Green builds for Pharo 3, 4, 5 and 6 using ConfigurationOfZincHTTPComponents (#stable 3.0.1)

  https://ci.inria.fr/pharo-contribution/job/ZincHTTPComponents/

If there are any problems or issues, don't hesitate to ask.

Sven

[ann] New Pharo success story

http://pharo.org/success/RMapViewer

Well done Tomohiro Oda and others !!!

 

 

Better management of encoding of environment variables

Hi all,

Thanks Ben for reading.

For those wanting a follow up, I’ve proposed this pull request:
https://github.com/pharo-project/pharo/pull/1980.
I’m still working on avoiding dependencies against UFFI, fixing one other
test.
This is however almost finished, and given that I had to adapt the
original *abstract
proposal* to fit the real system, here is an updated version:

API Proposal for OSEnvironment and friends
=========================

OSEnvironment is the common denominator for all platforms. They should
implement at least the following messages with the following semantics:

– *at: aVariableName [ifAbsent:/ifAbsentPut:/ifPresent:ifAbsent:]*

Gets the String value of an environment variable called `aVariableName`.
It is the system reponsibility to manage the encoding of *both arguments
and return values*.

– *at: aVariableName put: aValue*

Sets the environment variable called `aVariableName` to value `aValue`.
It is the system reponsibility to manage the encoding of *both arguments
and return values*.

– *removeKey: aVariableName*

Removes the environment variable called `aVariableName`.
It is the system reponsibility to manage the encoding of *both arguments
and return values*.

API Extensions for *Nix Systems (OSX & Linux)
=========================

Since *Nixes environment variables are binary data that could be encoded in
any encoding, the following methods provide more flexibility to access such
data in the encoding of the choice of the user, or even in binary form.

– *at: aVariableName encoding: anEncoding
[ifAbsent:/ifAbsentPut:/ifPresent:ifAbsent:/put:] / removeKey:**
aVariableName
encoding: anEncoding*

Variants of the common API from OSEnvironment.
The encoding used as argument will be used to encode/decode *both arguments
and return values*.

– *rawAt: anEncodedVariableName encoding: anEncoding
[ifAbsent:/ifAbsentPut:/ifPresent:ifAbsent:/put:] / removeRawKey:*
*anEncodedVariableName*

Variants of the common API from OSEnvironment.
These methods assume arguments and return values are encoded/decoded by the
user, so no marshalling or decoded is done by it.

Rationale
=========================

– Encoding/Decoding should be applied not only to values but to
variables names too. In most cases Ascii overlaps with utf* and Latin*
encodings, but this cannot be simply assumed.
– Windows requires calling the right *Wide version of the functions from
C, plus the correct encoding routine. This could be implemented as an FFI
call or by modifying the VM to do it properly instead of calling the Ascii
version.
– Unix FileSystems and environment variables could mix strings in
different encodings, thus the flexibility added by the low level *Nix
extensions.

Other Implementation Details
=========================

– VM primitives returning paths Strings should be carefuly managed to
decode them, since they are actually C strings (so byte arrays) disguised
as ByteStrings.
– Similar changes had to be applied to correctly obtain the current
working directory in case it is a wide string.

 

Guille

New random generator: WELL512 PRNG

Hi,

By accident I came across a pseudo random number generator that I never heard off before. It is supposed to be pretty good and had a very simple implementation. So I ported it to Pharo.

<class comment>

I am RandomWELL512, a random number generator.

I use the PRNG (Pseudo Randon Number Generator) WELL (Well equidistributed long-period linear) with a 512 bit state.

  https://en.wikipedia.org/wiki/Well_equidistributed_long-period_linear
  http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng.pdf

Implementation algorithm (See #nextUInt32)

  http://www.lomont.org/Math/Papers/2008/Lomont_PRNG_2008.pdf (Chris Lomont, www.lomont.org)

Usage

  RandomWELL512 new in: [ :r | (1 to: 10) collect: [ :i | r nextUInt32 ] ]. 

  RandomWELL512 new useUnixRandomGeneratorSeed; in: [ :r | (1 to: 10) collect: [ :i | r next ] ]. 

  RandomWELL512 new in: [ :r | (1 to: 10) collect: [ :i | r nextInt: 1000 ] ].

  RandomWELL512 new in: [ :random | | count all |
    random useUnixRandomGeneratorSeed.
    count := 1024 * 1024.
    all := Array new: count streamContents: [ :out |
      count timesRepeat: [ out nextPut: random next ] ].
    { all min. all max. all average. all stdev } ].

  [ RandomWELL512 new in: [ :random | 1 to: 1e6 do: [ :i | random next ] ] ] timeToRun.

Note that you should create one instance, seed it properly, and keep using it.

</class comment>

It is acceptably fast, generating 1M [0,1) Floats in about 0.1s. I compared the output with a fixed initial state to the C code that I started from and I got the same numbers. Maybe some people find this interesting.

I attached a file out.

Sven

Zn nicer API

Hi,

I added a new convenience method to Zinc HTTP Components: ZnClient>>forJsonREST. This configures a ZnClient (HTTP client) to talk to standard JSON REST web services. Here are a couple of examples:

ZnClient new
  forJsonREST;
  get: 'https://jsonplaceholder.typicode.com/users'.

What #forJsonREST does is 3 things: set the 'Accept' header to 'application/json', install a #contentReader that parses incoming JSON as well as a #contentWriter that generates JSON.

ZnClient new
  systemPolicy;
  forJsonREST;
  url: 'https://jsonplaceholder.typicode.com/posts';
  contents: { #foo->1. #bar->2 } asDictionary;
  post.

As you can see, the full ZnClient API can be combined when needed.

ZnClient new
  forJsonREST;
  post: 'https://jsonplaceholder.typicode.com/posts' 
  contents: (NeoJSONObject new foo: 1; bar: 2; yourself).

#post:contents: combines separate #url: #contents: and #post message.

#forJsonREST uses NeoJSON[Object|Writer] if found, else STONJSON. If both are missing, this results in an error.
	
ZnClient new
  systemPolicy;
  forJsonREST;
  url: 'http://easy.t3-platform.net/rest/geo-ip';
  queryAt: #address put: '81.83.7.35';
  get.

Finally, here is a more sophisticated example, doing a DNS request over HTTPS:

ZnClient new
  systemPolicy;
  beOneShot;
  forJsonREST;
  accept: 'application/dns-json';
  url: 'https://cloudflare-dns.com/dns-query';
  queryAt: #name put: 'stfx.eu';
  queryAt: #type put: #AAAA;
  get.

Note that in most cases, you will configure one client to a specific endpoint and keep on reusing it. At one point in time it might be good to #close the client (although that happens on finalise as well). For single requests, you can use #beOneShot.

All this can be found in #bleedingEdge (HEAD). There are unit tests as well.

Sven