Skip to content

Commit b647b42

Browse files
authored
Merge pull request #16 from nexB/v21.4.28-prep
Version v21.4.28
2 parents 76a03d9 + 513d8cc commit b647b42

7 files changed

Lines changed: 148 additions & 15 deletions

File tree

.gitattributes

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# Ignore all Git auto CR/LF line endings conversions
2-
* binary
2+
* -text

CHANGELOG.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ Release notes
44
vNext
55
-----
66

7+
8+
Version 21.4.28
9+
---------------
10+
11+
*2020-04-28*
12+
- Add new function to get a Resource path stripped from its root path segment
13+
14+
715
Version 21.1.21
816
---------------
917

src/commoncode/resource.py

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
from commoncode.fileutils import splitext_name
6161

6262
from commoncode import ignore
63+
from commoncode import paths
6364

6465
"""
6566
This module provides Codebase and Resource objects as an abstraction for files
@@ -1054,6 +1055,12 @@ def type(self, value):
10541055
else:
10551056
self.is_file = False
10561057

1058+
def get_path(self, strip_root=False):
1059+
if strip_root:
1060+
return strip_first_path_segment(self.path)
1061+
else:
1062+
return self.path
1063+
10571064
@property
10581065
def is_dir(self):
10591066
# note: we only store is_file
@@ -1354,6 +1361,29 @@ def get_path(root_location, location, full_root=False, strip_root=False):
13541361
return posix_loc.replace(posix_root_loc, '', 1)
13551362

13561363

1364+
def strip_first_path_segment(path):
1365+
"""
1366+
Return a POSIX path stripped from its first path segment.
1367+
1368+
For example::
1369+
>>> strip_first_path_segment('')
1370+
''
1371+
>>> strip_first_path_segment('foo')
1372+
'foo'
1373+
>>> strip_first_path_segment('foo/bar/baz')
1374+
'bar/baz'
1375+
>>> strip_first_path_segment('/foo/bar/baz/')
1376+
'bar/baz'
1377+
>>> strip_first_path_segment('foo/')
1378+
'foo/'
1379+
"""
1380+
segments = paths.split(path)
1381+
if not segments or len(segments) == 1:
1382+
return path
1383+
stripped = segments[1:]
1384+
return '/'.join(stripped)
1385+
1386+
13571387
def get_codebase_cache_dir(temp_dir):
13581388
"""
13591389
Return a new, created and unique per-run cache storage directory path rooted
@@ -1506,20 +1536,27 @@ def _get_or_create_parent(self, path, parent_by_path):
15061536
"""
15071537
Return a parent resource for a given `path` from `parent_by_path`.
15081538
1509-
If a parent resource for a `path` does not exist in `parent_by_path`, it is created recursively.
1539+
If a parent resource for a `path` does not exist in `parent_by_path`, it
1540+
is created recursively.
15101541
1511-
Note: the root path and root Resource must already be in `parent_by_path` or else this
1512-
function does not work.
1542+
Note: the root path and root Resource must already be in
1543+
`parent_by_path` or else this function does not work.
15131544
"""
1514-
parent_path = parent_directory(path).rstrip('/').rstrip('\\')
1545+
parent_path = parent_directory(path).rstrip('/').rstrip('\\').lstrip("/")
15151546
existing_parent = parent_by_path.get(parent_path)
15161547
if existing_parent:
15171548
return existing_parent
15181549
parent_parent = self._get_or_create_parent(parent_path, parent_by_path)
15191550
parent_name = file_base_name(parent_path)
15201551
parent_is_file = False
15211552
parent_resource_data = self._create_empty_resource_data()
1522-
parent_resource = self._create_resource(parent_name, parent_parent, parent_is_file, parent_path, parent_resource_data)
1553+
parent_resource = self._create_resource(
1554+
parent_name,
1555+
parent_parent,
1556+
parent_is_file,
1557+
parent_path,
1558+
parent_resource_data,
1559+
)
15231560
parent_by_path[parent_path] = parent_resource
15241561
return parent_resource
15251562

@@ -1620,7 +1657,12 @@ def _populate(self, scan_data):
16201657
root_name = root_path
16211658
root_is_file = False
16221659
root_data = self._create_empty_resource_data()
1623-
root_resource = self._create_root_resource(root_name, root_path, root_is_file, root_data)
1660+
root_resource = self._create_root_resource(
1661+
name=root_name,
1662+
path=root_path,
1663+
is_file=root_is_file,
1664+
root_data=root_data,
1665+
)
16241666

16251667
# To help recreate the resource tree we keep a mapping by path of any
16261668
# parent resource
@@ -1630,24 +1672,32 @@ def _populate(self, scan_data):
16301672
path = resource_data.get('path')
16311673
# Append virtual_root path to imported Resource path if we are merging multiple scans
16321674
if multiple_input:
1633-
path = os.path.join(root_path, path)
1675+
path = posixpath.join(root_path, path)
1676+
16341677
name = resource_data.get('name', None)
16351678
if not name:
16361679
name = file_name(path)
1680+
16371681
is_file = resource_data.get('type', 'file') == 'file'
16381682

