or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# Pantsbuild Pants Contrib Spindle

1

2

A Pants build system plugin that enables automatic generation of Scala libraries from Thrift IDL files using Foursquare's Spindle code generator. This plugin integrates Spindle's thrift-to-Scala compilation into the Pants build pipeline, providing seamless dependency management and incremental compilation for large-scale projects.

3

4

## Package Information

5

6

- **Package Name**: pantsbuild.pants.contrib.spindle

7

- **Language**: Python

8

- **Installation**: `pip install pantsbuild.pants.contrib.spindle`

9

- **Plugin Type**: Pants build system contrib plugin

10

11

## Core Imports

12

13

```python

14

from pants.contrib.spindle.register import build_file_aliases, register_goals

15

from pants.contrib.spindle.targets.spindle_thrift_library import SpindleThriftLibrary

16

from pants.contrib.spindle.tasks.spindle_gen import SpindleGen

17

```

18

19

## Basic Usage

20

21

### Plugin Registration

22

23

This plugin is typically registered automatically when installed. In Pants configuration:

24

25

```python

26

# pants.ini or pants.toml

27

[DEFAULT]

28

# The plugin provides 'spindle_thrift_library' target type and 'spindle' task

29

```

30

31

### BUILD File Usage

32

33

```python

34

# In a BUILD file

35

spindle_thrift_library(

36

name='user-service-thrift',

37

sources=['user.thrift', 'profile.thrift'],

38

dependencies=[

39

'3rdparty:spindle-runtime',

40

],

41

)

42

```

43

44

### Command Line Usage

45

46

```bash

47

# Generate Scala code from Thrift files

48

pants gen.spindle src/main/thrift:user-service-thrift

49

50

# The generated Scala and Java files will be placed in the workspace

51

# under appropriate namespace directories

52

```

53

54

### Example Thrift File

55

56

```thrift

57

namespace java com.example.user

58

59

typedef string UserId

60

61

struct User {

62

1: required UserId id

63

2: required string name

64

3: optional string email

65

}

66

67

service UserService {

68

User getUser(1: UserId userId)

69

list<User> listUsers()

70

}

71

```

72

73

## Capabilities

74

75

### Plugin Registration

76

77

Registration functions that integrate the plugin with the Pants build system.

78

79

```python { .api }

80

def build_file_aliases():

81

"""

82

Returns build file aliases for the spindle plugin.

83

84

Returns:

85

BuildFileAliases: Aliases containing the 'spindle_thrift_library' target type

86

"""

87

88

def register_goals():

89

"""

90

Registers the 'spindle' task under the 'gen' goal.

91

92

Installs the SpindleGen task to be executed when 'gen.spindle' is invoked.

93

"""

94

```

95

96

### Target Types

97

98

Target type for defining Thrift libraries that will be compiled to Scala using Spindle.

99

100

```python { .api }

101

class SpindleThriftLibrary(ExportableJvmLibrary):

102

"""

103

A Scala library generated from Spindle IDL files.

104

105

This target type represents Thrift files that should be compiled to Scala

106

using the Spindle code generator. Inherits from ExportableJvmLibrary to

107

provide JVM library capabilities.

108

"""

109

110

def __init__(self, *args, **kwargs):

111

"""

112

Initialize a SpindleThriftLibrary target.

113

114

Automatically adds 'scala', 'codegen', and 'synthetic' labels to the target.

115

116

Args:

117

*args: Variable arguments passed to parent ExportableJvmLibrary

118

**kwargs: Keyword arguments passed to parent ExportableJvmLibrary

119

"""

120

```

121

122

### Code Generation Task

123

124

The main task that performs Thrift-to-Scala code generation using Spindle.

125

126

```python { .api }

127

class SpindleGen(NailgunTask):

128

"""

129

Task that generates Scala code from Thrift files using Spindle.

130

131

This task processes SpindleThriftLibrary targets, executes the Spindle

132

code generator, and creates synthetic Scala and Java library targets

133

with the generated code.

134

"""

135

136

@classmethod

137

def product_types(cls):

138

"""

139

Returns the product types produced by this task.

140

141

Returns:

142

list: ['scala'] - indicates this task produces Scala code

143

"""

144

145

@classmethod

146

def register_options(cls, register):

147

"""

148

Register command-line options for the SpindleGen task.

149

150

Args:

151

register: Option registration function

152

153

Registers:

154

--runtime-dependency: Runtime dependencies for generated code

155

--spindle-codegen tool: Spindle code generator tool configuration

156

"""

157

158

@property

159

def spindle_classpath(self):

160

"""

161

Get the classpath for the Spindle code generator tool.

162

163

Returns:

164

list: Classpath entries for spindle-codegen tool

165

"""

166

167

@property

168

def synthetic_target_extra_dependencies(self):

169

"""

170

Get additional dependencies for synthetic targets.

171

172

Returns:

173

set: Set of dependency targets from runtime-dependency option

174

"""

175

176

@property

177

def namespace_out(self):

178

"""

179

Get the output directory for generated code.

180

181

Returns:

182

str: Path to output directory (workdir/src/jvm)

183

"""

184

185

def codegen_targets(self):

186

"""

187

Get all targets that need code generation.

188

189

Returns:

190

list: List of SpindleThriftLibrary targets

191

"""

192

193

def sources_generated_by_target(self, target):

194

"""

195

Calculate the source files that will be generated for a target.

196

197

Args:

198

target: SpindleThriftLibrary target

199

200

Returns:

201

list: List of paths to generated source files

202

"""

203

204

def execute_codegen(self, targets):

205

"""

206

Execute the Spindle code generation process.

207

208

Args:

209

targets: List of SpindleThriftLibrary targets to process

210

211

Raises:

212

TaskError: If code generation fails

213

"""

214

215

def execute(self):

216

"""

217

Main execution method for the task.

218

219

Orchestrates the entire code generation process:

220

1. Identifies targets needing generation

221

2. Executes code generation for invalid targets

222

3. Creates synthetic Scala and Java library targets

223

4. Manages dependencies and build graph updates

224

5. Updates artifact cache if enabled

225

"""

226

```

