Skip to content

Commit

Permalink
Update GraphViz (#8)
Browse files Browse the repository at this point in the history
* Update GraphViz

* Update Snapshots + remove linux test files

* Remove linux directive

* Revert "Remove linux directive"

This reverts commit 001808b.

* Fix error on linux

* Update package version

* Update macOS CI

* Fix Linux ci

* Fix everything
  • Loading branch information
ctreffs authored Apr 21, 2023
1 parent 3d46e60 commit 33a5749
Show file tree
Hide file tree
Showing 16 changed files with 169 additions and 166 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app

- name: Test
run: swift test -v --skip-update --parallel --enable-code-coverage
run: swift test --parallel --enable-code-coverage
env:
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer

Expand Down
8 changes: 4 additions & 4 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"pins": [
{
"package": "GraphViz",
"repositoryURL": "https://github.com/ctreffs/GraphViz.git",
"repositoryURL": "https://github.com/SwiftDocOrg/GraphViz.git",
"state": {
"branch": "master",
"revision": "b24203b1468e8e2faf89a907b268af5d73a18b42",
"version": null
"branch": null,
"revision": "74b6cbd8c5ecea9f64d84c4e1c88d65604dd033f",
"version": "0.4.1"
}
},
{
Expand Down
19 changes: 13 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
// swift-tools-version:5.2
// swift-tools-version:5.3

import PackageDescription

let package = Package(
name: "FirebladeGraph",
platforms: [
.macOS(.v11),
.iOS(.v13),
],
products: [
.library(
name: "FirebladeGraph",
targets: ["FirebladeGraph"]),
targets: ["FirebladeGraph"]
),
],
dependencies: [
.package(url: "https://github.com/ctreffs/GraphViz.git", .branch("master")),
.package(url: "https://github.com/SwiftDocOrg/GraphViz.git", from: "0.4.1"),
.package(url: "https://github.com/davecom/SwiftGraph.git", from: "3.1.0"),
.package(name: "SnapshotTesting", url: "https://github.com/pointfreeco/swift-snapshot-testing.git", from: "1.11.0")
.package(name: "SnapshotTesting", url: "https://github.com/pointfreeco/swift-snapshot-testing.git", from: "1.11.0"),
],
targets: [
.target(
name: "FirebladeGraph",
dependencies: ["GraphViz", "SwiftGraph"]),
dependencies: ["GraphViz", "SwiftGraph"]
),
.testTarget(
name: "FirebladeGraphTests",
dependencies: ["FirebladeGraph", "SnapshotTesting"]),
dependencies: ["FirebladeGraph", "SnapshotTesting"]
),
]
)
64 changes: 43 additions & 21 deletions Sources/FirebladeGraph/GraphvizRepresentable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,30 @@

import struct Foundation.Data
import struct Foundation.UUID
import DOT
import GraphViz

public protocol GraphVizNodeRepresentable {
func graphVizNodeDescription() -> String
}