16391683
existing_parent = parent_by_path.get(path)
16401684
if existing_parent:
1641-
# We update the empty parent Resouorce we in _get_or_create_parent() with the data
1642-
# from the scan
1685+
# We update the empty parent Resouorce we in
1686+
# _get_or_create_parent() with the data from the scan
16431687
for k, v in resource_data.items():
16441688
setattr(existing_parent, k, v)
16451689
self.save_resource(existing_parent)
16461690
else:
1647-
# Note: `root_path`: `root_resource` must be in `parent_by_path` in order for
1648-
# `_get_or_create_parent` to work
1691+
# Note: `root_path`: `root_resource` must be in `parent_by_path`
1692+
# in order for `_get_or_create_parent` to work
16491693
parent = self._get_or_create_parent(path, parent_by_path)
1650-
resource = self._create_resource(name, parent, is_file, path, resource_data)
1694+
resource = self._create_resource(
1695+
name=name,
1696+
parent=parent,
1697+
is_file=is_file,
1698+
path=path,
1699+
resource_data=resource_data,
1700+
)
16511701

16521702
# Files are not parents (for now), so we do not need to add this
16531703
# to the parent_by_path mapping
@@ -1665,7 +1715,14 @@ def _create_root_resource(self, name, path, is_file, root_data):
16651715
if root_data:
16661716
root_data = remove_properties_and_basics(root_data)
16671717
root = self.resource_class(
1668-
name=name, location=None, path=path, rid=0, pid=None, is_file=is_file, **root_data)
1718+
name=name,
1719+
location=None,
1720+
path=path,
1721+
rid=0,
1722+
pid=None,
1723+
is_file=is_file,
1724+
**root_data,
1725+
)
16691726

16701727
self.resource_ids.add(0)
16711728
self.resources[0] = root

src/commoncode/system.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
import getpass
2222
import os
23-
import subprocess
2423
import sys
2524

2625

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"scancode_notice": "Generated with ScanCode and provided on an \"AS IS\" BASIS, WITHOUT WARRANTIES\nOR CONDITIONS OF ANY KIND, either express or implied. No content created from\nScanCode should be considered or used as legal advice. Consult an Attorney\nfor any legal advice.\nScanCode is a free software code scanning tool from nexB Inc. and others.\nVisit https://github.com/nexB/scancode-toolkit/ for support and download.",
3+
"scancode_version": "2.2.1.post12.6d07756e",
4+
"scancode_options": {
5+
"--info": true,
6+
"--license-score": 0,
7+
"--full-root": true,
8+
"--format": "json-pp"
9+
},
10+
"files_count": 1,
11+
"files": [
12+
{
13+
"path": "/Users/sesser/code/nexb/scancode-toolkit/samples/README",
14+
"type": "file",
15+
"name": "README",
16+
"base_name": "README",
17+
"extension": "",
18+
"date": "2017-09-22",
19+
"size": 236,
20+
"sha1": "2e07e32c52d607204fad196052d70e3d18fb8636",
21+
"md5": "effc6856ef85a9250fb1a470792b3f38",
22+
"files_count": null,
23+
"mime_type": "text/plain",
24+
"file_type": "ASCII text",
25+
"programming_language": null,
26+
"is_binary": false,
27+
"is_text": true,
28+
"is_archive": false,
29+
"is_media": false,
30+
"is_source": false,
31+
"is_script": false,
32+
"scan_errors": []
33+
}
34+
]
35+
}
36+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"files": [
3+
{
4+
"path": "samples",
5+
"type": "directory",
6+
"scan_errors": []
7+
},
8+
{
9+
"path": "samples/README",
10+
"type": "file",
11+
"scan_errors": []
12+
},
13+
{
14+
"path": "samples/screenshot.png",
15+
"type": "file",
16+
"scan_errors": []
17+
}
18+
]
19+
}

tests/test_resource.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,13 @@ def test_virtual_codebase_walk_skip_root_basic(self):
802802
]
803803
assert expected == [(r.name, r.is_file) for r in results]
804804

805+
def test_virtual_codebase_get_path_with_strip_root_and_walk_with_skip_root(self):
806+
scan_data = self.get_test_loc('resource/virtual_codebase/stripped-and-skipped-root.json')
807+
virtual_codebase = VirtualCodebase(location=scan_data)
808+
results = [r.get_path(strip_root=True) for r in virtual_codebase.walk(skip_root=True)]
809+
expected = ['README', 'screenshot.png']
810+
assert results == expected
811+
805812
def test_virtual_codebase_walk_filtered_with_filtered_root(self):
806813
scan_data = self.get_test_loc('resource/virtual_codebase/virtual_codebase.json')
807814
virtual_codebase = VirtualCodebase(location=scan_data)
@@ -1323,6 +1330,13 @@ def test_VirtualCodebase_create_from_multiple_scans(self):
13231330
]
13241331
assert expected == results
13251332

1333+
def test_VirtualCodebase_scanning_full_root(self):
1334+
test_file = self.get_test_loc("resource/virtual_codebase/path_full_root.json")
1335+
codebase = VirtualCodebase(test_file)
1336+
resource = sorted(r for r in codebase.walk())[0]
1337+
assert resource.path == "/Users/sesser/code/nexb/scancode-toolkit/samples/README"
1338+
assert codebase.compute_counts()[0] == 1
1339+
13261340

13271341
class TestResource(FileBasedTesting):
13281342
test_data_dir = join(dirname(__file__), 'data')

0 commit comments

Comments
 (0)