gemmology-cdl-parser 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 gemmology.dev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,345 @@
1
+ Metadata-Version: 2.4
2
+ Name: gemmology-cdl-parser
3
+ Version: 1.0.0
4
+ Summary: Crystal Description Language (CDL) parser for crystallographic visualization
5
+ Author-email: Fabian Schuh <fabian@gemmology.dev>
6
+ Maintainer-email: Fabian Schuh <fabian@gemmology.dev>
7
+ License: MIT
8
+ Project-URL: Homepage, https://cdl-parser.gemmology.dev
9
+ Project-URL: Documentation, https://cdl-parser.gemmology.dev/docs
10
+ Project-URL: Repository, https://github.com/gemmology-dev/cdl-parser
11
+ Project-URL: Issues, https://github.com/gemmology-dev/cdl-parser/issues
12
+ Project-URL: Changelog, https://github.com/gemmology-dev/cdl-parser/blob/main/CHANGELOG.md
13
+ Keywords: crystallography,mineralogy,gemmology,parser,crystal,miller-index,crystal-morphology,visualization
14
+ Classifier: Development Status :: 5 - Production/Stable
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Intended Audience :: Education
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Topic :: Scientific/Engineering
25
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
26
+ Classifier: Topic :: Scientific/Engineering :: Visualization
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.10
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=7.0; extra == "dev"
33
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
34
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
35
+ Requires-Dist: mypy>=1.0; extra == "dev"
36
+ Provides-Extra: docs
37
+ Requires-Dist: mkdocs>=1.5; extra == "docs"
38
+ Requires-Dist: mkdocs-material>=9.0; extra == "docs"
39
+ Requires-Dist: mkdocstrings[python]>=0.24; extra == "docs"
40
+ Dynamic: license-file
41
+
42
+ # cdl-parser
43
+
44
+ [![PyPI version](https://badge.fury.io/py/cdl-parser.svg)](https://badge.fury.io/py/cdl-parser)
45
+ [![Python](https://img.shields.io/pypi/pyversions/cdl-parser.svg)](https://pypi.org/project/cdl-parser/)
46
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
47
+
48
+ **Crystal Description Language (CDL) Parser** - A Python library for parsing compact string notation describing crystal morphology for gemmological and mineralogical visualization.
49
+
50
+ Part of the [Gemmology Project](https://gemmology.dev).
51
+
52
+ ## Installation
53
+
54
+ ```bash
55
+ pip install cdl-parser
56
+ ```
57
+
58
+ ## Quick Start
59
+
60
+ ```python
61
+ from cdl_parser import parse_cdl
62
+
63
+ # Parse a simple octahedron
64
+ desc = parse_cdl("cubic[m3m]:{111}")
65
+ print(desc.system) # 'cubic'
66
+ print(desc.point_group) # 'm3m'
67
+
68
+ # Parse a truncated octahedron (diamond-like)
69
+ desc = parse_cdl("cubic[m3m]:{111}@1.0 + {100}@1.3")
70
+ print(len(desc.forms)) # 2
71
+
72
+ # Parse with twin specification
73
+ desc = parse_cdl("cubic[m3m]:{111} | twin(spinel)")
74
+ print(desc.twin.law) # 'spinel'
75
+ ```
76
+
77
+ ## CDL Specification
78
+
79
+ ### Syntax Overview
80
+
81
+ ```
82
+ system[point_group]:{form}@scale + {form}@scale | modification | twin(law)
83
+ ```
84
+
85
+ ### Crystal Systems
86
+
87
+ All 7 crystal systems are supported with their standard point groups:
88
+
89
+ | System | Default Point Group | All Point Groups |
90
+ |--------|---------------------|------------------|
91
+ | cubic | m3m | m3m, 432, -43m, m-3, 23 |
92
+ | hexagonal | 6/mmm | 6/mmm, 622, 6mm, -6m2, 6/m, -6, 6 |
93
+ | trigonal | -3m | -3m, 32, 3m, -3, 3 |
94
+ | tetragonal | 4/mmm | 4/mmm, 422, 4mm, -42m, 4/m, -4, 4 |
95
+ | orthorhombic | mmm | mmm, 222, mm2 |
96
+ | monoclinic | 2/m | 2/m, m, 2 |
97
+ | triclinic | -1 | -1, 1 |
98
+
99
+ ### Miller Indices
100
+
101
+ Forms are specified using Miller indices in curly braces:
102
+
103
+ ```python
104
+ # 3-index notation (hkl)
105
+ "{111}" # Octahedron face
106
+ "{100}" # Cube face
107
+ "{110}" # Dodecahedron face
108
+
109
+ # 4-index notation for hexagonal/trigonal (hkil where i = -(h+k))
110
+ "{10-10}" # Hexagonal prism
111
+ "{10-11}" # Rhombohedron
112
+ "{0001}" # Basal pinacoid
113
+ ```
114
+
115
+ ### Named Forms
116
+
117
+ Common forms can be referenced by name:
118
+
119
+ ```python
120
+ # Cubic named forms
121
+ "octahedron" # → {111}
122
+ "cube" # → {100}
123
+ "dodecahedron" # → {110}
124
+ "trapezohedron" # → {211}
125
+
126
+ # Hexagonal/Trigonal named forms
127
+ "prism" # → {10-10}
128
+ "basal" # → {0001}
129
+ "rhombohedron" # → {10-11}
130
+ ```
131
+
132
+ ### Scale Values
133
+
134
+ The `@scale` parameter controls the relative prominence of forms:
135
+
136
+ ```python
137
+ # Larger scale = form appears more (more truncation)
138
+ "{111}@1.0 + {100}@1.3" # Cube truncates the octahedron
139
+ "{111}@1.0 + {100}@0.3" # Octahedron with small cube facets
140
+ ```
141
+
142
+ ### Twin Laws
143
+
144
+ Named twin laws for common crystal twins:
145
+
146
+ ```python
147
+ # Contact twins
148
+ "twin(spinel)" # Spinel law (111) twin
149
+ "twin(brazil)" # Brazil law quartz twin
150
+ "twin(japan)" # Japan law quartz twin
151
+
152
+ # Penetration twins
153
+ "twin(fluorite)" # Fluorite interpenetration twin
154
+ "twin(iron_cross)" # Iron cross pyrite twin
155
+
156
+ # Cyclic twins
157
+ "twin(trilling,3)" # Three-fold cyclic twin
158
+ ```
159
+
160
+ ### Complete Examples
161
+
162
+ ```python
163
+ # Diamond (octahedron with cube truncation)
164
+ "cubic[m3m]:{111}@1.0 + {100}@0.3"
165
+
166
+ # Quartz prism with rhombohedron termination
167
+ "trigonal[-3m]:{10-10}@1.0 + {10-11}@0.8"
168
+
169
+ # Garnet (dodecahedron + trapezohedron)
170
+ "cubic[m3m]:{110}@1.0 + {211}@0.6"
171
+
172
+ # Spinel-law twinned octahedron
173
+ "cubic[m3m]:{111} | twin(spinel)"
174
+
175
+ # Fluorite cube
176
+ "cubic[m3m]:{100}"
177
+ ```
178
+
179
+ ## API Reference
180
+
181
+ ### Core Functions
182
+
183
+ #### `parse_cdl(text: str) -> CrystalDescription`
184
+
185
+ Parse a CDL string into a structured description.
186
+
187
+ ```python
188
+ from cdl_parser import parse_cdl
189
+
190
+ desc = parse_cdl("cubic[m3m]:{111}@1.0 + {100}@1.3")
191
+ ```
192
+
193
+ #### `validate_cdl(text: str) -> tuple[bool, str | None]`
194
+
195
+ Validate a CDL string without parsing.
196
+
197
+ ```python
198
+ from cdl_parser import validate_cdl
199
+
200
+ is_valid, error = validate_cdl("cubic[m3m]:{111}")
201
+ if not is_valid:
202
+ print(f"Error: {error}")
203
+ ```
204
+
205
+ ### Data Classes
206
+
207
+ #### `CrystalDescription`
208
+
209
+ Main output of CDL parsing.
210
+
211
+ ```python
212
+ @dataclass
213
+ class CrystalDescription:
214
+ system: str # Crystal system
215
+ point_group: str # Point group symbol
216
+ forms: List[CrystalForm] # Crystal forms
217
+ modifications: List[Modification] # Morphological mods
218
+ twin: Optional[TwinSpec] # Twin specification
219
+ ```
220
+
221
+ #### `MillerIndex`
222
+
223
+ Miller index representation.
224
+
225
+ ```python
226
+ @dataclass
227
+ class MillerIndex:
228
+ h: int
229
+ k: int
230
+ l: int
231
+ i: Optional[int] = None # For 4-index notation
232
+
233
+ def as_tuple(self) -> tuple[int, ...]
234
+ def as_3index(self) -> tuple[int, int, int]
235
+ ```
236
+
237
+ #### `CrystalForm`
238
+
239
+ A crystal form with scale.
240
+
241
+ ```python
242
+ @dataclass
243
+ class CrystalForm:
244
+ miller: MillerIndex
245
+ scale: float = 1.0
246
+ name: Optional[str] = None
247
+ ```
248
+
249
+ ### Constants
250
+
251
+ ```python
252
+ from cdl_parser import (
253
+ CRYSTAL_SYSTEMS, # Set of system names
254
+ POINT_GROUPS, # Dict[system, Set[groups]]
255
+ DEFAULT_POINT_GROUPS, # Dict[system, default_group]
256
+ NAMED_FORMS, # Dict[name, (h, k, l)]
257
+ TWIN_LAWS, # Set of twin law names
258
+ )
259
+ ```
260
+
261
+ ### Exceptions
262
+
263
+ ```python
264
+ from cdl_parser import ParseError, ValidationError
265
+
266
+ try:
267
+ desc = parse_cdl("invalid{{{")
268
+ except ParseError as e:
269
+ print(f"Syntax error at position {e.position}: {e.message}")
270
+ ```
271
+
272
+ ## CLI Usage
273
+
274
+ ```bash
275
+ # Parse and display
276
+ cdl parse "cubic[m3m]:{111}@1.0 + {100}@1.3"
277
+
278
+ # Validate
279
+ cdl validate "cubic[m3m]:{111}"
280
+
281
+ # Output as JSON
282
+ cdl parse "cubic[m3m]:{111}" --json
283
+
284
+ # List available options
285
+ cdl --list-systems
286
+ cdl --list-point-groups
287
+ cdl --list-forms
288
+ cdl --list-twins
289
+ ```
290
+
291
+ ## Integration with Other Packages
292
+
293
+ cdl-parser is designed to work with the Gemmology Project ecosystem:
294
+
295
+ ```python
296
+ from cdl_parser import parse_cdl
297
+ from crystal_geometry import cdl_to_geometry
298
+ from crystal_renderer import generate_cdl_svg, generate_geometry_svg
299
+
300
+ # Option 1: Direct CDL string to SVG
301
+ cdl = "cubic[m3m]:{111}@1.0 + {100}@1.3"
302
+ generate_cdl_svg(cdl, "crystal.svg")
303
+
304
+ # Option 2: Parse, then generate geometry for custom processing
305
+ desc = parse_cdl(cdl)
306
+ geometry = cdl_to_geometry(desc)
307
+
308
+ # Render geometry directly
309
+ generate_geometry_svg(geometry.vertices, geometry.faces, "geometry.svg")
310
+ ```
311
+
312
+ ## Development
313
+
314
+ ```bash
315
+ # Clone the repository
316
+ git clone https://github.com/gemmology-dev/cdl-parser.git
317
+ cd cdl-parser
318
+
319
+ # Install with dev dependencies
320
+ pip install -e ".[dev]"
321
+
322
+ # Run tests
323
+ pytest
324
+
325
+ # Type checking
326
+ mypy src/cdl_parser
327
+
328
+ # Linting
329
+ ruff check src/cdl_parser
330
+ ```
331
+
332
+ ## Documentation
333
+
334
+ Full documentation is available at [cdl-parser.gemmology.dev](https://cdl-parser.gemmology.dev).
335
+
336
+ ## License
337
+
338
+ MIT License - see [LICENSE](LICENSE) for details.
339
+
340
+ ## Related Projects
341
+
342
+ - [crystal-geometry](https://github.com/gemmology-dev/crystal-geometry) - 3D geometry from CDL
343
+ - [mineral-database](https://github.com/gemmology-dev/mineral-database) - Mineral presets
344
+ - [crystal-renderer](https://github.com/gemmology-dev/crystal-renderer) - SVG/3D rendering
345
+ - [gemmology-plugin](https://github.com/gemmology-dev/gemmology-plugin) - Claude Code plugin
@@ -0,0 +1,304 @@
1
+ # cdl-parser
2
+
3
+ [![PyPI version](https://badge.fury.io/py/cdl-parser.svg)](https://badge.fury.io/py/cdl-parser)
4
+ [![Python](https://img.shields.io/pypi/pyversions/cdl-parser.svg)](https://pypi.org/project/cdl-parser/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ **Crystal Description Language (CDL) Parser** - A Python library for parsing compact string notation describing crystal morphology for gemmological and mineralogical visualization.
8
+
9
+ Part of the [Gemmology Project](https://gemmology.dev).
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ pip install cdl-parser
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```python
20
+ from cdl_parser import parse_cdl
21
+
22
+ # Parse a simple octahedron
23
+ desc = parse_cdl("cubic[m3m]:{111}")
24
+ print(desc.system) # 'cubic'
25
+ print(desc.point_group) # 'm3m'
26
+
27
+ # Parse a truncated octahedron (diamond-like)
28
+ desc = parse_cdl("cubic[m3m]:{111}@1.0 + {100}@1.3")
29
+ print(len(desc.forms)) # 2
30
+
31
+ # Parse with twin specification
32
+ desc = parse_cdl("cubic[m3m]:{111} | twin(spinel)")
33
+ print(desc.twin.law) # 'spinel'
34
+ ```
35
+
36
+ ## CDL Specification
37
+
38
+ ### Syntax Overview
39
+
40
+ ```
41
+ system[point_group]:{form}@scale + {form}@scale | modification | twin(law)
42
+ ```
43
+
44
+ ### Crystal Systems
45
+
46
+ All 7 crystal systems are supported with their standard point groups:
47
+
48
+ | System | Default Point Group | All Point Groups |
49
+ |--------|---------------------|------------------|
50
+ | cubic | m3m | m3m, 432, -43m, m-3, 23 |
51
+ | hexagonal | 6/mmm | 6/mmm, 622, 6mm, -6m2, 6/m, -6, 6 |
52
+ | trigonal | -3m | -3m, 32, 3m, -3, 3 |
53
+ | tetragonal | 4/mmm | 4/mmm, 422, 4mm, -42m, 4/m, -4, 4 |
54
+ | orthorhombic | mmm | mmm, 222, mm2 |
55
+ | monoclinic | 2/m | 2/m, m, 2 |
56
+ | triclinic | -1 | -1, 1 |
57
+
58
+ ### Miller Indices
59
+
60
+ Forms are specified using Miller indices in curly braces:
61
+
62
+ ```python
63
+ # 3-index notation (hkl)
64
+ "{111}" # Octahedron face
65
+ "{100}" # Cube face
66
+ "{110}" # Dodecahedron face
67
+
68
+ # 4-index notation for hexagonal/trigonal (hkil where i = -(h+k))
69
+ "{10-10}" # Hexagonal prism
70
+ "{10-11}" # Rhombohedron
71
+ "{0001}" # Basal pinacoid
72
+ ```
73
+
74
+ ### Named Forms
75
+
76
+ Common forms can be referenced by name:
77
+
78
+ ```python
79
+ # Cubic named forms
80
+ "octahedron" # → {111}
81
+ "cube" # → {100}
82
+ "dodecahedron" # → {110}
83
+ "trapezohedron" # → {211}
84
+
85
+ # Hexagonal/Trigonal named forms
86
+ "prism" # → {10-10}
87
+ "basal" # → {0001}
88
+ "rhombohedron" # → {10-11}
89
+ ```
90
+
91
+ ### Scale Values
92
+
93
+ The `@scale` parameter controls the relative prominence of forms:
94
+
95
+ ```python
96
+ # Larger scale = form appears more (more truncation)
97
+ "{111}@1.0 + {100}@1.3" # Cube truncates the octahedron
98
+ "{111}@1.0 + {100}@0.3" # Octahedron with small cube facets
99
+ ```
100
+
101
+ ### Twin Laws
102
+
103
+ Named twin laws for common crystal twins:
104
+
105
+ ```python
106
+ # Contact twins
107
+ "twin(spinel)" # Spinel law (111) twin
108
+ "twin(brazil)" # Brazil law quartz twin
109
+ "twin(japan)" # Japan law quartz twin
110
+
111
+ # Penetration twins
112
+ "twin(fluorite)" # Fluorite interpenetration twin
113
+ "twin(iron_cross)" # Iron cross pyrite twin
114
+
115
+ # Cyclic twins
116
+ "twin(trilling,3)" # Three-fold cyclic twin
117
+ ```
118
+
119
+ ### Complete Examples
120
+
121
+ ```python
122
+ # Diamond (octahedron with cube truncation)
123
+ "cubic[m3m]:{111}@1.0 + {100}@0.3"
124
+
125
+ # Quartz prism with rhombohedron termination
126
+ "trigonal[-3m]:{10-10}@1.0 + {10-11}@0.8"
127
+
128
+ # Garnet (dodecahedron + trapezohedron)
129
+ "cubic[m3m]:{110}@1.0 + {211}@0.6"
130
+
131
+ # Spinel-law twinned octahedron
132
+ "cubic[m3m]:{111} | twin(spinel)"
133
+
134
+ # Fluorite cube
135
+ "cubic[m3m]:{100}"
136
+ ```
137
+
138
+ ## API Reference
139
+
140
+ ### Core Functions
141
+
142
+ #### `parse_cdl(text: str) -> CrystalDescription`
143
+
144
+ Parse a CDL string into a structured description.
145
+
146
+ ```python
147
+ from cdl_parser import parse_cdl
148
+
149
+ desc = parse_cdl("cubic[m3m]:{111}@1.0 + {100}@1.3")
150
+ ```
151
+
152
+ #### `validate_cdl(text: str) -> tuple[bool, str | None]`
153
+
154
+ Validate a CDL string without parsing.
155
+
156
+ ```python
157
+ from cdl_parser import validate_cdl
158
+
159
+ is_valid, error = validate_cdl("cubic[m3m]:{111}")
160
+ if not is_valid:
161
+ print(f"Error: {error}")
162
+ ```
163
+
164
+ ### Data Classes
165
+
166
+ #### `CrystalDescription`
167
+
168
+ Main output of CDL parsing.
169
+
170
+ ```python
171
+ @dataclass
172
+ class CrystalDescription:
173
+ system: str # Crystal system
174
+ point_group: str # Point group symbol
175
+ forms: List[CrystalForm] # Crystal forms
176
+ modifications: List[Modification] # Morphological mods
177
+ twin: Optional[TwinSpec] # Twin specification
178
+ ```
179
+
180
+ #### `MillerIndex`
181
+
182
+ Miller index representation.
183
+
184
+ ```python
185
+ @dataclass
186
+ class MillerIndex:
187
+ h: int
188
+ k: int
189
+ l: int
190
+ i: Optional[int] = None # For 4-index notation
191
+
192
+ def as_tuple(self) -> tuple[int, ...]
193
+ def as_3index(self) -> tuple[int, int, int]
194
+ ```
195
+
196
+ #### `CrystalForm`
197
+
198
+ A crystal form with scale.
199
+
200
+ ```python
201
+ @dataclass
202
+ class CrystalForm:
203
+ miller: MillerIndex
204
+ scale: float = 1.0
205
+ name: Optional[str] = None
206
+ ```
207
+
208
+ ### Constants
209
+
210
+ ```python
211
+ from cdl_parser import (
212
+ CRYSTAL_SYSTEMS, # Set of system names
213
+ POINT_GROUPS, # Dict[system, Set[groups]]
214
+ DEFAULT_POINT_GROUPS, # Dict[system, default_group]
215
+ NAMED_FORMS, # Dict[name, (h, k, l)]
216
+ TWIN_LAWS, # Set of twin law names
217
+ )
218
+ ```
219
+
220
+ ### Exceptions
221
+
222
+ ```python
223
+ from cdl_parser import ParseError, ValidationError
224
+
225
+ try:
226
+ desc = parse_cdl("invalid{{{")
227
+ except ParseError as e:
228
+ print(f"Syntax error at position {e.position}: {e.message}")
229
+ ```
230
+
231
+ ## CLI Usage
232
+
233
+ ```bash
234
+ # Parse and display
235
+ cdl parse "cubic[m3m]:{111}@1.0 + {100}@1.3"
236
+
237
+ # Validate
238
+ cdl validate "cubic[m3m]:{111}"
239
+
240
+ # Output as JSON
241
+ cdl parse "cubic[m3m]:{111}" --json
242
+
243
+ # List available options
244
+ cdl --list-systems
245
+ cdl --list-point-groups
246
+ cdl --list-forms
247
+ cdl --list-twins
248
+ ```
249
+
250
+ ## Integration with Other Packages
251
+
252
+ cdl-parser is designed to work with the Gemmology Project ecosystem:
253
+
254
+ ```python
255
+ from cdl_parser import parse_cdl
256
+ from crystal_geometry import cdl_to_geometry
257
+ from crystal_renderer import generate_cdl_svg, generate_geometry_svg
258
+
259
+ # Option 1: Direct CDL string to SVG
260
+ cdl = "cubic[m3m]:{111}@1.0 + {100}@1.3"
261
+ generate_cdl_svg(cdl, "crystal.svg")
262
+
263
+ # Option 2: Parse, then generate geometry for custom processing
264
+ desc = parse_cdl(cdl)
265
+ geometry = cdl_to_geometry(desc)
266
+
267
+ # Render geometry directly
268
+ generate_geometry_svg(geometry.vertices, geometry.faces, "geometry.svg")
269
+ ```
270
+
271
+ ## Development
272
+
273
+ ```bash
274
+ # Clone the repository
275
+ git clone https://github.com/gemmology-dev/cdl-parser.git
276
+ cd cdl-parser
277
+
278
+ # Install with dev dependencies
279
+ pip install -e ".[dev]"
280
+
281
+ # Run tests
282
+ pytest
283
+
284
+ # Type checking
285
+ mypy src/cdl_parser
286
+
287
+ # Linting
288
+ ruff check src/cdl_parser
289
+ ```
290
+
291
+ ## Documentation
292
+
293
+ Full documentation is available at [cdl-parser.gemmology.dev](https://cdl-parser.gemmology.dev).
294
+
295
+ ## License
296
+
297
+ MIT License - see [LICENSE](LICENSE) for details.
298
+
299
+ ## Related Projects
300
+
301
+ - [crystal-geometry](https://github.com/gemmology-dev/crystal-geometry) - 3D geometry from CDL
302
+ - [mineral-database](https://github.com/gemmology-dev/mineral-database) - Mineral presets
303
+ - [crystal-renderer](https://github.com/gemmology-dev/crystal-renderer) - SVG/3D rendering
304
+ - [gemmology-plugin](https://github.com/gemmology-dev/gemmology-plugin) - Claude Code plugin