Skip to content

Commit

Permalink
Move config to pyproject.yaml (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
codingjoe authored Nov 28, 2023
1 parent d2cb610 commit df44b1b
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 237 deletions.
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,23 @@ INSTALLED_APPS = [
]
```

### 2. Create an `importmap.toml` file
### 2. Configuring an import map

This should live next to your `manage.py` file.
Here you'll add a list of "packages" you want to use.
You JavaScript dependencies are conveniently located in your`pyproject.toml` file.

The "name" can be anything, but should probably be the same as what it you would import from in typical bundling setups (i.e. `import React from "react"`).

The "source" will get passed on to the [jspm.org generator](https://jspm.org/docs/api#install), but is basically the `<npm package>@<version>` you want to use.
They are listed under `[tool.importmap.dependencies]` and you can add them there. The format is `name = "version"`,
similar to how you would add a dependency to your `package.json` file.

```toml
[[packages]]
name = "react"
source = "[email protected]"
# pyproject.toml
[tool.importmap.dependencies]
react = "17.0.2"
react-dom = "17.0.2"
```

[jspm.org generator](https://jspm.org/docs/api#install) is used lock and serve the dependencies,
but is basically just like installing them via `npm i <npm package>@<version>`.

### 3. Run `importmap_generate`

To resolve the import map, you'll need to run `python manage.py importmap_generate`.
Expand Down
59 changes: 17 additions & 42 deletions importmap/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,22 @@
import json
import logging
import os
from pathlib import Path

import tomli
from marshmallow import Schema, fields
try:
import tomllib
except ImportError:
import tomli as tomllib

from .generator import ImportmapGenerator

logger = logging.getLogger(__name__)


DEFAULT_CONFIG_FILENAME = "importmap.toml"
DEFAULT_CONFIG_FILENAME = "pyproject.toml"
DEFAULT_LOCK_FILENAME = "importmap.lock"


class PackageSchema(Schema):
name = fields.String(required=True)
source = fields.String(required=True)
# preload
# vendor, or vendor all is one option?


class ConfigSchema(Schema):
packages = fields.List(fields.Nested(PackageSchema), required=True)


class LockfileSchema(Schema):
config_hash = fields.String(required=True)
importmap = fields.Dict(required=True)
importmap_dev = fields.Dict(required=True)


def hash_for_data(data):
return hashlib.md5(json.dumps(data, sort_keys=True).encode("utf-8")).hexdigest()

Expand All @@ -42,8 +28,8 @@ def __init__(
config_filename=DEFAULT_CONFIG_FILENAME,
lock_filename=DEFAULT_LOCK_FILENAME,
):
self.config_filename = config_filename
self.lock_filename = lock_filename
self.config_file = Path(config_filename)
self.lock_file = Path(lock_filename)
self.load()

@classmethod
Expand All @@ -70,7 +56,7 @@ def load(self):
# No config = no map and no lockfile
self.map = {}
self.map_dev = {}
self.delete_lockfile()
self.lock_file.unlink(missing_ok=True)
return

lockfile = self.load_lockfile()
Expand All @@ -95,34 +81,23 @@ def generate(self, force=False):
self.save_lockfile(lockfile)

def load_config(self):
# TODO raise custom exceptions

if not os.path.exists(self.config_filename):
logger.warning(f"{self.config_filename} not found")
if not self.config_file.exists():
return {}
with self.config_file.open("rb") as f:
pyproject = tomllib.load(f)

with open(self.config_filename, "r") as f:
# why doesn't tomli.load(f) work?
toml_data = tomli.loads(f.read())

return ConfigSchema().load(toml_data)
return pyproject["tool"]["importmap"]

def load_lockfile(self):
if not os.path.exists(self.lock_filename):
if not self.lock_file.exists():
return {}

with open(self.lock_filename, "r") as f:
json_data = json.load(f)

return LockfileSchema().load(json_data)
with self.lock_file.open("r") as f:
return json.load(f)

def save_lockfile(self, lockfile):
with open(self.lock_filename, "w+") as f:
with self.lock_file.open("w+") as f:
json.dump(lockfile, f, indent=2, sort_keys=True)

def delete_lockfile(self):
if os.path.exists(self.lock_filename):
os.remove(self.lock_filename)

def generate_map(self, *args, **kwargs):
return ImportmapGenerator.from_config(self.config, *args, **kwargs).generate()
14 changes: 8 additions & 6 deletions importmap/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ def __init__(self, targets, development=False, provider="jspm"):

@classmethod
def from_config(cls, config, *args, **kwargs):
targets = []

for map in config["packages"]:
targets.append(map["source"])

return cls(targets, *args, **kwargs)
return cls(
[
f"{package}@{version}"
for package, version in config["dependencies"].items()
],
*args,
**kwargs,
)

def get_env(self):
if self.development:
Expand Down
Loading

0 comments on commit df44b1b

Please sign in to comment.