Pharo-users
By thread
pharo-users@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- 3 participants
- 50348 messages
How does the SUnit debug view, highlight lower down in the stack?
by Tim Mackinnon
Iâve been working on improving some of my testing techniques and the tools used to do that, and it highlighted something where Iâm not clear on how it works.
Sometime the debugger highlights a failure lower down in the stack (not just the stack frame directly below the signaller).
How does it do it? I canât see what it does to achieve this - however curiously it differs between types of assert.
I.e. with: self assert: 2 =3 (it just shows the frame below)
Yet: self assert: 2 equals: 4 (shows two frames below, and actually directly shows where in the test failed - with no further clicks which is brilliant)
The photos (at the end) demonstrate what I mean - and I can see there is a defaultAction in TestFailure that pops open the debugger:
defaultAction
Processor activeProcess
debug: self signalerContext
title: self description
And if I try and do a similar thing for one of my own exceptions - but wind further down the stack manually (which TestFailure doesât do) like:
defaultAction
| triggerContext |
triggerContext := self signalerContext findContextSuchThat:
[ :context | context method selector = #doesNotUnderstand: ].
"Trigger the debugger where the failure happened"
Processor activeProcess
debug: (triggerContext ifNil: [ self signalerContext ])
title: self messageText
This gives me a debugger on the line of the failure (which I like), but the stack above this failure (which in my case was many frames deep) is gone (presumably as contexts only know their parent, and Iâve backed up through the parent chain). This is a bit confusing to understand how you got the error.
So Iâm left wondering how #assert:equals: ends up highlighting further down. Iâm missing some concept - and wondering if anyone knows? Itâs not urgent - but a smalltalkây curiosity about how our environment works.
Tim
The debugger that pops up for assert:
vs. The debugger that pops up for #assert:equals:
March 11, 2019
Re: [Pharo-users] complex json parsing.
by Roelof Wobben
Op 11-3-2019 om 00:03 schreef Ben Coman:
> collectionUrl :=Â
> 'https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=…'.
> Â Â json := NeoJSONReader fromString: (ZnEasy get: collectionUrl)
> contents.
> Â Â paintings := Paintings fromJSON: json.
Thanks a lot , Ben
I almost gave it up but I think I see a way to solve this
The first part gives back exactly the same output as my old code.
For the new one I have to do some trying but I think I can solve it
Roelof
March 11, 2019
Re: [Pharo-users] complex json parsing.
by Ben Coman
On Mon, 11 Mar 2019 at 01:09, Roelof Wobben <r.wobben(a)home.nl> wrote:
> Op 10-3-2019 om 17:45 schreef Ben Coman:
>
>
>
> On Sun, 10 Mar 2019 at 23:40, Roelof Wobben <r.wobben(a)home.nl> wrote:
>
>> Op 10-3-2019 om 16:19 schreef Ben Coman:
>>
>>
>>
>> On Sun, 10 Mar 2019 at 17:55, Roelof Wobben <r.wobben(a)home.nl> wrote:
>>
>>> I could do something like this :
>>>
>>> getImages
>>> | json numbers json2 |
>>> json := NeoJSONReader
>>> fromString:
>>> (ZnEasy
>>> get:
>>> '
>>> https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=…
>>> ')
>>> contents.
>>> numbers := self class fromJSON: json
>>> numbers do: [each | json := .........
>>> imageData = self class ???
>>>
>>
>> I'm not sure what "numbers" refers to. It seems a quite non-domain
>> related identifier.
>> To understand the domain, pasting the json contents of your link above
>> into https://jsonformatter.curiousconcept.com/
>> and collapsing objects I see the structure is...
>>
>> <snip>
>
> Did you work through this example I provided? Please do so.
> In a clean image...
>
>> Start with only your original code (which was good btw)...
>>
>> Paintings class >> fromJSON: json
>> | instance artObjects |
>> instance := self new.
>> artObjects := json at: #artObjects.
>> artObjects
>> do:
>> [ :eachArtObject | instance addPainting: (Painting
>> fromJSON: eachArtObject) ].
>> ^ instance
>>
>>
> except objectNumber(s) seem associated with each painting, so should be
> stored within the painting object, as ADDED here...
>
>
> Painting class >> fromJSON: json
>
> | instance |
> instance := self new.
> instance
> objectNumber: (json at: #objectNumber); "<<<<<<<<ADDED"
> title: (json at: #title);
> painter: (json at: #principalOrFirstMaker);
> imageUrl: ((json at: #webImage) at: #url).
> ^ instance
>
> Evaluate the following in Playground...
> collectionUrl := '
> https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=…
> '.
> collectionJson := NeoJSONReader fromString: (ZnEasy get:
> collectionUrl) contents.
> paintings := Paintings fromJSON: collectionJson.
> paintings inspect.
>
> then clean the DNU errors as they occur (i.e. click the <Create> button
> shown by the debugger, and fill in as follows...)
> when you save the methods, choose <Declare new instance variable>"
>
> Painting >> objectNumber: aString
> objectNumber := aString
>
>> Painting >> title: aString
>> title := aString
>>
>> Painting >> painter: aString
>> painter := aString
>>
>> Painting >> imageUrl: aString
>> imageUrl := aString
>>
>> Paintings >> addPainting: aPainting
>> paintings := paintings ifNil: [ OrderedCollection new ].
>> paintings add: aPainting.
>>
>> and an inspector will appear showing a list of paintings, which you can
>> drill down to a painting and see each has the expected data.
>> Now just to round things off...
>>
>> Painting >> title
>> ^ title
>>
>> Painting >> printOn: aStream
>> super printOn: aStream.
>> aStream << ' (' << self title << ')'
>>
>> to help distinguish each item in the Inspector.
>>
>>
>> To extend the Playground code to download and display a painting, in
>> Playground evaluate...
>>
>> painting := paintings first.
>> imageResponse := ZnEasy get: painting imageUrl.
>> image := ImageReadWriter formFromStream: imageResponse entity
>> readStream.
>> image inspect.
>>
>> Paintings >> first
>> ^ paintings first
>>
>> Painting >> imageUrl
>> ^ imageUrl
>>
>> and an inspector on the `image` variable displays the painting on the
>> Morph tab.
>>
>>
>> Now to mold the IDE to your domain...
>> using Spotter to browser gtInspector* methods, a promising find is...
>> AbstractFileReference>>gitInspectorJpegIn:
>> from which I produced...
>>
>> Painting >> gtInspectorJpegIn: composite
>> <gtInspectorPresentationOrder: 0>
>> composite morph
>> title: 'Painting';
>> display: [ ImageReadWriter formFromStream: self imageEntity readStream ]
>>
>> Then inspecting the `paintings` variable and drilling down to a painting
>> pops up a DNU #imageEntity, which can be resolved by...
>>
>> Painting >> imageEntity
>> ^ imageEntity ifNil: [ imageEntity := (ZnEasy get: self imageUrl) entity
>> ].
>>
>> and you get to see the painting shown in the Inspector.
>>
>>
>> Now if I understand your question... "Do I need to make some more object
>> to get this working..."
>> I'd say... No. You only want one object for each painting. Once you have
>> a painting object, it should handle all getting all further data it needs
>> for itself.
>> You don't want duplicate objects each having half of the data.
>>
>>
>> can I for example name the function fromJson2 or fromJSONFromLink2 ?
>>>
>>
>> By naming convention #fromJson: implies it sits on the class side.
>> To get further data for an existing object you want an instance-side
>> method, maybe named #getLink2Json.
>>
>> HTH,
>> cheers -ben
>>
>>
>>
>> oke
>>
>> numbers should be the objectNumbers because for the rest I need them
>>
>
>
>
>
>>
>>
>> I use a instance variable called painting to hold the data.
>>
>>
>> so I can change the call to get data for the painting to :
>>
>> Painting class >> fromJSON: json
>> | instance |
>> instance := self new.
>> instance
>> objectNumber: ((json at: #objectNumber).
>> ^ instance
>>
>>
>> so numbers should be a collection of 10 ObjectNumbers
>>
>
> I'm presuming that 10 objectNumbers relate to 10 different paintings,
> in which case, No, you should never need to deal with a collection of 10
> objectNumbers.
> What you should have is a collection of painting-objects which know their
> own objectNumber
> and then iterate that collection sending each painting-object the message
> "getLink2Json".
>
>
>
>> so I should use a loop to make a call to the second api call
>>
>
> In Pharo OO approach, you don't "loop" on the "calls",
> you "iterate" on the "objects" asking them to use their own data to do the
> stuff they know how to do.
> i.e. Let each object take care of itself.
>
> Which class is getImages defined on? That is really important to
> understand your proposed solution.
> I'm just presuming its defined on the class side of Paintings since your
> are referring to the same URL as before.
>
>>
>> getImages
>> | json numbers |
>> json := NeoJSONReader
>> fromString:
>> (ZnEasy
>> get:
>> '
>> https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=…
>> ')
>> contents.
>> numbers painting := self class fromJSON: json
>>
>
> btw, it won't work with two identifiers "numbers painting" to the left of
> the assignment symbol. Space here bad.
>
>
> numbers do: [each | json := call to the second url.here I used
>> each
>> imageData = self class
>> getLink2Json
>>
> json2 := call to the 3th url
>> otherData := self class
>> getLink3Json
>>
>>
>
> no :) the "self class" seems wrong.
> getting extra data about a painting should be handled by the instance side
> of its painting-object.
>
>
>
>> Then I can I hope on every json method fill in the data I need
>>
>> Do I understand you well
>>
>
> I think not so well yet :) (or else I am missing something)
> Keep trying. It will change the way you think about programming.
>
> Please work though the example I provided.
> cheers -ben
>
>
>
>
> I did and it worked the same as my code
> Still I do not see how to use then the objectNumber in a second call to
> the api
> for example
>
> lets say we have only 1 objectNumber now
> for example
>
> SK-C-5
>
> then I need that one here : https://www.rijksmuseum.nl/api/nl/collection/SK-C-5?key=[API_KEY]&format=js…
> so I see a json response of this :
>
> <snip>
> where I at this moment need only artObjects -> makers -> name and artobject -> title
>
> And I need to do that for all 10
>
> But as far as I know I can only have one fromJson
>
> You can have as many Painting-class>>fromJsonXxxx methods as you like,
but you only call one of them once per painting. This has nothing to do
with Json
and everything to do with your Painting-class>>fromJson method creating a
new Painting-object,
and you only want *one* Painting-object per Json-painting, so you can only
call one.
But actually, you don't need any Painting>>fromJSON:.
Please delete it !!!!
Then modify the other one as follows...
Paintings class >> fromJSON: json
| instance |
instance := self new.
(json at: #artObjects)
do:
[ :artObjectJson |
|painting|
painting := Painting new.
painting
objectNumber: (artObjectJson at: #objectNumber);
title: (artObjectJson at: #title);
painter: (artObjectJson at: #principalOrFirstMaker);
imageUrl: ((artObjectJson at: #webImage) at: #url).
instance addPainting: painting ].
^ instance
Does...
collectionUrl := '
https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=…
'.
json := NeoJSONReader fromString: (ZnEasy get: collectionUrl) contents.
paintings := Paintings fromJSON: json.
give you the same result as before?
so how do I take care that the second one is called and parsed
> and the right info is on the Painting object
>
> That is my question all the time
>
>
As I said before...
> What you should have is a collection of painting-objects which know their
own objectNumber
> and then iterate that collection sending each painting-object the message
"getLink2Json".
So more generically, add something like...
Painting >> getMoreData "or a better name of your own"
| url json artObjectJson |
url := 'https://www.rijksmuseum.nl/api/nl/collection/' ,
objectNumber , '?key=[API_KEY]&format=json'
Transcript crShow: 'Getting description from ', url.
json := (NeoJSONReader fromString: (ZnEasy get: url) contents).
artObjectJson := json at: 'artObject.
description := artObjectJson at: 'description'.
title := artObjectJson at: 'title'.
Now in playground, variable paintings holds a collection 10 ten paintings.
So lets ask each of them to get more data.
paintings do: [ :painting | painting getMoreData ].
cheers -ben
March 10, 2019
Re: [Pharo-users] FUEL serialization to a file
by Konrad Hinsen
Hi Sven,
Thanks for all that background information on the history of streams. It
makes everything a lot clearer for me.
> But first, it would help a lot that you give a self-contained
> reproducible snippet that raises your problem, like mine. I tried
> reproducing your failure but could not.
My bug is difficult to reproduce because it is triggered only when the
"right" kind of buffer overflow happens. I didn't succeed yet to provoke
it while serializing simple objects such as strings or arrays.
I did manage to reduce my code quite a lot, so here is the shortest
example I have for the moment that provokes the bug:
Metacello new
baseline: 'ComputationalDocuments';
repository: 'github://khinsen/computational-documents-with-gtoolkit:minimal-code-for-serialization-bug';
load.
And then
APLibraryTest new setUp; testScanDirectory
Konrad.
March 10, 2019
Re: [Pharo-users] complex json parsing.
by Ben Coman
On Sun, 10 Mar 2019 at 23:19, Ben Coman <btc(a)openinworld.com> wrote:
>
> Now to mold the IDE to your domain...
> using Spotter to browser gtInspector* methods, a promising find is...
> AbstractFileReference>>gitInspectorJpegIn:
> from which I produced...
>
> Painting >> gtInspectorJpegIn: composite
> <gtInspectorPresentationOrder: 0>
> composite morph
> title: 'Painting';
> display: [ ImageReadWriter formFromStream: self imageEntity readStream ]
>
@all, can someone suggest a better #display: block that would shrink the
image to the window size,
and/or zooming.
cheers -ben
March 10, 2019
Re: [Pharo-users] complex json parsing.
by Ben Coman
On Sun, 10 Mar 2019 at 23:40, Roelof Wobben <r.wobben(a)home.nl> wrote:
> Op 10-3-2019 om 16:19 schreef Ben Coman:
>
>
>
> On Sun, 10 Mar 2019 at 17:55, Roelof Wobben <r.wobben(a)home.nl> wrote:
>
>> I could do something like this :
>>
>> getImages
>> | json numbers json2 |
>> json := NeoJSONReader
>> fromString:
>> (ZnEasy
>> get:
>> '
>> https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=…
>> ')
>> contents.
>> numbers := self class fromJSON: json
>> numbers do: [each | json := .........
>> imageData = self class ???
>>
>
> I'm not sure what "numbers" refers to. It seems a quite non-domain related
> identifier.
> To understand the domain, pasting the json contents of your link above
> into https://jsonformatter.curiousconcept.com/
> and collapsing objects I see the structure is...
>
> <snip>
Did you work through this example I provided? Please do so.
In a clean image...
> Start with only your original code (which was good btw)...
>
> Paintings class >> fromJSON: json
> | instance artObjects |
> instance := self new.
> artObjects := json at: #artObjects.
> artObjects
> do:
> [ :eachArtObject | instance addPainting: (Painting
> fromJSON: eachArtObject) ].
> ^ instance
>
>
except objectNumber(s) seem associated with each painting, so should be
stored within the painting object, as ADDED here...
Painting class >> fromJSON: json
| instance |
instance := self new.
instance
objectNumber: (json at: #objectNumber); "<<<<<<<<ADDED"
title: (json at: #title);
painter: (json at: #principalOrFirstMaker);
imageUrl: ((json at: #webImage) at: #url).
^ instance
Evaluate the following in Playground...
collectionUrl := '
https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=…
'.
collectionJson := NeoJSONReader fromString: (ZnEasy get: collectionUrl)
contents.
paintings := Paintings fromJSON: collectionJson.
paintings inspect.
then clean the DNU errors as they occur (i.e. click the <Create> button
shown by the debugger, and fill in as follows...)
when you save the methods, choose <Declare new instance variable>"
Painting >> objectNumber: aString
objectNumber := aString
> Painting >> title: aString
> title := aString
>
> Painting >> painter: aString
> painter := aString
>
> Painting >> imageUrl: aString
> imageUrl := aString
>
> Paintings >> addPainting: aPainting
> paintings := paintings ifNil: [ OrderedCollection new ].
> paintings add: aPainting.
>
> and an inspector will appear showing a list of paintings, which you can
> drill down to a painting and see each has the expected data.
> Now just to round things off...
>
> Painting >> title
> ^ title
>
> Painting >> printOn: aStream
> super printOn: aStream.
> aStream << ' (' << self title << ')'
>
> to help distinguish each item in the Inspector.
>
>
> To extend the Playground code to download and display a painting, in
> Playground evaluate...
>
> painting := paintings first.
> imageResponse := ZnEasy get: painting imageUrl.
> image := ImageReadWriter formFromStream: imageResponse entity
> readStream.
> image inspect.
>
> Paintings >> first
> ^ paintings first
>
> Painting >> imageUrl
> ^ imageUrl
>
> and an inspector on the `image` variable displays the painting on the
> Morph tab.
>
>
> Now to mold the IDE to your domain...
> using Spotter to browser gtInspector* methods, a promising find is...
> AbstractFileReference>>gitInspectorJpegIn:
> from which I produced...
>
> Painting >> gtInspectorJpegIn: composite
> <gtInspectorPresentationOrder: 0>
> composite morph
> title: 'Painting';
> display: [ ImageReadWriter formFromStream: self imageEntity readStream ]
>
> Then inspecting the `paintings` variable and drilling down to a painting
> pops up a DNU #imageEntity, which can be resolved by...
>
> Painting >> imageEntity
> ^ imageEntity ifNil: [ imageEntity := (ZnEasy get: self imageUrl) entity ].
>
> and you get to see the painting shown in the Inspector.
>
>
> Now if I understand your question... "Do I need to make some more object
> to get this working..."
> I'd say... No. You only want one object for each painting. Once you have a
> painting object, it should handle all getting all further data it needs for
> itself.
> You don't want duplicate objects each having half of the data.
>
>
> can I for example name the function fromJson2 or fromJSONFromLink2 ?
>>
>
> By naming convention #fromJson: implies it sits on the class side.
> To get further data for an existing object you want an instance-side
> method, maybe named #getLink2Json.
>
> HTH,
> cheers -ben
>
>
>
> oke
>
> numbers should be the objectNumbers because for the rest I need them
>
>
>
> I use a instance variable called painting to hold the data.
>
>
> so I can change the call to get data for the painting to :
>
> Painting class >> fromJSON: json
> | instance |
> instance := self new.
> instance
> objectNumber: ((json at: #objectNumber).
> ^ instance
>
>
> so numbers should be a collection of 10 ObjectNumbers
>
I'm presuming that 10 objectNumbers relate to 10 different paintings,
in which case, No, you should never need to deal with a collection of 10
objectNumbers.
What you should have is a collection of painting-objects which know their
own objectNumber
and then iterate that collection sending each painting-object the message
"getLink2Json".
> so I should use a loop to make a call to the second api call
>
In Pharo OO approach, you don't "loop" on the "calls",
you "iterate" on the "objects" asking them to use their own data to do the
stuff they know how to do.
i.e. Let each object take care of itself.
Which class is getImages defined on? That is really important to
understand your proposed solution.
I'm just presuming its defined on the class side of Paintings since your
are referring to the same URL as before.
>
> getImages
> | json numbers |
> json := NeoJSONReader
> fromString:
> (ZnEasy
> get:
> '
> https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=…
> ')
> contents.
> numbers painting := self class fromJSON: json
>
btw, it won't work with two identifiers "numbers painting" to the left of
the assignment symbol. Space here bad.
numbers do: [each | json := call to the second url.here I used each
> imageData = self class
> getLink2Json
>
json2 := call to the 3th url
> otherData := self class
> getLink3Json
>
>
no :) the "self class" seems wrong.
getting extra data about a painting should be handled by the instance side
of its painting-object.
> Then I can I hope on every json method fill in the data I need
>
> Do I understand you well
>
I think not so well yet :) (or else I am missing something)
Keep trying. It will change the way you think about programming.
Please work though the example I provided.
cheers -ben
March 10, 2019
Re: [Pharo-users] complex json parsing.
by Ben Coman
On Sun, 10 Mar 2019 at 17:55, Roelof Wobben <r.wobben(a)home.nl> wrote:
> I could do something like this :
>
> getImages
> | json numbers json2 |
> json := NeoJSONReader
> fromString:
> (ZnEasy
> get:
> '
> https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=…
> ')
> contents.
> numbers := self class fromJSON: json
> numbers do: [each | json := .........
> imageData = self class ???
>
I'm not sure what "numbers" refers to. It seems a quite non-domain related
identifier.
To understand the domain, pasting the json contents of your link above into
https://jsonformatter.curiousconcept.com/
and collapsing objects I see the structure is...
{
"elapsedMilliseconds":0,
"count":4782,
"countFacets":{
"hasimage":4359,
"ondisplay":748
},
"artObjects":[ + ] ,
"facets":[ + ]
}
where artObjects is an array with each art object like this==>
{
"links":{
"self":"https://www.rijksmuseum.nl/api/nl/collection/SK-A-3580",
"web":"https://www.rijksmuseum.nl/nl/collectie/SK-A-3580"
},
"id":"nl-SK-A-3580",
"objectNumber":"SK-A-3580",
"title":"De Singelbrug bij de Paleisstraat in Amsterdam",
"hasImage":true,
"principalOrFirstMaker":"George Hendrik Breitner",
"longTitle":"De Singelbrug bij de Paleisstraat in Amsterdam,
George Hendrik Breitner, 1898",
"showImage":true,
"permitDownload":true,
"webImage":{
"guid":"cd15e2fa-b1f6-41f4-9e9e-c2ca87abcca3",
"offsetPercentageX":0,
"offsetPercentageY":0,
"width":2880,
"height":1897,
"url":"
https://lh3.googleusercontent.com/Bawo7r1nPZV6sJ4OHZJHdKV_4Ky59vquAR7KoUXcN…
"
},
"headerImage":{
"guid":"fef39f74-9783-44c9-acae-69eac3a76b01",
"offsetPercentageX":0,
"offsetPercentageY":0,
"width":1920,
"height":460,
"url":"
https://lh3.googleusercontent.com/jR6y5a8lFvgYe37WxLPQJZTjBAaBB6aIFYMsFw9gG…
"
},
"productionPlaces":[
"Amsterdam"
]
}
So evaluating the following in Playground...
collectionUrl := '
https://www.rijksmuseum.nl/api/nl/collection?key=14OGzuak&format=json&type=…
'.
collectionJson := NeoJSONReader fromString: (ZnEasy get: collectionUrl)
contents.
paintings := Paintings fromJSON: collectionJson.
paintings inspect.
then cleaning the DNU errors as i went,
starting with your original code (which was good btw)...
Paintings class >> fromJSON: json
| instance artObjects |
instance := self new.
artObjects := json at: #artObjects.
artObjects
do:
[ :eachArtObject | instance addPainting: (Painting
fromJSON: eachArtObject) ].
^ instance
Painting class >> fromJSON: json
| instance |
instance := self new.
instance
title: (json at: #title);
painter: (json at: #principalOrFirstMaker);
imageUrl: ((json at: #webImage) at: #url).
^ instance
I added (roughly in order that each DNU occurred)...
Painting >> title: aString
title := aString
Painting >> painter: aString
painter := aString
Painting >> imageUrl: aString
imageUrl := aString
Paintings >> addPainting: aPainting
paintings := paintings ifNil: [ OrderedCollection new ].
paintings add: aPainting.
I get an inspector on a list of paintings and can drill down to a painting
and see each has the expected data,
and just to round things off...
Painting >> title
^ title
Painting >> printOn: aStream
super printOn: aStream.
aStream << ' (' << self title << ')'
helps distinguish each item in the Inspector.
Now to extend the Playground code to download and display a painting, in
Playground I evaluated...
painting := paintings first.
imageResponse := ZnEasy get: painting imageUrl.
image := ImageReadWriter formFromStream: imageResponse entity
readStream.
image inspect.
Paintings >> first
^ paintings first
Painting >> imageUrl
^ imageUrl
and an inspector on the `image` variable displays the painting on the Morph
tab.
Now to mold the IDE to your domain...
using Spotter to browser gtInspector* methods, a promising find is...
AbstractFileReference>>gitInspectorJpegIn:
from which I produced...
Painting >> gtInspectorJpegIn: composite
<gtInspectorPresentationOrder: 0>
composite morph
title: 'Painting';
display: [ ImageReadWriter formFromStream: self imageEntity readStream ]
Then inspecting the `paintings` variable and drilling down to a painting
pops up a DNU #imageEntity, which can be resolved by...
Painting >> imageEntity
^ imageEntity ifNil: [ imageEntity := (ZnEasy get: self imageUrl) entity ].
and you get to see the painting shown in the Inspector.
Now if I understand your question... "Do I need to make some more object to
get this working..."
I'd say... No. You only want one object for each painting. Once you have a
painting object, it should handle all getting all further data it needs for
itself.
You don't want duplicate objects each having half of the data.
can I for example name the function fromJson2 or fromJSONFromLink2 ?
>
By naming convention #fromJson: implies it sits on the class side.
To get further data for an existing object you want an instance-side
method, maybe named #getLink2Json.
HTH,
cheers -ben
March 10, 2019
Re: [Pharo-users] Pharo 7.0 image size
by Sven Van Caekenberghe
Hi,
I am confused by what you are reporting.
If you add 10.000 entries to the Transcript, then I don't see how that results in 1000s of those Strings being alive (and certainly not after a GC).
I tried the following (both with the Transcript window open and closed):
Transcript.
Transcript open.
Transcript clear.
1 to: 1e4 do: [ :each |
Transcript crShow: DateAndTime now asString , ' MARKTEST ' , each asString ].
3 timesRepeat: [ Smalltalk garbageCollect ].
[ | count |
count := 0.
String allSubInstancesDo: [ :each |
(each includesSubstring: 'MARKTEST') ifTrue: [ count := count + 1 ] ].
count ] value.
The count never went above 100. I am using Pharo 8 but 7 would be similar.
If you are retaining so many of the messages that you wrote to the Transcript, then you must be doing something else.
That being said, we do have an issue with the WriteStream held by the stream instance variable inside ThreadSafeTranscript. It is being reset from time to time and when #clear is called, but that does not bring down the size of the underlying collection below its 'one time peak'.
Sven
> On 8 Mar 2019, at 11:59, Trussardi Dario Romano <dario.trussardi(a)tiscali.it> wrote:
>
> Ciao,
>
> this morning i started with an image of about 240 MB.
>
> I have 3 System Browser open ( for a long time ).
>
> I close all the System Browser and save the image.
>
> The image size after the save is about 131 MB.
>
> The new SpaceTally printSpaceAnalysis report:
>
> Class code space # instances inst space percent inst average size
> Array 4115 561766 37353480 25.60 66.49
> ByteString 2942 249761 31313136 21.50 125.37
>
>
> The Transcript entry reference basically does not change:
>
> ByteString allInstances select:[ :i | i includesSubstring: 'NETWORK' ]
>
> where 'NETWORK' is a string used in the methods to add Transcript entry Transcript show: ...... NETWORK' ......' .
>
>
> The system found 2958 ByteString instances.... ( relative to the NETWORK )
>
> The system found 22655 ByteString instances.... ( relative to the CASH )
>
>
> Why are there many references in the system to the ByteString instances, created in the methods to report the data in Transcript ?
>
> Someone to considerations ?
>
> Thanks,
>
> Dario
>
>> Ciao,
>>
>> I thought that using Transcript as a report to analyze the operation of the code was a good thing - solution.
>>
>> Unfortunately, however, the size of the image continues to increase ( and I think it's due to the use of the transcript )
>>
>> and i can not find the solution to avoid the problem.
>>
>> I could create a file to report everything about the operations code, but then it becomes difficult to manage, or am i wrong?
>>
>> Other solutions - indications - references ?
>>
>> Thanks,
>>
>> Dario
>>
>>> Ciao,
>>>
>>> thanks.
>>>
>>> i have a Pharo 7.0 alpha build 1262.
>>>
>>> I development a Seaside application.
>>>
>>>> May be you have a lot of still open Seaside session, which if I remember
>>>> correctly are automatically shutdown after 10 min when not active.
>>>>
>>>> Looking at Seaside session instances may give clue.
>>>
>>> OK, i clear the seaside session with the relative seaside status Clear action.
>>>
>>>
>>>
>>> But the image size keeps increasing, without an apparent reason.
>>>
>>> The consideration that I can do and that in the method code i often use Transcript show: '.....NETWORK | CASH | .....' to check the correct functioning.
>>>
>>> With the SpaceTally printSpaceAnalysis i note:
>>>
>>> as of February 16th:
>>>
>>> Class code space # in stances inst space percent inst average size
>>> Array 4115 656764 43904528 23.30 66.85
>>> ByteString 2942 233871 27527272 14.60 117.70
>>>
>>>
>>> as of March 4th
>>> Class code space # instances inst space percent inst average size
>>> Array 4115 837017 50564552 23.40 60.41
>>> ByteString 2942 266620 31933216 14.80 119.77
>>>
>>> Now i do:
>>>
>>> ByteString allInstances select:[ :i | i includesSubstring: 'NETWORK' ]
>>>
>>> where 'NETWORK' is a string used in the Transcript show: ...... NETWORK' ......' report entry.
>>>
>>>
>>> The system found 3214 ByteString instances.... ( relative to the NETWORK )
>>>
>>> The system found 22650 ByteString instances.... ( relative to the CASH )
>>>
>>> The system found ..............
>>>
>>>
>>> Because ?????
>>>
>>>
>>> Does the system remember something about the string create for the Transcript show: entry ?
>>>
>>> I need to reset something?
>>>
>>> How can I analyze the situation?
>>>
>>> I follow some aByteString entry with the pointersTo method
>>>
>>> but for now I have not found the solution.
>>>
>>>
>>>
>>> Thanks,
>>>
>>> Dario
>>>
>>>
>>
>>
>
>
March 10, 2019