3535from commoncode import filetype
3636from commoncode import fileutils
3737
38- from packagedcode .models import AssertedLicense
39- from packagedcode .models import Dependency
40- from packagedcode .models import Package
41- from packagedcode .models import Party
42- from packagedcode .models import Repository
43- from packagedcode .models import Versioning
44- from schematics .types import StringType
45- from schematics .types .compound import ModelType
38+ from packagedcode import models
4639
4740"""
4841Handle Node.js NPM packages
6154# logger.setLevel(logging.DEBUG)
6255
6356
57+ class NpmPackage (models .Package ):
58+ metafiles = ('package.json' , 'npm-shrinkwrap.json' )
59+ filetypes = ('.tgz' ,)
60+ mimetypes = ('application/x-tar' ,)
61+ repo_types = (models .repo_npm ,)
62+
63+ type = models .StringType (default = 'npm' )
64+ primary_language = models .StringType (default = 'JavaScript' )
65+
66+ @staticmethod
67+ def recognize (location ):
68+ return parse (location )
69+
70+
6471def is_package_json (location ):
6572 return (filetype .is_file (location )
6673 and fileutils .file_name (location ).lower () == 'package.json' )
@@ -71,27 +78,9 @@ def is_node_modules(location):
7178 and fileutils .file_name (location ).lower () == 'node_modules' )
7279
7380
74- class NpmVersion (Versioning ):
75- version = StringType ()
76-
77-
78- class NpmPackage (Package ):
79- type = StringType (default = 'npm' )
80- versioning = ModelType (NpmVersion )
81- metafiles = ('package.json' ,)
82- primary_language = StringType (default = 'JavaScript' )
83- filetypes = ('.tgz' ,)
84- mimetypes = ('application/x-tar' ,)
85- repo_types = (Repository .repo_type_npm ,)
86-
87- @staticmethod
88- def getPackage (location ):
89- return parse (location )
90-
91-
9281def parse (location ):
9382 """
94- Return a Package object from a package.json
83+ Return a Package object from a package.json file or None.
9584 """
9685 if not is_package_json (location ):
9786 return
@@ -104,8 +93,8 @@ def parse(location):
10493 ('homepage' , 'homepage_url' ),
10594 ])
10695
107- # mapping of top level package.json items to a function accepting as arguments:
108- # - the package.json element value and a Package Object to update
96+ # mapping of top level package.json items to a function accepting as arguments
97+ # the package.json element value and returning an iterable of key, values Package Object to update
10998 field_mappers = OrderedDict ([
11099 ('author' , author_mapper ),
111100 ('bugs' , bugs_mapper ),
@@ -129,11 +118,13 @@ def parse(location):
129118 # a package.json without name and version is not a usable NPM package
130119 return
131120
121+ package = NpmPackage ()
132122 # a package.json is at the root of an NPM package
133123 base_dir = fileutils .parent_directory (location )
134- package = NpmPackage ()
124+ package .location = base_dir
125+ # for now we only recognize a pcakge.json, not a node_modules directory yet
135126 package .metafile_locations = [location ]
136- package .versioning = NpmVersion ( version = data .get ('version' ) )
127+ package .version = data .get ('version' )
137128 for source , target in plain_fields .items ():
138129 value = data .get (source )
139130 if value :
@@ -151,7 +142,7 @@ def parse(location):
151142 if value :
152143 func (value , package )
153144
154- package .download_urls .append (public_download_url (package .name , package .versioning . version ))
145+ package .download_urls .append (public_download_url (package .name , package .version ))
155146 package .metafile_locations .append (location )
156147 return package
157148
@@ -172,7 +163,7 @@ def licensing_mapper(licenses, package):
172163 return package
173164
174165 if isinstance (licenses , basestring ):
175- package .asserted_licenses .append (AssertedLicense (license = licenses ))
166+ package .asserted_licenses .append (models . AssertedLicense (license = licenses ))
176167
177168 elif isinstance (licenses , dict ):
178169 """
@@ -181,7 +172,7 @@ def licensing_mapper(licenses, package):
181172 "url": "http://github.com/kriskowal/q/raw/master/LICENSE"
182173 }
183174 """
184- package .asserted_licenses .append (AssertedLicense (license = licenses .get ('type' ),
175+ package .asserted_licenses .append (models . AssertedLicense (license = licenses .get ('type' ),
185176 url = licenses .get ('url' )))
186177
187178 elif isinstance (licenses , list ):
@@ -194,18 +185,18 @@ def licensing_mapper(licenses, package):
194185 # TODO: handle multiple values
195186 for lic in licenses :
196187 if isinstance (lic , basestring ):
197- package .asserted_licenses .append (AssertedLicense (license = lic ))
188+ package .asserted_licenses .append (models . AssertedLicense (license = lic ))
198189 elif isinstance (lic , dict ):
199- package .asserted_licenses .append (AssertedLicense (license = lic .get ('type' ),
190+ package .asserted_licenses .append (models . AssertedLicense (license = lic .get ('type' ),
200191 url = lic .get ('url' )))
201192 else :
202193 # use the bare repr
203194 if lic :
204- package .asserted_licenses .append (AssertedLicense (license = repr (lic )))
195+ package .asserted_licenses .append (models . AssertedLicense (license = repr (lic )))
205196
206197 else :
207198 # use the bare repr
208- package .asserted_licenses .append (AssertedLicense (license = repr (licenses )))
199+ package .asserted_licenses .append (models . AssertedLicense (license = repr (licenses )))
209200
210201 return package
211202
@@ -217,10 +208,7 @@ def author_mapper(author, package):
217208 The "author" is one person.
218209 """
219210 name , email , url = parse_person (author )
220- package .authors = [Party (type = Party .party_person ,
221- name = name ,
222- email = email ,
223- url = url )]
211+ package .authors = [models .Party (type = models .party_person , name = name , email = email , url = url )]
224212 return package
225213
226214
@@ -234,16 +222,13 @@ def contributors_mapper(contributors, package):
234222 if isinstance (contributors , list ):
235223 for contrib in contributors :
236224 name , email , url = parse_person (contrib )
237- contribs .append (Party (type = Party .party_person ,
238- name = name ,
239- email = email ,
240- url = url ))
225+
226+ contribs .append (models .Party (type = models .party_person , name = name , email = email , url = url ))
227+
241228 else : # a string or dict
242229 name , email , url = parse_person (contributors )
243- contribs .append (Party (type = Party .party_person ,
244- name = name ,
245- email = email ,
246- url = url ))
230+ contribs .append (models .Party (type = models .party_person , name = name , email = email , url = url ))
231+
247232 package .contributors = contribs
248233 return package
249234
@@ -259,16 +244,10 @@ def maintainers_mapper(maintainers, package):
259244 if isinstance (maintainers , list ):
260245 for contrib in maintainers :
261246 name , email , url = parse_person (contrib )
262- maintains .append (Party (type = Party .party_person ,
263- name = name ,
264- email = email ,
265- url = url ))
247+ maintains .append (models .Party (type = models .party_person , name = name , email = email , url = url ))
266248 else : # a string or dict
267249 name , email , url = parse_person (maintainers )
268- maintains .append (Party (type = Party .party_person ,
269- name = name ,
270- email = email ,
271- url = url ))
250+ maintains .append (models .Party (type = models .party_person , name = name , email = email , url = url ))
272251 package .maintainers = maintains
273252 return package
274253
@@ -338,10 +317,12 @@ def repository_mapper(repo, package):
338317
339318def parse_repo_url (repo_url ):
340319 """
341- https://docs.npmjs.com/files/package.json#repository
342320 Validate a repo_ulr and handle shortcuts for GitHub, GitHub gist,
343321 Bitbucket, or GitLab repositories (same syntax as npm install):
344- This is done here: https://github.com/npm/npm/blob/d3c858ce4cfb3aee515bb299eb034fe1b5e44344/node_modules/hosted-git-info/git-host-info.js
322+
323+ See https://docs.npmjs.com/files/package.json#repository
324+ This is done here in npm:
325+ https://github.com/npm/npm/blob/d3c858ce4cfb3aee515bb299eb034fe1b5e44344/node_modules/hosted-git-info/git-host-info.js
345326
346327 These should be resolved:
347328 npm/npm
@@ -394,8 +375,9 @@ def parse_repo_url(repo_url):
394375
395376def url_mapper (url , package ):
396377 """
397- a "url" fieldis a redirection to your package that has been published
398- somewhere else than the public npm registry
378+ In a package.json, the "url" field is a redirection to a package download
379+ URL published somewhere else than on the public npm registry.
380+ We map it to a download url.
399381 """
400382 if url :
401383 package .download_urls .append (url )
@@ -404,7 +386,7 @@ def url_mapper(url, package):
404386
405387def dist_mapper (dist , package ):
406388 """
407- only present in some package.json forms (as installed or from a registry?)
389+ Only present in some package.json forms (as installed or from a registry?)
408390 "dist": {
409391 "shasum": "a124386bce4a90506f28ad4b1d1a804a17baaf32",
410392 "tarball": "http://registry.npmjs.org/npm/-/npm-2.13.5.tgz"
@@ -422,11 +404,11 @@ def bundle_deps_mapper(bundle_deps, package):
422404 """
423405 https://docs.npmjs.com/files/package.json#bundleddependencies
424406 """
425- package .dependencies [Package .dep_bundled ] = bundle_deps
407+ package .dependencies [models .dep_bundled ] = bundle_deps
426408 return package
427409
428410
429- def _deps_mapper (deps , package , field_name ):
411+ def deps_mapper (deps , package , field_name ):
430412 """
431413 Handle deps such as dependencies, devDependencies, peerDependencies, optionalDependencies
432414 return a tuple of (dep type, list of deps)
@@ -435,15 +417,16 @@ def _deps_mapper(deps, package, field_name):
435417 https://docs.npmjs.com/files/package.json#devdependencies
436418 https://docs.npmjs.com/files/package.json#optionaldependencies
437419 """
438- dep_types = {'dependencies' : Package .dep_runtime ,
439- 'devDependencies' : Package .dep_dev ,
440- 'peerDependencies' : Package .dep_optional ,
441- 'optionalDependencies' : Package .dep_optional ,
442- }
420+ dep_types = {
421+ 'dependencies' : models .dep_runtime ,
422+ 'devDependencies' : models .dep_dev ,
423+ 'peerDependencies' : models .dep_optional ,
424+ 'optionalDependencies' : models .dep_optional ,
425+ }
443426 resolved_type = dep_types [field_name ]
444427 dependencies = []
445- for pid , version_constraint in deps .items ():
446- dep = Dependency (id = pid , version_constraint = version_constraint )
428+ for name , version_constraint in deps .items ():
429+ dep = models . Dependency (name = name , version_constraint = version_constraint )
447430 dependencies .append (dep )
448431 if resolved_type in package .dependencies :
449432 package .dependencies [resolved_type ].extend (dependencies )
@@ -452,10 +435,10 @@ def _deps_mapper(deps, package, field_name):
452435 return package
453436
454437
455- dependencies_mapper = partial (_deps_mapper , field_name = 'dependencies' )
456- dev_dependencies_mapper = partial (_deps_mapper , field_name = 'devDependencies' )
457- peer_dependencies_mapper = partial (_deps_mapper , field_name = 'peerDependencies' )
458- optional_dependencies_mapper = partial (_deps_mapper , field_name = 'optionalDependencies' )
438+ dependencies_mapper = partial (deps_mapper , field_name = 'dependencies' )
439+ dev_dependencies_mapper = partial (deps_mapper , field_name = 'devDependencies' )
440+ peer_dependencies_mapper = partial (deps_mapper , field_name = 'peerDependencies' )
441+ optional_dependencies_mapper = partial (deps_mapper , field_name = 'optionalDependencies' )
459442
460443
461444person_parser = re .compile (
@@ -507,13 +490,15 @@ def parse_person(person):
507490
508491def public_download_url (name , version , registry = 'https://registry.npmjs.org' ):
509492 """
510- Return a package tarball download URL
493+ Return a package tarball download URL given a name, version and a base
494+ registry URL.
511495 """
512496 return '%(registry)s/%(name)s/-/%(name)s-%(version)s.tgz' % locals ()
513497
514498
515499def public_package_data_url (name , version , registry = 'https://registry.npmjs.org' ):
516500 """
517- Return a package metadata download URL
501+ Return a package metadata download URL given a name, version and a base
502+ registry URL.
518503 """
519504 return '%(registry)s/%(name)s/%(version)s' % locals ()
0 commit comments