227

228

### Utility Functions

229

230

Helper functions for calculating generated file paths and parsing Thrift files.

231

232

```python { .api }

233

def calculate_genfiles(source):

234

"""

235

Calculate which files will be generated from a Thrift source file.

236

237

Parses the Thrift file to extract namespace information and determines

238

the output file paths that Spindle will generate.

239

240

Args:

241

source (str): Path to Thrift source file relative to build root

242

243

Returns:

244

list: List of generated file basenames (without .scala/.java extensions)

245

246

Raises:

247

TaskError: If no Java namespace is found in the source file

248

"""

249

250

def calculate_scala_record_genfiles(namespace, source):

251

"""

252

Calculate generated file basenames for Scala records.

253

254

Args:

255

namespace (str): Java namespace from Thrift file

256

source (str): Path to source Thrift file

257

258

Returns:

259

list: List of generated file paths (basenames, add .scala/.java for full path)

260

"""

261

```

262

263

## Types

264

265

### Build System Integration Types

266

267

```python { .api }

268

BuildFileAliases:

269

"""

270

Pants build system type for registering target aliases.

271

Contains mappings from target names to target classes.

272

"""

273

274

TaskRegistrar:

275

"""

276

Pants build system type for registering tasks under goals.

277

Provides the task() method for goal registration.

278

"""

279

280

ExportableJvmLibrary:

281

"""

282

Base class for JVM library targets that can be exported.

283

Provides standard JVM library functionality and export capabilities.

284

"""

285

286

NailgunTask:

287

"""

288

Base class for tasks that execute JVM tools via Nailgun.

289

Provides JVM tool execution and classpath management.

290

"""

291

```

292

293

### Configuration Types

294

295

```python { .api }

296

JarDependency:

297

"""

298

Represents a JAR dependency with org, name, and revision.

299

Used to specify the Spindle codegen tool dependency.

300

"""

301

302

# Default tool configuration

303

SPINDLE_CODEGEN_DEFAULT = JarDependency(

304

org='com.foursquare',

305

name='spindle-codegen-binary_2.10',

306

rev='3.0.0-M7'

307

)

308

```

309

310

## Error Handling

311

312

The plugin raises `TaskError` exceptions in the following cases:

313

314

- **Missing namespace**: When a Thrift file lacks a required Java namespace declaration

315

- **Code generation failure**: When the Spindle code generator returns a non-zero exit code

316

- **File system errors**: When output directories cannot be created or accessed

317

318

## Plugin Configuration

319

320

### Default Settings

321

322

- **Runtime dependency**: `['3rdparty:spindle-runtime']`

323

- **Spindle version**: `3.0.0-M7` (com.foursquare:spindle-codegen-binary_2.10)

324

- **Templates**:

325

- Scala: `scala/record.ssp`

326

- Java: `javagen/record.ssp`

327

328

### Options

329

330

```bash

331

# Configure runtime dependencies

332

pants gen.spindle --runtime-dependency=path/to:runtime-dep

333

334

# Configure JVM options for code generation

335

pants gen.spindle --jvm-options="-Xmx2g -XX:MaxPermSize=256m"

336

```

337

338

## Generated Output

339

340

The plugin generates:

341

342

1. **Scala files**: `.scala` files containing Scala case classes and companion objects

343

2. **Java files**: `.java` files with Java representations for interoperability

344

3. **Synthetic targets**: Scala and Java library targets with proper dependency management

345

4. **Namespace structure**: Files organized according to Thrift namespace declarations

346

347

Generated files follow the pattern:

348

- Input: `com/example/user.thrift` with `namespace java com.example.user`

349

- Output: `src/jvm/com/example/user/user.scala` and `src/jvm/com/example/user/java_user.java`