settingspec 0.1.0__tar.gz → 0.1.2__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.
Files changed (29) hide show
  1. {settingspec-0.1.0 → settingspec-0.1.2}/Cargo.lock +1 -1
  2. {settingspec-0.1.0 → settingspec-0.1.2}/Cargo.toml +1 -1
  3. settingspec-0.1.2/PKG-INFO +182 -0
  4. {settingspec-0.1.0 → settingspec-0.1.2}/README.md +9 -1
  5. {settingspec-0.1.0 → settingspec-0.1.2}/pyproject.toml +11 -1
  6. {settingspec-0.1.0 → settingspec-0.1.2}/src/cli.rs +8 -8
  7. {settingspec-0.1.0 → settingspec-0.1.2}/src/model.rs +10 -8
  8. settingspec-0.1.0/PKG-INFO +0 -9
  9. {settingspec-0.1.0 → settingspec-0.1.2}/LICENSE-APACHE +0 -0
  10. {settingspec-0.1.0 → settingspec-0.1.2}/LICENSE-MIT +0 -0
  11. {settingspec-0.1.0 → settingspec-0.1.2}/src/envfile.rs +0 -0
  12. {settingspec-0.1.0 → settingspec-0.1.2}/src/error.rs +0 -0
  13. {settingspec-0.1.0 → settingspec-0.1.2}/src/filter.rs +0 -0
  14. {settingspec-0.1.0 → settingspec-0.1.2}/src/generator/common.rs +0 -0
  15. {settingspec-0.1.0 → settingspec-0.1.2}/src/generator/env.rs +0 -0
  16. {settingspec-0.1.0 → settingspec-0.1.2}/src/generator/javascript.rs +0 -0
  17. {settingspec-0.1.0 → settingspec-0.1.2}/src/generator/json.rs +0 -0
  18. {settingspec-0.1.0 → settingspec-0.1.2}/src/generator/lua.rs +0 -0
  19. {settingspec-0.1.0 → settingspec-0.1.2}/src/generator/mod.rs +0 -0
  20. {settingspec-0.1.0 → settingspec-0.1.2}/src/generator/python.rs +0 -0
  21. {settingspec-0.1.0 → settingspec-0.1.2}/src/generator/toml.rs +0 -0
  22. {settingspec-0.1.0 → settingspec-0.1.2}/src/generator/tree.rs +0 -0
  23. {settingspec-0.1.0 → settingspec-0.1.2}/src/generator/typescript.rs +0 -0
  24. {settingspec-0.1.0 → settingspec-0.1.2}/src/generator/yaml.rs +0 -0
  25. {settingspec-0.1.0 → settingspec-0.1.2}/src/lib.rs +0 -0
  26. {settingspec-0.1.0 → settingspec-0.1.2}/src/main.rs +0 -0
  27. {settingspec-0.1.0 → settingspec-0.1.2}/src/parser.rs +0 -0
  28. {settingspec-0.1.0 → settingspec-0.1.2}/src/profile.rs +0 -0
  29. {settingspec-0.1.0 → settingspec-0.1.2}/src/resolver.rs +0 -0