extension GraphVizNodeRepresentable {
internal func graphVizNode() -> GraphViz.Node {
func graphVizNode() -> GraphViz.Node {
.init(graphVizNodeDescription())
}
}

extension String: GraphVizNodeRepresentable {
public func graphVizNodeDescription() -> String { self }
}

extension Int: GraphVizNodeRepresentable {
public func graphVizNodeDescription() -> String { "\(self)" }
}

extension UInt: GraphVizNodeRepresentable {
public func graphVizNodeDescription() -> String { "\(self)" }
}

extension UInt8: GraphVizNodeRepresentable {
public func graphVizNodeDescription() -> String { "\(self)" }
}
Expand All @@ -38,32 +40,52 @@ extension UUID: GraphVizNodeRepresentable {
}

public protocol GraphVizRenderable {
func renderGraph(as format: Format) -> Data?
func renderGraph(as format: Format, completion: @escaping (Result<Data, Swift.Error>) -> Void)
}

public enum ImageError: Swift.Error {
case failedToCreateImage(_ from: Data)
}

#if canImport(AppKit)
import class AppKit.NSImage
public typealias Image = NSImage
extension GraphVizRenderable {
public func renderGraphAsImage() -> Image? {
guard let data = renderGraph(as: .png) else {
return nil
}
import class AppKit.NSImage
public typealias Image = NSImage
public extension GraphVizRenderable {
func renderGraphAsImage(completion: @escaping (Result<Image, Swift.Error>) -> Void) {
renderGraph(as: .png) { result in
switch result {
case let .success(data):
if let image = Image(data: data) {
completion(.success(image))
} else {
completion(.failure(ImageError.failedToCreateImage(data)))
}

return Image(data: data)
case let .failure(failure):
completion(.failure(failure))
}
}
}
}
}

#elseif canImport(UIKit)
import class UIKit.UIImage
public typealias Image = UIImage
extension GraphVizRenderable {
public final func renderGraphAsImage() -> Image? {
guard let data = renderGraph(as: .png) else {
return nil
}
import class UIKit.UIImage
public typealias Image = UIImage
public extension GraphVizRenderable {
func renderGraphAsImage(completion: @escaping (Result<Image, Swift.Error>) -> Void) {
renderGraph(as: .png) { result in
switch result {
case let .success(data):
if let image = Image(data: data) {
completion(.success(image))
} else {
completion(.failure(ImageError.failedToCreateImage(data)))
}

return Image(data: data)
case let .failure(failure):
completion(.failure(failure))
}
}
}
}
}
#endif
10 changes: 3 additions & 7 deletions Sources/FirebladeGraph/Node+Graphviz.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,18 @@
// Created by Christian Treffs on 24.03.20.
//

import GraphViz
import struct Foundation.Data
import GraphViz

extension Node: GraphVizRenderable where Content: GraphVizNodeRepresentable {
public final func renderGraph(as format: Format) -> Data? {
public final func renderGraph(as format: Format, completion: @escaping (Result<Data, Swift.Error>) -> Void) {
var graph = Graph(directed: true, strict: true)

descend { node in
node.renderNode(in: &graph)
}

do {
return try graph.render(using: .dot, to: format)
} catch {
return nil
}
graph.render(using: .dot, to: format, completion: completion)
}

final func renderNode(in graph: inout GraphViz.Graph) {
Expand Down
28 changes: 16 additions & 12 deletions Sources/FirebladeGraph/Node.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ open class Node<Content> {

public init(_ content: Content) {
self.content = content
self.children = []
children = []
}

deinit {
Expand Down Expand Up @@ -164,66 +164,70 @@ open class Node<Content> {
/// Splitting the implementation of the update away from the update call
/// itself allows the detail to be overridden without disrupting the
/// general sequence of updateFromParent (e.g. raising events).
open func updateFromParent() {
}
open func updateFromParent() {}

open func childrenNeedingUpdate() -> AnyIterator<ChildNode> {
AnyIterator(children.makeIterator())
}
}

// MARK: Equatable

extension Node: Equatable where Content: Equatable {
public static func == (lhs: Node<Content>, rhs: Node<Content>) -> Bool {
lhs.content == rhs.content
}
}

// MARK: Comparable

extension Node: Comparable where Content: Comparable {
public static func < (lhs: Node<Content>, rhs: Node<Content>) -> Bool {
lhs.content < rhs.content
}
}

// MARK: CustomStringConvertible

extension Node: CustomStringConvertible {
open var description: String {
public var description: String {
"<\(type(of: self))>"
}
}

// MARK: CustomDebugStringConvertible

extension Node: CustomDebugStringConvertible {
open var debugDescription: String {
public var debugDescription: String {
"<\(type(of: self)) \(content)>"
}
}

// MARK: Recursive description
extension Node {

public extension Node {
/// Recursively descripes this node and all it's children.
public var descriptionDescending: String {
var descriptionDescending: String {
describeDescending(self) { $0.description }
}

/// Recursively debug descripes this node and all it's children.
public var debugDescriptionDescending: String {
var debugDescriptionDescending: String {
describeDescending(self) { $0.debugDescription }
}

/// Recursively describe given node and all it's children using a given closure.
/// - Parameter node: the start node.
/// - Parameter level: current indentation level.
/// - Parameter closure: a closure to apply for each node.
public func describeDescending(_ node: Node<Content>, _ level: Int = 0, using closure: (Node<Content>) -> String) -> String {
func describeDescending(_ node: Node<Content>, _ level: Int = 0, using closure: (Node<Content>) -> String) -> String {
let prefix = String(repeating: " ", count: level) + ""
return prefix + closure(node) + "\n" + self.children.map { $0.describeDescending($0, level + 1, using: closure) }.joined()
return prefix + closure(node) + "\n" + children.map { $0.describeDescending($0, level + 1, using: closure) }.joined()
}
}

extension Node where Content == Void {
public convenience init() {
public extension Node where Content == Void {
convenience init() {
self.init(())
}
}
29 changes: 10 additions & 19 deletions Sources/FirebladeGraph/SwiftGraph+Graphviz.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,29 @@
// Created by Christian Treffs on 24.03.20.
//

import DOT
import Foundation
import GraphViz
@_exported import SwiftGraph

extension UniqueElementsGraph: GraphVizRenderable where V: GraphVizNodeRepresentable {
public final func renderGraph(as format: Format) -> Data? {
drawGraphUnweigted(self, as: format)
public final func renderGraph(as format: Format, completion: @escaping (Result<Data, Swift.Error>) -> Void) {
drawGraphUnweigted(self, as: format, completion: completion)
}
}

extension UnweightedGraph: GraphVizRenderable where V: GraphVizNodeRepresentable {
public final func renderGraph(as format: Format) -> Data? {
drawGraphUnweigted(self, as: format)
public final func renderGraph(as format: Format, completion: @escaping (Result<Data, Swift.Error>) -> Void) {
drawGraphUnweigted(self, as: format, completion: completion)
}
}

extension WeightedGraph: GraphVizRenderable where V: GraphVizNodeRepresentable, W: Numeric {
public final func renderGraph(as format: Format) -> Data? {
drawGraphWeigted(self, as: format)
public final func renderGraph(as format: Format, completion: @escaping (Result<Data, Swift.Error>) -> Void) {
drawGraphWeigted(self, as: format, completion: completion)
}
}

private func drawGraphUnweigted<G>(_ graph: G, as format: Format) -> Data? where G: SwiftGraph.Graph, G.V: GraphVizNodeRepresentable {
private func drawGraphUnweigted<G>(_ graph: G, as format: Format, completion: @escaping (Result<Data, Swift.Error>) -> Void) where G: SwiftGraph.Graph, G.V: GraphVizNodeRepresentable {
let directed = graph.isDAG
var graphvizGraph = Graph(directed: directed, strict: true)

Expand All @@ -47,14 +46,10 @@ private func drawGraphUnweigted<G>(_ graph: G, as format: Format) -> Data? where

let layout: LayoutAlgorithm = directed ? .dot : .sfdp

do {
return try graphvizGraph.render(using: layout, to: format)
} catch {
return nil
}
graphvizGraph.render(using: layout, to: format, completion: completion)
}

private func drawGraphWeigted<G, W>(_ graph: G, as format: Format) -> Data? where G: SwiftGraph.Graph, G.V: GraphVizNodeRepresentable, G.E == WeightedEdge<W>, W: Numeric {
private func drawGraphWeigted<G, W>(_ graph: G, as format: Format, completion: @escaping (Result<Data, Swift.Error>) -> Void) where G: SwiftGraph.Graph, G.V: GraphVizNodeRepresentable, G.E == WeightedEdge<W>, W: Numeric {
let directed = graph.isDAG
var graphvizGraph = Graph(directed: directed, strict: true)

Expand All @@ -76,9 +71,5 @@ private func drawGraphWeigted<G, W>(_ graph: G, as format: Format) -> Data? wher

let layout: LayoutAlgorithm = directed ? .dot : .sfdp

do {
return try graphvizGraph.render(using: layout, to: format)
} catch {
return nil
}
graphvizGraph.render(using: layout, to: format, completion: completion)
}
Loading

0 comments on commit 33a5749

Please sign in to comment.