@@ -564,7 +564,7 @@ dependencies = [
564
564
 
565
565
  [[package]]
566
566
  name = "settingspec"
567
- version = "0.1.0"
567
+ version = "0.1.2"
568
568
  dependencies = [
569
569
  "anyhow",
570
570
  "assert_cmd",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "settingspec"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  edition = "2024"
5
5
  description = "One file for all environments, all languages, all submodules."
6
6
  readme = "README.md"
@@ -0,0 +1,182 @@
1
+ Metadata-Version: 2.4
2
+ Name: settingspec
3
+ Version: 0.1.2
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
7
+ License-File: LICENSE-APACHE
8
+ License-File: LICENSE-MIT
9
+ Summary: One file for all environments, all languages, all submodules.
10
+ Keywords: configuration,settings,secrets,cli,command-line
11
+ Author: Arijit Basu <settingspec@arijitbasu.in>
12
+ Author-email: Arijit Basu <settingspec@arijitbasu.in>
13
+ License: MIT OR Apache-2.0
14
+ Requires-Python: >=3.8
15
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
16
+ Project-URL: Source Code, https://github.com/sayanarijit/settingspec
17
+
18
+ <p align="center">
19
+ <picture>
20
+ <source media="(prefers-color-scheme: dark)" srcset="https://s15.gifyu.com/images/buXVO.png">
21
+ <source media="(prefers-color-scheme: light)" srcset="https://s15.gifyu.com/images/buXZJ.png">
22
+ <img alt="The settingspec cover" width="600" src="https://s15.gifyu.com/images/buXZJ.png">
23
+ </picture>
24
+ </p>
25
+
26
+ [![SettingSpec Check](https://github.com/sayanarijit/settingspec/actions/workflows/settingspec-check.yml/badge.svg)](https://github.com/sayanarijit/settingspec/actions/workflows/settingspec-check.yml)
27
+ [![Crates.io Version](https://img.shields.io/crates/v/settingspec)](https://crates.io/crates/settingspec)
28
+ [![PyPI Version](https://img.shields.io/pypi/v/settingspec)](https://pypi.org/project/settingspec)
29
+ [![NPM Version](https://img.shields.io/npm/v/%40sayanarijit%2Fsettingspec)](https://www.npmjs.com/package/@sayanarijit/settingspec)
30
+
31
+ 1. [Concepts](#concepts)
32
+ 1. [Single file convenience](#single-file-convenience)
33
+ 2. [Declarative profiles / environments](#declarative-profiles-/-environments)
34
+ 3. [Language independent](#language-independent)
35
+ 4. [Easy secrets](#easy-secrets)
36
+ 1. [SecretSpec](#secretspec)
37
+ 2. [Dotenv](#dotenv)
38
+ 2. [Learn more](#learn-more)
39
+
40
+ ## Concepts
41
+
42
+ ### Single file convenience
43
+
44
+ With a single source of truth, i.e., `settingspec.toml`, you don't need to mentally merge settings from multiple files, say `common.toml`, `dev.toml`, `prod.toml`, etc. No surprise overwrites. One file for all environments, all languages, all submodules.
45
+
46
+ ### Declarative profiles / environments
47
+
48
+ ```toml
49
+ [spec] # Optional: Declare the specification here
50
+ profile.key = "SETTINGSPEC_PROFILE" # Default: Environment variable name to switch between profiles
51
+ profile.options = [ # Optional: Enables strict checking of per-profile declarations
52
+ "dev",
53
+ "stage",
54
+ "prod",
55
+ ]
56
+ profile.default = "dev" # Optional: Default profile when the switch is not set
57
+
58
+ [settings] # Declare the settings here with syntax: `<key>.<profile>.<directive> = <value>`
59
+ key1.default.val = "val1" # Default value for all profiles
60
+ key1.prod.val = "prod1" # Override the default value when SETTINGSPEC_PROFILE=prod
61
+
62
+ # Strictly define different values for different profiles
63
+ key2.dev.val = "dev2" # When SETTINGSPEC_PROFILE=dev, key2=dev2
64
+ key2.stage.val = "stage2"
65
+ key2.prod.val = "prod2"
66
+ ```
67
+
68
+ Overrides are intentional and kept in plain sight (see `key1`).
69
+
70
+ By not defining a default value, you can ensure that you never miss adding a value for a specific profile (e.g. this file will refuse to load if `key2.prod` declaration is missing).
71
+
72
+ ### Language independent
73
+
74
+ The command-line tool `settingspec` can export the final settings into well-known formats such as `toml`, `json`, `yaml`, etc., or hard-coded modules such as `.py`, `.js`, `.lua`, etc., write them to disk, print, or pipe them via stdin or even export as environment variables, allowing you to use a single `settingspec.toml` without worrying about the target language.
75
+
76
+ ```toml
77
+ [spec]
78
+ export.file = true # Default: Export all settings into settings.toml (or specify fine-grained file map)
79
+ # export.file = { # Optional: Fine-grained control over what to export
80
+ # "settings.json" = true,
81
+ # "settings.yaml" = {
82
+ # key1 = true,
83
+ # group1 = true,
84
+ # group2.subgroup = true,
85
+ # group3.subgroup.key1 = false,
86
+ # "#tag1" = true,
87
+ # },
88
+ # }
89
+ export.skip_gitignore = false # Default: Auto-append exported files to .gitignore if inside a git repo
90
+ export.mode = 0x600 # Default: File permission mode for the exported files
91
+ export.keep = false # Default: Cleanup the exported files after the program exits
92
+ export.stdout = "toml" # Optional: Print in toml format
93
+ export.env = "PREFIX_" # Optional: Export as environment variables prefixed with this string
94
+ export.stdin = "toml" # Optional: Pass settings to program stdin in specified format
95
+
96
+ [settings]
97
+ key1.default.val = "val1"
98
+ group1.key1.default.val = "group1val1"
99
+ group2.subgroup.key1.default.val = "group2val1"
100
+ group3.subgroup.key1.default.val = "group3val1"
101
+ group3.subgroup.key1.default.tags = ["tag1", "tag2"]
102
+ ```
103
+
104
+ Now export the final settings as declared.
105
+
106
+ ```bash
107
+ settingspec export
108
+ ```
109
+
110
+ Or directly run the program with exported settings.
111
+
112
+ ```bash
113
+ settingspec run -- [your program]...
114
+ ```
115
+
116
+ If no export option is specified, the default behavior is to export all settings into `settings.toml`.
117
+
118
+ > [!NOTE]
119
+ > If the target programming language supports null values, you can declare it as `key.default.null = true` in the settings section.
120
+
121
+ ### Easy secrets
122
+
123
+ Unlike regular settings, secrets aren't supposed to be easily visible. So, they are best declared inside hidden/encrypted files and passed via environment variables or via stdin.
124
+
125
+ However, with SettingSpec, we can ensure that they are actually set and also include them in the final exported settings.
126
+
127
+ #### SecretSpec
128
+
129
+ You can pair up SettingSpec with a declarative secrets manager such as [SecretSpec](https://secretspec.dev).
130
+
131
+ secretspec.toml
132
+
133
+ ```toml
134
+ [project]
135
+ name = "my-app"
136
+ revision = "1.0"
137
+
138
+ [profiles.default]
139
+ SECRET1 = { description = "Secret One", required = true }
140
+ SECRET2 = { description = "Secret Two", required = false }
141
+ ```
142
+
143
+ settingspec.toml
144
+
145
+ ```toml
146
+ [spec]
147
+ profile.options = ["dev", "stage", "prod"]
148
+
149
+ [settings]
150
+ secret1.default.env = "SECRET1" # Load value from $SECRET1
151
+
152
+ # Override the default value from environment variables
153
+ secret2.default.val = "defaultvalue" # Default value if $SECRET2 is not set
154
+ secret2.default.env = "SECRET2" # Load value from $SECRET2 if set
155
+ secret2.prod.env = "PRODSECRET" # Load value from $PRODSECRET if SETTINGSPEC_PROFILE=prod
156
+ ```
157
+
158
+ With these set up, run:
159
+
160
+ ```bash
161
+ secretspec run -- settingspec run -- [your program]...
162
+ ```
163
+
164
+ #### Dotenv
165
+
166
+ Or keep things simple with [Dotenv](https://www.dotenv.org).
167
+
168
+ ```toml
169
+ [spec]
170
+ profile.options = ["dev", "stage", "prod"]
171
+
172
+ envfile.default = ".env" # Load environment variables from this file for all profiles
173
+ envfile.prod = "-" # Load environment variables from stdin when SETTINGSPEC_PROFILE=prod
174
+
175
+ [settings]
176
+ secret1.default.env = "SECRET1" # Load value from $SECRET1
177
+ ```
178
+
179
+ ## Learn more
180
+
181
+ Check out the [settingspec.toml](./settingspec.toml) example file and [full specification](./SPECIFICATION.md) for more details.
182
+
@@ -10,7 +10,15 @@
10
10
  [![Crates.io Version](https://img.shields.io/crates/v/settingspec)](https://crates.io/crates/settingspec)
11
11
  [![PyPI Version](https://img.shields.io/pypi/v/settingspec)](https://pypi.org/project/settingspec)
12
12
  [![NPM Version](https://img.shields.io/npm/v/%40sayanarijit%2Fsettingspec)](https://www.npmjs.com/package/@sayanarijit/settingspec)
13
- [![Docker Image Version](https://img.shields.io/docker/v/sayanarijit/settingspec?label=docker)](https://hub.docker.com/r/sayanarijit/settingspec)
13
+
14
+ 1. [Concepts](#concepts)
15
+ 1. [Single file convenience](#single-file-convenience)
16
+ 2. [Declarative profiles / environments](#declarative-profiles-/-environments)
17
+ 3. [Language independent](#language-independent)
18
+ 4. [Easy secrets](#easy-secrets)
19
+ 1. [SecretSpec](#secretspec)
20
+ 2. [Dotenv](#dotenv)
21
+ 2. [Learn more](#learn-more)
14
22
 
15
23
  ## Concepts
16
24
 
@@ -10,4 +10,14 @@ classifiers = [
10
10
  "Programming Language :: Python :: Implementation :: CPython",
11
11
  "Programming Language :: Python :: Implementation :: PyPy",
12
12
  ]
13
- dynamic = ["version"]
13
+ dynamic = [
14
+ "version",
15
+ "description",
16
+ "readme",
17
+ "license",
18
+ "authors",
19
+ "keywords",
20
+ "urls",
21
+ ]
22
+ [tool.maturin]
23
+ bindings = "bin"
@@ -224,7 +224,7 @@ fn execute_run(ctx: &ExecutionContext, command_args: &[String]) -> Result<()> {
224
224
  Ok(())
225
225
  }
226
226
 
227
- pub fn write_export_file(path: &Path, content: &str, mode: u32) -> Result<()> {
227
+ pub fn write_export_file(path: &Path, content: &str, _mode: u32) -> Result<()> {
228
228
  if let Some(parent) = path.parent()
229
229
  && !parent.as_os_str().is_empty()
230
230
  {
@@ -236,7 +236,7 @@ pub fn write_export_file(path: &Path, content: &str, mode: u32) -> Result<()> {
236
236
  #[cfg(unix)]
237
237
  {
238
238
  use std::os::unix::fs::PermissionsExt;
239
- let perms = std::fs::Permissions::from_mode(mode);
239
+ let perms = std::fs::Permissions::from_mode(_mode);
240
240
  let _ = std::fs::set_permissions(path, perms);
241
241
  }
242
242
 
@@ -296,12 +296,12 @@ fn is_entry_in_gitignore(existing_content: &str, entry: &str) -> bool {
296
296
  }
297
297
  // In git, a pattern without '/' matches anywhere in the repository:
298
298
  // E.g. if .gitignore has "settings.toml", it matches "subdir/settings.toml".
299
- if !trimmed.starts_with('/') && !norm_line.contains('/') {
300
- if let Some((_, file_name)) = norm_entry.rsplit_once('/') {
301
- if file_name == norm_line {
302
- return true;
303
- }
304
- }
299
+ if !trimmed.starts_with('/')
300
+ && !norm_line.contains('/')
301
+ && let Some((_, file_name)) = norm_entry.rsplit_once('/')
302
+ && file_name == norm_line
303
+ {
304
+ return true;
305
305
  }
306
306
  }
307
307
  false
@@ -155,14 +155,16 @@ where
155
155
  D: Deserializer<'de>,
156
156
  {
157
157
  let val = i64::deserialize(deserializer)?;
158
- let mode_u32 = if val == 0x600 || val == 0o600 {
159
- 0o600
160
- } else if (0..=0o777).contains(&val) {
161
- val as u32
162
- } else {
163
- 0o600
164
- };
165
- Ok(mode_u32)
158
+ if (0..=0o777).contains(&val) {
159
+ return Ok(val as u32);
160
+ }
161
+ let hex = format!("{:x}", val);
162
+ if let Ok(octal) = u32::from_str_radix(&hex, 8)
163
+ && (0..=0o7777).contains(&octal)
164
+ {
165
+ return Ok(octal);
166
+ }
167
+ Ok(0o600)
166
168
  }
167
169
 
168
170
  /// A field that accepts either a boolean toggle or a string value in TOML.
@@ -1,9 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: settingspec
3
- Version: 0.1.0
4
- Classifier: Programming Language :: Rust
5
- Classifier: Programming Language :: Python :: Implementation :: CPython
6
- Classifier: Programming Language :: Python :: Implementation :: PyPy
7
- License-File: LICENSE-APACHE
8
- License-File: LICENSE-MIT
9
- Requires-Python: >=3.8
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes